From a1e87782116671521f73a23bb36fd788345366cb Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Thu, 19 Mar 2015 15:37:08 +0100 Subject: [PATCH 01/30] First piece of the refactor of the CitrisResourceBase - The same pattern will be used by the other subclasses of the ServerResource interface. --- .../com/cloud/resource/CommandWrapper.java | 34 +++++ .../com/cloud/resource/RequestWrapper.java | 32 ++++ .../resource/CitrixResourceBase.java | 6 +- .../resource/XenServer56Resource.java | 141 +++++++++--------- .../CitrixRebootRouterCommandWrapper.java | 50 +++++++ .../wrapper/CitrixRequestWrapper.java | 63 ++++++++ .../wrapper/CitrixRequestWrapperTest.java | 52 +++++++ 7 files changed, 304 insertions(+), 74 deletions(-) create mode 100644 core/src/com/cloud/resource/CommandWrapper.java create mode 100644 core/src/com/cloud/resource/RequestWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootRouterCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java create mode 100644 plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapperTest.java diff --git a/core/src/com/cloud/resource/CommandWrapper.java b/core/src/com/cloud/resource/CommandWrapper.java new file mode 100644 index 00000000000..f68e92a2327 --- /dev/null +++ b/core/src/com/cloud/resource/CommandWrapper.java @@ -0,0 +1,34 @@ +// +// 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.resource; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + + +public abstract class CommandWrapper { + + /** + * @param T is the command to be used. + * @param R is the resource base to be used. + * @return A and the Answer from the command. + */ + public abstract A execute(T command, R serverResource); +} \ No newline at end of file diff --git a/core/src/com/cloud/resource/RequestWrapper.java b/core/src/com/cloud/resource/RequestWrapper.java new file mode 100644 index 00000000000..6fd1c668855 --- /dev/null +++ b/core/src/com/cloud/resource/RequestWrapper.java @@ -0,0 +1,32 @@ +// +// 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.resource; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public abstract class RequestWrapper { + + /** + * @param command to be executed. + * @return an Answer for the executed command. + */ + public abstract Answer execute(Command command, ServerResource serverResource); +} \ No newline at end of file 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 96374e4ca8d..73f11c22e89 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 @@ -2047,7 +2047,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected String networkUsage(final Connection conn, final String privateIpAddress, final String option, final String vif) { + public String networkUsage(final Connection conn, final String privateIpAddress, final String option, final String vif) { if (option.equals("get")) { return "0:0"; } @@ -3096,7 +3096,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected Answer execute(final RebootRouterCommand cmd) { + public Answer execute(final RebootRouterCommand cmd) { final Connection conn = getConnection(); final RebootAnswer answer = execute((RebootCommand)cmd); if (answer.getResult()) { @@ -3630,7 +3630,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return msg; } - protected String connect(final Connection conn, final String vmname, final String ipAddress) { + public String connect(final Connection conn, final String vmname, final String ipAddress) { return connect(conn, vmname, ipAddress, 3922); } 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 eec972e6b64..a8e9efac9aa 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 @@ -26,15 +26,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.Network; -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; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckOnHostAnswer; import com.cloud.agent.api.CheckOnHostCommand; @@ -49,13 +40,21 @@ import com.cloud.utils.ExecutionResult; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SSHCmdHelper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Network; +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 { private final static Logger s_logger = Logger.getLogger(XenServer56Resource.class); @Override - public Answer executeRequest(Command cmd) { + public Answer executeRequest(final Command cmd) { if (cmd instanceof FenceCommand) { return execute((FenceCommand)cmd); } else if (cmd instanceof NetworkUsageCommand) { @@ -68,63 +67,63 @@ public class XenServer56Resource extends CitrixResourceBase { @Override protected List getPatchFiles() { - List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xenserver56/patch"; - String patchfilePath = Script.findScript("", patch); + final List files = new ArrayList(); + final String patch = "scripts/vm/hypervisor/xenserver/xenserver56/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 void disableVlanNetwork(Connection conn, Network network) { + protected void disableVlanNetwork(final Connection conn, final Network network) { try { - Network.Record networkr = network.getRecord(conn); + final Network.Record networkr = network.getRecord(conn); if (!networkr.nameLabel.startsWith("VLAN")) { return; } - String bridge = networkr.bridge.trim(); - for (PIF pif : networkr.PIFs) { - PIF.Record pifr = pif.getRecord(conn); + final String bridge = networkr.bridge.trim(); + for (final PIF pif : networkr.PIFs) { + final PIF.Record pifr = pif.getRecord(conn); if (!pifr.host.getUuid(conn).equalsIgnoreCase(_host.uuid)) { continue; } - VLAN vlan = pifr.VLANMasterOf; + final VLAN vlan = pifr.VLANMasterOf; if (vlan != null) { - String vlannum = pifr.VLAN.toString(); - String device = pifr.device.trim(); + final String vlannum = pifr.VLAN.toString(); + final String device = pifr.device.trim(); if (vlannum.equals("-1")) { return; } try { vlan.destroy(conn); - Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.uuid); host.forgetDataSourceArchives(conn, "pif_" + bridge + "_tx"); host.forgetDataSourceArchives(conn, "pif_" + bridge + "_rx"); host.forgetDataSourceArchives(conn, "pif_" + device + "." + vlannum + "_tx"); host.forgetDataSourceArchives(conn, "pif_" + device + "." + vlannum + "_rx"); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { s_logger.trace("Catch " + e.getClass().getName() + ": failed to destory VLAN " + device + " on host " + _host.uuid + " due to " + e.toString()); } } return; } - } catch (XenAPIException e) { - String msg = "Unable to disable VLAN network due to " + e.toString(); + } catch (final XenAPIException e) { + final String msg = "Unable to disable VLAN network due to " + e.toString(); s_logger.warn(msg, e); - } catch (Exception e) { - String msg = "Unable to disable VLAN network due to " + e.getMessage(); + } catch (final Exception e) { + final String msg = "Unable to disable VLAN network due to " + e.getMessage(); s_logger.warn(msg, e); } } @Override - protected String networkUsage(Connection conn, final String privateIpAddress, final String option, final String vif) { + public String networkUsage(final Connection conn, final String privateIpAddress, final String option, final String vif) { String args = ""; if (option.equals("get")) { args += "-g"; @@ -143,18 +142,18 @@ public class XenServer56Resource extends CitrixResourceBase { return executeInVR(privateIpAddress, "netusage.sh", args).getDetails(); } - protected NetworkUsageAnswer VPCNetworkUsage(NetworkUsageCommand cmd) { + protected NetworkUsageAnswer VPCNetworkUsage(final NetworkUsageCommand cmd) { try { - Connection conn = getConnection(); - String option = cmd.getOption(); - String publicIp = cmd.getGatewayIP(); + final Connection conn = getConnection(); + final String option = cmd.getOption(); + final String publicIp = cmd.getGatewayIP(); String args = " -l " + publicIp + " "; if (option.equals("get")) { args += "-g"; } else if (option.equals("create")) { args += "-c"; - String vpcCIDR = cmd.getVpcCIDR(); + final String vpcCIDR = cmd.getVpcCIDR(); args += " -v " + vpcCIDR; } else if (option.equals("reset")) { args += "-r"; @@ -166,67 +165,67 @@ public class XenServer56Resource extends CitrixResourceBase { return new NetworkUsageAnswer(cmd, "success", 0L, 0L); } - ExecutionResult result = executeInVR(cmd.getPrivateIP(), "vpc_netusage.sh", args); - String detail = result.getDetails(); + final ExecutionResult result = executeInVR(cmd.getPrivateIP(), "vpc_netusage.sh", args); + final String detail = result.getDetails(); if (!result.isSuccess()) { throw new Exception(" vpc network usage plugin call failed "); } if (option.equals("get") || option.equals("vpn")) { - long[] stats = new long[2]; + final long[] stats = new long[2]; if (detail != null) { - String[] splitResult = detail.split(":"); + final String[] splitResult = detail.split(":"); int i = 0; while (i < splitResult.length - 1) { - stats[0] += (new Long(splitResult[i++])).longValue(); - stats[1] += (new Long(splitResult[i++])).longValue(); + stats[0] += new Long(splitResult[i++]).longValue(); + stats[1] += new Long(splitResult[i++]).longValue(); } return new NetworkUsageAnswer(cmd, "success", stats[0], stats[1]); } } return new NetworkUsageAnswer(cmd, "success", 0L, 0L); - } catch (Exception ex) { + } catch (final Exception ex) { s_logger.warn("Failed to get network usage stats due to ", ex); return new NetworkUsageAnswer(cmd, ex); } } - protected NetworkUsageAnswer execute(NetworkUsageCommand cmd) { + protected NetworkUsageAnswer execute(final NetworkUsageCommand cmd) { if (cmd.isForVpc()) { return VPCNetworkUsage(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); } } - protected Boolean check_heartbeat(String hostuuid) { - com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.ip, 22); + protected Boolean check_heartbeat(final String hostuuid) { + final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.ip, 22); try { sshConnection.connect(null, 60000, 60000); if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { throw new CloudRuntimeException("Unable to authenticate"); } - String shcmd = "/opt/cloud/bin/check_heartbeat.sh " + hostuuid + " " - + Integer.toString(_heartbeatInterval * 2); + final String shcmd = "/opt/cloud/bin/check_heartbeat.sh " + hostuuid + " " + + Integer.toString(_heartbeatInterval * 2); if (!SSHCmdHelper.sshExecuteCmd(sshConnection, shcmd)) { s_logger.debug("Heart beat is gone so dead."); return false; } s_logger.debug("Heart beat is still going"); return true; - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("health check failed due to catch exception " + e.toString()); return null; } finally { @@ -234,10 +233,10 @@ public class XenServer56Resource extends CitrixResourceBase { } } - 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"); @@ -246,17 +245,17 @@ public class XenServer56Resource extends CitrixResourceBase { 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) { + 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 (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()); } @@ -264,11 +263,11 @@ public class XenServer56Resource extends CitrixResourceBase { @Override - protected boolean transferManagementNetwork(Connection conn, Host host, PIF src, PIF.Record spr, PIF dest) throws XmlRpcException, XenAPIException { + protected 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); Host.managementReconfigure(conn, dest); String hostUuid = null; - int count = 0; + final int count = 0; while (count < 10) { try { Thread.sleep(10000); @@ -276,11 +275,11 @@ public class XenServer56Resource extends CitrixResourceBase { if (hostUuid != null) { break; } - } catch (XmlRpcException e) { + } catch (final XmlRpcException e) { s_logger.debug("Waiting for host to come back: " + e.getMessage()); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { s_logger.debug("Waiting for host to come back: " + e.getMessage()); - } catch (InterruptedException e) { + } catch (final InterruptedException e) { s_logger.debug("Gotta run"); return false; } @@ -297,21 +296,21 @@ public class XenServer56Resource extends CitrixResourceBase { @Override public StartupCommand[] initialize() { pingXAPI(); - StartupCommand[] cmds = super.initialize(); + final StartupCommand[] cmds = super.initialize(); return cmds; } @Override - protected CheckOnHostAnswer execute(CheckOnHostCommand cmd) { - Boolean alive = check_heartbeat(cmd.getHost().getGuid()); + protected CheckOnHostAnswer execute(final CheckOnHostCommand cmd) { + final Boolean alive = check_heartbeat(cmd.getHost().getGuid()); String msg = ""; if (alive == null) { - msg = " cannot determine "; + msg = " cannot determine "; } else if ( alive == true) { - msg = "Heart beat is still going"; + msg = "Heart beat is still going"; } else { - msg = "Heart beat is gone so dead."; + msg = "Heart beat is gone so dead."; } s_logger.debug(msg); return new CheckOnHostAnswer(cmd, alive, msg); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootRouterCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootRouterCommandWrapper.java new file mode 100644 index 00000000000..c244335119c --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootRouterCommandWrapper.java @@ -0,0 +1,50 @@ +// +// 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.RebootAnswer; +import com.cloud.agent.api.RebootCommand; +import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixRebootRouterCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final RebootRouterCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + + final RebootAnswer answer = citrixResourceBase.execute((RebootCommand)command); + + if (answer.getResult()) { + final String cnct = citrixResourceBase.connect(conn, command.getVmName(), command.getPrivateIpAddress()); + citrixResourceBase.networkUsage(conn, command.getPrivateIpAddress(), "create", null); + + if (cnct == null) { + return answer; + } else { + return new Answer(command, false, cnct); + } + } + return answer; + } +} \ 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 new file mode 100644 index 00000000000..124b2973844 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java @@ -0,0 +1,63 @@ +// +// 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.Hashtable; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.resource.CommandWrapper; +import com.cloud.resource.RequestWrapper; +import com.cloud.resource.ServerResource; + +public class CitrixRequestWrapper extends RequestWrapper { + + private static CitrixRequestWrapper instance; + + static { + instance = new CitrixRequestWrapper(); + } + + @SuppressWarnings("rawtypes") + private final Hashtable, CommandWrapper> map; + + @SuppressWarnings("rawtypes") + private CitrixRequestWrapper() { + map = new Hashtable, CommandWrapper>(); + init(); + } + + private void init() { + map.put(RebootRouterCommand.class, new CitrixRebootRouterCommandWrapper()); + } + + public static CitrixRequestWrapper getInstance() { + return instance; + } + + @Override + public Answer execute(final Command command, final ServerResource serverResource) { + @SuppressWarnings("unchecked") + final CommandWrapper commandWrapper = map.get(command.getClass()); + + return commandWrapper.execute(command, serverResource); + } +} \ No newline at end of file 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 new file mode 100644 index 00000000000..aa4ebb9f100 --- /dev/null +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapperTest.java @@ -0,0 +1,52 @@ +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.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.RebootAnswer; +import com.cloud.agent.api.RebootCommand; +import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; + +@RunWith(MockitoJUnitRunner.class) +public class CitrixRequestWrapperTest { + + @Mock + protected CitrixResourceBase citrixResourceBase; + @Mock + protected RebootAnswer rebootAnswer; + + @Test + public void testWrapperInstance() { + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + } + + @Test + public void testExecuteRebootRouterCommand() { + final RebootRouterCommand rebootCommand = new RebootRouterCommand("", ""); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + doReturn(rebootAnswer).when(citrixResourceBase).execute((RebootCommand)rebootCommand); + doReturn(false).when(rebootAnswer).getResult(); + + final Answer answer = wrapper.execute(rebootCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).execute((RebootCommand)rebootCommand); + + assertFalse(rebootAnswer.getResult()); + assertEquals(answer, rebootAnswer); + } +} \ No newline at end of file From 4256418af9e1c3f5b97c6fe77968f31c0693ce15 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Fri, 20 Mar 2015 10:14:04 +0100 Subject: [PATCH 02/30] Adding CitrixCreateCommandWrapper.java and basic unit tests --- .../resource/CitrixResourceBase.java | 4 +- .../wrapper/CitrixCreateCommandWrapper.java | 82 +++++++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 2 + .../wrapper/CitrixRequestWrapperTest.java | 21 +++++ 4 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateCommandWrapper.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 73f11c22e89..b2847681292 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 @@ -5851,7 +5851,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - protected VDI getVDIbyUuid(final Connection conn, final String uuid) { + public VDI getVDIbyUuid(final Connection conn, final String uuid) { return getVDIbyUuid(conn, uuid, true); } @@ -6742,7 +6742,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected SR getStorageRepository(final Connection conn, final String srNameLabel) { + public SR getStorageRepository(final Connection conn, final String srNameLabel) { Set srs; try { srs = SR.getByNameLabel(conn, srNameLabel); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateCommandWrapper.java new file mode 100644 index 00000000000..c58c5a9a87a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateCommandWrapper.java @@ -0,0 +1,82 @@ +// +// 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.HashMap; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.CreateAnswer; +import com.cloud.agent.api.storage.CreateCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.vm.DiskProfile; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VDI; + +public final class CitrixCreateCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixCreateCommandWrapper.class); + + @Override + public Answer execute(final CreateCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final StorageFilerTO pool = command.getPool(); + final DiskProfile dskch = command.getDiskCharacteristics(); + + VDI vdi = null; + try { + final SR poolSr = citrixResourceBase.getStorageRepository(conn, pool.getUuid()); + if (command.getTemplateUrl() != null) { + VDI tmpltvdi = null; + + tmpltvdi = citrixResourceBase.getVDIbyUuid(conn, command.getTemplateUrl()); + vdi = tmpltvdi.createClone(conn, new HashMap()); + vdi.setNameLabel(conn, dskch.getName()); + } else { + final VDI.Record vdir = new VDI.Record(); + vdir.nameLabel = dskch.getName(); + vdir.SR = poolSr; + vdir.type = Types.VdiType.USER; + + vdir.virtualSize = dskch.getSize(); + vdi = VDI.create(conn, vdir); + } + + VDI.Record vdir; + vdir = vdi.getRecord(conn); + + s_logger.debug("Succesfully created VDI for " + command + ". Uuid = " + vdir.uuid); + + final VolumeTO vol = + new VolumeTO(command.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), vdir.nameLabel, pool.getPath(), vdir.uuid, vdir.virtualSize, null); + + return new CreateAnswer(command, vol); + } catch (final Exception e) { + s_logger.warn("Unable to create volume; Pool=" + pool + "; Disk: " + dskch, e); + return new CreateAnswer(command, e); + } + } +} \ 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 124b2973844..854116c80f7 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 @@ -24,6 +24,7 @@ import java.util.Hashtable; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.storage.CreateCommand; import com.cloud.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; import com.cloud.resource.ServerResource; @@ -47,6 +48,7 @@ public class CitrixRequestWrapper extends RequestWrapper { private void init() { map.put(RebootRouterCommand.class, new CitrixRebootRouterCommandWrapper()); + map.put(CreateCommand.class, new CitrixCreateCommandWrapper()); } 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 aa4ebb9f100..e19883a449d 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 @@ -7,6 +7,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -16,7 +17,10 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.storage.CreateAnswer; +import com.cloud.agent.api.storage.CreateCommand; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.vm.DiskProfile; @RunWith(MockitoJUnitRunner.class) public class CitrixRequestWrapperTest { @@ -25,6 +29,8 @@ public class CitrixRequestWrapperTest { protected CitrixResourceBase citrixResourceBase; @Mock protected RebootAnswer rebootAnswer; + @Mock + protected CreateAnswer createAnswer; @Test public void testWrapperInstance() { @@ -44,9 +50,24 @@ public class CitrixRequestWrapperTest { final Answer answer = wrapper.execute(rebootCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); verify(citrixResourceBase, times(1)).execute((RebootCommand)rebootCommand); assertFalse(rebootAnswer.getResult()); assertEquals(answer, rebootAnswer); } + + @Test + public void testExecuteCreateCommand() { + final CreateCommand createCommand = new CreateCommand(new DiskProfile(null), "", new StoragePoolVO(), false); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(createCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } } \ No newline at end of file From c3ae8c793b8092cf092d66c01ba672a277714ba8 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Fri, 20 Mar 2015 11:17:46 +0100 Subject: [PATCH 03/30] Adding the refactor of CitrixCheckConsoleProxyLoadCommandWrapper.java and CitrixWatchConsoleProxyLoadCommandWrapper.java - plus basic tests --- .../com/cloud/resource/CommandWrapper.java | 64 +++++++++++++++++++ ...ixCheckConsoleProxyLoadCommandWrapper.java | 38 +++++++++++ .../wrapper/CitrixRequestWrapper.java | 4 ++ ...ixWatchConsoleProxyLoadCommandWrapper.java | 38 +++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 26 ++++++++ 5 files changed, 170 insertions(+) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckConsoleProxyLoadCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixWatchConsoleProxyLoadCommandWrapper.java diff --git a/core/src/com/cloud/resource/CommandWrapper.java b/core/src/com/cloud/resource/CommandWrapper.java index f68e92a2327..15f7b080992 100644 --- a/core/src/com/cloud/resource/CommandWrapper.java +++ b/core/src/com/cloud/resource/CommandWrapper.java @@ -19,16 +19,80 @@ package com.cloud.resource; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; + +import org.apache.log4j.Logger; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer; public abstract class CommandWrapper { + private static final Logger s_logger = Logger.getLogger(CommandWrapper.class); + /** * @param T is the command to be used. * @param R is the resource base to be used. * @return A and the Answer from the command. */ public abstract A execute(T command, R serverResource); + + /** + * Common method so we added it here. + * + * @param cmd + * @param proxyVmId + * @param proxyVmName + * @param proxyManagementIp + * @param cmdPort + * @return + */ + protected Answer executeProxyLoadScan(final Command cmd, final long proxyVmId, final String proxyVmName, final String proxyManagementIp, final int cmdPort) { + String result = null; + + final StringBuffer sb = new StringBuffer(); + sb.append("http://").append(proxyManagementIp).append(":" + cmdPort).append("/cmd/getstatus"); + + boolean success = true; + try { + final URL url = new URL(sb.toString()); + final URLConnection conn = url.openConnection(); + + // setting TIMEOUTs to avoid possible waiting until death situations + conn.setConnectTimeout(5000); + conn.setReadTimeout(5000); + + final InputStream is = conn.getInputStream(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + final StringBuilder sb2 = new StringBuilder(); + String line = null; + try { + while ((line = reader.readLine()) != null) { + sb2.append(line + "\n"); + } + result = sb2.toString(); + } catch (final IOException e) { + success = false; + } finally { + try { + is.close(); + } catch (final IOException e) { + s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp); + success = false; + } + } + } catch (final IOException e) { + s_logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp); + success = false; + } + + return new ConsoleProxyLoadAnswer(cmd, proxyVmId, proxyVmName, success, result); + } } \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckConsoleProxyLoadCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckConsoleProxyLoadCommandWrapper.java new file mode 100644 index 00000000000..bdf7c319a59 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckConsoleProxyLoadCommandWrapper.java @@ -0,0 +1,38 @@ +// +// 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.proxy.CheckConsoleProxyLoadCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; + +public final class CitrixCheckConsoleProxyLoadCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final CheckConsoleProxyLoadCommand command, final CitrixResourceBase citrixResourceBase) { + final long proxyVmId = command.getProxyVmId(); + final String proxyVmName = command.getProxyVmName(); + final String proxyManagementIp = command.getProxyManagementIp(); + final int cmdPort = command.getProxyCmdPort(); + + return executeProxyLoadScan(command, proxyVmId, proxyVmName, proxyManagementIp, cmdPort); + } +} \ 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 854116c80f7..5495f60c7a6 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 @@ -24,6 +24,8 @@ import java.util.Hashtable; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; +import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; @@ -49,6 +51,8 @@ public class CitrixRequestWrapper extends RequestWrapper { private void init() { map.put(RebootRouterCommand.class, new CitrixRebootRouterCommandWrapper()); map.put(CreateCommand.class, new CitrixCreateCommandWrapper()); + map.put(CheckConsoleProxyLoadCommand.class, new CitrixCheckConsoleProxyLoadCommandWrapper()); + map.put(WatchConsoleProxyLoadCommand.class, new CitrixWatchConsoleProxyLoadCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixWatchConsoleProxyLoadCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixWatchConsoleProxyLoadCommandWrapper.java new file mode 100644 index 00000000000..4ee961402f9 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixWatchConsoleProxyLoadCommandWrapper.java @@ -0,0 +1,38 @@ +// +// 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.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; + +public final class CitrixWatchConsoleProxyLoadCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final WatchConsoleProxyLoadCommand command, final CitrixResourceBase citrixResourceBase) { + final long proxyVmId = command.getProxyVmId(); + final String proxyVmName = command.getProxyVmName(); + final String proxyManagementIp = command.getProxyManagementIp(); + final int cmdPort = command.getProxyCmdPort(); + + return executeProxyLoadScan(command, proxyVmId, proxyVmName, proxyManagementIp, cmdPort); + } +} \ No newline at end of file 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 e19883a449d..f8af54336e7 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 @@ -17,6 +17,8 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; +import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; @@ -70,4 +72,28 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testCheckConsoleProxyLoadCommand() { + final CheckConsoleProxyLoadCommand consoleProxyCommand = new CheckConsoleProxyLoadCommand(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(consoleProxyCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } + + @Test + public void testWatchConsoleProxyLoadCommand() { + final WatchConsoleProxyLoadCommand watchConsoleProxyCommand = new WatchConsoleProxyLoadCommand(0, 0, "", "", 0); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(watchConsoleProxyCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } } \ No newline at end of file From 30e72e4a156a224f109f67b277e1e439bdcc9158 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Fri, 20 Mar 2015 13:51:46 +0100 Subject: [PATCH 04/30] Refactoring the whole XsHost thing Refactor the ReadyCommand Fixing the old test Adding basic tests for ReadyCommandWrapper --- .../xenserver/resource/CitrixHelper.java | 28 +- .../resource/CitrixResourceBase.java | 472 +++++----- .../xenserver/resource/XcpOssResource.java | 103 ++- .../resource/XenServer56Resource.java | 8 +- .../resource/XenServer610Resource.java | 226 +++-- .../resource/XenServer620Resource.java | 33 +- .../resource/XenServer620SP1Resource.java | 82 +- .../resource/XenServerStorageProcessor.java | 864 +++++++++--------- .../resource/Xenserver625Resource.java | 57 +- .../Xenserver625StorageProcessor.java | 572 ++++++------ .../hypervisor/xenserver/resource/XsHost.java | 212 +++++ .../wrapper/CitrixReadyCommandWrapper.java | 75 ++ .../wrapper/CitrixRequestWrapper.java | 2 + .../xenserver/XenServerResourceNewBase.java | 75 +- .../resource/CitrixResourceBaseTest.java | 38 +- .../wrapper/CitrixRequestWrapperTest.java | 13 + 16 files changed, 1556 insertions(+), 1304 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XsHost.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixReadyCommandWrapper.java diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixHelper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixHelper.java index 5bc80363e17..265573d7e4a 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixHelper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixHelper.java @@ -16,11 +16,8 @@ // under the License. package com.cloud.hypervisor.xenserver.resource; -import java.util.ArrayList; import java.util.HashMap; -import org.apache.log4j.Logger; - import com.xensource.xenapi.Host; /** @@ -28,18 +25,13 @@ import com.xensource.xenapi.Host; * */ public class CitrixHelper { - private static final Logger s_logger = Logger.getLogger(CitrixHelper.class); - - private static final HashMap XenServerGuestOsMemoryMap = new HashMap(70); - private static final ArrayList GuestOsList = new ArrayList(70); - public static class MemoryValues { long max; long min; - public MemoryValues(long min, long max) { + public MemoryValues(final long min, final long max) { this.min = min * 1024 * 1024; this.max = max * 1024 * 1024; } @@ -53,8 +45,6 @@ public class CitrixHelper { } } - - static { XenServerGuestOsMemoryMap.put("CentOS 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); XenServerGuestOsMemoryMap.put("CentOS 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); @@ -207,37 +197,37 @@ public class CitrixHelper { XenServerGuestOsMemoryMap.put("Windows XP SP3 (32-bit)", new MemoryValues(256l, 4 * 1024l)); XenServerGuestOsMemoryMap.put("Ubuntu 10.04 (32-bit)", new MemoryValues(128l, 512l)); XenServerGuestOsMemoryMap.put("Ubuntu 10.04 (64-bit)", new MemoryValues(128l, 32 * 1024l)); - XenServerGuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16*1024l)); - XenServerGuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16*1024l)); + XenServerGuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServerGuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16 * 1024l)); XenServerGuestOsMemoryMap.put("Ubuntu 12.04 (32-bit)", new MemoryValues(512l, 32 * 1024l)); XenServerGuestOsMemoryMap.put("Ubuntu 12.04 (64-bit)", new MemoryValues(512l, 128 * 1024l)); XenServerGuestOsMemoryMap.put("Ubuntu 14.04 (32-bit)", new MemoryValues(512l, 32 * 1024l)); XenServerGuestOsMemoryMap.put("Ubuntu 14.04 (64-bit)", new MemoryValues(512l, 128 * 1024l)); } - public static long getXenServerStaticMax(String stdType, boolean bootFromCD) { - MemoryValues recommendedMaxMinMemory = XenServerGuestOsMemoryMap.get(stdType); + public static long getXenServerStaticMax(final String stdType, final boolean bootFromCD) { + final MemoryValues recommendedMaxMinMemory = XenServerGuestOsMemoryMap.get(stdType); if (recommendedMaxMinMemory == null) { return 0l; } return recommendedMaxMinMemory.getMax(); } - public static long getXenServerStaticMin(String stdType, boolean bootFromCD) { - MemoryValues recommendedMaxMinMemory = XenServerGuestOsMemoryMap.get(stdType); + public static long getXenServerStaticMin(final String stdType, final boolean bootFromCD) { + final MemoryValues recommendedMaxMinMemory = XenServerGuestOsMemoryMap.get(stdType); if (recommendedMaxMinMemory == null) { return 0l; } return recommendedMaxMinMemory.getMin(); } - public static String getProductVersion(Host.Record record) { + public static String getProductVersion(final Host.Record record) { String prodVersion = record.softwareVersion.get("product_version"); if (prodVersion == null) { prodVersion = record.softwareVersion.get("platform_version").trim(); } else { prodVersion = prodVersion.trim(); - String[] items = prodVersion.split("\\."); + final String[] items = prodVersion.split("\\."); if (Integer.parseInt(items[0]) > 6) { prodVersion = "6.5.0"; } else if (Integer.parseInt(items[0]) == 6 && Integer.parseInt(items[1]) >= 4) { 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 b2847681292..850cbb39aa9 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 @@ -349,8 +349,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return true; } - protected boolean cleanupHaltedVms(final Connection conn) throws XenAPIException, XmlRpcException { - final Host host = Host.getByUuid(conn, _host.uuid); + public boolean cleanupHaltedVms(final Connection conn) throws XenAPIException, XmlRpcException { + final Host host = Host.getByUuid(conn, _host.getUuid()); final Map vms = VM.getAllRecords(conn); boolean success = true; if(vms != null && !vms.isEmpty()) { @@ -397,19 +397,19 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected boolean pingXAPI() { final Connection conn = getConnection(); try { - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); if( !host.getEnabled(conn) ) { - s_logger.debug("Host " + _host.ip + " is not enabled!"); + s_logger.debug("Host " + _host.getIp() + " is not enabled!"); return false; } } catch (final Exception e) { - s_logger.debug("cannot get host enabled status, host " + _host.ip + " due to " + e.toString(), e); + s_logger.debug("cannot get host enabled status, host " + _host.getIp() + " due to " + e.toString(), e); return false; } try { callHostPlugin(conn, "echo", "main"); } catch (final Exception e) { - s_logger.debug("cannot ping host " + _host.ip + " due to " + e.toString(), e); + s_logger.debug("cannot ping host " + _host.getIp() + " due to " + e.toString(), e); return false; } return true; @@ -417,7 +417,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected String logX(final XenAPIObject obj, final String msg) { - return new StringBuilder("Host ").append(_host.ip).append(" ").append(obj.toWireString()).append(": ").append(msg).toString(); + return new StringBuilder("Host ").append(_host.getIp()).append(" ").append(obj.toWireString()).append(": ").append(msg).toString(); } @Override @@ -554,7 +554,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe cmdline = cmdline.replaceAll(";", "\\\\;"); try { s_logger.debug("Executing command in VR: " + cmdline); - result = SshHelper.sshExecute(_host.ip, 22, _username, null, _password.peek(), cmdline, + result = SshHelper.sshExecute(_host.getIp(), 22, _username, null, _password.peek(), cmdline, 60000, 60000, timeout * 1000); } catch (final Exception e) { return new ExecutionResult(false, e.getMessage()); @@ -573,11 +573,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Connection conn = getConnection(); final String hostPath = "/tmp/"; - s_logger.debug("Copying VR with ip " + routerIp +" config file into host "+ _host.ip ); + s_logger.debug("Copying VR with ip " + routerIp +" config file into host "+ _host.getIp() ); try { - SshHelper.scpTo(_host.ip, 22, _username, null, _password.peek(), hostPath, content.getBytes(Charset.defaultCharset()), filename, null); + SshHelper.scpTo(_host.getIp(), 22, _username, null, _password.peek(), hostPath, content.getBytes(Charset.defaultCharset()), filename, null); } catch (final Exception e) { - s_logger.warn("scp VR config file into host " + _host.ip + " failed with exception " + e.getMessage().toString()); + s_logger.warn("scp VR config file into host " + _host.getIp() + " failed with exception " + e.getMessage().toString()); } final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path); @@ -652,7 +652,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); } - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); task = host.callPluginAsync(conn, plugin, cmd, args); // poll every 1 seconds waitForTask(conn, task, 1000, timeout); @@ -678,7 +678,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } } @@ -706,14 +706,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe // weight based allocation - cpuWeight = (int)(speed * 0.99 / _host.speed * _maxWeight); + cpuWeight = (int)(speed * 0.99 / _host.getSpeed() * _maxWeight); if (cpuWeight > _maxWeight) { cpuWeight = _maxWeight; } if (vmSpec.getLimitCpuUse()) { long utilization = 0; // max CPU cap, default is unlimited - utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.speed * 100); + utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100); //vm.addToVCPUsParamsLive(conn, "cap", Long.toString(utilization)); currently xenserver doesnot support Xapi to add VCPUs params live. callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", Long.toString(utilization), "vmname", vmSpec.getName()); } @@ -728,11 +728,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { final Connection conn = getConnection(); final Set vms = VM.getByNameLabel(conn, vmName); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); // If DMC is not enable then don't execute this command. if (!isDmcEnabled(conn, host)) { - throw new CloudRuntimeException("Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.uuid + + throw new CloudRuntimeException("Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.getUuid() + " ,check your license and hypervisor version."); } @@ -743,13 +743,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final VM.Record vmr = vm.getRecord(conn); if (vmr.powerState == VmPowerState.HALTED || - vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.uuid)) { + vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.getUuid())) { iter.remove(); } } if (vms.size() == 0) { - s_logger.info("No running VM " + vmName + " exists on XenServer" + _host.uuid); + s_logger.info("No running VM " + vmName + " exists on XenServer" + _host.getUuid()); return new ScaleVmAnswer(cmd, false, "VM does not exist"); } @@ -812,7 +812,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } // call plugin to execute revert - revertToSnapshot(conn, vmSnapshot, vmName, vm.getUuid(conn), snapshotMemory, _host.uuid); + revertToSnapshot(conn, vmSnapshot, vmName, vm.getUuid(conn), snapshotMemory, _host.getUuid()); vm = getVM(conn, vmName); final Set vbds = vm.getVBDs(conn); final Map vdiMap = new HashMap(); @@ -875,17 +875,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (type == TrafficType.Guest) { - return new XsLocalNetwork(Network.getByUuid(conn, _host.guestNetwork), null, PIF.getByUuid(conn, _host.guestPif), null); + return new XsLocalNetwork(Network.getByUuid(conn, _host.getGuestNetwork()), null, PIF.getByUuid(conn, _host.getGuestPif()), null); } else if (type == TrafficType.Control) { setupLinkLocalNetwork(conn); - return new XsLocalNetwork(Network.getByUuid(conn, _host.linkLocalNetwork)); + return new XsLocalNetwork(Network.getByUuid(conn, _host.getLinkLocalNetwork())); } else if (type == TrafficType.Management) { - return new XsLocalNetwork(Network.getByUuid(conn, _host.privateNetwork), null, PIF.getByUuid(conn, _host.privatePif), null); + return new XsLocalNetwork(Network.getByUuid(conn, _host.getPrivateNetwork()), null, PIF.getByUuid(conn, _host.getPrivatePif()), null); } else if (type == TrafficType.Public) { - return new XsLocalNetwork(Network.getByUuid(conn, _host.publicNetwork), null, PIF.getByUuid(conn, _host.publicPif), null); + return new XsLocalNetwork(Network.getByUuid(conn, _host.getPublicNetwork()), null, PIF.getByUuid(conn, _host.getPublicPif()), null); } else if (type == TrafficType.Storage) { /* TrafficType.Storage is for secondary storage, while storageNetwork1 is for primary storage, we need better name here */ - return new XsLocalNetwork(Network.getByUuid(conn, _host.storageNetwork1), null, PIF.getByUuid(conn, _host.storagePif1), null); + return new XsLocalNetwork(Network.getByUuid(conn, _host.getStorageNetwork1()), null, PIF.getByUuid(conn, _host.getStoragePif1()), null); } throw new CloudRuntimeException("Unsupported network type: " + type); @@ -893,7 +893,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private synchronized Network setupvSwitchNetwork(final Connection conn) { try { - if (_host.vswitchNetwork == null) { + if (_host.getVswitchNetwork() == null) { Network vswitchNw = null; final Network.Record rec = new Network.Record(); final String nwName = Networks.BroadcastScheme.VSwitch.toString(); @@ -906,9 +906,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } else { vswitchNw = networks.iterator().next(); } - _host.vswitchNetwork = vswitchNw; + _host.setVswitchNetwork(vswitchNw); } - return _host.vswitchNetwork; + return _host.getVswitchNetwork(); } catch (final BadServerResponse e) { s_logger.error("Failed to setup vswitch network", e); } catch (final XenAPIException e) { @@ -1152,12 +1152,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } for (final PBD pbd : pbds) { final PBD.Record pbdr = pbd.getRecord(conn); - if (pbdr.host.getUuid(conn).equals(_host.uuid)) { + if (pbdr.host.getUuid(conn).equals(_host.getUuid())) { return; } } sr.setShared(conn, true); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final PBD.Record pbdr = pbds.iterator().next().getRecord(conn); pbdr.host = host; pbdr.uuid = ""; @@ -1383,14 +1383,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe int utilization = 0; // max CPU cap, default is unlimited // weight based allocation, CPU weight is calculated per VCPU - cpuWeight = (int)(speed * 0.99 / _host.speed * _maxWeight); + cpuWeight = (int)(speed * 0.99 / _host.getSpeed() * _maxWeight); if (cpuWeight > _maxWeight) { cpuWeight = _maxWeight; } if (vmSpec.getLimitCpuUse()) { // CPU cap is per VM, so need to assign cap based on the number of vcpus - utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.speed * 100); + utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100); } vcpuParams.put("weight", Integer.toString(cpuWeight)); @@ -1549,7 +1549,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected VBD createPatchVbd(final Connection conn, final String vmName, final VM vm) throws XmlRpcException, XenAPIException { - if (_host.systemvmisouuid == null) { + if (_host.getSystemvmisouuid() == null) { final Set srs = SR.getByNameLabel(conn, "XenServer Tools"); if (srs.size() != 1) { throw new CloudRuntimeException("There are " + srs.size() + " SRs with name XenServer Tools"); @@ -1559,16 +1559,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final SR.Record srr = sr.getRecord(conn); - if (_host.systemvmisouuid == null) { + if (_host.getSystemvmisouuid() == null) { for (final VDI vdi : srr.VDIs) { final VDI.Record vdir = vdi.getRecord(conn); if (vdir.nameLabel.contains("systemvm.iso")) { - _host.systemvmisouuid = vdir.uuid; + _host.setSystemvmisouuid(vdir.uuid); break; } } } - if (_host.systemvmisouuid == null) { + if (_host.getSystemvmisouuid() == null) { throw new CloudRuntimeException("can not find systemvmiso"); } } @@ -1581,12 +1581,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe cdromVBDR.mode = Types.VbdMode.RO; cdromVBDR.type = Types.VbdType.CD; final VBD cdromVBD = VBD.create(conn, cdromVBDR); - cdromVBD.insert(conn, VDI.getByUuid(conn, _host.systemvmisouuid)); + cdromVBD.insert(conn, VDI.getByUuid(conn, _host.getSystemvmisouuid())); return cdromVBD; } - protected void destroyPatchVbd(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException { + public void destroyPatchVbd(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException { try { if (!vmName.startsWith("r-") && !vmName.startsWith("s-") && !vmName.startsWith("v-")) { return; @@ -1763,7 +1763,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } s_logger.debug("1. The VM " + vmName + " is in Starting state."); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); vm = createVmFromTemplate(conn, vmSpec, host); final GPUDeviceTO gpuDevice = vmSpec.getGpuDevice(); @@ -1972,7 +1972,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } private boolean doPingTest(final Connection conn, final String computingHostIp) { - final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.ip, 22); + final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); try { sshConnection.connect(null, 60000, 60000); if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { @@ -1981,7 +1981,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final String cmd = "ping -c 2 " + computingHostIp; if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { - throw new CloudRuntimeException("Cannot ping host " + computingHostIp + " from host " + _host.ip); + throw new CloudRuntimeException("Cannot ping host " + computingHostIp + " from host " + _host.getIp()); } return true; } catch (final Exception e) { @@ -2026,7 +2026,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Connection conn = getConnection(); try { - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); // remove all tags cloud stack final Host.Record hr = host.getRecord(conn); final Iterator it = hr.tags.iterator(); @@ -2441,7 +2441,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected Document getStatsRawXML(final Connection conn, final boolean host) { final Date currentDate = new Date(); - String urlStr = "http://" + _host.ip + "/rrd_updates?"; + String urlStr = "http://" + _host.getIp() + "/rrd_updates?"; urlStr += "session_id=" + conn.getSessionReference(); urlStr += "&host=" + (host ? "true" : "false"); urlStr += "&cf=" + _consolidationFunction; @@ -2605,7 +2605,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); } - if (host_uuid.equalsIgnoreCase(_host.uuid)) { + if (host_uuid.equalsIgnoreCase(_host.getUuid())) { vmStates.put( record.nameLabel, new HostVmStateReportEntry(convertToPowerState(ps), host_uuid) @@ -2832,7 +2832,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } return new PrimaryStorageDownloadAnswer(snapshotvdi.getUuid(conn), phySize); } catch (final Exception e) { - final String msg = "Catch Exception " + e.getClass().getName() + " on host:" + _host.uuid + " for template: " + tmplturl + " due to " + e.toString(); + final String msg = "Catch Exception " + e.getClass().getName() + " on host:" + _host.getUuid() + " for template: " + tmplturl + " due to " + e.toString(); s_logger.warn(msg, e); return new PrimaryStorageDownloadAnswer(msg); } @@ -2957,7 +2957,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } if (dsthost == null) { - final String msg = "Migration failed due to unable to find host " + ipaddr + " in XenServer pool " + _host.pool; + final String msg = "Migration failed due to unable to find host " + ipaddr + " in XenServer pool " + _host.getPool(); s_logger.warn(msg); return new MigrateAnswer(cmd, false, msg, null); } @@ -2982,7 +2982,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } protected Pair getControlDomain(final Connection conn) throws XenAPIException, XmlRpcException { - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); Set vms = null; vms = host.getResidentVMs(conn); for (final VM vm : vms) { @@ -2994,7 +2994,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("Com'on no control domain? What the crap?!#@!##$@"); } - protected void umountSnapshotDir(final Connection conn, final Long dcId) { + public void umountSnapshotDir(final Connection conn, final Long dcId) { try { callHostPlugin(conn, "vmopsSnapshot", "unmountSnapshotsDir", "dcId", dcId.toString()); } catch (final Exception e) { @@ -3013,7 +3013,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe setupLinkLocalNetwork(conn); // try to destroy CD-ROM device for all system VMs on this host try { - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final Set vms = host.getResidentVMs(conn); for (final VM vm : vms) { destroyPatchVbd(conn, vm.getNameLabel(conn)); @@ -3240,11 +3240,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("Reboot VM catch HandleInvalid and VM is not in RUNNING state"); } } catch (final XenAPIException e) { - s_logger.debug("Unable to Clean Reboot VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString() + ", try hard reboot"); + s_logger.debug("Unable to Clean Reboot VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString() + ", try hard reboot"); try { vm.hardReboot(conn); } catch (final Exception e1) { - final String msg = "Unable to hard Reboot VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString(); + final String msg = "Unable to hard Reboot VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); s_logger.warn(msg, e1); throw new CloudRuntimeException(msg); } @@ -3253,7 +3253,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } } @@ -3288,14 +3288,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("Shutdown VM catch HandleInvalid and VM is not in HALTED state"); } } catch (final XenAPIException e) { - s_logger.debug("Unable to cleanShutdown VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString()); + s_logger.debug("Unable to cleanShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString()); try { VmPowerState state = vm.getPowerState(conn); if (state == VmPowerState.RUNNING) { try { vm.hardShutdown(conn); } catch (final Exception e1) { - s_logger.debug("Unable to hardShutdown VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString()); + s_logger.debug("Unable to hardShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString()); state = vm.getPowerState(conn); if (state == VmPowerState.RUNNING) { forceShutdownVM(conn, vm); @@ -3310,7 +3310,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException(msg); } } catch (final Exception e1) { - final String msg = "Unable to hardShutdown VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString(); + final String msg = "Unable to hardShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); s_logger.warn(msg, e1); throw new CloudRuntimeException(msg); } @@ -3319,7 +3319,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } } @@ -3349,7 +3349,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("Start VM " + vmName + " catch BadAsyncResult and VM is not in RUNNING state"); } } catch (final XenAPIException e) { - final String msg = "Unable to start VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString(); + final String msg = "Unable to start VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); s_logger.warn(msg, e); throw new CloudRuntimeException(msg); } finally { @@ -3357,7 +3357,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } } @@ -3382,7 +3382,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("migrate VM catch HandleInvalid and VM is not running on dest host"); } } catch (final XenAPIException e) { - final String msg = "Unable to migrate VM(" + vmName + ") from host(" + _host.uuid + ")"; + final String msg = "Unable to migrate VM(" + vmName + ") from host(" + _host.getUuid() + ")"; s_logger.warn(msg, e); throw new CloudRuntimeException(msg); } finally { @@ -3390,7 +3390,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } } @@ -3413,7 +3413,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (final Exception e) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e.toString()); } } } @@ -3430,7 +3430,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (s_logger.isTraceEnabled()) { s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); } - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); task = host.callPluginAsync(conn, plugin, cmd, args); // poll every 1 seconds waitForTask(conn, task, 1000, timeout); @@ -3452,7 +3452,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } } @@ -3477,7 +3477,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (isRefNull(vmr.residentOn)) { continue; } - if (vmr.residentOn.getUuid(conn).equals(_host.uuid)) { + if (vmr.residentOn.getUuid(conn).equals(_host.getUuid())) { continue; } iter.remove(); @@ -3495,8 +3495,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new StopAnswer(cmd, msg, false); } - if (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.uuid)) { - final String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + _host.uuid + " but host:" + vmr.residentOn.getUuid(conn); + if (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.getUuid())) { + final String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + _host.getUuid() + " but host:" + vmr.residentOn.getUuid(conn); s_logger.warn(msg); return new StopAnswer(cmd, msg, platformstring, false); } @@ -3683,7 +3683,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (s_logger.isTraceEnabled()) { s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); } - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final String result = host.callPlugin(conn, plugin, cmd, args); if (s_logger.isTraceEnabled()) { s_logger.trace("callHostPlugin Result: " + result); @@ -3718,14 +3718,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected XsLocalNetwork getManagementNetwork(final Connection conn) throws XmlRpcException, XenAPIException { PIF mgmtPif = null; PIF.Record mgmtPifRec = null; - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final Set hostPifs = host.getPIFs(conn); for (final PIF pif : hostPifs) { final PIF.Record rec = pif.getRecord(conn); if (rec.management) { if (rec.VLAN != null && rec.VLAN != -1) { final String msg = - new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.uuid) + new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.getUuid()) .append("; pif=") .append(rec.uuid) .append("; vlan=") @@ -3743,14 +3743,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } if (mgmtPif == null) { - final String msg = "Unable to find management network for " + _host.uuid; + final String msg = "Unable to find management network for " + _host.getUuid(); s_logger.warn(msg); throw new CloudRuntimeException(msg); } final Bond bond = mgmtPifRec.bondSlaveOf; if (!isRefNull(bond)) { final String msg = - "Management interface is on slave(" + mgmtPifRec.uuid + ") of bond(" + bond.getUuid(conn) + ") on host(" + _host.uuid + + "Management interface is on slave(" + mgmtPifRec.uuid + ") of bond(" + bond.getUuid(conn) + ") on host(" + _host.getUuid() + "), please move management interface to bond!"; s_logger.warn(msg); throw new CloudRuntimeException(msg); @@ -4020,7 +4020,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (vlanNic == null) { // Can't find it, then create it. if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.ip); + s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.getIp()); } final Network.Record nwr = new Network.Record(); nwr.nameLabel = newName; @@ -4042,7 +4042,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating VLAN " + tag + " on host " + _host.ip + " on device " + nPifr.device); + s_logger.debug("Creating VLAN " + tag + " on host " + _host.getIp() + " on device " + nPifr.device); } final VLAN vlan = VLAN.create(conn, nPif, tag, vlanNetwork); if (vlan != null) { @@ -4072,7 +4072,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } for (final PBD pbd : pbds) { final Host host = pbd.getHost(conn); - if (!isRefNull(host) && host.getUuid(conn).equals(_host.uuid)) { + if (!isRefNull(host) && host.getUuid(conn).equals(_host.getUuid())) { if (!pbd.getCurrentlyAttached(conn)) { pbd.plug(conn); } @@ -4085,10 +4085,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } } catch (final XenAPIException e) { - final String msg = "Unable to get local LVMSR in host:" + _host.uuid + e.toString(); + final String msg = "Unable to get local LVMSR in host:" + _host.getUuid() + e.toString(); s_logger.warn(msg); } catch (final XmlRpcException e) { - final String msg = "Unable to get local LVMSR in host:" + _host.uuid + e.getCause(); + final String msg = "Unable to get local LVMSR in host:" + _host.getUuid() + e.getCause(); s_logger.warn(msg); } return null; @@ -4107,7 +4107,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } for (final PBD pbd : pbds) { final Host host = pbd.getHost(conn); - if (!isRefNull(host) && host.getUuid(conn).equals(_host.uuid)) { + if (!isRefNull(host) && host.getUuid(conn).equals(_host.getUuid())) { if (!pbd.getCurrentlyAttached(conn)) { pbd.plug(conn); } @@ -4120,10 +4120,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } } catch (final XenAPIException e) { - final String msg = "Unable to get local EXTSR in host:" + _host.uuid + e.toString(); + final String msg = "Unable to get local EXTSR in host:" + _host.getUuid() + e.toString(); s_logger.warn(msg); } catch (final XmlRpcException e) { - final String msg = "Unable to get local EXTSR in host:" + _host.uuid + e.getCause(); + final String msg = "Unable to get local EXTSR in host:" + _host.getUuid() + e.getCause(); s_logger.warn(msg); } return null; @@ -4133,30 +4133,30 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final SR lvmsr = getLocalLVMSR(conn); if (lvmsr != null) { try { - _host.localSRuuid = lvmsr.getUuid(conn); + _host.setLocalSRuuid(lvmsr.getUuid(conn)); final String lvmuuid = lvmsr.getUuid(conn); final long cap = lvmsr.getPhysicalSize(conn); if (cap > 0) { final long avail = cap - lvmsr.getPhysicalUtilisation(conn); lvmsr.setNameLabel(conn, lvmuuid); - final String name = "Cloud Stack Local LVM Storage Pool for " + _host.uuid; + final String name = "Cloud Stack Local LVM Storage Pool for " + _host.getUuid(); lvmsr.setNameDescription(conn, name); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final String address = host.getAddress(conn); final StoragePoolInfo pInfo = new StoragePoolInfo(lvmuuid, address, SRType.LVM.toString(), SRType.LVM.toString(), StoragePoolType.LVM, cap, avail); final StartupStorageCommand cmd = new StartupStorageCommand(); cmd.setPoolInfo(pInfo); - cmd.setGuid(_host.uuid); + cmd.setGuid(_host.getUuid()); cmd.setDataCenter(Long.toString(_dcId)); cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); return cmd; } } catch (final XenAPIException e) { - final String msg = "build local LVM info err in host:" + _host.uuid + e.toString(); + final String msg = "build local LVM info err in host:" + _host.getUuid() + e.toString(); s_logger.warn(msg); } catch (final XmlRpcException e) { - final String msg = "build local LVM info err in host:" + _host.uuid + e.getMessage(); + final String msg = "build local LVM info err in host:" + _host.getUuid() + e.getMessage(); s_logger.warn(msg); } } @@ -4165,28 +4165,28 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (extsr != null) { try { final String extuuid = extsr.getUuid(conn); - _host.localSRuuid = extuuid; + _host.setLocalSRuuid(extuuid); final long cap = extsr.getPhysicalSize(conn); if (cap > 0) { final long avail = cap - extsr.getPhysicalUtilisation(conn); extsr.setNameLabel(conn, extuuid); - final String name = "Cloud Stack Local EXT Storage Pool for " + _host.uuid; + final String name = "Cloud Stack Local EXT Storage Pool for " + _host.getUuid(); extsr.setNameDescription(conn, name); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final String address = host.getAddress(conn); final StoragePoolInfo pInfo = new StoragePoolInfo(extuuid, address, SRType.EXT.toString(), SRType.EXT.toString(), StoragePoolType.EXT, cap, avail); final StartupStorageCommand cmd = new StartupStorageCommand(); cmd.setPoolInfo(pInfo); - cmd.setGuid(_host.uuid); + cmd.setGuid(_host.getUuid()); cmd.setDataCenter(Long.toString(_dcId)); cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); return cmd; } } catch (final XenAPIException e) { - final String msg = "build local EXT info err in host:" + _host.uuid + e.toString(); + final String msg = "build local EXT info err in host:" + _host.getUuid() + e.toString(); s_logger.warn(msg); } catch (final XmlRpcException e) { - final String msg = "build local EXT info err in host:" + _host.uuid + e.getMessage(); + final String msg = "build local EXT info err in host:" + _host.getUuid() + e.getMessage(); s_logger.warn(msg); } } @@ -4199,7 +4199,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (!pingXAPI()) { Thread.sleep(1000); if (!pingXAPI()) { - s_logger.warn("can not ping xenserver " + _host.uuid); + s_logger.warn("can not ping xenserver " + _host.getUuid()); return null; } } @@ -4222,7 +4222,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private HashMap> syncNetworkGroups(final Connection conn, final long id) { final HashMap> states = new HashMap>(); - final String result = callHostPlugin(conn, "vmops", "get_rule_logs_for_vms", "host_uuid", _host.uuid); + final String result = callHostPlugin(conn, "vmops", "get_rule_logs_for_vms", "host_uuid", _host.getUuid()); s_logger.trace("syncNetworkGroups: id=" + id + " got: " + result); final String[] rulelogs = result != null ? result.split(";") : new String[0]; for (final String rulesforvm : rulelogs) { @@ -4247,98 +4247,98 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected boolean getHostInfo(final Connection conn) throws IllegalArgumentException { try { - final Host myself = Host.getByUuid(conn, _host.uuid); + final Host myself = Host.getByUuid(conn, _host.getUuid()); Set hcs = null; for (int i = 0; i < 10; i++) { hcs = myself.getHostCPUs(conn); if(hcs != null) { - _host.cpus = hcs.size(); - if (_host.cpus > 0) { + _host.setCpus(hcs.size()); + if (_host.getCpus() > 0) { break; } } Thread.sleep(5000); } - if (_host.cpus <= 0) { - throw new CloudRuntimeException("Cannot get the numbers of cpu from XenServer host " + _host.ip); + if (_host.getCpus() <= 0) { + throw new CloudRuntimeException("Cannot get the numbers of cpu from XenServer host " + _host.getIp()); } final Map cpuInfo = myself.getCpuInfo(conn); if (cpuInfo.get("socket_count") != null) { - _host.cpuSockets = Integer.parseInt(cpuInfo.get("socket_count")); + _host.setCpuSockets(Integer.parseInt(cpuInfo.get("socket_count"))); } - // would hcs be null we would have thrown an exception on condition (_host.cpus <= 0) by now + // would hcs be null we would have thrown an exception on condition (_host.getCpus() <= 0) by now for (final HostCpu hc : hcs) { - _host.speed = hc.getSpeed(conn).intValue(); + _host.setSpeed(hc.getSpeed(conn).intValue()); break; } final Host.Record hr = myself.getRecord(conn); - _host.productVersion = CitrixHelper.getProductVersion(hr); + _host.setProductVersion(CitrixHelper.getProductVersion(hr)); final XsLocalNetwork privateNic = getManagementNetwork(conn); _privateNetworkName = privateNic.getNetworkRecord(conn).nameLabel; - _host.privatePif = privateNic.getPifRecord(conn).uuid; - _host.privateNetwork = privateNic.getNetworkRecord(conn).uuid; - _host.systemvmisouuid = null; + _host.setPrivatePif(privateNic.getPifRecord(conn).uuid); + _host.setPrivateNetwork(privateNic.getNetworkRecord(conn).uuid); + _host.setSystemvmisouuid(null); XsLocalNetwork guestNic = null; if (_guestNetworkName != null && !_guestNetworkName.equals(_privateNetworkName)) { guestNic = getNetworkByName(conn, _guestNetworkName); if (guestNic == null) { s_logger.warn("Unable to find guest network " + _guestNetworkName); - throw new IllegalArgumentException("Unable to find guest network " + _guestNetworkName + " for host " + _host.ip); + throw new IllegalArgumentException("Unable to find guest network " + _guestNetworkName + " for host " + _host.getIp()); } } else { guestNic = privateNic; _guestNetworkName = _privateNetworkName; } - _host.guestNetwork = guestNic.getNetworkRecord(conn).uuid; - _host.guestPif = guestNic.getPifRecord(conn).uuid; + _host.setGuestNetwork(guestNic.getNetworkRecord(conn).uuid); + _host.setGuestPif(guestNic.getPifRecord(conn).uuid); XsLocalNetwork publicNic = null; if (_publicNetworkName != null && !_publicNetworkName.equals(_guestNetworkName)) { publicNic = getNetworkByName(conn, _publicNetworkName); if (publicNic == null) { - s_logger.warn("Unable to find public network " + _publicNetworkName + " for host " + _host.ip); - throw new IllegalArgumentException("Unable to find public network " + _publicNetworkName + " for host " + _host.ip); + s_logger.warn("Unable to find public network " + _publicNetworkName + " for host " + _host.getIp()); + throw new IllegalArgumentException("Unable to find public network " + _publicNetworkName + " for host " + _host.getIp()); } } else { publicNic = guestNic; _publicNetworkName = _guestNetworkName; } - _host.publicPif = publicNic.getPifRecord(conn).uuid; - _host.publicNetwork = publicNic.getNetworkRecord(conn).uuid; + _host.setPublicPif(publicNic.getPifRecord(conn).uuid); + _host.setPublicNetwork(publicNic.getNetworkRecord(conn).uuid); if (_storageNetworkName1 == null) { _storageNetworkName1 = _guestNetworkName; } XsLocalNetwork storageNic1 = null; storageNic1 = getNetworkByName(conn, _storageNetworkName1); if (storageNic1 == null) { - s_logger.warn("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.ip); - throw new IllegalArgumentException("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.ip); + s_logger.warn("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.getIp()); + throw new IllegalArgumentException("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.getIp()); } else { - _host.storageNetwork1 = storageNic1.getNetworkRecord(conn).uuid; - _host.storagePif1 = storageNic1.getPifRecord(conn).uuid; + _host.setStorageNetwork1(storageNic1.getNetworkRecord(conn).uuid); + _host.setStoragePif1(storageNic1.getPifRecord(conn).uuid); } XsLocalNetwork storageNic2 = null; if (_storageNetworkName2 != null) { storageNic2 = getNetworkByName(conn, _storageNetworkName2); if(storageNic2 != null) { - _host.storagePif2 = storageNic2.getPifRecord(conn).uuid; + _host.setStoragePif2(storageNic2.getPifRecord(conn).uuid); } } - s_logger.info("XenServer Version is " + _host.productVersion + " for host " + _host.ip); - s_logger.info("Private Network is " + _privateNetworkName + " for host " + _host.ip); - s_logger.info("Guest Network is " + _guestNetworkName + " for host " + _host.ip); - s_logger.info("Public Network is " + _publicNetworkName + " for host " + _host.ip); + s_logger.info("XenServer Version is " + _host.getProductVersion() + " for host " + _host.getIp()); + s_logger.info("Private Network is " + _privateNetworkName + " for host " + _host.getIp()); + s_logger.info("Guest Network is " + _guestNetworkName + " for host " + _host.getIp()); + s_logger.info("Public Network is " + _publicNetworkName + " for host " + _host.getIp()); return true; } catch (final XenAPIException e) { - s_logger.warn("Unable to get host information for " + _host.ip, e); + s_logger.warn("Unable to get host information for " + _host.getIp(), e); return false; } catch (final Exception e) { - s_logger.warn("Unable to get host information for " + _host.ip, e); + s_logger.warn("Unable to get host information for " + _host.getIp(), e); return false; } } @@ -4349,7 +4349,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - private void setupLinkLocalNetwork(final Connection conn) { + public void setupLinkLocalNetwork(final Connection conn) { try { final Network.Record rec = new Network.Record(); final Set networks = Network.getByNameLabel(conn, _linkLocalPrivateNetworkName); @@ -4416,7 +4416,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final String brName = linkLocal.getBridge(conn); callHostPlugin(conn, "vmops", "setLinkLocalIP", "brName", brName); - _host.linkLocalNetwork = linkLocal.getUuid(conn); + _host.setLinkLocalNetwork(linkLocal.getUuid(conn)); } catch (final XenAPIException e) { s_logger.warn("Unable to create local link network", e); @@ -4461,7 +4461,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public StartupCommand[] initialize() throws IllegalArgumentException { final Connection conn = getConnection(); if (!getHostInfo(conn)) { - s_logger.warn("Unable to get host information for " + _host.ip); + s_logger.warn("Unable to get host information for " + _host.getIp()); return null; } final StartupRoutingCommand cmd = new StartupRoutingCommand(); @@ -4471,7 +4471,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe cmd.setPoolSync(false); try { - final Pool pool = Pool.getByUuid(conn, _host.pool); + final Pool pool = Pool.getByUuid(conn, _host.getPool()); final Pool.Record poolr = pool.getRecord(conn); poolr.master.getRecord(conn); } catch (final Throwable e) { @@ -4487,7 +4487,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private void cleanupTemplateSR(final Connection conn) { Set pbds = null; try { - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); pbds = host.getPBDs(conn); } catch (final XenAPIException e) { s_logger.warn("Unable to get the SRs " + e.toString(), e); @@ -4523,11 +4523,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected boolean launchHeartBeat(final Connection conn) { final String result = callHostPluginPremium(conn, "heartbeat", - "host", _host.uuid, + "host", _host.getUuid(), "timeout", Integer.toString(_heartbeatTimeout), "interval", Integer.toString(_heartbeatInterval)); if (result == null || !result.contains("> DONE <")) { - s_logger.warn("Unable to launch the heartbeat process on " + _host.ip); + s_logger.warn("Unable to launch the heartbeat process on " + _host.getIp()); return false; } return true; @@ -4538,11 +4538,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { final Map poolRecs = Pool.getAllRecords(conn); if (poolRecs.size() != 1) { - throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.uuid); + throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.getUuid()); } final Host master = poolRecs.values().iterator().next().master; setupServer(conn, master); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); setupServer(conn, host); if (!setIptables(conn)) { @@ -4555,7 +4555,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (!_canBridgeFirewall) { final String msg = "Failed to configure brige firewall"; s_logger.warn(msg); - s_logger.warn("Check host " + _host.ip +" for CSP is installed or not and check network mode for bridge"); + s_logger.warn("Check host " + _host.getIp() +" for CSP is installed or not and check network mode for bridge"); return new SetupAnswer(cmd, msg); } @@ -4579,7 +4579,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (cmd.needSetup() ) { - final String result = callHostPlugin(conn, "vmops", "setup_iscsi", "uuid", _host.uuid); + final String result = callHostPlugin(conn, "vmops", "setup_iscsi", "uuid", _host.getUuid()); if (!result.contains("> DONE <")) { s_logger.warn("Unable to setup iscsi: " + result); @@ -4593,7 +4593,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (rec.management) { if (rec.VLAN != null && rec.VLAN != -1) { final String msg = - new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.uuid) + new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.getUuid()) .append("; pif=") .append(rec.uuid) .append("; vlan=") @@ -4611,14 +4611,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (mgmtPif == null) { - final String msg = "Unable to find management network for " + _host.uuid; + final String msg = "Unable to find management network for " + _host.getUuid(); s_logger.warn(msg); return new SetupAnswer(cmd, msg); } final Map networks = Network.getAllRecords(conn); if(networks == null) { - final String msg = "Unable to setup as there are no networks in the host: " + _host.uuid; + final String msg = "Unable to setup as there are no networks in the host: " + _host.getUuid(); s_logger.warn(msg); return new SetupAnswer(cmd, msg); } @@ -4626,9 +4626,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (network.nameLabel.equals("cloud-private")) { for (final PIF pif : network.PIFs) { final PIF.Record pr = pif.getRecord(conn); - if (_host.uuid.equals(pr.host.getUuid(conn))) { + if (_host.getUuid().equals(pr.host.getUuid(conn))) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Found a network called cloud-private. host=" + _host.uuid + "; Network=" + network.uuid + "; pif=" + pr.uuid); + s_logger.debug("Found a network called cloud-private. host=" + _host.getUuid() + "; Network=" + network.uuid + "; pif=" + pr.uuid); } if (pr.VLAN != null && pr.VLAN != -1) { final String msg = @@ -4657,7 +4657,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (!transferManagementNetwork(conn, host, slave, spr, pif)) { final String msg = new StringBuilder("Unable to transfer management network. slave=" + spr.uuid + "; master=" + pr.uuid + "; host=" + - _host.uuid).toString(); + _host.getUuid()).toString(); s_logger.warn(msg); return new SetupAnswer(cmd, msg); } @@ -4849,11 +4849,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } catch (final XenAPIException e) { - final String msg = "CheckNetworkCommand failed with XenAPIException:" + e.toString() + " host:" + _host.uuid; + final String msg = "CheckNetworkCommand failed with XenAPIException:" + e.toString() + " host:" + _host.getUuid(); s_logger.warn(msg, e); return new CheckNetworkAnswer(cmd, false, msg); } catch (final Exception e) { - final String msg = "CheckNetworkCommand failed with Exception:" + e.getMessage() + " host:" + _host.uuid; + final String msg = "CheckNetworkCommand failed with Exception:" + e.getMessage() + " host:" + _host.getUuid(); s_logger.warn(msg, e); return new CheckNetworkAnswer(cmd, false, msg); } @@ -4885,7 +4885,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe pbds = sr.getPBDs(conn); for (final PBD pbd : pbds) { final PBD.Record pbdr = pbd.getRecord(conn); - if (pbdr.host != null && pbdr.host.getUuid(conn).equals(_host.uuid)) { + if (pbdr.host != null && pbdr.host.getUuid(conn).equals(_host.getUuid())) { if (!pbdr.currentlyAttached) { pbd.plug(conn); } @@ -4912,11 +4912,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final long used = sr.getPhysicalUtilisation(conn); return new GetStorageStatsAnswer(cmd, capacity, used); } catch (final XenAPIException e) { - final String msg = "GetStorageStats Exception:" + e.toString() + "host:" + _host.uuid + "storageid: " + cmd.getStorageId(); + final String msg = "GetStorageStats Exception:" + e.toString() + "host:" + _host.getUuid() + "storageid: " + cmd.getStorageId(); s_logger.warn(msg); return new GetStorageStatsAnswer(cmd, msg); } catch (final XmlRpcException e) { - final String msg = "GetStorageStats Exception:" + e.getMessage() + "host:" + _host.uuid + "storageid: " + cmd.getStorageId(); + final String msg = "GetStorageStats Exception:" + e.getMessage() + "host:" + _host.getUuid() + "storageid: " + cmd.getStorageId(); s_logger.warn(msg); return new GetStorageStatsAnswer(cmd, msg); } @@ -4940,7 +4940,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final SR.Record srr = sr.getRecord(conn); final Set pbds = sr.getPBDs(conn); if (pbds.size() == 0) { - final String msg = "There is no PBDs for this SR: " + srr.nameLabel + " on host:" + _host.uuid; + final String msg = "There is no PBDs for this SR: " + srr.nameLabel + " on host:" + _host.getUuid(); s_logger.warn(msg); return false; } @@ -4956,7 +4956,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); boolean found = false; for (final PBD pbd : pbds) { final PBD.Record pbdr = pbd.getRecord(conn); @@ -5007,7 +5007,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new Answer(cmd, true, "success"); } catch (final Exception e) { final String msg = - "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.uuid + " pool: " + + "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); @@ -5021,7 +5021,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { final Map poolRecs = Pool.getAllRecords(conn); if (poolRecs.size() != 1) { - throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.uuid); + throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.getUuid()); } final Host master = poolRecs.values().iterator().next().master; for (int i = 0; i < params.length; i += 2) { @@ -5058,21 +5058,21 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return srUuid; } String result = null; - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final Set tags = host.getTags(conn); if (force || !tags.contains("cloud-heartbeat-" + srUuid)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Setting up the heartbeat sr for host " + _host.ip + " and sr " + srUuid); + s_logger.debug("Setting up the heartbeat sr for host " + _host.getIp() + " and sr " + srUuid); } final Set pbds = sr.getPBDs(conn); for (final PBD pbd : pbds) { final PBD.Record pbdr = pbd.getRecord(conn); - if (!pbdr.currentlyAttached && pbdr.host.getUuid(conn).equals(_host.uuid)) { + if (!pbdr.currentlyAttached && pbdr.host.getUuid(conn).equals(_host.getUuid())) { pbd.plug(conn); break; } } - result = callHostPluginThroughMaster(conn, "vmopspremium", "setup_heartbeat_sr", "host", _host.uuid, "sr", srUuid); + result = callHostPluginThroughMaster(conn, "vmopspremium", "setup_heartbeat_sr", "host", _host.getUuid(), "sr", srUuid); if (result == null || !result.split("#")[1].equals("0")) { throw new CloudRuntimeException("Unable to setup heartbeat sr on SR " + srUuid + " due to " + result); } @@ -5082,7 +5082,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe host.setTags(conn, tags); } } - result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "true"); + result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.getUuid(), "sr", srUuid, "add", "true"); if (result == null || !result.split("#")[1].equals("0")) { throw new CloudRuntimeException("Unable to setup heartbeat file entry on SR " + srUuid + " due to " + result); } @@ -5108,11 +5108,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); return answer; } catch (final XenAPIException e) { - final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.toString() + " host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); } catch (final Exception e) { - final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.getMessage() + " host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); } @@ -5120,17 +5120,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { final SR sr = getStorageRepository(conn, pool.getUuid()); final String srUuid = sr.getUuid(conn); - final String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "false"); + final String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.getUuid(), "sr", srUuid, "add", "false"); if (result == null || !result.split("#")[1].equals("0")) { throw new CloudRuntimeException("Unable to remove heartbeat file entry for SR " + srUuid + " due to " + result); } return new Answer(cmd, true, "seccuss"); } catch (final XenAPIException e) { - final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.toString() + " host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); } catch (final Exception e) { - final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.getMessage() + " host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); } @@ -5139,7 +5139,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } protected boolean can_bridge_firewall(final Connection conn) { - return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid, "instance", _instance)); + return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.getUuid(), "instance", _instance)); } private Answer execute(final OvsSetupBridgeCommand cmd) { @@ -5289,7 +5289,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private List> ovsFullSyncStates() { final Connection conn = getConnection(); - final String result = callHostPlugin(conn, "ovsgre", "ovs_get_vm_log", "host_uuid", _host.uuid); + final String result = callHostPlugin(conn, "ovsgre", "ovs_get_vm_log", "host_uuid", _host.getUuid()); final String[] logs = result != null ? result.split(";") : new String[0]; final List> states = new ArrayList>(); for (final String log : logs) { @@ -5349,12 +5349,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (is_xcp()) { label = getLabel(); } - s_logger.debug("Will look for network with name-label:" + label + " on host " + _host.ip); + s_logger.debug("Will look for network with name-label:" + label + " on host " + _host.getIp()); final Connection conn = getConnection(); try { final XsLocalNetwork nw = getNetworkByName(conn, label); if(nw == null) { - throw new CloudRuntimeException("Unable to locate the network with name-label: " + label + " on host: " + _host.ip); + throw new CloudRuntimeException("Unable to locate the network with name-label: " + label + " on host: " + _host.getIp()); } s_logger.debug("Network object:" + nw.getNetwork().getUuid(conn)); final PIF pif = nw.getPif(conn); @@ -5362,13 +5362,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.debug("PIF object:" + pifRec.uuid + "(" + pifRec.device + ")"); return new OvsFetchInterfaceAnswer(cmd, true, "Interface " + pifRec.device + " retrieved successfully", pifRec.IP, pifRec.netmask, pifRec.MAC); } catch (final BadServerResponse e) { - s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.ip, e); + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.getIp(), e); return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); } catch (final XenAPIException e) { - s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.ip, e); + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.getIp(), e); return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); } catch (final XmlRpcException e) { - s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.ip, e); + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.getIp(), e); return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); } } @@ -5387,30 +5387,30 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe Long.toString(cmd.getFrom()), "to", Long.toString(cmd.getTo())); final String[] res = result.split(":"); if (res.length != 2 || res.length == 2 && res[1].equalsIgnoreCase("[]")) { - return new OvsCreateGreTunnelAnswer(cmd, false, result, _host.ip, bridge); + return new OvsCreateGreTunnelAnswer(cmd, false, result, _host.getIp(), bridge); } else { - return new OvsCreateGreTunnelAnswer(cmd, true, result, _host.ip, bridge, Integer.parseInt(res[1])); + return new OvsCreateGreTunnelAnswer(cmd, true, result, _host.getIp(), bridge, Integer.parseInt(res[1])); } } catch (final BadServerResponse e) { - s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.ip, e); + s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.getIp(), e); } catch (final XenAPIException e) { - s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.ip, e); + s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.getIp(), e); } catch (final XmlRpcException e) { - s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.ip, e); + s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.getIp(), e); } - return new OvsCreateGreTunnelAnswer(cmd, false, "EXCEPTION", _host.ip, bridge); + return new OvsCreateGreTunnelAnswer(cmd, false, "EXCEPTION", _host.getIp(), bridge); } private Answer execute(final SecurityGroupRulesCmd cmd) { final Connection conn = getConnection(); if (s_logger.isTraceEnabled()) { - s_logger.trace("Sending network rules command to " + _host.ip); + s_logger.trace("Sending network rules command to " + _host.getIp()); } if (!_canBridgeFirewall) { - s_logger.warn("Host " + _host.ip + " cannot do bridge firewalling"); - return new SecurityGroupRuleAnswer(cmd, false, "Host " + _host.ip + " cannot do bridge firewalling", + s_logger.warn("Host " + _host.getIp() + " cannot do bridge firewalling"); + return new SecurityGroupRuleAnswer(cmd, false, "Host " + _host.getIp() + " cannot do bridge firewalling", SecurityGroupRuleAnswer.FailureReason.CANNOT_BRIDGE_FIREWALL); } @@ -5438,7 +5438,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Answer answer = new Answer(cmd, true, "success"); return answer; } catch (final Exception e) { - final String msg = "DeleteStoragePoolCommand XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + poolTO.getHost() + poolTO.getPath(); + final String msg = "DeleteStoragePoolCommand XenAPIException:" + e.getMessage() + " host:" + _host.getUuid() + " pool: " + poolTO.getHost() + poolTO.getPath(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); } @@ -5446,7 +5446,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } public Connection getConnection() { - return ConnPool.connect(_host.uuid, _host.pool, _host.ip, _username, _password, _wait); + return ConnPool.connect(_host.getUuid(), _host.getPool(), _host.getIp(), _username, _password, _wait); } @@ -5454,7 +5454,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final StringBuilder caps = new StringBuilder(); try { - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final Host.Record hr = host.getRecord(conn); Map details = cmd.getHostDetails(); @@ -5467,12 +5467,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe productBrand = hr.softwareVersion.get("platform_name"); } details.put("product_brand", productBrand); - details.put("product_version", _host.productVersion); + details.put("product_version", _host.getProductVersion()); if (hr.softwareVersion.get("product_version_text_short") != null) { details.put("product_version_text_short", hr.softwareVersion.get("product_version_text_short")); cmd.setHypervisorVersion(hr.softwareVersion.get("product_version_text_short")); - cmd.setHypervisorVersion(_host.productVersion); + cmd.setHypervisorVersion(_host.getProductVersion()); } if (_privateNetworkName != null) { details.put("private.network.device", _privateNetworkName); @@ -5480,8 +5480,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe cmd.setHostDetails(details); cmd.setName(hr.nameLabel); - cmd.setGuid(_host.uuid); - cmd.setPool(_host.pool); + cmd.setGuid(_host.getUuid()); + cmd.setPool(_host.getPool()); cmd.setDataCenter(Long.toString(_dcId)); for (final String cap : hr.capabilities) { if (cap.length() > 0) { @@ -5493,9 +5493,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } cmd.setCaps(caps.toString()); - cmd.setSpeed(_host.speed); - cmd.setCpuSockets(_host.cpuSockets); - cmd.setCpus(_host.cpus); + cmd.setSpeed(_host.getSpeed()); + cmd.setCpuSockets(_host.getCpuSockets()); + cmd.setCpus(_host.getCpus()); final HostMetrics hm = host.getMetrics(conn); @@ -5518,19 +5518,19 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.debug("Total Ram: " + ram + " dom0 Ram: " + dom0Ram); } - PIF pif = PIF.getByUuid(conn, _host.privatePif); + PIF pif = PIF.getByUuid(conn, _host.getPrivatePif()); PIF.Record pifr = pif.getRecord(conn); if (pifr.IP != null && pifr.IP.length() > 0) { cmd.setPrivateIpAddress(pifr.IP); cmd.setPrivateMacAddress(pifr.MAC); cmd.setPrivateNetmask(pifr.netmask); } else { - cmd.setPrivateIpAddress(_host.ip); + cmd.setPrivateIpAddress(_host.getIp()); cmd.setPrivateMacAddress(pifr.MAC); cmd.setPrivateNetmask("255.255.255.0"); } - pif = PIF.getByUuid(conn, _host.publicPif); + pif = PIF.getByUuid(conn, _host.getPublicPif()); pifr = pif.getRecord(conn); if (pifr.IP != null && pifr.IP.length() > 0) { cmd.setPublicIpAddress(pifr.IP); @@ -5538,8 +5538,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe cmd.setPublicNetmask(pifr.netmask); } - if (_host.storagePif1 != null) { - pif = PIF.getByUuid(conn, _host.storagePif1); + if (_host.getStoragePif1() != null) { + pif = PIF.getByUuid(conn, _host.getStoragePif1()); pifr = pif.getRecord(conn); if (pifr.IP != null && pifr.IP.length() > 0) { cmd.setStorageIpAddress(pifr.IP); @@ -5548,8 +5548,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - if (_host.storagePif2 != null) { - pif = PIF.getByUuid(conn, _host.storagePif2); + if (_host.getStoragePif2() != null) { + pif = PIF.getByUuid(conn, _host.getStoragePif2()); pifr = pif.getRecord(conn); if (pifr.IP != null && pifr.IP.length() > 0) { cmd.setStorageIpAddressDeux(pifr.IP); @@ -5584,10 +5584,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new ConfigurationException("Unable to get the zone " + params.get("zone")); } - _host.uuid = (String)params.get("guid"); + _host.setUuid((String)params.get("guid")); - _name = _host.uuid; - _host.ip = (String)params.get("ipaddress"); + _name = _host.getUuid(); + _host.setIp((String)params.get("ipaddress")); _username = (String)params.get("username"); _password.add((String)params.get("password")); @@ -5622,7 +5622,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new ConfigurationException("Unable to get the pod"); } - if (_host.ip == null) { + if (_host.getIp() == null) { throw new ConfigurationException("Unable to get the host address"); } @@ -5634,7 +5634,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new ConfigurationException("Unable to get the password"); } - if (_host.uuid == null) { + if (_host.getUuid() == null) { throw new ConfigurationException("Unable to get the uuid"); } @@ -5655,23 +5655,23 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } private void CheckXenHostInfo() throws ConfigurationException { - final Connection conn = ConnPool.getConnect(_host.ip, _username, _password); + final Connection conn = ConnPool.getConnect(_host.getIp(), _username, _password); if( conn == null ) { - throw new ConfigurationException("Can not create connection to " + _host.ip); + throw new ConfigurationException("Can not create connection to " + _host.getIp()); } try { Host.Record hostRec = null; try { - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); hostRec = host.getRecord(conn); final Pool.Record poolRec = Pool.getAllRecords(conn).values().iterator().next(); - _host.pool = poolRec.uuid; + _host.setPool(poolRec.uuid); } catch (final Exception e) { - throw new ConfigurationException("Can not get host information from " + _host.ip); + throw new ConfigurationException("Can not get host information from " + _host.getIp()); } - if (!hostRec.address.equals(_host.ip)) { - final String msg = "Host " + _host.ip + " seems be reinstalled, please remove this host and readd"; + if (!hostRec.address.equals(_host.getIp())) { + final String msg = "Host " + _host.getIp() + " seems be reinstalled, please remove this host and readd"; s_logger.error(msg); throw new ConfigurationException(msg); } @@ -5779,7 +5779,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final Map smConfig = new HashMap(); smConfig.put("nosubdir", "true"); final SR sr = SR.create(conn, host, deviceConfig, new Long(0), name, uri.getHost() + uri.getPath(), SRType.NFS.toString(), "user", shared, smConfig); @@ -5809,7 +5809,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String path = uri.getPath(); path = path.replace("//", "/"); deviceConfig.put("location", uri.getHost() + ":" + path); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final SR sr = SR.create(conn, host, deviceConfig, new Long(0), uri.getHost() + path, "iso", "iso", "iso", shared, new HashMap()); sr.setNameLabel(conn, vmName + "-ISO"); sr.setNameDescription(conn, deviceConfig.get("location")); @@ -5915,7 +5915,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) { throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" + dc.get("targetIQN") + - ", lunid:" + dc.get("lunid") + " for pool " + srNameLabel + "on host:" + _host.uuid); + ", lunid:" + dc.get("lunid") + " for pool " + srNameLabel + "on host:" + _host.getUuid()); } } deviceConfig.put("target", target); @@ -5926,7 +5926,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe deviceConfig.put("chappassword", chapInitiatorPassword); } - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final Map smConfig = new HashMap(); final String type = SRType.LVMOISCSI.toString(); SR sr = null; @@ -6049,14 +6049,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) { throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + dc.get("serverpath") + - " for pool " + uuid + " on host:" + _host.uuid); + " for pool " + uuid + " on host:" + _host.getUuid()); } } } deviceConfig.put("server", server); deviceConfig.put("serverpath", serverpath); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); final Map smConfig = new HashMap(); smConfig.put("nosubdir", "true"); final SR sr = SR.create(conn, host, deviceConfig, new Long(0), uuid, poolid, SRType.NFS.toString(), "user", true, smConfig); @@ -6355,7 +6355,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe task = vm.snapshotAsync(conn, vmSnapshotName); } else { final Set vbds = vm.getVBDs(conn); - final Pool pool = Pool.getByUuid(conn, _host.pool); + final Pool pool = Pool.getByUuid(conn, _host.getPool()); for (final VBD vbd : vbds) { final VBD.Record vbdr = vbd.getRecord(conn); if (vbdr.userdevice.equals("0")) { @@ -6763,9 +6763,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (checkSR(conn, sr)) { return sr; } - throw new CloudRuntimeException("SR check failed for storage pool: " + srNameLabel + "on host:" + _host.uuid); + throw new CloudRuntimeException("SR check failed for storage pool: " + srNameLabel + "on host:" + _host.getUuid()); } else { - throw new CloudRuntimeException("Can not see storage pool: " + srNameLabel + " from on host:" + _host.uuid); + throw new CloudRuntimeException("Can not see storage pool: " + srNameLabel + " from on host:" + _host.getUuid()); } } @@ -6917,11 +6917,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final String result = callHostPlugin(conn, "vmops", "cleanup_rules", "instance", _instance); final int numCleaned = Integer.parseInt(result); if (result == null || result.isEmpty() || numCleaned < 0) { - s_logger.warn("Failed to cleanup rules for host " + _host.ip); + s_logger.warn("Failed to cleanup rules for host " + _host.getIp()); return new Answer(cmd, false, result); } if (numCleaned > 0) { - s_logger.info("Cleaned up rules for " + result + " vms on host " + _host.ip); + s_logger.info("Cleaned up rules for " + result + " vms on host " + _host.getIp()); } return new Answer(cmd, true, result); } @@ -6963,9 +6963,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Network.Record nr = getNetworkRecord(conn); for (final PIF pif : nr.PIFs) { final PIF.Record pr = pif.getRecord(conn); - if (_host.uuid.equals(pr.host.getUuid(conn))) { + if (_host.getUuid().equals(pr.host.getUuid(conn))) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Found a network called " + nr.nameLabel + " on host=" + _host.ip + "; Network=" + nr.uuid + "; pif=" + pr.uuid); + s_logger.debug("Found a network called " + nr.nameLabel + " on host=" + _host.getIp() + "; Network=" + nr.uuid + "; pif=" + pr.uuid); } _p = pif; _pr = pr; @@ -6987,38 +6987,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - // A list of UUIDs that are gathered from the XenServer when - // the resource first connects to XenServer. These UUIDs do - // not change over time. - protected class XsHost { - public String systemvmisouuid; - public String uuid; - public String ip; - public String publicNetwork; - public String privateNetwork; - public String linkLocalNetwork; - public Network vswitchNetwork; - public String storageNetwork1; - public String guestNetwork; - public String guestPif; - public String publicPif; - public String privatePif; - public String storagePif1; - public String storagePif2; - public String pool; - public int speed; - public Integer cpuSockets; - public int cpus; - public String productVersion; - public String localSRuuid; - - @Override - public String toString() { - return new StringBuilder("XS[").append(uuid).append("-").append(ip).append("]").toString(); - } - } - - protected String getGuestOsType(final String stdType, String platformEmulator, final boolean bootFromCD) { if (platformEmulator == null) { s_logger.debug("no guest OS type, start it as HVM guest"); @@ -7059,10 +7027,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe //check if this is master Pool pool; try { - pool = Pool.getByUuid(conn, _host.pool); + pool = Pool.getByUuid(conn, _host.getPool()); final Pool.Record poolr = pool.getRecord(conn); final Host.Record hostr = poolr.master.getRecord(conn); - if (!_host.uuid.equals(hostr.uuid)) { + if (!_host.getUuid().equals(hostr.uuid)) { return new ClusterVMMetaDataSyncAnswer(cmd.getClusterId(), null); } } catch (final Throwable e) { @@ -7086,7 +7054,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } } catch (final Throwable e) { - final String msg = "Unable to get vms through host " + _host.uuid + " due to to " + e.toString(); + final String msg = "Unable to get vms through host " + _host.getUuid() + " due to to " + e.toString(); s_logger.warn(msg, e); throw new CloudRuntimeException(msg); } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java index 1a6de1f2daa..b5eef7eeee1 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java @@ -27,15 +27,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.SR; -import com.xensource.xenapi.Types; -import com.xensource.xenapi.Types.XenAPIException; -import com.xensource.xenapi.VBD; -import com.xensource.xenapi.VDI; -import com.xensource.xenapi.VM; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.NetworkUsageAnswer; @@ -49,6 +40,14 @@ import com.cloud.resource.ServerResource; import com.cloud.storage.Storage; 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.SR; +import com.xensource.xenapi.Types; +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 XcpOssResource extends CitrixResourceBase { @@ -57,55 +56,55 @@ public class XcpOssResource extends CitrixResourceBase { @Override protected List getPatchFiles() { - List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xcposs/patch"; - String patchfilePath = Script.findScript("", patch); + final List files = new ArrayList(); + final String patch = "scripts/vm/hypervisor/xenserver/xcposs/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 void fillHostInfo(Connection conn, StartupRoutingCommand cmd) { + protected void fillHostInfo(final Connection conn, final StartupRoutingCommand cmd) { super.fillHostInfo(conn, cmd); cmd.setCaps(cmd.getCapabilities() + " , hvm"); } @Override - protected boolean launchHeartBeat(Connection conn) { + protected boolean launchHeartBeat(final Connection conn) { return true; } @Override - protected StartupStorageCommand initializeLocalSR(Connection conn) { - SR extsr = getLocalEXTSR(conn); + protected StartupStorageCommand initializeLocalSR(final Connection conn) { + final SR extsr = getLocalEXTSR(conn); if (extsr != null) { try { - String extuuid = extsr.getUuid(conn); - _host.localSRuuid = extuuid; - long cap = extsr.getPhysicalSize(conn); + final String extuuid = extsr.getUuid(conn); + _host.setLocalSRuuid(extuuid); + final long cap = extsr.getPhysicalSize(conn); if (cap > 0) { - long avail = cap - extsr.getPhysicalUtilisation(conn); - String name = "Cloud Stack Local EXT Storage Pool for " + _host.uuid; + final long avail = cap - extsr.getPhysicalUtilisation(conn); + final String name = "Cloud Stack Local EXT Storage Pool for " + _host.getUuid(); extsr.setNameDescription(conn, name); - Host host = Host.getByUuid(conn, _host.uuid); - String address = host.getAddress(conn); - StoragePoolInfo pInfo = new StoragePoolInfo(extsr.getNameLabel(conn), address, SRType.EXT.toString(), SRType.EXT.toString(), Storage.StoragePoolType.EXT, cap, avail); - StartupStorageCommand cmd = new StartupStorageCommand(); + final Host host = Host.getByUuid(conn, _host.getUuid()); + final String address = host.getAddress(conn); + final StoragePoolInfo pInfo = new StoragePoolInfo(extsr.getNameLabel(conn), address, SRType.EXT.toString(), SRType.EXT.toString(), Storage.StoragePoolType.EXT, cap, avail); + final StartupStorageCommand cmd = new StartupStorageCommand(); cmd.setPoolInfo(pInfo); - cmd.setGuid(_host.uuid); + cmd.setGuid(_host.getUuid()); cmd.setDataCenter(Long.toString(_dcId)); cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); return cmd; } - } catch (XenAPIException e) { - String msg = "build local EXT info err in host:" + _host.uuid + e.toString(); + } catch (final XenAPIException e) { + final String msg = "build local EXT info err in host:" + _host.getUuid() + e.toString(); s_logger.warn(msg); - } catch (XmlRpcException e) { - String msg = "build local EXT info err in host:" + _host.uuid + e.getMessage(); + } catch (final XmlRpcException e) { + final String msg = "build local EXT info err in host:" + _host.getUuid() + e.getMessage(); s_logger.warn(msg); } } @@ -113,7 +112,7 @@ public class XcpOssResource extends CitrixResourceBase { } @Override - protected String getGuestOsType(String stdType, String platformEmulator, boolean bootFromCD) { + protected String getGuestOsType(final String stdType, final String platformEmulator, final boolean bootFromCD) { if (stdType.equalsIgnoreCase("Debian GNU/Linux 6(64-bit)")) { return "Debian Squeeze 6.0 (64-bit)"; } else if (stdType.equalsIgnoreCase("CentOS 5.6 (64-bit)")) { @@ -124,21 +123,21 @@ public class XcpOssResource extends CitrixResourceBase { } @Override - protected synchronized VBD createPatchVbd(Connection conn, String vmName, VM vm) throws XmlRpcException, XenAPIException { - if (_host.localSRuuid != null) { + protected synchronized VBD createPatchVbd(final Connection conn, final String vmName, final VM vm) throws XmlRpcException, XenAPIException { + if (_host.getLocalSRuuid() != null) { //create an iso vdi on it - String result = callHostPlugin(conn, "vmops", "createISOVHD", "uuid", _host.localSRuuid); + final String result = callHostPlugin(conn, "vmops", "createISOVHD", "uuid", _host.getLocalSRuuid()); if (result == null || result.equalsIgnoreCase("Failed")) { throw new CloudRuntimeException("can not create systemvm vdi"); } - Set vdis = VDI.getByNameLabel(conn, "systemvm-vdi"); + final Set vdis = VDI.getByNameLabel(conn, "systemvm-vdi"); if (vdis.size() != 1) { throw new CloudRuntimeException("can not find systemvmiso"); } - VDI systemvmVDI = vdis.iterator().next(); + final VDI systemvmVDI = vdis.iterator().next(); - VBD.Record cdromVBDR = new VBD.Record(); + final VBD.Record cdromVBDR = new VBD.Record(); cdromVBDR.VM = vm; cdromVBDR.empty = false; cdromVBDR.bootable = false; @@ -146,32 +145,32 @@ public class XcpOssResource extends CitrixResourceBase { cdromVBDR.mode = Types.VbdMode.RO; cdromVBDR.type = Types.VbdType.DISK; cdromVBDR.VDI = systemvmVDI; - VBD cdromVBD = VBD.create(conn, cdromVBDR); + final VBD cdromVBD = VBD.create(conn, cdromVBDR); return cdromVBD; } else { throw new CloudRuntimeException("can not find local sr"); } } - 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); } } @Override - public Answer executeRequest(Command cmd) { + public Answer executeRequest(final Command cmd) { if (cmd instanceof NetworkUsageCommand) { return execute((NetworkUsageCommand) cmd); } else { @@ -180,18 +179,18 @@ public class XcpOssResource extends CitrixResourceBase { } @Override - public StopAnswer execute(StopCommand cmd) { - StopAnswer answer = super.execute(cmd); - String vmName = cmd.getVmName(); + public StopAnswer execute(final StopCommand cmd) { + final StopAnswer answer = super.execute(cmd); + final String vmName = cmd.getVmName(); if (vmName.startsWith("v-")) { - Connection conn = getConnection(); + final Connection conn = getConnection(); callHostPlugin(conn, "vmops", "setDNATRule", "add", "false"); } return answer; } @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 { vm.setMemoryLimits(conn, mem_32m, maxMemsize, minMemsize, maxMemsize); } } 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 a8e9efac9aa..1de7b963be2 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 @@ -89,7 +89,7 @@ public class XenServer56Resource extends CitrixResourceBase { final String bridge = networkr.bridge.trim(); for (final PIF pif : networkr.PIFs) { final PIF.Record pifr = pif.getRecord(conn); - if (!pifr.host.getUuid(conn).equalsIgnoreCase(_host.uuid)) { + if (!pifr.host.getUuid(conn).equalsIgnoreCase(_host.getUuid())) { continue; } @@ -102,13 +102,13 @@ public class XenServer56Resource extends CitrixResourceBase { } try { vlan.destroy(conn); - final Host host = Host.getByUuid(conn, _host.uuid); + final Host host = Host.getByUuid(conn, _host.getUuid()); host.forgetDataSourceArchives(conn, "pif_" + bridge + "_tx"); host.forgetDataSourceArchives(conn, "pif_" + bridge + "_rx"); host.forgetDataSourceArchives(conn, "pif_" + device + "." + vlannum + "_tx"); host.forgetDataSourceArchives(conn, "pif_" + device + "." + vlannum + "_rx"); } catch (final XenAPIException e) { - s_logger.trace("Catch " + e.getClass().getName() + ": failed to destory VLAN " + device + " on host " + _host.uuid + " due to " + e.toString()); + s_logger.trace("Catch " + e.getClass().getName() + ": failed to destory VLAN " + device + " on host " + _host.getUuid() + " due to " + e.toString()); } } return; @@ -210,7 +210,7 @@ public class XenServer56Resource extends CitrixResourceBase { } protected Boolean check_heartbeat(final String hostuuid) { - final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.ip, 22); + final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); try { sshConnection.connect(null, 60000, 60000); if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java index 2283477eac3..3c5caf03ce3 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java @@ -24,23 +24,10 @@ import java.util.Set; import javax.ejb.Local; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; -import com.xensource.xenapi.Connection; -import com.xensource.xenapi.Host; -import com.xensource.xenapi.Network; -import com.xensource.xenapi.SR; -import com.xensource.xenapi.Task; -import com.xensource.xenapi.Types; -import com.xensource.xenapi.Types.XenAPIException; -import com.xensource.xenapi.VBD; -import com.xensource.xenapi.VDI; -import com.xensource.xenapi.VIF; -import com.xensource.xenapi.VM; - -import org.apache.cloudstack.storage.to.VolumeObjectTO; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.MigrateWithStorageAnswer; @@ -62,6 +49,17 @@ import com.cloud.network.Networks.TrafficType; import com.cloud.resource.ServerResource; import com.cloud.storage.Volume; import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Task; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VIF; +import com.xensource.xenapi.VM; @Local(value = ServerResource.class) public class XenServer610Resource extends XenServer600Resource { @@ -72,7 +70,7 @@ public class XenServer610Resource extends XenServer600Resource { } @Override - public Answer executeRequest(Command cmd) { + public Answer executeRequest(final Command cmd) { if (cmd instanceof MigrateWithStorageCommand) { return execute((MigrateWithStorageCommand)cmd); } else if (cmd instanceof MigrateWithStorageReceiveCommand) { @@ -88,34 +86,34 @@ public class XenServer610Resource extends XenServer600Resource { } } - private List getUpdatedVolumePathsOfMigratedVm(Connection connection, VM migratedVm, DiskTO[] volumes) throws CloudRuntimeException { - List volumeToList = new ArrayList(); + private List getUpdatedVolumePathsOfMigratedVm(final Connection connection, final VM migratedVm, final DiskTO[] volumes) throws CloudRuntimeException { + final List volumeToList = new ArrayList(); try { // Volume paths would have changed. Return that information. - Set vbds = migratedVm.getVBDs(connection); - Map deviceIdToVdiMap = new HashMap(); + final Set vbds = migratedVm.getVBDs(connection); + final Map deviceIdToVdiMap = new HashMap(); // get vdi:vbdr to a map - for (VBD vbd : vbds) { - VBD.Record vbdr = vbd.getRecord(connection); + for (final VBD vbd : vbds) { + final VBD.Record vbdr = vbd.getRecord(connection); if (vbdr.type == Types.VbdType.DISK) { - VDI vdi = vbdr.VDI; + final VDI vdi = vbdr.VDI; deviceIdToVdiMap.put(vbdr.userdevice, vdi); } } - for (DiskTO volumeTo : volumes) { + for (final DiskTO volumeTo : volumes) { if (volumeTo.getType() != Volume.Type.ISO) { - VolumeObjectTO vol = (VolumeObjectTO)volumeTo.getData(); - Long deviceId = volumeTo.getDiskSeq(); - VDI vdi = deviceIdToVdiMap.get(deviceId.toString()); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VolumeObjectTO vol = (VolumeObjectTO)volumeTo.getData(); + final Long deviceId = volumeTo.getDiskSeq(); + final VDI vdi = deviceIdToVdiMap.get(deviceId.toString()); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setPath(vdi.getUuid(connection)); newVol.setId(vol.getId()); volumeToList.add(newVol); } } - } catch (Exception e) { + } catch (final Exception e) { s_logger.error("Unable to get the updated VDI paths of the migrated vm " + e.toString(), e); throw new CloudRuntimeException("Unable to get the updated VDI paths of the migrated vm " + e.toString(), e); } @@ -123,10 +121,10 @@ public class XenServer610Resource extends XenServer600Resource { return volumeToList; } - protected MigrateWithStorageAnswer execute(MigrateWithStorageCommand cmd) { - Connection connection = getConnection(); - VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - Map volumeToFiler = cmd.getVolumeToFiler(); + protected MigrateWithStorageAnswer execute(final MigrateWithStorageCommand cmd) { + final Connection connection = getConnection(); + final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + final Map volumeToFiler = cmd.getVolumeToFiler(); final String vmName = vmSpec.getName(); Task task = null; @@ -134,24 +132,24 @@ public class XenServer610Resource extends XenServer600Resource { prepareISO(connection, vmSpec.getName()); // Get the list of networks and recreate VLAN, if required. - for (NicTO nicTo : vmSpec.getNics()) { + for (final NicTO nicTo : vmSpec.getNics()) { getNetwork(connection, nicTo); } - Map other = new HashMap(); + final Map other = new HashMap(); other.put("live", "true"); - Network networkForSm = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); - Host host = Host.getByUuid(connection, _host.uuid); - Map token = host.migrateReceive(connection, networkForSm, other); + final Network networkForSm = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); + final Host host = Host.getByUuid(connection, _host.getUuid()); + final Map token = host.migrateReceive(connection, networkForSm, other); // Get the vm to migrate. - Set vms = VM.getByNameLabel(connection, vmSpec.getName()); - VM vmToMigrate = vms.iterator().next(); + final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + final VM vmToMigrate = vms.iterator().next(); // Create the vif map. The vm stays in the same cluster so we have to pass an empty vif map. - Map vifMap = new HashMap(); - Map vdiMap = new HashMap(); - for (Map.Entry entry : volumeToFiler.entrySet()) { + final Map vifMap = new HashMap(); + final Map vdiMap = new HashMap(); + for (final Map.Entry entry : volumeToFiler.entrySet()) { vdiMap.put(getVDIbyUuid(connection, entry.getKey().getPath()), getStorageRepository(connection, entry.getValue().getUuid())); } @@ -159,10 +157,10 @@ public class XenServer610Resource extends XenServer600Resource { task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); try { // poll every 1 seconds - long timeout = (_migratewait) * 1000L; + final long timeout = _migratewait * 1000L; waitForTask(connection, task, 1000, timeout); checkForSuccess(connection, task); - } catch (Types.HandleInvalid e) { + } catch (final Types.HandleInvalid e) { s_logger.error("Error while checking if vm " + vmName + " can be migrated to the destination host " + host, e); throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated to the " + "destination host " + host, e); } @@ -171,90 +169,90 @@ public class XenServer610Resource extends XenServer600Resource { task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); try { // poll every 1 seconds. - long timeout = (_migratewait) * 1000L; + final long timeout = _migratewait * 1000L; waitForTask(connection, task, 1000, timeout); checkForSuccess(connection, task); - } catch (Types.HandleInvalid e) { + } catch (final Types.HandleInvalid e) { s_logger.error("Error while migrating vm " + vmName + " to the destination host " + host, e); throw new CloudRuntimeException("Error while migrating vm " + vmName + " to the destination host " + host, e); } // Volume paths would have changed. Return that information. - List volumeToList = getUpdatedVolumePathsOfMigratedVm(connection, vmToMigrate, vmSpec.getDisks()); + final List volumeToList = getUpdatedVolumePathsOfMigratedVm(connection, vmToMigrate, vmSpec.getDisks()); vmToMigrate.setAffinity(connection, host); return new MigrateWithStorageAnswer(cmd, volumeToList); - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("Catch Exception " + e.getClass().getName() + ". Storage motion failed due to " + e.toString(), e); return new MigrateWithStorageAnswer(cmd, e); } finally { if (task != null) { try { task.destroy(connection); - } catch (Exception e) { - s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.uuid + " due to " + e.toString()); + } catch (final Exception e) { + s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.getUuid() + " due to " + e.toString()); } } } } - protected MigrateWithStorageReceiveAnswer execute(MigrateWithStorageReceiveCommand cmd) { - Connection connection = getConnection(); - VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - Map volumeToFiler = cmd.getVolumeToFiler(); + protected MigrateWithStorageReceiveAnswer execute(final MigrateWithStorageReceiveCommand cmd) { + final Connection connection = getConnection(); + final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + final Map volumeToFiler = cmd.getVolumeToFiler(); try { // Get a map of all the SRs to which the vdis will be migrated. - Map volumeToSr = new HashMap(); - for (Map.Entry entry : volumeToFiler.entrySet()) { - SR sr = getStorageRepository(connection, entry.getValue().getUuid()); + final Map volumeToSr = new HashMap(); + for (final Map.Entry entry : volumeToFiler.entrySet()) { + final SR sr = getStorageRepository(connection, entry.getValue().getUuid()); volumeToSr.put(entry.getKey(), sr); } // Get the list of networks to which the vifs will attach. - Map nicToNetwork = new HashMap(); - for (NicTO nicTo : vmSpec.getNics()) { - Network network = getNetwork(connection, nicTo); + final Map nicToNetwork = new HashMap(); + for (final NicTO nicTo : vmSpec.getNics()) { + final Network network = getNetwork(connection, nicTo); nicToNetwork.put(nicTo, network); } - Map other = new HashMap(); + final Map other = new HashMap(); other.put("live", "true"); - Network network = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); - Host host = Host.getByUuid(connection, _host.uuid); - Map token = host.migrateReceive(connection, network, other); + final Network network = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); + final Host host = Host.getByUuid(connection, _host.getUuid()); + final Map token = host.migrateReceive(connection, network, other); return new MigrateWithStorageReceiveAnswer(cmd, volumeToSr, nicToNetwork, token); - } catch (CloudRuntimeException e) { + } catch (final CloudRuntimeException e) { s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); return new MigrateWithStorageReceiveAnswer(cmd, e); - } catch (Exception e) { + } catch (final Exception e) { s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); return new MigrateWithStorageReceiveAnswer(cmd, e); } } - protected MigrateWithStorageSendAnswer execute(MigrateWithStorageSendCommand cmd) { - Connection connection = getConnection(); - VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - Map volumeToSr = cmd.getVolumeToSr(); - Map nicToNetwork = cmd.getNicToNetwork(); - Map token = cmd.getToken(); + protected MigrateWithStorageSendAnswer execute(final MigrateWithStorageSendCommand cmd) { + final Connection connection = getConnection(); + final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + final Map volumeToSr = cmd.getVolumeToSr(); + final Map nicToNetwork = cmd.getNicToNetwork(); + final Map token = cmd.getToken(); final String vmName = vmSpec.getName(); - Set volumeToSet = null; + final Set volumeToSet = null; boolean migrated = false; Task task = null; try { - Set vms = VM.getByNameLabel(connection, vmSpec.getName()); - VM vmToMigrate = vms.iterator().next(); - Map other = new HashMap(); + final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + final VM vmToMigrate = vms.iterator().next(); + final Map other = new HashMap(); other.put("live", "true"); // Create the vdi map which tells what volumes of the vm need to go on which sr on the destination. - Map vdiMap = new HashMap(); - for (Map.Entry entry : volumeToSr.entrySet()) { + final Map vdiMap = new HashMap(); + for (final Map.Entry entry : volumeToSr.entrySet()) { if (entry.getValue() instanceof SR) { - SR sr = (SR)entry.getValue(); - VDI vdi = getVDIbyUuid(connection, entry.getKey().getPath()); + final SR sr = (SR)entry.getValue(); + final VDI vdi = getVDIbyUuid(connection, entry.getKey().getPath()); vdiMap.put(vdi, sr); } else { throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type SR."); @@ -262,11 +260,11 @@ public class XenServer610Resource extends XenServer600Resource { } // Create the vif map. - Map vifMap = new HashMap(); - for (Map.Entry entry : nicToNetwork.entrySet()) { + final Map vifMap = new HashMap(); + for (final Map.Entry entry : nicToNetwork.entrySet()) { if (entry.getValue() instanceof Network) { - Network network = (Network)entry.getValue(); - VIF vif = getVifByMac(connection, vmToMigrate, entry.getKey().getMac()); + final Network network = (Network)entry.getValue(); + final VIF vif = getVifByMac(connection, vmToMigrate, entry.getKey().getMac()); vifMap.put(vif, network); } else { throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type Network."); @@ -277,10 +275,10 @@ public class XenServer610Resource extends XenServer600Resource { task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); try { // poll every 1 seconds. - long timeout = (_migratewait) * 1000L; + final long timeout = _migratewait * 1000L; waitForTask(connection, task, 1000, timeout); checkForSuccess(connection, task); - } catch (Types.HandleInvalid e) { + } catch (final Types.HandleInvalid e) { s_logger.error("Error while checking if vm " + vmName + " can be migrated.", e); throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated.", e); } @@ -289,41 +287,41 @@ public class XenServer610Resource extends XenServer600Resource { task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); try { // poll every 1 seconds. - long timeout = (_migratewait) * 1000L; + final long timeout = _migratewait * 1000L; waitForTask(connection, task, 1000, timeout); checkForSuccess(connection, task); - } catch (Types.HandleInvalid e) { + } catch (final Types.HandleInvalid e) { s_logger.error("Error while migrating vm " + vmName, e); throw new CloudRuntimeException("Error while migrating vm " + vmName, e); } migrated = true; return new MigrateWithStorageSendAnswer(cmd, volumeToSet); - } catch (CloudRuntimeException e) { + } catch (final CloudRuntimeException e) { s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); return new MigrateWithStorageSendAnswer(cmd, e); - } catch (Exception e) { + } catch (final Exception e) { s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); return new MigrateWithStorageSendAnswer(cmd, e); } finally { if (task != null) { try { task.destroy(connection); - } catch (Exception e) { - s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.uuid + " due to " + e.toString()); + } catch (final Exception e) { + s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.getUuid() + " due to " + e.toString()); } } } } - protected MigrateWithStorageCompleteAnswer execute(MigrateWithStorageCompleteCommand cmd) { - Connection connection = getConnection(); - VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + protected MigrateWithStorageCompleteAnswer execute(final MigrateWithStorageCompleteCommand cmd) { + final Connection connection = getConnection(); + final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); try { - Host host = Host.getByUuid(connection, _host.uuid); - Set vms = VM.getByNameLabel(connection, vmSpec.getName()); - VM migratedVm = vms.iterator().next(); + final Host host = Host.getByUuid(connection, _host.getUuid()); + final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + final VM migratedVm = vms.iterator().next(); // Check the vm is present on the new host. if (migratedVm == null) { @@ -331,47 +329,47 @@ public class XenServer610Resource extends XenServer600Resource { } // Volume paths would have changed. Return that information. - List volumeToSet = getUpdatedVolumePathsOfMigratedVm(connection, migratedVm, vmSpec.getDisks()); + final List volumeToSet = getUpdatedVolumePathsOfMigratedVm(connection, migratedVm, vmSpec.getDisks()); migratedVm.setAffinity(connection, host); return new MigrateWithStorageCompleteAnswer(cmd, volumeToSet); - } catch (CloudRuntimeException e) { + } catch (final CloudRuntimeException e) { s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); return new MigrateWithStorageCompleteAnswer(cmd, e); - } catch (Exception e) { + } catch (final Exception e) { s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); return new MigrateWithStorageCompleteAnswer(cmd, e); } } - protected MigrateVolumeAnswer execute(MigrateVolumeCommand cmd) { - Connection connection = getConnection(); - String volumeUUID = cmd.getVolumePath(); - StorageFilerTO poolTO = cmd.getPool(); + protected MigrateVolumeAnswer execute(final MigrateVolumeCommand cmd) { + final Connection connection = getConnection(); + final String volumeUUID = cmd.getVolumePath(); + final StorageFilerTO poolTO = cmd.getPool(); try { - SR destinationPool = getStorageRepository(connection, poolTO.getUuid()); - VDI srcVolume = getVDIbyUuid(connection, volumeUUID); - Map other = new HashMap(); + final SR destinationPool = getStorageRepository(connection, poolTO.getUuid()); + final VDI srcVolume = getVDIbyUuid(connection, volumeUUID); + final Map other = new HashMap(); other.put("live", "true"); // Live migrate the vdi across pool. - Task task = srcVolume.poolMigrateAsync(connection, destinationPool, other); - long timeout = (_migratewait) * 1000L; + final Task task = srcVolume.poolMigrateAsync(connection, destinationPool, other); + final long timeout = _migratewait * 1000L; waitForTask(connection, task, 1000, timeout); checkForSuccess(connection, task); - VDI dvdi = Types.toVDI(task, connection); + final VDI dvdi = Types.toVDI(task, connection); return new MigrateVolumeAnswer(cmd, true, null, dvdi.getUuid(connection)); - } catch (Exception e) { - String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); s_logger.error(msg, e); return new MigrateVolumeAnswer(cmd, false, msg, null); } } @Override - protected void plugDom0Vif(Connection conn, VIF dom0Vif) throws XmlRpcException, XenAPIException { + protected void plugDom0Vif(final Connection conn, final VIF dom0Vif) throws XmlRpcException, XenAPIException { // do nothing. In xenserver 6.1 and beyond this step isn't needed. } } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620Resource.java index ecc30895232..858fc154957 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620Resource.java @@ -20,18 +20,16 @@ import java.util.Set; import javax.ejb.Local; +import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs; import org.apache.log4j.Logger; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.resource.ServerResource; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.HostPatch; import com.xensource.xenapi.PoolPatch; -import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs; - -import com.cloud.agent.api.StartupRoutingCommand; -import com.cloud.resource.ServerResource; - @Local(value = ServerResource.class) public class XenServer620Resource extends XenServer610Resource { private static final Logger s_logger = Logger.getLogger(XenServer620Resource.class); @@ -40,34 +38,33 @@ public class XenServer620Resource extends XenServer610Resource { super(); } - - protected boolean hostHasHotFix(Connection conn, String hotFixUuid) { + protected boolean hostHasHotFix(final Connection conn, final String hotFixUuid) { try { - Host host = Host.getByUuid(conn, _host.uuid); - Host.Record re = host.getRecord(conn); - Set patches = re.patches; - PoolPatch poolPatch = PoolPatch.getByUuid(conn, hotFixUuid); - for(HostPatch patch : patches) { - PoolPatch pp = patch.getPoolPatch(conn); + final Host host = Host.getByUuid(conn, _host.getUuid()); + final Host.Record re = host.getRecord(conn); + final Set patches = re.patches; + final PoolPatch poolPatch = PoolPatch.getByUuid(conn, hotFixUuid); + for(final HostPatch patch : patches) { + final PoolPatch pp = patch.getPoolPatch(conn); if (pp.equals(poolPatch) && patch.getApplied(conn)) { return true; } } - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("can't get patches information for hotFix: " + hotFixUuid); } return false; } @Override - protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) { + protected void fillHostInfo(final Connection conn, final StartupRoutingCommand cmd) { super.fillHostInfo(conn, cmd); - Map details = cmd.getHostDetails(); - Boolean hotFix62ESP1004 = hostHasHotFix(conn, XenserverConfigs.XSHotFix62ESP1004); + final Map details = cmd.getHostDetails(); + final Boolean hotFix62ESP1004 = hostHasHotFix(conn, XenserverConfigs.XSHotFix62ESP1004); if( hotFix62ESP1004 != null && hotFix62ESP1004 ) { details.put(XenserverConfigs.XS620HotFix , XenserverConfigs.XSHotFix62ESP1004); } else { - Boolean hotFix62ESP1 = hostHasHotFix(conn, XenserverConfigs.XSHotFix62ESP1); + final Boolean hotFix62ESP1 = hostHasHotFix(conn, XenserverConfigs.XSHotFix62ESP1); if( hotFix62ESP1 != null && hotFix62ESP1 ) { details.put(XenserverConfigs.XS620HotFix , XenserverConfigs.XSHotFix62ESP1); } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java index 5553553d49a..ac2b2a62f9d 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java @@ -28,6 +28,15 @@ import javax.ejb.Local; import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.GetGPUStatsAnswer; +import com.cloud.agent.api.GetGPUStatsCommand; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.VgpuTypesInfo; +import com.cloud.agent.api.to.GPUDeviceTO; +import com.cloud.resource.ServerResource; import com.xensource.xenapi.Connection; import com.xensource.xenapi.GPUGroup; import com.xensource.xenapi.Host; @@ -38,16 +47,6 @@ import com.xensource.xenapi.VGPUType; import com.xensource.xenapi.VGPUType.Record; import com.xensource.xenapi.VM; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.GetGPUStatsAnswer; -import com.cloud.agent.api.GetGPUStatsCommand; -import com.cloud.agent.api.StartCommand; -import com.cloud.agent.api.StartupRoutingCommand; -import com.cloud.agent.api.VgpuTypesInfo; -import com.cloud.agent.api.to.GPUDeviceTO; -import com.cloud.resource.ServerResource; - @Local(value=ServerResource.class) public class XenServer620SP1Resource extends XenServer620Resource { private static final Logger s_logger = Logger.getLogger(XenServer620SP1Resource.class); @@ -57,8 +56,8 @@ public class XenServer620SP1Resource extends XenServer620Resource { } @Override - public Answer executeRequest(Command cmd) { - Class clazz = cmd.getClass(); + public Answer executeRequest(final Command cmd) { + final Class clazz = cmd.getClass(); if (clazz == GetGPUStatsCommand.class) { return execute((GetGPUStatsCommand) cmd); } else { @@ -66,28 +65,28 @@ public class XenServer620SP1Resource extends XenServer620Resource { } } - protected GetGPUStatsAnswer execute(GetGPUStatsCommand cmd) { - Connection conn = getConnection(); + protected GetGPUStatsAnswer execute(final GetGPUStatsCommand cmd) { + final Connection conn = getConnection(); HashMap> groupDetails = new HashMap>(); try { groupDetails = getGPUGroupDetails(conn); - } catch (Exception e) { - String msg = "Unable to get GPU stats" + e.toString(); + } catch (final Exception e) { + final String msg = "Unable to get GPU stats" + e.toString(); s_logger.warn(msg, e); } return new GetGPUStatsAnswer(cmd, groupDetails); } @Override - protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) { + protected void fillHostInfo(final Connection conn, final StartupRoutingCommand cmd) { super.fillHostInfo(conn, cmd); try { - HashMap> groupDetails = getGPUGroupDetails(conn); + final HashMap> groupDetails = getGPUGroupDetails(conn); cmd.setGpuGroupDetails(groupDetails); if (groupDetails != null && !groupDetails.isEmpty()) { cmd.setHostTags("GPU"); } - } catch (Exception e) { + } catch (final Exception e) { if (s_logger.isDebugEnabled()) { s_logger.debug("Error while getting GPU device info from host " + cmd.getName(), e); } @@ -95,26 +94,26 @@ public class XenServer620SP1Resource extends XenServer620Resource { } @Override - protected HashMap> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException { - HashMap> groupDetails = new HashMap>(); - Host host = Host.getByUuid(conn, _host.uuid); - Set pgpus = host.getPGPUs(conn); - Iterator iter = pgpus.iterator(); + protected HashMap> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException { + final HashMap> groupDetails = new HashMap>(); + final Host host = Host.getByUuid(conn, _host.getUuid()); + final Set pgpus = host.getPGPUs(conn); + final Iterator iter = pgpus.iterator(); while (iter.hasNext()) { - PGPU pgpu = iter.next(); - GPUGroup gpuGroup = pgpu.getGPUGroup(conn); - Set enabledVGPUTypes = gpuGroup.getEnabledVGPUTypes(conn); - String groupName = gpuGroup.getNameLabel(conn); + final PGPU pgpu = iter.next(); + final GPUGroup gpuGroup = pgpu.getGPUGroup(conn); + final Set enabledVGPUTypes = gpuGroup.getEnabledVGPUTypes(conn); + final String groupName = gpuGroup.getNameLabel(conn); HashMap gpuCapacity = new HashMap(); if (groupDetails.get(groupName) != null) { gpuCapacity = groupDetails.get(groupName); } // Get remaining capacity of all the enabled VGPU in a PGPU if(enabledVGPUTypes != null) { - Iterator it = enabledVGPUTypes.iterator(); + final Iterator it = enabledVGPUTypes.iterator(); while (it.hasNext()) { - VGPUType type = it.next(); - Record record = type.getRecord(conn); + final VGPUType type = it.next(); + final Record record = type.getRecord(conn); Long remainingCapacity = pgpu.getRemainingCapacity(conn, type); Long maxCapacity = pgpu.getSupportedVGPUMaxCapacities(conn).get(type); VgpuTypesInfo entry; @@ -125,7 +124,7 @@ public class XenServer620SP1Resource extends XenServer620Resource { entry.setMaxVmCapacity(maxCapacity); gpuCapacity.put(record.modelName, entry); } else { - VgpuTypesInfo vgpuTypeRecord = new VgpuTypesInfo(null, record.modelName, record.framebufferSize, record.maxHeads, + final VgpuTypesInfo vgpuTypeRecord = new VgpuTypesInfo(null, record.modelName, record.framebufferSize, record.maxHeads, record.maxResolutionX, record.maxResolutionY, maxCapacity, remainingCapacity, maxCapacity); gpuCapacity.put(record.modelName, vgpuTypeRecord); } @@ -137,27 +136,27 @@ public class XenServer620SP1Resource extends XenServer620Resource { } @Override - protected void createVGPU(Connection conn, StartCommand cmd, VM vm, GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { + protected void createVGPU(final Connection conn, final StartCommand cmd, final VM vm, final GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { if (s_logger.isDebugEnabled()) { s_logger.debug("Creating VGPU of VGPU type [ " + gpuDevice.getVgpuType() + " ] in gpu group" + gpuDevice.getGpuGroup() + " for VM " + cmd.getVirtualMachine().getName()); } - Set groups = GPUGroup.getByNameLabel(conn, gpuDevice.getGpuGroup()); + final Set groups = GPUGroup.getByNameLabel(conn, gpuDevice.getGpuGroup()); assert groups.size() == 1 : "Should only have 1 group but found " + groups.size(); - GPUGroup gpuGroup = groups.iterator().next(); + final GPUGroup gpuGroup = groups.iterator().next(); - Set vgpuTypes = gpuGroup.getEnabledVGPUTypes(conn); - Iterator iter = vgpuTypes.iterator(); + final Set vgpuTypes = gpuGroup.getEnabledVGPUTypes(conn); + final Iterator iter = vgpuTypes.iterator(); VGPUType vgpuType = null; while (iter.hasNext()) { - VGPUType entry = iter.next(); + final VGPUType entry = iter.next(); if (entry.getModelName(conn).equals(gpuDevice.getVgpuType())) { vgpuType = entry; } } - String device = "0"; // Only allow device = "0" for now, as XenServer supports just a single vGPU per VM. - Map other_config = new HashMap(); + final String device = "0"; // Only allow device = "0" for now, as XenServer supports just a single vGPU per VM. + final Map other_config = new HashMap(); VGPU.create(conn, vm, gpuGroup, device, other_config, vgpuType); if (s_logger.isDebugEnabled()) { @@ -166,5 +165,4 @@ public class XenServer620SP1Resource extends XenServer620Resource { // Calculate and set remaining GPU capacity in the host. cmd.getVirtualMachine().getGpuDevice().setGroupDetails(getGPUGroupDetails(conn)); } - -} +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java index 10a97a21c12..0cf40f58d63 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java @@ -92,7 +92,7 @@ public class XenServerStorageProcessor implements StorageProcessor { protected CitrixResourceBase hypervisorResource; protected String BaseMountPointOnHost = "/var/run/cloud_mount"; - public XenServerStorageProcessor(CitrixResourceBase resource) { + public XenServerStorageProcessor(final CitrixResourceBase resource) { hypervisorResource = resource; } @@ -104,39 +104,39 @@ public class XenServerStorageProcessor implements StorageProcessor { // detach the new SR // if we needed to perform an attach to the source SR, detach from it @Override - public SnapshotAndCopyAnswer snapshotAndCopy(SnapshotAndCopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); + public SnapshotAndCopyAnswer snapshotAndCopy(final SnapshotAndCopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); try { SR sourceSr = null; - Map sourceDetails = cmd.getSourceDetails(); + final Map sourceDetails = cmd.getSourceDetails(); if (sourceDetails != null && sourceDetails.keySet().size() > 0) { - String iScsiName = sourceDetails.get(DiskTO.IQN); - String storageHost = sourceDetails.get(DiskTO.STORAGE_HOST); - String chapInitiatorUsername = sourceDetails.get(DiskTO.CHAP_INITIATOR_USERNAME); - String chapInitiatorSecret = sourceDetails.get(DiskTO.CHAP_INITIATOR_SECRET); + final String iScsiName = sourceDetails.get(DiskTO.IQN); + final String storageHost = sourceDetails.get(DiskTO.STORAGE_HOST); + final String chapInitiatorUsername = sourceDetails.get(DiskTO.CHAP_INITIATOR_USERNAME); + final String chapInitiatorSecret = sourceDetails.get(DiskTO.CHAP_INITIATOR_SECRET); sourceSr = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, false); } - VDI vdiToSnapshot = VDI.getByUuid(conn, cmd.getUuidOfSourceVdi()); + final VDI vdiToSnapshot = VDI.getByUuid(conn, cmd.getUuidOfSourceVdi()); - VDI vdiSnapshot = vdiToSnapshot.snapshot(conn, new HashMap()); + final VDI vdiSnapshot = vdiToSnapshot.snapshot(conn, new HashMap()); - Map destDetails = cmd.getDestDetails(); + final Map destDetails = cmd.getDestDetails(); - String iScsiName = destDetails.get(DiskTO.IQN); - String storageHost = destDetails.get(DiskTO.STORAGE_HOST); - String chapInitiatorUsername = destDetails.get(DiskTO.CHAP_INITIATOR_USERNAME); - String chapInitiatorSecret = destDetails.get(DiskTO.CHAP_INITIATOR_SECRET); + final String iScsiName = destDetails.get(DiskTO.IQN); + final String storageHost = destDetails.get(DiskTO.STORAGE_HOST); + final String chapInitiatorUsername = destDetails.get(DiskTO.CHAP_INITIATOR_USERNAME); + final String chapInitiatorSecret = destDetails.get(DiskTO.CHAP_INITIATOR_SECRET); - SR newSr = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, false); + final SR newSr = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, false); - VDI vdiCopy = vdiSnapshot.copy(conn, newSr); + final VDI vdiCopy = vdiSnapshot.copy(conn, newSr); - String vdiUuid = vdiCopy.getUuid(conn); + final String vdiUuid = vdiCopy.getUuid(conn); vdiSnapshot.destroy(conn); @@ -146,13 +146,13 @@ public class XenServerStorageProcessor implements StorageProcessor { hypervisorResource.removeSR(conn, newSr); - SnapshotAndCopyAnswer snapshotAndCopyAnswer = new SnapshotAndCopyAnswer(); + final SnapshotAndCopyAnswer snapshotAndCopyAnswer = new SnapshotAndCopyAnswer(); snapshotAndCopyAnswer.setPath(vdiUuid); return snapshotAndCopyAnswer; } - catch (Exception ex) { + catch (final Exception ex) { s_logger.warn("Failed to take and copy snapshot: " + ex.toString(), ex); return new SnapshotAndCopyAnswer(ex.getMessage()); @@ -160,40 +160,40 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public AttachAnswer attachIso(AttachCommand cmd) { - DiskTO disk = cmd.getDisk(); - DataTO data = disk.getData(); - DataStoreTO store = data.getDataStore(); + public AttachAnswer attachIso(final AttachCommand cmd) { + final DiskTO disk = cmd.getDisk(); + final DataTO data = disk.getData(); + final DataStoreTO store = data.getDataStore(); String isoURL = null; if (store == null) { - TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); + final TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); isoURL = iso.getName(); } else { if (!(store instanceof NfsTO)) { s_logger.debug("Can't attach a iso which is not created on nfs: "); return new AttachAnswer("Can't attach a iso which is not created on nfs: "); } - NfsTO nfsStore = (NfsTO) store; + final NfsTO nfsStore = (NfsTO) store; isoURL = nfsStore.getUrl() + nfsStore.getPathSeparator() + data.getPath(); } - String vmName = cmd.getVmName(); + final String vmName = cmd.getVmName(); try { - Connection conn = hypervisorResource.getConnection(); + final Connection conn = hypervisorResource.getConnection(); VBD isoVBD = null; // Find the VM - VM vm = hypervisorResource.getVM(conn, vmName); + final VM vm = hypervisorResource.getVM(conn, vmName); // Find the ISO VDI - VDI isoVDI = hypervisorResource.getIsoVDIByURL(conn, vmName, isoURL); + final VDI isoVDI = hypervisorResource.getIsoVDIByURL(conn, vmName, isoURL); // Find the VM's CD-ROM VBD - Set vbds = vm.getVBDs(conn); - for (VBD vbd : vbds) { - String userDevice = vbd.getUserdevice(conn); - Types.VbdType type = vbd.getType(conn); + final Set vbds = vm.getVBDs(conn); + for (final VBD vbd : vbds) { + final String userDevice = vbd.getUserdevice(conn); + final Types.VbdType type = vbd.getType(conn); if (userDevice.equals("3") && type == Types.VbdType.CD) { isoVBD = vbd; @@ -215,39 +215,39 @@ public class XenServerStorageProcessor implements StorageProcessor { return new AttachAnswer(disk); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { s_logger.warn("Failed to attach iso" + ": " + e.toString(), e); return new AttachAnswer(e.toString()); - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("Failed to attach iso" + ": " + e.toString(), e); return new AttachAnswer(e.toString()); } } @Override - public AttachAnswer attachVolume(AttachCommand cmd) { - DiskTO disk = cmd.getDisk(); - DataTO data = disk.getData(); + public AttachAnswer attachVolume(final AttachCommand cmd) { + final DiskTO disk = cmd.getDisk(); + final DataTO data = disk.getData(); try { - String vmName = cmd.getVmName(); - String vdiNameLabel = vmName + "-DATA"; + final String vmName = cmd.getVmName(); + final String vdiNameLabel = vmName + "-DATA"; - Connection conn = this.hypervisorResource.getConnection(); + final Connection conn = hypervisorResource.getConnection(); VM vm = null; boolean vmNotRunning = true; try { - vm = this.hypervisorResource.getVM(conn, vmName); + vm = hypervisorResource.getVM(conn, vmName); - VM.Record vmr = vm.getRecord(conn); + final VM.Record vmr = vm.getRecord(conn); vmNotRunning = vmr.powerState != VmPowerState.RUNNING; - } catch (CloudRuntimeException ex) { + } catch (final CloudRuntimeException ex) { } - Map details = disk.getDetails(); - boolean isManaged = Boolean.parseBoolean(details.get(DiskTO.MANAGED)); + final Map details = disk.getDetails(); + final boolean isManaged = Boolean.parseBoolean(details.get(DiskTO.MANAGED)); // if the VM is not running and we're not dealing with managed storage, just return success (nothing to do here) // this should probably never actually happen @@ -261,7 +261,7 @@ public class XenServerStorageProcessor implements StorageProcessor { vdi = hypervisorResource.prepareManagedStorage(conn, details, data.getPath(), vdiNameLabel); if (vmNotRunning) { - DiskTO newDisk = new DiskTO(disk.getData(), disk.getDiskSeq(), vdi.getUuid(conn), disk.getType()); + final DiskTO newDisk = new DiskTO(disk.getData(), disk.getDiskSeq(), vdi.getUuid(conn), disk.getType()); return new AttachAnswer(newDisk); } @@ -271,17 +271,17 @@ public class XenServerStorageProcessor implements StorageProcessor { // Figure out the disk number to attach the VM to String diskNumber = null; - Long deviceId = disk.getDiskSeq(); + final Long deviceId = disk.getDiskSeq(); if (deviceId != null) { if (deviceId.longValue() == 3) { - String msg = "Device 3 is reserved for CD-ROM, choose other device"; + final String msg = "Device 3 is reserved for CD-ROM, choose other device"; return new AttachAnswer(msg); } if (hypervisorResource.isDeviceUsed(conn, vm, deviceId)) { - String msg = "Device " + deviceId + " is used in VM " + vmName; + final String msg = "Device " + deviceId + " is used in VM " + vmName; return new AttachAnswer(msg); } @@ -291,7 +291,7 @@ public class XenServerStorageProcessor implements StorageProcessor { diskNumber = hypervisorResource.getUnusedDeviceNum(conn, vm); } - VBD.Record vbdr = new VBD.Record(); + final VBD.Record vbdr = new VBD.Record(); vbdr.VM = vm; vbdr.VDI = vdi; @@ -301,66 +301,66 @@ public class XenServerStorageProcessor implements StorageProcessor { vbdr.type = Types.VbdType.DISK; vbdr.unpluggable = true; - VBD vbd = VBD.create(conn, vbdr); + final VBD vbd = VBD.create(conn, vbdr); // Attach the VBD to the VM try { vbd.plug(conn); - } catch (Exception e) { + } catch (final Exception e) { vbd.destroy(conn); throw e; } // Update the VDI's label to include the VM name vdi.setNameLabel(conn, vdiNameLabel); - DiskTO newDisk = new DiskTO(disk.getData(), Long.parseLong(diskNumber), vdi.getUuid(conn), disk.getType()); + final DiskTO newDisk = new DiskTO(disk.getData(), Long.parseLong(diskNumber), vdi.getUuid(conn), disk.getType()); return new AttachAnswer(newDisk); - } catch (Exception e) { - String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.toString(); s_logger.warn(msg, e); return new AttachAnswer(msg); } } @Override - public Answer dettachIso(DettachCommand cmd) { - DiskTO disk = cmd.getDisk(); - DataTO data = disk.getData(); - DataStoreTO store = data.getDataStore(); + public Answer dettachIso(final DettachCommand cmd) { + final DiskTO disk = cmd.getDisk(); + final DataTO data = disk.getData(); + final DataStoreTO store = data.getDataStore(); String isoURL = null; if (store == null) { - TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); + final TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); isoURL = iso.getName(); } else { if (!(store instanceof NfsTO)) { s_logger.debug("Can't attach a iso which is not created on nfs: "); return new AttachAnswer("Can't attach a iso which is not created on nfs: "); } - NfsTO nfsStore = (NfsTO) store; + final NfsTO nfsStore = (NfsTO) store; isoURL = nfsStore.getUrl() + nfsStore.getPathSeparator() + data.getPath(); } try { - Connection conn = hypervisorResource.getConnection(); + final Connection conn = hypervisorResource.getConnection(); // Find the VM - VM vm = hypervisorResource.getVM(conn, cmd.getVmName()); - String vmUUID = vm.getUuid(conn); + final VM vm = hypervisorResource.getVM(conn, cmd.getVmName()); + final String vmUUID = vm.getUuid(conn); // Find the ISO VDI - VDI isoVDI = hypervisorResource.getIsoVDIByURL(conn, cmd.getVmName(), isoURL); + final VDI isoVDI = hypervisorResource.getIsoVDIByURL(conn, cmd.getVmName(), isoURL); - SR sr = isoVDI.getSR(conn); + final SR sr = isoVDI.getSR(conn); // Look up all VBDs for this VDI - Set vbds = isoVDI.getVBDs(conn); + final Set vbds = isoVDI.getVBDs(conn); // Iterate through VBDs, and if the VBD belongs the VM, eject // the ISO from it - for (VBD vbd : vbds) { - VM vbdVM = vbd.getVM(conn); - String vbdVmUUID = vbdVM.getUuid(conn); + for (final VBD vbd : vbds) { + final VM vbdVM = vbd.getVM(conn); + final String vbdVmUUID = vbdVM.getUuid(conn); if (vbdVmUUID.equals(vmUUID)) { // If an ISO is already inserted, eject it @@ -376,37 +376,37 @@ public class XenServerStorageProcessor implements StorageProcessor { } return new DettachAnswer(disk); - } catch (XenAPIException e) { - String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.toString(); + } catch (final XenAPIException e) { + final String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.toString(); s_logger.warn(msg, e); return new DettachAnswer(msg); - } catch (Exception e) { - String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage(); + } catch (final Exception e) { + final String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage(); s_logger.warn(msg, e); return new DettachAnswer(msg); } } @Override - public Answer dettachVolume(DettachCommand cmd) { - DiskTO disk = cmd.getDisk(); - DataTO data = disk.getData(); + public Answer dettachVolume(final DettachCommand cmd) { + final DiskTO disk = cmd.getDisk(); + final DataTO data = disk.getData(); try { - Connection conn = this.hypervisorResource.getConnection(); + final Connection conn = hypervisorResource.getConnection(); - String vmName = cmd.getVmName(); + final String vmName = cmd.getVmName(); VM vm = null; boolean vmNotRunning = true; try { - vm = this.hypervisorResource.getVM(conn, vmName); + vm = hypervisorResource.getVM(conn, vmName); - VM.Record vmr = vm.getRecord(conn); + final VM.Record vmr = vm.getRecord(conn); vmNotRunning = vmr.powerState != VmPowerState.RUNNING; - } catch (CloudRuntimeException ex) { + } catch (final CloudRuntimeException ex) { } // if the VM is not running and we're not dealing with managed storage, just return success (nothing to do here) @@ -416,14 +416,14 @@ public class XenServerStorageProcessor implements StorageProcessor { } if (!vmNotRunning) { - VDI vdi = this.hypervisorResource.mount(conn, null, null, data.getPath()); + final VDI vdi = hypervisorResource.mount(conn, null, null, data.getPath()); // Look up all VBDs for this VDI - Set vbds = vdi.getVBDs(conn); + final Set vbds = vdi.getVBDs(conn); // Detach each VBD from its VM, and then destroy it - for (VBD vbd : vbds) { - VBD.Record vbdr = vbd.getRecord(conn); + for (final VBD vbd : vbds) { + final VBD.Record vbdr = vbd.getRecord(conn); if (vbdr.currentlyAttached) { vbd.unplug(conn); @@ -435,7 +435,7 @@ public class XenServerStorageProcessor implements StorageProcessor { // Update the VDI's label to be "detached" vdi.setNameLabel(conn, "detached"); - this.hypervisorResource.umount(conn, vdi); + hypervisorResource.umount(conn, vdi); } if (cmd.isManaged()) { @@ -443,83 +443,83 @@ public class XenServerStorageProcessor implements StorageProcessor { } return new DettachAnswer(disk); - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("Failed dettach volume: " + data.getPath()); return new DettachAnswer("Failed dettach volume: " + data.getPath() + ", due to " + e.toString()); } } - protected SR getSRByNameLabel(Connection conn, String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException { - Set srs = SR.getByNameLabel(conn, nameLabel); + protected SR getSRByNameLabel(final Connection conn, final String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException { + final Set srs = SR.getByNameLabel(conn, nameLabel); if (srs.size() != 1) { throw new CloudRuntimeException("storage uuid: " + nameLabel + " is not unique"); } - SR poolsr = srs.iterator().next(); + final SR poolsr = srs.iterator().next(); return poolsr; } - protected VDI createVdi(Connection conn, String vdiName, SR sr, long size) throws BadServerResponse, XenAPIException, XmlRpcException { - VDI.Record vdir = new VDI.Record(); + protected VDI createVdi(final Connection conn, final String vdiName, final SR sr, final long size) throws BadServerResponse, XenAPIException, XmlRpcException { + final VDI.Record vdir = new VDI.Record(); vdir.nameLabel = vdiName; vdir.SR = sr; vdir.type = Types.VdiType.USER; vdir.virtualSize = size; - VDI vdi = VDI.create(conn, vdir); + final VDI vdi = VDI.create(conn, vdir); return vdi; } - protected void deleteVDI(Connection conn, VDI vdi) throws BadServerResponse, XenAPIException, XmlRpcException { + protected void deleteVDI(final Connection conn, final VDI vdi) throws BadServerResponse, XenAPIException, XmlRpcException { vdi.destroy(conn); } @Override - public Answer createSnapshot(CreateObjectCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - SnapshotObjectTO snapshotTO = (SnapshotObjectTO) cmd.getData(); - long snapshotId = snapshotTO.getId(); - String snapshotName = snapshotTO.getName(); + public Answer createSnapshot(final CreateObjectCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final SnapshotObjectTO snapshotTO = (SnapshotObjectTO) cmd.getData(); + final long snapshotId = snapshotTO.getId(); + final String snapshotName = snapshotTO.getName(); String details = "create snapshot operation Failed for snapshotId: " + snapshotId; String snapshotUUID = null; try { - String volumeUUID = snapshotTO.getVolume().getPath(); - VDI volume = VDI.getByUuid(conn, volumeUUID); + final String volumeUUID = snapshotTO.getVolume().getPath(); + final VDI volume = VDI.getByUuid(conn, volumeUUID); - VDI snapshot = volume.snapshot(conn, new HashMap()); + final VDI snapshot = volume.snapshot(conn, new HashMap()); if (snapshotName != null) { snapshot.setNameLabel(conn, snapshotName); } snapshotUUID = snapshot.getUuid(conn); - String preSnapshotUUID = snapshotTO.getParentSnapshotPath(); + final String preSnapshotUUID = snapshotTO.getParentSnapshotPath(); //check if it is a empty snapshot if (preSnapshotUUID != null) { - SR sr = volume.getSR(conn); - String srUUID = sr.getUuid(conn); - String type = sr.getType(conn); - Boolean isISCSI = IsISCSI(type); - String snapshotParentUUID = getVhdParent(conn, srUUID, snapshotUUID, isISCSI); + final SR sr = volume.getSR(conn); + final String srUUID = sr.getUuid(conn); + final String type = sr.getType(conn); + final Boolean isISCSI = IsISCSI(type); + final String snapshotParentUUID = getVhdParent(conn, srUUID, snapshotUUID, isISCSI); try { - String preSnapshotParentUUID = getVhdParent(conn, srUUID, preSnapshotUUID, isISCSI); + final String preSnapshotParentUUID = getVhdParent(conn, srUUID, preSnapshotUUID, isISCSI); if (snapshotParentUUID != null && snapshotParentUUID.equals(preSnapshotParentUUID)) { // this is empty snapshot, remove it snapshot.destroy(conn); snapshotUUID = preSnapshotUUID; } - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to get parent snapshot", e); } } - SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + final SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); newSnapshot.setPath(snapshotUUID); return new CreateObjectAnswer(newSnapshot); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { details += ", reason: " + e.toString(); s_logger.warn(details, e); - } catch (Exception e) { + } catch (final Exception e) { details += ", reason: " + e.toString(); s_logger.warn(details, e); } @@ -528,47 +528,47 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer deleteVolume(DeleteCommand cmd) { - DataTO volume = cmd.getData(); - Connection conn = hypervisorResource.getConnection(); + public Answer deleteVolume(final DeleteCommand cmd) { + final DataTO volume = cmd.getData(); + final Connection conn = hypervisorResource.getConnection(); String errorMsg = null; try { - VDI vdi = VDI.getByUuid(conn, volume.getPath()); + final VDI vdi = VDI.getByUuid(conn, volume.getPath()); deleteVDI(conn, vdi); return new Answer(null); - } catch (BadServerResponse e) { + } catch (final BadServerResponse e) { s_logger.debug("Failed to delete volume", e); errorMsg = e.toString(); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { s_logger.debug("Failed to delete volume", e); errorMsg = e.toString(); - } catch (XmlRpcException e) { + } catch (final XmlRpcException e) { s_logger.debug("Failed to delete volume", e); errorMsg = e.toString(); } return new Answer(null, false, errorMsg); } - protected SR getNfsSR(Connection conn, StorageFilerTO pool) { - Map deviceConfig = new HashMap(); + protected SR getNfsSR(final Connection conn, final StorageFilerTO pool) { + final Map deviceConfig = new HashMap(); try { - String server = pool.getHost(); + final String server = pool.getHost(); String serverpath = pool.getPath(); serverpath = serverpath.replace("//", "/"); - Set srs = SR.getAll(conn); - for (SR sr : srs) { + final Set srs = SR.getAll(conn); + for (final SR sr : srs) { if (!SRType.NFS.equals(sr.getType(conn))) { continue; } - Set pbds = sr.getPBDs(conn); + final Set pbds = sr.getPBDs(conn); if (pbds.isEmpty()) { continue; } - PBD pbd = pbds.iterator().next(); + final PBD pbd = pbds.iterator().next(); - Map dc = pbd.getDeviceConfig(conn); + final Map dc = pbd.getDeviceConfig(conn); if (dc == null) { continue; @@ -584,27 +584,27 @@ public class XenServerStorageProcessor implements StorageProcessor { if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) { throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + dc.get("serverpath") + - " for pool " + pool.getUuid() + "on host:" + hypervisorResource.getHost().uuid); + " for pool " + pool.getUuid() + "on host:" + hypervisorResource.getHost().getUuid()); } } deviceConfig.put("server", server); deviceConfig.put("serverpath", serverpath); - Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid); - Map smConfig = new HashMap(); + final Host host = Host.getByUuid(conn, hypervisorResource.getHost().getUuid()); + final Map smConfig = new HashMap(); smConfig.put("nosubdir", "true"); - SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true, smConfig); + final SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true, smConfig); sr.scan(conn); return sr; - } catch (XenAPIException e) { + } catch (final XenAPIException e) { throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e); - } catch (XmlRpcException e) { + } catch (final XmlRpcException e) { throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e); } } - protected Answer directDownloadHttpTemplate(CopyCommand cmd, DecodedDataObject srcObj, DecodedDataObject destObj) { - Connection conn = hypervisorResource.getConnection(); + protected Answer directDownloadHttpTemplate(final CopyCommand cmd, final DecodedDataObject srcObj, final DecodedDataObject destObj) { + final Connection conn = hypervisorResource.getConnection(); SR poolsr = null; VDI vdi = null; boolean result = false; @@ -617,53 +617,53 @@ public class XenServerStorageProcessor implements StorageProcessor { if (vdi == null) { throw new CloudRuntimeException("can't find volume: " + destObj.getPath()); } - String destStoreUuid = destObj.getStore().getUuid(); - Set srs = SR.getByNameLabel(conn, destStoreUuid); + final String destStoreUuid = destObj.getStore().getUuid(); + final Set srs = SR.getByNameLabel(conn, destStoreUuid); if (srs.size() != 1) { throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique"); } poolsr = srs.iterator().next(); - VDI.Record vdir = vdi.getRecord(conn); - String vdiLocation = vdir.location; + final VDI.Record vdir = vdi.getRecord(conn); + final String vdiLocation = vdir.location; String pbdLocation = null; if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) { pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn); } else { - Set pbds = poolsr.getPBDs(conn); + final Set pbds = poolsr.getPBDs(conn); if (pbds.size() != 1) { throw new CloudRuntimeException("Don't how to handle multiple pbds:" + pbds.size() + " for sr: " + poolsr.getUuid(conn)); } - PBD pbd = pbds.iterator().next(); - Map deviceCfg = pbd.getDeviceConfig(conn); + final PBD pbd = pbds.iterator().next(); + final Map deviceCfg = pbd.getDeviceConfig(conn); pbdLocation = deviceCfg.get("location"); } if (pbdLocation == null) { throw new CloudRuntimeException("Can't get pbd location"); } - String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd"; + final String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd"; //download a url into vdipath //downloadHttpToLocalFile(vdiPath, template.getPath()); hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath()); result = true; //return new CopyCmdAnswer(cmd, vdi.getUuid(conn)); - } catch (BadServerResponse e) { + } catch (final BadServerResponse e) { s_logger.debug("Failed to download template", e); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { s_logger.debug("Failed to download template", e); - } catch (XmlRpcException e) { + } catch (final XmlRpcException e) { s_logger.debug("Failed to download template", e); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to download template", e); } finally { if (!result && vdi != null) { try { vdi.destroy(conn); - } catch (BadServerResponse e) { + } catch (final BadServerResponse e) { s_logger.debug("Failed to cleanup newly created vdi"); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { s_logger.debug("Failed to cleanup newly created vdi"); - } catch (XmlRpcException e) { + } catch (final XmlRpcException e) { s_logger.debug("Failed to cleanup newly created vdi"); } } @@ -671,61 +671,61 @@ public class XenServerStorageProcessor implements StorageProcessor { return new Answer(cmd, false, "Failed to download template"); } - protected Answer execute(AttachPrimaryDataStoreCmd cmd) { - String dataStoreUri = cmd.getDataStore(); - Connection conn = hypervisorResource.getConnection(); + protected Answer execute(final AttachPrimaryDataStoreCmd cmd) { + final String dataStoreUri = cmd.getDataStore(); + final Connection conn = hypervisorResource.getConnection(); try { - DecodedDataObject obj = Decoder.decode(dataStoreUri); + final DecodedDataObject obj = Decoder.decode(dataStoreUri); - DecodedDataStore store = obj.getStore(); + final DecodedDataStore store = obj.getStore(); - SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid()); + final SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid()); hypervisorResource.setupHeartbeatSr(conn, sr, false); - long capacity = sr.getPhysicalSize(conn); - long available = capacity - sr.getPhysicalUtilisation(conn); + final long capacity = sr.getPhysicalSize(conn); + final long available = capacity - sr.getPhysicalUtilisation(conn); if (capacity == -1) { - String msg = "Pool capacity is -1! pool: "; + final String msg = "Pool capacity is -1! pool: "; s_logger.warn(msg); return new Answer(cmd, false, msg); } - AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd); + final AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd); answer.setCapacity(capacity); answer.setUuid(sr.getUuid(conn)); answer.setAvailable(available); return answer; - } catch (XenAPIException e) { - String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString(); + } catch (final XenAPIException e) { + final String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); - } catch (Exception e) { - String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage(); + } catch (final Exception e) { + final String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); } } - protected boolean IsISCSI(String type) { + protected boolean IsISCSI(final String type) { return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type); } - private String copy_vhd_from_secondarystorage(Connection conn, String mountpoint, String sruuid, int wait) { - String nameLabel = "cloud-" + UUID.randomUUID().toString(); - String results = + private String copy_vhd_from_secondarystorage(final Connection conn, final String mountpoint, final String sruuid, final int wait) { + final String nameLabel = "cloud-" + UUID.randomUUID().toString(); + final String results = hypervisorResource.callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel); String errMsg = null; if (results == null || results.isEmpty()) { errMsg = "copy_vhd_from_secondarystorage return null"; } else { - String[] tmp = results.split("#"); - String status = tmp[0]; + final String[] tmp = results.split("#"); + final String status = tmp[0]; if (status.equals("0")) { return tmp[1]; } else { errMsg = tmp[1]; } } - String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1); + final String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1); if (hypervisorResource.killCopyProcess(conn, source)) { destroyVDIbyNameLabel(conn, nameLabel); } @@ -733,35 +733,35 @@ public class XenServerStorageProcessor implements StorageProcessor { throw new CloudRuntimeException(errMsg); } - private void destroyVDIbyNameLabel(Connection conn, String nameLabel) { + private void destroyVDIbyNameLabel(final Connection conn, final String nameLabel) { try { - Set vdis = VDI.getByNameLabel(conn, nameLabel); + final Set vdis = VDI.getByNameLabel(conn, nameLabel); if (vdis.size() != 1) { s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel); return; } - for (VDI vdi : vdis) { + for (final VDI vdi : vdis) { try { vdi.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { } } - } catch (Exception e) { + } catch (final Exception e) { } } - protected VDI getVDIbyUuid(Connection conn, String uuid) { + protected VDI getVDIbyUuid(final Connection conn, final String uuid) { try { return VDI.getByUuid(conn, uuid); - } catch (Exception e) { - String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); s_logger.debug(msg); throw new CloudRuntimeException(msg, e); } } - protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) { - String parentUuid = + protected String getVhdParent(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI) { + final String parentUuid = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString()); @@ -774,20 +774,20 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) { - DataTO srcDataTo = cmd.getSrcTO(); - DataTO destDataTo = cmd.getDestTO(); - int wait = cmd.getWait(); - DataStoreTO srcDataStoreTo = srcDataTo.getDataStore(); + public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) { + final DataTO srcDataTo = cmd.getSrcTO(); + final DataTO destDataTo = cmd.getDestTO(); + final int wait = cmd.getWait(); + final DataStoreTO srcDataStoreTo = srcDataTo.getDataStore(); try { - if ((srcDataStoreTo instanceof NfsTO) && (srcDataTo.getObjectType() == DataObjectType.TEMPLATE)) { - NfsTO srcImageStore = (NfsTO) srcDataStoreTo; - TemplateObjectTO srcTemplateObjectTo = (TemplateObjectTO) srcDataTo; - String storeUrl = srcImageStore.getUrl(); - URI uri = new URI(storeUrl); - String tmplPath = uri.getHost() + ":" + uri.getPath() + "/" + srcDataTo.getPath(); - DataStoreTO destDataStoreTo = destDataTo.getDataStore(); + if (srcDataStoreTo instanceof NfsTO && srcDataTo.getObjectType() == DataObjectType.TEMPLATE) { + final NfsTO srcImageStore = (NfsTO) srcDataStoreTo; + final TemplateObjectTO srcTemplateObjectTo = (TemplateObjectTO) srcDataTo; + final String storeUrl = srcImageStore.getUrl(); + final URI uri = new URI(storeUrl); + final String tmplPath = uri.getHost() + ":" + uri.getPath() + "/" + srcDataTo.getPath(); + final DataStoreTO destDataStoreTo = destDataTo.getDataStore(); boolean managed = false; String storageHost = null; @@ -798,9 +798,9 @@ public class XenServerStorageProcessor implements StorageProcessor { String chapInitiatorSecret = null; if (destDataStoreTo instanceof PrimaryDataStoreTO) { - PrimaryDataStoreTO destPrimaryDataStoreTo = (PrimaryDataStoreTO)destDataStoreTo; + final PrimaryDataStoreTO destPrimaryDataStoreTo = (PrimaryDataStoreTO)destDataStoreTo; - Map details = destPrimaryDataStoreTo.getDetails(); + final Map details = destPrimaryDataStoreTo.getDetails(); if (details != null) { managed = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED)); @@ -816,12 +816,12 @@ public class XenServerStorageProcessor implements StorageProcessor { } } - Connection conn = hypervisorResource.getConnection(); + final Connection conn = hypervisorResource.getConnection(); final SR sr; if (managed) { - Map details = new HashMap(); + final Map details = new HashMap(); details.put(DiskTO.STORAGE_HOST, storageHost); details.put(DiskTO.IQN, managedStoragePoolName); @@ -831,11 +831,11 @@ public class XenServerStorageProcessor implements StorageProcessor { sr = hypervisorResource.prepareManagedSr(conn, details); } else { - String srName = destDataStoreTo.getUuid(); - Set srs = SR.getByNameLabel(conn, srName); + final String srName = destDataStoreTo.getUuid(); + final Set srs = SR.getByNameLabel(conn, srName); if (srs.size() != 1) { - String msg = "There are " + srs.size() + " SRs with same name: " + srName; + final String msg = "There are " + srs.size() + " SRs with same name: " + srName; s_logger.warn(msg); @@ -845,19 +845,19 @@ public class XenServerStorageProcessor implements StorageProcessor { } } - String srUuid = sr.getUuid(conn); - String tmplUuid = copy_vhd_from_secondarystorage(conn, tmplPath, srUuid, wait); - VDI tmplVdi = getVDIbyUuid(conn, tmplUuid); + final String srUuid = sr.getUuid(conn); + final String tmplUuid = copy_vhd_from_secondarystorage(conn, tmplPath, srUuid, wait); + final VDI tmplVdi = getVDIbyUuid(conn, tmplUuid); final String uuidToReturn; - Long physicalSize = tmplVdi.getPhysicalUtilisation(conn); + final Long physicalSize = tmplVdi.getPhysicalUtilisation(conn); if (managed) { uuidToReturn = tmplUuid; tmplVdi.setNameLabel(conn, managedStoragePoolRootVolumeName); } else { - VDI snapshotVdi = tmplVdi.snapshot(conn, new HashMap()); + final VDI snapshotVdi = tmplVdi.snapshot(conn, new HashMap()); uuidToReturn = snapshotVdi.getUuid(conn); @@ -870,10 +870,10 @@ public class XenServerStorageProcessor implements StorageProcessor { try { Thread.sleep(5000); - } catch (InterruptedException e) { + } catch (final InterruptedException e) { } - TemplateObjectTO newVol = new TemplateObjectTO(); + final TemplateObjectTO newVol = new TemplateObjectTO(); newVol.setUuid(uuidToReturn); newVol.setPath(uuidToReturn); @@ -884,8 +884,8 @@ public class XenServerStorageProcessor implements StorageProcessor { return new CopyCmdAnswer(newVol); } - } catch (Exception e) { - String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString(); s_logger.warn(msg, e); @@ -896,13 +896,13 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer createVolume(CreateObjectCommand cmd) { - DataTO data = cmd.getData(); - VolumeObjectTO volume = (VolumeObjectTO) data; + public Answer createVolume(final CreateObjectCommand cmd) { + final DataTO data = cmd.getData(); + final VolumeObjectTO volume = (VolumeObjectTO) data; try { - Connection conn = hypervisorResource.getConnection(); - SR poolSr = hypervisorResource.getStorageRepository(conn, data.getDataStore().getUuid()); + final Connection conn = hypervisorResource.getConnection(); + final SR poolSr = hypervisorResource.getStorageRepository(conn, data.getDataStore().getUuid()); VDI.Record vdir = new VDI.Record(); vdir.nameLabel = volume.getName(); vdir.SR = poolSr; @@ -913,24 +913,24 @@ public class XenServerStorageProcessor implements StorageProcessor { vdi = VDI.create(conn, vdir); vdir = vdi.getRecord(conn); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setName(vdir.nameLabel); newVol.setSize(vdir.virtualSize); newVol.setPath(vdir.uuid); return new CreateObjectAnswer(newVol); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("create volume failed: " + e.toString()); return new CreateObjectAnswer(e.toString()); } } @Override - public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - DataTO srcData = cmd.getSrcTO(); - DataTO destData = cmd.getDestTO(); - VolumeObjectTO volume = (VolumeObjectTO) destData; + public Answer cloneVolumeFromBaseTemplate(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final DataTO srcData = cmd.getSrcTO(); + final DataTO destData = cmd.getDestTO(); + final VolumeObjectTO volume = (VolumeObjectTO) destData; VDI vdi = null; try { VDI tmpltvdi = null; @@ -943,43 +943,43 @@ public class XenServerStorageProcessor implements StorageProcessor { vdir = vdi.getRecord(conn); s_logger.debug("Succesfully created VDI: Uuid = " + vdir.uuid); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setName(vdir.nameLabel); newVol.setSize(vdir.virtualSize); newVol.setPath(vdir.uuid); return new CopyCmdAnswer(newVol); - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("Unable to create volume; Pool=" + destData + "; Disk: ", e); return new CopyCmdAnswer(e.toString()); } } @Override - public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - DataTO srcData = cmd.getSrcTO(); - DataTO destData = cmd.getDestTO(); - int wait = cmd.getWait(); - VolumeObjectTO srcVolume = (VolumeObjectTO) srcData; - VolumeObjectTO destVolume = (VolumeObjectTO) destData; - DataStoreTO srcStore = srcVolume.getDataStore(); + public Answer copyVolumeFromImageCacheToPrimary(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final DataTO srcData = cmd.getSrcTO(); + final DataTO destData = cmd.getDestTO(); + final int wait = cmd.getWait(); + final VolumeObjectTO srcVolume = (VolumeObjectTO) srcData; + final VolumeObjectTO destVolume = (VolumeObjectTO) destData; + final DataStoreTO srcStore = srcVolume.getDataStore(); if (srcStore instanceof NfsTO) { - NfsTO nfsStore = (NfsTO) srcStore; + final NfsTO nfsStore = (NfsTO) srcStore; try { - SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, destVolume.getDataStore().getUuid()); - String srUuid = primaryStoragePool.getUuid(conn); - URI uri = new URI(nfsStore.getUrl()); - String volumePath = uri.getHost() + ":" + uri.getPath() + nfsStore.getPathSeparator() + srcVolume.getPath(); - String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait); - VolumeObjectTO newVol = new VolumeObjectTO(); + final SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, destVolume.getDataStore().getUuid()); + final String srUuid = primaryStoragePool.getUuid(conn); + final URI uri = new URI(nfsStore.getUrl()); + final String volumePath = uri.getHost() + ":" + uri.getPath() + nfsStore.getPathSeparator() + srcVolume.getPath(); + final String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setPath(uuid); newVol.setSize(srcVolume.getSize()); return new CopyCmdAnswer(newVol); - } catch (Exception e) { - String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); s_logger.warn(msg, e); return new CopyCmdAnswer(e.toString()); } @@ -990,18 +990,18 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - VolumeObjectTO srcVolume = (VolumeObjectTO) cmd.getSrcTO(); - VolumeObjectTO destVolume = (VolumeObjectTO) cmd.getDestTO(); - int wait = cmd.getWait(); - DataStoreTO destStore = destVolume.getDataStore(); + public Answer copyVolumeFromPrimaryToSecondary(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final VolumeObjectTO srcVolume = (VolumeObjectTO) cmd.getSrcTO(); + final VolumeObjectTO destVolume = (VolumeObjectTO) cmd.getDestTO(); + final int wait = cmd.getWait(); + final DataStoreTO destStore = destVolume.getDataStore(); if (destStore instanceof NfsTO) { SR secondaryStorage = null; try { - NfsTO nfsStore = (NfsTO) destStore; - URI uri = new URI(nfsStore.getUrl()); + final NfsTO nfsStore = (NfsTO) destStore; + final URI uri = new URI(nfsStore.getUrl()); // Create the volume folder if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) { throw new InternalErrorException("Failed to create the volume folder."); @@ -1010,16 +1010,16 @@ public class XenServerStorageProcessor implements StorageProcessor { // Create a SR for the volume UUID folder secondaryStorage = hypervisorResource.createNfsSRbyURI(conn, new URI(nfsStore.getUrl() + nfsStore.getPathSeparator() + destVolume.getPath()), false); // Look up the volume on the source primary storage pool - VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath()); + final VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath()); // Copy the volume to secondary storage - VDI destVdi = hypervisorResource.cloudVDIcopy(conn, srcVdi, secondaryStorage, wait); - String destVolumeUUID = destVdi.getUuid(conn); + final VDI destVdi = hypervisorResource.cloudVDIcopy(conn, srcVdi, secondaryStorage, wait); + final String destVolumeUUID = destVdi.getUuid(conn); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setPath(destVolume.getPath() + nfsStore.getPathSeparator() + destVolumeUUID + ".vhd"); newVol.setSize(srcVolume.getSize()); return new CopyCmdAnswer(newVol); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to copy volume to secondary: " + e.toString()); return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString()); } finally { @@ -1029,7 +1029,7 @@ public class XenServerStorageProcessor implements StorageProcessor { return new CopyCmdAnswer("unsupported protocol"); } - boolean swiftUpload(Connection conn, SwiftTO swift, String container, String ldir, String lfilename, Boolean isISCSI, int wait) { + boolean swiftUpload(final Connection conn, final SwiftTO swift, final String container, final String ldir, final String lfilename, final Boolean isISCSI, final int wait) { String result = null; try { result = @@ -1038,23 +1038,23 @@ public class XenServerStorageProcessor implements StorageProcessor { if (result != null && result.equals("true")) { return true; } - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("swift upload failed due to " + e.toString(), e); } return false; } - protected String deleteSnapshotBackup(Connection conn, String localMountPoint, String path, String secondaryStorageMountPath, String backupUUID) { + protected String deleteSnapshotBackup(final Connection conn, final String localMountPoint, final String path, final String secondaryStorageMountPath, final String backupUUID) { // If anybody modifies the formatting below again, I'll skin them - String result = + final String result = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath, "localMountPoint", localMountPoint); return result; } - public String swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) { + public String swiftBackupSnapshot(final Connection conn, final SwiftTO swift, final String srUuid, final String snapshotUuid, final String container, final Boolean isISCSI, final int wait) { String lfilename; String ldir; if (isISCSI) { @@ -1069,7 +1069,7 @@ public class XenServerStorageProcessor implements StorageProcessor { } protected String backupSnapshotToS3(final Connection connection, final S3TO s3, final String srUuid, final String folder, final String snapshotUuid, - final Boolean iSCSIFlag, final int wait) { + final Boolean iSCSIFlag, final int wait) { final String filename = iSCSIFlag ? "VHD-" + snapshotUuid : snapshotUuid + ".vhd"; final String dir = (iSCSIFlag ? "/dev/VG_XenStorage-" : "/var/run/sr-mount/") + srUuid; @@ -1090,7 +1090,7 @@ public class XenServerStorageProcessor implements StorageProcessor { } return null; - } catch (Exception e) { + } catch (final Exception e) { s_logger.error(String.format("S3 upload failed of snapshot %1$s due to %2$s.", snapshotUuid, e.toString()), e); } @@ -1098,8 +1098,8 @@ public class XenServerStorageProcessor implements StorageProcessor { } - protected Long getSnapshotSize(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI, int wait) { - String physicalSize = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "getSnapshotSize", wait, + protected Long getSnapshotSize(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI, final int wait) { + final String physicalSize = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "getSnapshotSize", wait, "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString()); if (physicalSize == null || physicalSize.isEmpty()) { return (long) 0; @@ -1108,8 +1108,8 @@ public class XenServerStorageProcessor implements StorageProcessor { } } - protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, String localMountPoint, String path, String secondaryStorageMountPath, - String snapshotUuid, String prevBackupUuid, Boolean isISCSI, int wait) { + protected String backupSnapshot(final Connection conn, final String primaryStorageSRUuid, final String localMountPoint, final String path, final String secondaryStorageMountPath, + final String snapshotUuid, String prevBackupUuid, final Boolean isISCSI, final int wait) { String backupSnapshotUuid = null; if (prevBackupUuid == null) { @@ -1118,8 +1118,8 @@ public class XenServerStorageProcessor implements StorageProcessor { // Each argument is put in a separate line for readability. // Using more lines does not harm the environment. - String backupUuid = UUID.randomUUID().toString(); - String results = + final String backupUuid = UUID.randomUUID().toString(); + final String results = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "backupSnapshot", wait, "primaryStorageSRUuid", primaryStorageSRUuid, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath, "snapshotUuid", snapshotUuid, "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, "isISCSI", isISCSI.toString(), "localMountPoint", localMountPoint); @@ -1130,8 +1130,8 @@ public class XenServerStorageProcessor implements StorageProcessor { secondaryStorageMountPath + " due to null"; } else { - String[] tmp = results.split("#"); - String status = tmp[0]; + final String[] tmp = results.split("#"); + final String status = tmp[0]; backupSnapshotUuid = tmp[1]; // status == "1" if and only if backupSnapshotUuid != null // So we don't rely on status value but return backupSnapshotUuid as an @@ -1145,45 +1145,45 @@ public class XenServerStorageProcessor implements StorageProcessor { secondaryStorageMountPath + " due to " + tmp[1]; } } - String source = backupUuid + ".vhd"; + final String source = backupUuid + ".vhd"; hypervisorResource.killCopyProcess(conn, source); s_logger.warn(errMsg); throw new CloudRuntimeException(errMsg); } - protected boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid) { + protected boolean destroySnapshotOnPrimaryStorageExceptThis(final Connection conn, final String volumeUuid, final String avoidSnapshotUuid) { try { - VDI volume = getVDIbyUuid(conn, volumeUuid); + final VDI volume = getVDIbyUuid(conn, volumeUuid); if (volume == null) { throw new InternalErrorException("Could not destroy snapshot on volume " + volumeUuid + " due to can not find it"); } - Set snapshots = volume.getSnapshots(conn); - for (VDI snapshot : snapshots) { + final Set snapshots = volume.getSnapshots(conn); + for (final VDI snapshot : snapshots) { try { if (!snapshot.getUuid(conn).equals(avoidSnapshotUuid)) { snapshot.destroy(conn); } - } catch (Exception e) { - String msg = "Destroying snapshot: " + snapshot + " on primary storage failed due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Destroying snapshot: " + snapshot + " on primary storage failed due to " + e.toString(); s_logger.warn(msg, e); } } s_logger.debug("Successfully destroyed snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid); return true; - } catch (XenAPIException e) { - String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); + } catch (final XenAPIException e) { + final String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); s_logger.error(msg, e); - } catch (Exception e) { - String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); s_logger.warn(msg, e); } return false; } - private boolean destroySnapshotOnPrimaryStorage(Connection conn, String lastSnapshotUuid) { + private boolean destroySnapshotOnPrimaryStorage(final Connection conn, final String lastSnapshotUuid) { try { - VDI snapshot = getVDIbyUuid(conn, lastSnapshotUuid); + final VDI snapshot = getVDIbyUuid(conn, lastSnapshotUuid); if (snapshot == null) { // since this is just used to cleanup leftover bad snapshots, no need to throw exception s_logger.warn("Could not destroy snapshot " + lastSnapshotUuid + " due to can not find it"); @@ -1191,24 +1191,24 @@ public class XenServerStorageProcessor implements StorageProcessor { } snapshot.destroy(conn); return true; - } catch (XenAPIException e) { - String msg = "Destroying snapshot: " + lastSnapshotUuid + " failed due to " + e.toString(); + } catch (final XenAPIException e) { + final String msg = "Destroying snapshot: " + lastSnapshotUuid + " failed due to " + e.toString(); s_logger.error(msg, e); - } catch (Exception e) { - String msg = "Destroying snapshot: " + lastSnapshotUuid + " failed due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Destroying snapshot: " + lastSnapshotUuid + " failed due to " + e.toString(); s_logger.warn(msg, e); } return false; } @Override - public Answer backupSnapshot(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - DataTO srcData = cmd.getSrcTO(); - DataTO cacheData = cmd.getCacheTO(); - DataTO destData = cmd.getDestTO(); - int wait = cmd.getWait(); - String primaryStorageNameLabel = srcData.getDataStore().getUuid(); + public Answer backupSnapshot(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final DataTO srcData = cmd.getSrcTO(); + final DataTO cacheData = cmd.getCacheTO(); + final DataTO destData = cmd.getDestTO(); + final int wait = cmd.getWait(); + final String primaryStorageNameLabel = srcData.getDataStore().getUuid(); String secondaryStorageUrl = null; NfsTO cacheStore = null; String destPath = null; @@ -1222,58 +1222,58 @@ public class XenServerStorageProcessor implements StorageProcessor { destPath = destData.getPath(); } - SnapshotObjectTO snapshotTO = (SnapshotObjectTO) srcData; - SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO) destData; - String snapshotUuid = snapshotTO.getPath(); - String volumeUuid = snapshotTO.getVolume().getPath(); + final SnapshotObjectTO snapshotTO = (SnapshotObjectTO) srcData; + final SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO) destData; + final String snapshotUuid = snapshotTO.getPath(); + final String volumeUuid = snapshotTO.getVolume().getPath(); - String prevBackupUuid = snapshotOnImage.getParentSnapshotPath(); - String prevSnapshotUuid = snapshotTO.getParentSnapshotPath(); + final String prevBackupUuid = snapshotOnImage.getParentSnapshotPath(); + final String prevSnapshotUuid = snapshotTO.getParentSnapshotPath(); // By default assume failure String details = null; String snapshotBackupUuid = null; Long physicalSize = null; - Map options = cmd.getOptions(); + final Map options = cmd.getOptions(); boolean fullbackup = Boolean.parseBoolean(options.get("fullSnapshot")); boolean result = false; try { - SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + final SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); if (primaryStorageSR == null) { throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel); } - String psUuid = primaryStorageSR.getUuid(conn); - Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn)); + final String psUuid = primaryStorageSR.getUuid(conn); + final Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn)); - VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid); + final VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid); String snapshotPaUuid = null; if (prevSnapshotUuid != null && !fullbackup) { try { snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI); if (snapshotPaUuid != null) { - String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI); - String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI); + final String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI); + final String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI); if (snashotPaPaPaUuid != null && prevSnashotPaUuid != null && prevSnashotPaUuid.equals(snashotPaPaPaUuid)) { fullbackup = false; } else { fullbackup = true; } } - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to get parent snapshots, take full snapshot", e); fullbackup = true; } } - URI uri = new URI(secondaryStorageUrl); - String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); - DataStoreTO destStore = destData.getDataStore(); - String folder = destPath; + final URI uri = new URI(secondaryStorageUrl); + final String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + final DataStoreTO destStore = destData.getDataStore(); + final String folder = destPath; String finalPath = null; - String localMountPoint = BaseMountPointOnHost + File.separator + UUID.nameUUIDFromBytes(secondaryStorageUrl.getBytes()).toString(); + final String localMountPoint = BaseMountPointOnHost + File.separator + UUID.nameUUIDFromBytes(secondaryStorageUrl.getBytes()).toString(); if (fullbackup) { // the first snapshot is always a full snapshot @@ -1282,25 +1282,25 @@ public class XenServerStorageProcessor implements StorageProcessor { s_logger.warn(details); return new CopyCmdAnswer(details); } - String snapshotMountpoint = secondaryStorageUrl + "/" + folder; + final String snapshotMountpoint = secondaryStorageUrl + "/" + folder; SR snapshotSr = null; try { snapshotSr = hypervisorResource.createNfsSRbyURI(conn, new URI(snapshotMountpoint), false); - VDI backedVdi = hypervisorResource.cloudVDIcopy(conn, snapshotVdi, snapshotSr, wait); + final VDI backedVdi = hypervisorResource.cloudVDIcopy(conn, snapshotVdi, snapshotSr, wait); snapshotBackupUuid = backedVdi.getUuid(conn); - String primarySRuuid = snapshotSr.getUuid(conn); + final String primarySRuuid = snapshotSr.getUuid(conn); physicalSize = getSnapshotSize(conn, primarySRuuid, snapshotBackupUuid, isISCSI, wait); if (destStore instanceof SwiftTO) { try { - String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); - String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO) destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait); - String swiftPath = container + File.separator + destSnapshotName; + final String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); + final String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO) destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait); + final String swiftPath = container + File.separator + destSnapshotName; finalPath = swiftPath; } finally { try { deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to delete snapshot on cache storages", e); } } @@ -1314,7 +1314,7 @@ public class XenServerStorageProcessor implements StorageProcessor { } finally { try { deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to delete snapshot on cache storages", e); } } @@ -1329,9 +1329,9 @@ public class XenServerStorageProcessor implements StorageProcessor { } } } else { - String primaryStorageSRUuid = primaryStorageSR.getUuid(conn); + final String primaryStorageSRUuid = primaryStorageSR.getUuid(conn); if (destStore instanceof SwiftTO) { - String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); + final String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); snapshotBackupUuid = swiftBackupSnapshot(conn, (SwiftTO) destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait); @@ -1342,10 +1342,10 @@ public class XenServerStorageProcessor implements StorageProcessor { throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed"); } } else { - String results = + final String results = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait); - String[] tmp = results.split("#"); + final String[] tmp = results.split("#"); snapshotBackupUuid = tmp[1]; physicalSize = Long.parseLong(tmp[2]); finalPath = folder + cacheStore.getPathSeparator() + snapshotBackupUuid; @@ -1354,7 +1354,7 @@ public class XenServerStorageProcessor implements StorageProcessor { // delete primary snapshots with only the last one left destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid); - SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + final SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); newSnapshot.setPath(finalPath); newSnapshot.setPhysicalSize(physicalSize); if (fullbackup) { @@ -1364,10 +1364,10 @@ public class XenServerStorageProcessor implements StorageProcessor { } result = true; return new CopyCmdAnswer(newSnapshot); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { details = "BackupSnapshot Failed due to " + e.toString(); s_logger.warn(details, e); - } catch (Exception e) { + } catch (final Exception e) { details = "BackupSnapshot Failed due to " + e.getMessage(); s_logger.warn(details, e); } finally { @@ -1375,7 +1375,7 @@ public class XenServerStorageProcessor implements StorageProcessor { // remove last bad primary snapshot when exception happens try { destroySnapshotOnPrimaryStorage(conn, snapshotUuid); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("clean up snapshot failed", e); } } @@ -1385,17 +1385,17 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer createTemplateFromVolume(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - VolumeObjectTO volume = (VolumeObjectTO) cmd.getSrcTO(); - TemplateObjectTO template = (TemplateObjectTO) cmd.getDestTO(); - NfsTO destStore = (NfsTO) cmd.getDestTO().getDataStore(); - int wait = cmd.getWait(); + public Answer createTemplateFromVolume(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final VolumeObjectTO volume = (VolumeObjectTO) cmd.getSrcTO(); + final TemplateObjectTO template = (TemplateObjectTO) cmd.getDestTO(); + final NfsTO destStore = (NfsTO) cmd.getDestTO().getDataStore(); + final int wait = cmd.getWait(); - String secondaryStoragePoolURL = destStore.getUrl(); - String volumeUUID = volume.getPath(); + final String secondaryStoragePoolURL = destStore.getUrl(); + final String volumeUUID = volume.getPath(); - String userSpecifiedName = template.getName(); + final String userSpecifiedName = template.getName(); String details = null; SR tmpltSR = null; @@ -1403,7 +1403,7 @@ public class XenServerStorageProcessor implements StorageProcessor { String secondaryStorageMountPath = null; String installPath = null; try { - URI uri = new URI(secondaryStoragePoolURL); + final URI uri = new URI(secondaryStoragePoolURL); secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); installPath = template.getPath(); if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) { @@ -1412,25 +1412,25 @@ public class XenServerStorageProcessor implements StorageProcessor { return new CopyCmdAnswer(details); } - VDI vol = getVDIbyUuid(conn, volumeUUID); + final VDI vol = getVDIbyUuid(conn, volumeUUID); // create template SR - URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath); + final URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath); tmpltSR = hypervisorResource.createNfsSRbyURI(conn, tmpltURI, false); // copy volume to template SR - VDI tmpltVDI = hypervisorResource.cloudVDIcopy(conn, vol, tmpltSR, wait); + final VDI tmpltVDI = hypervisorResource.cloudVDIcopy(conn, vol, tmpltSR, wait); // scan makes XenServer pick up VDI physicalSize tmpltSR.scan(conn); if (userSpecifiedName != null) { tmpltVDI.setNameLabel(conn, userSpecifiedName); } - String tmpltUUID = tmpltVDI.getUuid(conn); - String tmpltFilename = tmpltUUID + ".vhd"; - long virtualSize = tmpltVDI.getVirtualSize(conn); - long physicalSize = tmpltVDI.getPhysicalUtilisation(conn); + final String tmpltUUID = tmpltVDI.getUuid(conn); + final String tmpltFilename = tmpltUUID + ".vhd"; + final long virtualSize = tmpltVDI.getVirtualSize(conn); + final long physicalSize = tmpltVDI.getPhysicalUtilisation(conn); // create the template.properties file - String templatePath = secondaryStorageMountPath + "/" + installPath; + final String templatePath = secondaryStorageMountPath + "/" + installPath; result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId()); @@ -1440,15 +1440,15 @@ public class XenServerStorageProcessor implements StorageProcessor { installPath = installPath + "/" + tmpltFilename; hypervisorResource.removeSR(conn, tmpltSR); tmpltSR = null; - TemplateObjectTO newTemplate = new TemplateObjectTO(); + final TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(installPath); newTemplate.setFormat(ImageFormat.VHD); newTemplate.setSize(virtualSize); newTemplate.setPhysicalSize(physicalSize); newTemplate.setName(tmpltUUID); - CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); + final CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); return answer; - } catch (Exception e) { + } catch (final Exception e) { if (tmpltSR != null) { hypervisorResource.removeSR(conn, tmpltSR); } @@ -1462,17 +1462,17 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer createTemplateFromSnapshot(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); + public Answer createTemplateFromSnapshot(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); - SnapshotObjectTO snapshotObjTO = (SnapshotObjectTO)cmd.getSrcTO(); - TemplateObjectTO templateObjTO = (TemplateObjectTO)cmd.getDestTO(); + final SnapshotObjectTO snapshotObjTO = (SnapshotObjectTO)cmd.getSrcTO(); + final TemplateObjectTO templateObjTO = (TemplateObjectTO)cmd.getDestTO(); if (!(snapshotObjTO.getDataStore() instanceof PrimaryDataStoreTO) || !(templateObjTO.getDataStore() instanceof NfsTO)) { return null; } - String userSpecifiedTemplateName = templateObjTO.getName(); + final String userSpecifiedTemplateName = templateObjTO.getName(); NfsTO destStore = null; URI destUri = null; @@ -1481,7 +1481,7 @@ public class XenServerStorageProcessor implements StorageProcessor { destStore = (NfsTO)templateObjTO.getDataStore(); destUri = new URI(destStore.getUrl()); - } catch (Exception ex) { + } catch (final Exception ex) { s_logger.debug("Invalid URI", ex); return new CopyCmdAnswer("Invalid URI: " + ex.toString()); @@ -1490,37 +1490,37 @@ public class XenServerStorageProcessor implements StorageProcessor { SR srcSr = null; SR destSr = null; - String destDir = templateObjTO.getPath(); + final String destDir = templateObjTO.getPath(); VDI destVdi = null; boolean result = false; try { - Map srcDetails = cmd.getOptions(); + final Map srcDetails = cmd.getOptions(); - String iScsiName = srcDetails.get(DiskTO.IQN); - String storageHost = srcDetails.get(DiskTO.STORAGE_HOST); - String chapInitiatorUsername = srcDetails.get(DiskTO.CHAP_INITIATOR_USERNAME); - String chapInitiatorSecret = srcDetails.get(DiskTO.CHAP_INITIATOR_SECRET); + final String iScsiName = srcDetails.get(DiskTO.IQN); + final String storageHost = srcDetails.get(DiskTO.STORAGE_HOST); + final String chapInitiatorUsername = srcDetails.get(DiskTO.CHAP_INITIATOR_USERNAME); + final String chapInitiatorSecret = srcDetails.get(DiskTO.CHAP_INITIATOR_SECRET); srcSr = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true); - String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); + final String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); if (!hypervisorResource.createSecondaryStorageFolder(conn, destNfsPath, destDir)) { - String details = " Failed to create folder " + destDir + " in secondary storage"; + final String details = " Failed to create folder " + destDir + " in secondary storage"; s_logger.warn(details); return new CopyCmdAnswer(details); } - URI templateUri = new URI(destStore.getUrl() + "/" + destDir); + final URI templateUri = new URI(destStore.getUrl() + "/" + destDir); destSr = hypervisorResource.createNfsSRbyURI(conn, templateUri, false); // there should only be one VDI in this SR - VDI srcVdi = srcSr.getVDIs(conn).iterator().next(); + final VDI srcVdi = srcSr.getVDIs(conn).iterator().next(); destVdi = srcVdi.copy(conn, destSr); @@ -1531,10 +1531,10 @@ public class XenServerStorageProcessor implements StorageProcessor { destVdi.setNameLabel(conn, userSpecifiedTemplateName); } - String templateUuid = destVdi.getUuid(conn); - String templateFilename = templateUuid + ".vhd"; - long virtualSize = destVdi.getVirtualSize(conn); - long physicalSize = destVdi.getPhysicalUtilisation(conn); + final String templateUuid = destVdi.getUuid(conn); + final String templateFilename = templateUuid + ".vhd"; + final long virtualSize = destVdi.getVirtualSize(conn); + final long physicalSize = destVdi.getPhysicalUtilisation(conn); // create the template.properties file String templatePath = destNfsPath + "/" + destDir; @@ -1548,7 +1548,7 @@ public class XenServerStorageProcessor implements StorageProcessor { throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + templateUri); } - TemplateObjectTO newTemplate = new TemplateObjectTO(); + final TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(destDir + "/" + templateFilename); newTemplate.setFormat(Storage.ImageFormat.VHD); @@ -1560,7 +1560,7 @@ public class XenServerStorageProcessor implements StorageProcessor { result = true; return new CopyCmdAnswer(newTemplate); - } catch (Exception ex) { + } catch (final Exception ex) { s_logger.error("Failed to create a template from a snapshot", ex); return new CopyCmdAnswer("Failed to create a template from a snapshot: " + ex.toString()); @@ -1569,7 +1569,7 @@ public class XenServerStorageProcessor implements StorageProcessor { if (destVdi != null) { try { destVdi.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Cleaned up leftover VDI on destination storage due to failure: ", e); } } @@ -1586,12 +1586,12 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer createVolumeFromSnapshot(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - DataTO srcData = cmd.getSrcTO(); - SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData; - DataTO destData = cmd.getDestTO(); - DataStoreTO imageStore = srcData.getDataStore(); + public Answer createVolumeFromSnapshot(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final DataTO srcData = cmd.getSrcTO(); + final SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData; + final DataTO destData = cmd.getDestTO(); + final DataStoreTO imageStore = srcData.getDataStore(); if (srcData.getDataStore() instanceof PrimaryDataStoreTO && destData.getDataStore() instanceof PrimaryDataStoreTO) { return createVolumeFromSnapshot2(cmd); @@ -1601,10 +1601,10 @@ public class XenServerStorageProcessor implements StorageProcessor { return new CopyCmdAnswer("unsupported protocol"); } - NfsTO nfsImageStore = (NfsTO) imageStore; - String primaryStorageNameLabel = destData.getDataStore().getUuid(); - String secondaryStorageUrl = nfsImageStore.getUrl(); - int wait = cmd.getWait(); + final NfsTO nfsImageStore = (NfsTO) imageStore; + final String primaryStorageNameLabel = destData.getDataStore().getUuid(); + final String secondaryStorageUrl = nfsImageStore.getUrl(); + final int wait = cmd.getWait(); boolean result = false; // Generic error message. String details = null; @@ -1615,34 +1615,34 @@ public class XenServerStorageProcessor implements StorageProcessor { return new CopyCmdAnswer(details); } try { - SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + final SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); if (primaryStorageSR == null) { throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel); } // Get the absolute path of the snapshot on the secondary storage. String snapshotInstallPath = snapshot.getPath(); - int index = snapshotInstallPath.lastIndexOf(nfsImageStore.getPathSeparator()); - String snapshotName = snapshotInstallPath.substring(index + 1); + final int index = snapshotInstallPath.lastIndexOf(nfsImageStore.getPathSeparator()); + final String snapshotName = snapshotInstallPath.substring(index + 1); if (!snapshotName.startsWith("VHD-") && !snapshotName.endsWith(".vhd")) { snapshotInstallPath = snapshotInstallPath + ".vhd"; } - URI snapshotURI = new URI(secondaryStorageUrl + nfsImageStore.getPathSeparator() + snapshotInstallPath); - String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath(); - String srUuid = primaryStorageSR.getUuid(conn); + final URI snapshotURI = new URI(secondaryStorageUrl + nfsImageStore.getPathSeparator() + snapshotInstallPath); + final String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath(); + final String srUuid = primaryStorageSR.getUuid(conn); volumeUUID = copy_vhd_from_secondarystorage(conn, snapshotPath, srUuid, wait); result = true; - VDI volume = VDI.getByUuid(conn, volumeUUID); - VDI.Record vdir = volume.getRecord(conn); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VDI volume = VDI.getByUuid(conn, volumeUUID); + final VDI.Record vdir = volume.getRecord(conn); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setPath(volumeUUID); newVol.setSize(vdir.virtualSize); return new CopyCmdAnswer(newVol); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { details += " due to " + e.toString(); s_logger.warn(details, e); - } catch (Exception e) { + } catch (final Exception e) { details += " due to " + e.getMessage(); s_logger.warn(details, e); } @@ -1655,34 +1655,34 @@ public class XenServerStorageProcessor implements StorageProcessor { return new CopyCmdAnswer(details); } - protected Answer createVolumeFromSnapshot2(CopyCommand cmd) { + protected Answer createVolumeFromSnapshot2(final CopyCommand cmd) { try { - Connection conn = hypervisorResource.getConnection(); + final Connection conn = hypervisorResource.getConnection(); - Map srcOptions = cmd.getOptions(); + final Map srcOptions = cmd.getOptions(); - String src_iScsiName = srcOptions.get(DiskTO.IQN); - String srcStorageHost = srcOptions.get(DiskTO.STORAGE_HOST); - String srcChapInitiatorUsername = srcOptions.get(DiskTO.CHAP_INITIATOR_USERNAME); - String srcChapInitiatorSecret = srcOptions.get(DiskTO.CHAP_INITIATOR_SECRET); + final String src_iScsiName = srcOptions.get(DiskTO.IQN); + final String srcStorageHost = srcOptions.get(DiskTO.STORAGE_HOST); + final String srcChapInitiatorUsername = srcOptions.get(DiskTO.CHAP_INITIATOR_USERNAME); + final String srcChapInitiatorSecret = srcOptions.get(DiskTO.CHAP_INITIATOR_SECRET); - SR srcSr = hypervisorResource.getIscsiSR(conn, src_iScsiName, srcStorageHost, src_iScsiName, srcChapInitiatorUsername, srcChapInitiatorSecret, false); + final SR srcSr = hypervisorResource.getIscsiSR(conn, src_iScsiName, srcStorageHost, src_iScsiName, srcChapInitiatorUsername, srcChapInitiatorSecret, false); - Map destOptions = cmd.getOptions2(); + final Map destOptions = cmd.getOptions2(); - String dest_iScsiName = destOptions.get(DiskTO.IQN); - String destStorageHost = destOptions.get(DiskTO.STORAGE_HOST); - String destChapInitiatorUsername = destOptions.get(DiskTO.CHAP_INITIATOR_USERNAME); - String destChapInitiatorSecret = destOptions.get(DiskTO.CHAP_INITIATOR_SECRET); + final String dest_iScsiName = destOptions.get(DiskTO.IQN); + final String destStorageHost = destOptions.get(DiskTO.STORAGE_HOST); + final String destChapInitiatorUsername = destOptions.get(DiskTO.CHAP_INITIATOR_USERNAME); + final String destChapInitiatorSecret = destOptions.get(DiskTO.CHAP_INITIATOR_SECRET); - SR destSr = hypervisorResource.getIscsiSR(conn, dest_iScsiName, destStorageHost, dest_iScsiName, destChapInitiatorUsername, destChapInitiatorSecret, false); + final SR destSr = hypervisorResource.getIscsiSR(conn, dest_iScsiName, destStorageHost, dest_iScsiName, destChapInitiatorUsername, destChapInitiatorSecret, false); // there should only be one VDI in this SR - VDI srcVdi = srcSr.getVDIs(conn).iterator().next(); + final VDI srcVdi = srcSr.getVDIs(conn).iterator().next(); - VDI vdiCopy = srcVdi.copy(conn, destSr); + final VDI vdiCopy = srcVdi.copy(conn, destSr); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setSize(vdiCopy.getVirtualSize(conn)); newVol.setPath(vdiCopy.getUuid(conn)); @@ -1693,7 +1693,7 @@ public class XenServerStorageProcessor implements StorageProcessor { return new CopyCmdAnswer(newVol); } - catch (Exception ex) { + catch (final Exception ex) { s_logger.warn("Failed to copy snapshot to volume: " + ex.toString(), ex); return new CopyCmdAnswer(ex.getMessage()); @@ -1701,25 +1701,25 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer deleteSnapshot(DeleteCommand cmd) { - SnapshotObjectTO snapshot = (SnapshotObjectTO) cmd.getData(); - DataStoreTO store = snapshot.getDataStore(); + public Answer deleteSnapshot(final DeleteCommand cmd) { + final SnapshotObjectTO snapshot = (SnapshotObjectTO) cmd.getData(); + final DataStoreTO store = snapshot.getDataStore(); if (store.getRole() == DataStoreRole.Primary) { - Connection conn = hypervisorResource.getConnection(); - VDI snapshotVdi = getVDIbyUuid(conn, snapshot.getPath()); + final Connection conn = hypervisorResource.getConnection(); + final VDI snapshotVdi = getVDIbyUuid(conn, snapshot.getPath()); if (snapshotVdi == null) { return new Answer(null); } String errMsg = null; try { deleteVDI(conn, snapshotVdi); - } catch (BadServerResponse e) { + } catch (final BadServerResponse e) { s_logger.debug("delete snapshot failed:" + e.toString()); errMsg = e.toString(); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { s_logger.debug("delete snapshot failed:" + e.toString()); errMsg = e.toString(); - } catch (XmlRpcException e) { + } catch (final XmlRpcException e) { s_logger.debug("delete snapshot failed:" + e.toString()); errMsg = e.toString(); } @@ -1729,28 +1729,28 @@ public class XenServerStorageProcessor implements StorageProcessor { } @Override - public Answer introduceObject(IntroduceObjectCmd cmd) { + public Answer introduceObject(final IntroduceObjectCmd cmd) { try { - Connection conn = hypervisorResource.getConnection(); - DataStoreTO store = cmd.getDataTO().getDataStore(); - SR poolSr = hypervisorResource.getStorageRepository(conn, store.getUuid()); + final Connection conn = hypervisorResource.getConnection(); + final DataStoreTO store = cmd.getDataTO().getDataStore(); + final SR poolSr = hypervisorResource.getStorageRepository(conn, store.getUuid()); poolSr.scan(conn); return new IntroduceObjectAnswer(cmd.getDataTO()); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to introduce object", e); return new Answer(cmd, false, e.toString()); } } @Override - public Answer forgetObject(ForgetObjectCmd cmd) { + public Answer forgetObject(final ForgetObjectCmd cmd) { try { - Connection conn = hypervisorResource.getConnection(); - DataTO data = cmd.getDataTO(); - VDI vdi = VDI.getByUuid(conn, data.getPath()); + final Connection conn = hypervisorResource.getConnection(); + final DataTO data = cmd.getDataTO(); + final VDI vdi = VDI.getByUuid(conn, data.getPath()); vdi.forget(conn); return new IntroduceObjectAnswer(cmd.getDataTO()); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to introduce object", e); return new Answer(cmd, false, e.toString()); } 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 c10844e0f67..a01e1927d1d 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 @@ -24,22 +24,20 @@ import java.util.List; import javax.ejb.Local; +import org.apache.cloudstack.hypervisor.xenserver.XenServerResourceNewBase; 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; -import com.xensource.xenapi.VM; - -import org.apache.cloudstack.hypervisor.xenserver.XenServerResourceNewBase; - import com.cloud.resource.ServerResource; import com.cloud.storage.resource.StorageSubsystemCommandHandler; import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SSHCmdHelper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VM; @Local(value=ServerResource.class) public class Xenserver625Resource extends XenServerResourceNewBase { @@ -51,49 +49,48 @@ public class Xenserver625Resource extends XenServerResourceNewBase { @Override protected List getPatchFiles() { - List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xenserver62/patch"; - String patchfilePath = Script.findScript("", patch); + final List files = new ArrayList(); + final String patch = "scripts/vm/hypervisor/xenserver/xenserver62/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 StorageSubsystemCommandHandler getStorageHandler() { - XenServerStorageProcessor processor = new Xenserver625StorageProcessor(this); + final XenServerStorageProcessor processor = new Xenserver625StorageProcessor(this); return new StorageSubsystemCommandHandlerBase(processor); } @Override - protected void umountSnapshotDir(Connection conn, Long dcId) { - + public void umountSnapshotDir(final Connection conn, final Long dcId) { } @Override - protected boolean setupServer(Connection conn,Host host) { - com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.ip, 22); + protected boolean setupServer(final Connection conn,final Host host) { + final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); try { sshConnection.connect(null, 60000, 60000); if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { throw new CloudRuntimeException("Unable to authenticate"); } - String cmd = "rm -f /opt/xensource/sm/hostvmstats.py " + - "/opt/xensource/bin/copy_vhd_to_secondarystorage.sh " + - "/opt/xensource/bin/copy_vhd_from_secondarystorage.sh " + - "/opt/xensource/bin/create_privatetemplate_from_snapshot.sh " + - "/opt/xensource/bin/vhd-util " + - "/opt/cloud/bin/copy_vhd_to_secondarystorage.sh " + - "/opt/cloud/bin/copy_vhd_from_secondarystorage.sh " + - "/opt/cloud/bin/create_privatetemplate_from_snapshot.sh " + - "/opt/cloud/bin/vhd-util"; + final String cmd = "rm -f /opt/xensource/sm/hostvmstats.py " + + "/opt/xensource/bin/copy_vhd_to_secondarystorage.sh " + + "/opt/xensource/bin/copy_vhd_from_secondarystorage.sh " + + "/opt/xensource/bin/create_privatetemplate_from_snapshot.sh " + + "/opt/xensource/bin/vhd-util " + + "/opt/cloud/bin/copy_vhd_to_secondarystorage.sh " + + "/opt/cloud/bin/copy_vhd_from_secondarystorage.sh " + + "/opt/cloud/bin/create_privatetemplate_from_snapshot.sh " + + "/opt/cloud/bin/vhd-util"; SSHCmdHelper.sshExecuteCmd(sshConnection, cmd); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Catch exception " + e.toString(), e); } finally { sshConnection.close(); @@ -102,11 +99,11 @@ public class Xenserver625Resource extends XenServerResourceNewBase { } @Override - protected String revertToSnapshot(Connection conn, VM vmSnapshot, - String vmName, String oldVmUuid, Boolean snapshotMemory, String hostUUID) - throws Types.XenAPIException, XmlRpcException { + protected String revertToSnapshot(final Connection conn, final VM vmSnapshot, + final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) + throws Types.XenAPIException, XmlRpcException { - String results = callHostPluginAsync(conn, "vmopsSnapshot", + final String results = callHostPluginAsync(conn, "vmopsSnapshot", "revert_memory_snapshot", 10 * 60 * 1000, "snapshotUUID", vmSnapshot.getUuid(conn), "vmName", vmName, "oldVmUuid", oldVmUuid, "snapshotMemory", snapshotMemory.toString(), "hostUUID", hostUUID); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java index c4f2dc916ea..37c311a6759 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java @@ -62,20 +62,20 @@ import com.xensource.xenapi.VDI; public class Xenserver625StorageProcessor extends XenServerStorageProcessor { private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class); - public Xenserver625StorageProcessor(CitrixResourceBase resource) { + public Xenserver625StorageProcessor(final CitrixResourceBase resource) { super(resource); } - protected boolean mountNfs(Connection conn, String remoteDir, String localDir) { + protected boolean mountNfs(final Connection conn, final String remoteDir, String localDir) { if (localDir == null) { localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remoteDir.getBytes()); } - String results = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000, - "localDir", localDir, "remoteDir", remoteDir); + final String results = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000, "localDir", localDir, "remoteDir", + remoteDir); if (results == null || results.isEmpty()) { - String errMsg = "Could not mount secondary storage " + remoteDir + " on host " + localDir; + final String errMsg = "Could not mount secondary storage " + remoteDir + " on host " + localDir; s_logger.warn(errMsg); @@ -85,8 +85,8 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { return true; } - protected boolean makeDirectory(Connection conn, String path) { - String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "makeDirectory", "path", path); + protected boolean makeDirectory(final Connection conn, final String path) { + final String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "makeDirectory", "path", path); if (result == null || result.isEmpty()) { return false; @@ -95,27 +95,27 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { return true; } - protected SR createFileSR(Connection conn, String path) { + protected SR createFileSR(final Connection conn, final String path) { SR sr = null; PBD pbd = null; try { - String srname = hypervisorResource.getHost().uuid + path.trim(); + final String srname = hypervisorResource.getHost().getUuid() + path.trim(); - Set srs = SR.getByNameLabel(conn, srname); + final Set srs = SR.getByNameLabel(conn, srname); if (srs != null && !srs.isEmpty()) { return srs.iterator().next(); } - Map smConfig = new HashMap(); + final Map smConfig = new HashMap(); - Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid); - String uuid = UUID.randomUUID().toString(); + final Host host = Host.getByUuid(conn, hypervisorResource.getHost().getUuid()); + final String uuid = UUID.randomUUID().toString(); sr = SR.introduce(conn, uuid, srname, srname, "file", "file", false, smConfig); - PBD.Record record = new PBD.Record(); + final PBD.Record record = new PBD.Record(); record.host = host; record.SR = sr; @@ -131,12 +131,12 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { sr.scan(conn); return sr; - } catch (Exception ex) { + } catch (final Exception ex) { try { if (pbd != null) { pbd.destroy(conn); } - } catch (Exception e1) { + } catch (final Exception e1) { s_logger.debug("Failed to destroy PBD", ex); } @@ -144,11 +144,11 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (sr != null) { sr.forget(conn); } - } catch (Exception e2) { + } catch (final Exception e2) { s_logger.error("Failed to forget SR", ex); } - String msg = "createFileSR failed! due to the following: " + ex.toString(); + final String msg = "createFileSR failed! due to the following: " + ex.toString(); s_logger.warn(msg, ex); @@ -156,52 +156,52 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } } - protected SR createFileSr(Connection conn, String remotePath, String dir) { - String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remotePath.getBytes()); + protected SR createFileSr(final Connection conn, final String remotePath, final String dir) { + final String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remotePath.getBytes()); mountNfs(conn, remotePath, localDir); - SR sr = createFileSR(conn, localDir + "/" + dir); + final SR sr = createFileSR(conn, localDir + "/" + dir); return sr; } @Override - public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) { - DataTO srcData = cmd.getSrcTO(); - DataTO destData = cmd.getDestTO(); - int wait = cmd.getWait(); - DataStoreTO srcStore = srcData.getDataStore(); - Connection conn = hypervisorResource.getConnection(); + public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) { + final DataTO srcData = cmd.getSrcTO(); + final DataTO destData = cmd.getDestTO(); + final int wait = cmd.getWait(); + final DataStoreTO srcStore = srcData.getDataStore(); + final Connection conn = hypervisorResource.getConnection(); SR srcSr = null; Task task = null; try { - if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) { - NfsTO srcImageStore = (NfsTO)srcStore; - TemplateObjectTO srcTemplate = (TemplateObjectTO)srcData; - String storeUrl = srcImageStore.getUrl(); - URI uri = new URI(storeUrl); + if (srcStore instanceof NfsTO && srcData.getObjectType() == DataObjectType.TEMPLATE) { + final NfsTO srcImageStore = (NfsTO) srcStore; + final TemplateObjectTO srcTemplate = (TemplateObjectTO) srcData; + final String storeUrl = srcImageStore.getUrl(); + final URI uri = new URI(storeUrl); String volumePath = srcData.getPath(); volumePath = StringUtils.stripEnd(volumePath, "/"); - String[] splits = volumePath.split("/"); + final String[] splits = volumePath.split("/"); String volumeDirectory = volumePath; if (splits.length > 4) { - //"template/tmpl/dcid/templateId/templatename" - int index = volumePath.lastIndexOf("/"); + // "template/tmpl/dcid/templateId/templatename" + final int index = volumePath.lastIndexOf("/"); volumeDirectory = volumePath.substring(0, index); } srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory); - Set setVdis = srcSr.getVDIs(conn); + final Set setVdis = srcSr.getVDIs(conn); if (setVdis.size() != 1) { return new CopyCmdAnswer("Can't find template VDI under: " + uri.getHost() + ":" + uri.getPath() + "/" + volumeDirectory); } - VDI srcVdi = setVdis.iterator().next(); + final VDI srcVdi = setVdis.iterator().next(); boolean managed = false; String storageHost = null; @@ -211,7 +211,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { String chapInitiatorUsername = null; String chapInitiatorSecret = null; - PrimaryDataStoreTO destStore = (PrimaryDataStoreTO)destData.getDataStore(); + final PrimaryDataStoreTO destStore = (PrimaryDataStoreTO) destData.getDataStore(); Map details = destStore.getDetails(); @@ -240,13 +240,12 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { details.put(DiskTO.CHAP_INITIATOR_SECRET, chapInitiatorSecret); destSr = hypervisorResource.prepareManagedSr(conn, details); - } - else { - String srName = destStore.getUuid(); - Set srs = SR.getByNameLabel(conn, srName); + } else { + final String srName = destStore.getUuid(); + final Set srs = SR.getByNameLabel(conn, srName); if (srs.size() != 1) { - String msg = "There are " + srs.size() + " SRs with same name: " + srName; + final String msg = "There are " + srs.size() + " SRs with same name: " + srName; s_logger.warn(msg); @@ -262,17 +261,17 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); hypervisorResource.checkForSuccess(conn, task); - VDI tmplVdi = Types.toVDI(task, conn); + final VDI tmplVdi = Types.toVDI(task, conn); final String uuidToReturn; - Long physicalSize = tmplVdi.getPhysicalUtilisation(conn); + final Long physicalSize = tmplVdi.getPhysicalUtilisation(conn); if (managed) { uuidToReturn = tmplVdi.getUuid(conn); tmplVdi.setNameLabel(conn, managedStoragePoolRootVolumeName); } else { - VDI snapshotVdi = tmplVdi.snapshot(conn, new HashMap()); + final VDI snapshotVdi = tmplVdi.snapshot(conn, new HashMap()); uuidToReturn = snapshotVdi.getUuid(conn); @@ -283,12 +282,12 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { destSr.scan(conn); - try{ + try { Thread.sleep(5000); - } catch (Exception e) { + } catch (final Exception e) { } - TemplateObjectTO newVol = new TemplateObjectTO(); + final TemplateObjectTO newVol = new TemplateObjectTO(); newVol.setUuid(uuidToReturn); newVol.setPath(uuidToReturn); @@ -299,8 +298,8 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { return new CopyCmdAnswer(newVol); } - } catch (Exception e) { - String msg = "Catch Exception " + e.getClass().getName() + " for template due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Catch Exception " + e.getClass().getName() + " for template due to " + e.toString(); s_logger.warn(msg, e); @@ -309,7 +308,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (task != null) { try { task.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("unable to destroy task (" + task.toWireString() + ") due to " + e.toString()); } } @@ -322,7 +321,8 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { return new CopyCmdAnswer("not implemented yet"); } - protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, String localMountPoint, String path, String secondaryStorageMountPath, String snapshotUuid, String prevBackupUuid, String prevSnapshotUuid, Boolean isISCSI, int wait) { + protected String backupSnapshot(final Connection conn, final String primaryStorageSRUuid, final String localMountPoint, final String path, + final String secondaryStorageMountPath, final String snapshotUuid, String prevBackupUuid, final String prevSnapshotUuid, final Boolean isISCSI, int wait) { boolean filesrcreated = false; // boolean copied = false; @@ -331,12 +331,12 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } SR ssSR = null; - String remoteDir = secondaryStorageMountPath; + final String remoteDir = secondaryStorageMountPath; try { ssSR = createFileSr(conn, remoteDir, path); filesrcreated = true; - VDI snapshotvdi = VDI.getByUuid(conn, snapshotUuid); + final VDI snapshotvdi = VDI.getByUuid(conn, snapshotUuid); if (wait == 0) { wait = 2 * 60 * 60; } @@ -345,7 +345,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { try { VDI previousSnapshotVdi = null; if (prevSnapshotUuid != null) { - previousSnapshotVdi = VDI.getByUuid(conn,prevSnapshotUuid); + previousSnapshotVdi = VDI.getByUuid(conn, prevSnapshotUuid); } task = snapshotvdi.copyAsync(conn, ssSR, previousSnapshotVdi, null); // poll every 1 seconds , @@ -357,15 +357,15 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (task != null) { try { task.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("unable to destroy task(" + task.toWireString() + ") due to " + e.toString()); } } } - String result = dvdi.getUuid(conn).concat("#").concat(dvdi.getPhysicalUtilisation(conn).toString()); + final String result = dvdi.getUuid(conn).concat("#").concat(dvdi.getPhysicalUtilisation(conn).toString()); return result; - } catch (Exception e) { - String msg = "Exception in backupsnapshot stage due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Exception in backupsnapshot stage due to " + e.toString(); s_logger.debug(msg); throw new CloudRuntimeException(msg, e); } finally { @@ -373,16 +373,16 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (filesrcreated && ssSR != null) { hypervisorResource.removeSR(conn, ssSR); } - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Exception in backupsnapshot cleanup stage due to " + e.toString()); } } } @Override - protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) { - String parentUuid = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, - "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString()); + protected String getVhdParent(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI) { + final String parentUuid = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", + snapshotUuid, "isISCSI", isISCSI.toString()); if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid); @@ -393,64 +393,64 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } @Override - public Answer backupSnapshot(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - DataTO srcData = cmd.getSrcTO(); - DataTO cacheData = cmd.getCacheTO(); - DataTO destData = cmd.getDestTO(); - int wait = cmd.getWait(); - PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcData.getDataStore(); - String primaryStorageNameLabel = primaryStore.getUuid(); + public Answer backupSnapshot(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final DataTO srcData = cmd.getSrcTO(); + final DataTO cacheData = cmd.getCacheTO(); + final DataTO destData = cmd.getDestTO(); + final int wait = cmd.getWait(); + final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) srcData.getDataStore(); + final String primaryStorageNameLabel = primaryStore.getUuid(); String secondaryStorageUrl = null; NfsTO cacheStore = null; String destPath = null; if (cacheData != null) { - cacheStore = (NfsTO)cacheData.getDataStore(); + cacheStore = (NfsTO) cacheData.getDataStore(); secondaryStorageUrl = cacheStore.getUrl(); destPath = cacheData.getPath(); } else { - cacheStore = (NfsTO)destData.getDataStore(); + cacheStore = (NfsTO) destData.getDataStore(); secondaryStorageUrl = cacheStore.getUrl(); destPath = destData.getPath(); } - SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData; - SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData; - String snapshotUuid = snapshotTO.getPath(); + final SnapshotObjectTO snapshotTO = (SnapshotObjectTO) srcData; + final SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO) destData; + final String snapshotUuid = snapshotTO.getPath(); - String prevBackupUuid = snapshotOnImage.getParentSnapshotPath(); - String prevSnapshotUuid = snapshotTO.getParentSnapshotPath(); - Map options = cmd.getOptions(); + final String prevBackupUuid = snapshotOnImage.getParentSnapshotPath(); + final String prevSnapshotUuid = snapshotTO.getParentSnapshotPath(); + final Map options = cmd.getOptions(); // By default assume failure String details = null; String snapshotBackupUuid = null; - boolean fullbackup = Boolean.parseBoolean(options.get("fullSnapshot")); + final boolean fullbackup = Boolean.parseBoolean(options.get("fullSnapshot")); Long physicalSize = null; try { - SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + final SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); if (primaryStorageSR == null) { throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel); } // String psUuid = primaryStorageSR.getUuid(conn); - Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn)); + final Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn)); - VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid); - String snapshotPaUuid = null; + final VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid); + final String snapshotPaUuid = null; - URI uri = new URI(secondaryStorageUrl); - String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); - DataStoreTO destStore = destData.getDataStore(); - String folder = destPath; + final URI uri = new URI(secondaryStorageUrl); + final String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + final DataStoreTO destStore = destData.getDataStore(); + final String folder = destPath; String finalPath = null; - String localMountPoint = BaseMountPointOnHost + File.separator + UUID.nameUUIDFromBytes(secondaryStorageUrl.getBytes()).toString(); + final String localMountPoint = BaseMountPointOnHost + File.separator + UUID.nameUUIDFromBytes(secondaryStorageUrl.getBytes()).toString(); if (fullbackup) { SR snapshotSr = null; Task task = null; try { - String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes()); + final String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes()); mountNfs(conn, secondaryStorageMountPath, localDir); - boolean result = makeDirectory(conn, localDir + "/" + folder); + final boolean result = makeDirectory(conn, localDir + "/" + folder); if (!result) { details = " Filed to create folder " + folder + " in secondary storage"; s_logger.warn(details); @@ -463,21 +463,21 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { // poll every 1 seconds , hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); hypervisorResource.checkForSuccess(conn, task); - VDI backedVdi = Types.toVDI(task, conn); + final VDI backedVdi = Types.toVDI(task, conn); snapshotBackupUuid = backedVdi.getUuid(conn); physicalSize = backedVdi.getPhysicalUtilisation(conn); - if( destStore instanceof SwiftTO) { + if (destStore instanceof SwiftTO) { try { - String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); - String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait); - String swiftPath = container + File.separator + destSnapshotName; + final String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); + final String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO) destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait); + final String swiftPath = container + File.separator + destSnapshotName; finalPath = swiftPath; } finally { try { deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid); - } catch (Exception e) { - s_logger.debug("Failed to delete snapshot on cache storages" ,e); + } catch (final Exception e) { + s_logger.debug("Failed to delete snapshot on cache storages", e); } } @@ -490,11 +490,12 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } finally { try { deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid); - } catch (Exception e) { - s_logger.debug("Failed to delete snapshot on cache storages" ,e); + } catch (final Exception e) { + s_logger.debug("Failed to delete snapshot on cache storages", e); } } - // finalPath = folder + File.separator + snapshotBackupUuid; + // finalPath = folder + File.separator + + // snapshotBackupUuid; } else { finalPath = folder + File.separator + snapshotBackupUuid; } @@ -503,38 +504,39 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (task != null) { try { task.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("unable to destroy task(" + task.toWireString() + ") due to " + e.toString()); } } - if( snapshotSr != null) { + if (snapshotSr != null) { hypervisorResource.removeSR(conn, snapshotSr); } } } else { - String primaryStorageSRUuid = primaryStorageSR.getUuid(conn); - if( destStore instanceof SwiftTO ) { - String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); - snapshotBackupUuid = swiftBackupSnapshot(conn, (SwiftTO)destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait); + final String primaryStorageSRUuid = primaryStorageSR.getUuid(conn); + if (destStore instanceof SwiftTO) { + final String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); + snapshotBackupUuid = swiftBackupSnapshot(conn, (SwiftTO) destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait); finalPath = container + File.separator + snapshotBackupUuid; - } else if (destStore instanceof S3TO ) { + } else if (destStore instanceof S3TO) { finalPath = backupSnapshotToS3(conn, (S3TO) destStore, primaryStorageSRUuid, folder, snapshotPaUuid, isISCSI, wait); if (finalPath == null) { throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed"); } } else { - String result = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, - secondaryStorageMountPath, snapshotUuid, prevBackupUuid, prevSnapshotUuid, isISCSI, wait); - String[] tmp = result.split("#"); + final String result = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, secondaryStorageMountPath, snapshotUuid, prevBackupUuid, + prevSnapshotUuid, isISCSI, wait); + final String[] tmp = result.split("#"); snapshotBackupUuid = tmp[0]; physicalSize = Long.parseLong(tmp[1]); finalPath = folder + File.separator + snapshotBackupUuid; } } - String volumeUuid = snapshotTO.getVolume().getPath(); + final String volumeUuid = snapshotTO.getVolume().getPath(); destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid); - SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + final SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); newSnapshot.setPath(finalPath); newSnapshot.setPhysicalSize(physicalSize); if (fullbackup) { @@ -543,10 +545,10 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { newSnapshot.setParentSnapshotPath(prevBackupUuid); } return new CopyCmdAnswer(newSnapshot); - } catch (Types.XenAPIException e) { + } catch (final Types.XenAPIException e) { details = "BackupSnapshot Failed due to " + e.toString(); s_logger.warn(details, e); - } catch (Exception e) { + } catch (final Exception e) { details = "BackupSnapshot Failed due to " + e.getMessage(); s_logger.warn(details, e); } @@ -555,18 +557,17 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } @Override - public Answer createTemplateFromVolume(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO(); - TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO(); - NfsTO destStore = (NfsTO)cmd.getDestTO().getDataStore(); - int wait = cmd.getWait(); + public Answer createTemplateFromVolume(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final VolumeObjectTO volume = (VolumeObjectTO) cmd.getSrcTO(); + final TemplateObjectTO template = (TemplateObjectTO) cmd.getDestTO(); + final NfsTO destStore = (NfsTO) cmd.getDestTO().getDataStore(); + final int wait = cmd.getWait(); - String secondaryStoragePoolURL = destStore.getUrl(); - String volumeUUID = volume.getPath(); - - String userSpecifiedName = template.getName(); + final String secondaryStoragePoolURL = destStore.getUrl(); + final String volumeUUID = volume.getPath(); + final String userSpecifiedName = template.getName(); String details = null; SR tmpltSR = null; @@ -575,16 +576,16 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { String installPath = null; Task task = null; try { - URI uri = new URI(secondaryStoragePoolURL); + final URI uri = new URI(secondaryStoragePoolURL); secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); installPath = template.getPath(); - if( !hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) { + if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) { details = " Filed to create folder " + installPath + " in secondary storage"; s_logger.warn(details); return new CopyCmdAnswer(details); } - VDI vol = getVDIbyUuid(conn, volumeUUID); + final VDI vol = getVDIbyUuid(conn, volumeUUID); // create template SR tmpltSR = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), installPath); @@ -593,39 +594,40 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { // poll every 1 seconds , hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); hypervisorResource.checkForSuccess(conn, task); - VDI tmpltVDI = Types.toVDI(task, conn); + final VDI tmpltVDI = Types.toVDI(task, conn); // scan makes XenServer pick up VDI physicalSize tmpltSR.scan(conn); if (userSpecifiedName != null) { tmpltVDI.setNameLabel(conn, userSpecifiedName); } - String tmpltUUID = tmpltVDI.getUuid(conn); - String tmpltFilename = tmpltUUID + ".vhd"; - long virtualSize = tmpltVDI.getVirtualSize(conn); - long physicalSize = tmpltVDI.getPhysicalUtilisation(conn); + final String tmpltUUID = tmpltVDI.getUuid(conn); + final String tmpltFilename = tmpltUUID + ".vhd"; + final long virtualSize = tmpltVDI.getVirtualSize(conn); + final long physicalSize = tmpltVDI.getPhysicalUtilisation(conn); // create the template.properties file - String templatePath = secondaryStorageMountPath + "/" + installPath; - result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId()); + final String templatePath = secondaryStorageMountPath + "/" + installPath; + result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, + template.getId()); if (!result) { throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir"); } installPath = installPath + "/" + tmpltFilename; hypervisorResource.removeSR(conn, tmpltSR); tmpltSR = null; - TemplateObjectTO newTemplate = new TemplateObjectTO(); + final TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(installPath); newTemplate.setFormat(Storage.ImageFormat.VHD); newTemplate.setSize(virtualSize); newTemplate.setPhysicalSize(physicalSize); newTemplate.setName(tmpltUUID); - CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); + final CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); return answer; - } catch (Exception e) { + } catch (final Exception e) { if (tmpltSR != null) { hypervisorResource.removeSR(conn, tmpltSR); } - if ( secondaryStorageMountPath != null) { + if (secondaryStorageMountPath != null) { hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath); } details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString(); @@ -634,15 +636,15 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (task != null) { try { task.destroy(conn); - } catch (Exception e) { - s_logger.warn("unable to destroy task(" + task.toWireString() + ") due to " + e.toString()); + } catch (final Exception e) { + s_logger.warn("unable to destroy task(" + task.toWireString() + ") due to " + e.toString()); } } } return new CopyCmdAnswer(details); } - protected String getSnapshotUuid(String snapshotPath) { + protected String getSnapshotUuid(final String snapshotPath) { int index = snapshotPath.lastIndexOf(File.separator); String snapshotUuid = snapshotPath.substring(index + 1); index = snapshotUuid.lastIndexOf("."); @@ -653,14 +655,14 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } @Override - public Answer createVolumeFromSnapshot(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - DataTO srcData = cmd.getSrcTO(); - SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData; - DataTO destData = cmd.getDestTO(); - PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore(); - VolumeObjectTO volume = (VolumeObjectTO)destData; - DataStoreTO imageStore = srcData.getDataStore(); + public Answer createVolumeFromSnapshot(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final DataTO srcData = cmd.getSrcTO(); + final SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData; + final DataTO destData = cmd.getDestTO(); + final PrimaryDataStoreTO pool = (PrimaryDataStoreTO) destData.getDataStore(); + final VolumeObjectTO volume = (VolumeObjectTO) destData; + final DataStoreTO imageStore = srcData.getDataStore(); if (srcData.getDataStore() instanceof PrimaryDataStoreTO && destData.getDataStore() instanceof PrimaryDataStoreTO) { return createVolumeFromSnapshot2(cmd); @@ -670,10 +672,10 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { return new CopyCmdAnswer("unsupported protocol"); } - NfsTO nfsImageStore = (NfsTO)imageStore; - String primaryStorageNameLabel = pool.getUuid(); - String secondaryStorageUrl = nfsImageStore.getUrl(); - int wait = cmd.getWait(); + final NfsTO nfsImageStore = (NfsTO) imageStore; + final String primaryStorageNameLabel = pool.getUuid(); + final String secondaryStorageUrl = nfsImageStore.getUrl(); + final int wait = cmd.getWait(); boolean result = false; // Generic error message. String details = null; @@ -686,38 +688,38 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { SR srcSr = null; VDI destVdi = null; try { - SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + final SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); if (primaryStorageSR == null) { throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel); } - String nameLabel = "cloud-" + UUID.randomUUID().toString(); + final String nameLabel = "cloud-" + UUID.randomUUID().toString(); destVdi = createVdi(conn, nameLabel, primaryStorageSR, volume.getSize()); volumeUUID = destVdi.getUuid(conn); - String snapshotInstallPath = snapshot.getPath(); - int index = snapshotInstallPath.lastIndexOf(File.separator); - String snapshotDirectory = snapshotInstallPath.substring(0, index); - String snapshotUuid = getSnapshotUuid(snapshotInstallPath); + final String snapshotInstallPath = snapshot.getPath(); + final int index = snapshotInstallPath.lastIndexOf(File.separator); + final String snapshotDirectory = snapshotInstallPath.substring(0, index); + final String snapshotUuid = getSnapshotUuid(snapshotInstallPath); - URI uri = new URI(secondaryStorageUrl); + final URI uri = new URI(secondaryStorageUrl); srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), snapshotDirectory); - String[] parents = snapshot.getParents(); - List snapshotChains = new ArrayList(); + final String[] parents = snapshot.getParents(); + final List snapshotChains = new ArrayList(); if (parents != null) { - for(int i = 0; i < parents.length; i++) { - String snChainPath = parents[i]; - String uuid = getSnapshotUuid(snChainPath); - VDI chain = VDI.getByUuid(conn, uuid); + for (int i = 0; i < parents.length; i++) { + final String snChainPath = parents[i]; + final String uuid = getSnapshotUuid(snChainPath); + final VDI chain = VDI.getByUuid(conn, uuid); snapshotChains.add(chain); } } - VDI snapshotVdi = VDI.getByUuid(conn, snapshotUuid); + final VDI snapshotVdi = VDI.getByUuid(conn, snapshotUuid); snapshotChains.add(snapshotVdi); - for(VDI snapChain : snapshotChains) { - Task task = snapChain.copyAsync(conn, null, null, destVdi); + for (final VDI snapChain : snapshotChains) { + final Task task = snapChain.copyAsync(conn, null, null, destVdi); // poll every 1 seconds , hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); hypervisorResource.checkForSuccess(conn, task); @@ -726,15 +728,15 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { result = true; destVdi = VDI.getByUuid(conn, volumeUUID); - VDI.Record vdir = destVdi.getRecord(conn); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VDI.Record vdir = destVdi.getRecord(conn); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setPath(volumeUUID); newVol.setSize(vdir.virtualSize); return new CopyCmdAnswer(newVol); - } catch (Types.XenAPIException e) { + } catch (final Types.XenAPIException e) { details += " due to " + e.toString(); s_logger.warn(details, e); - } catch (Exception e) { + } catch (final Exception e) { details += " due to " + e.getMessage(); s_logger.warn(details, e); } finally { @@ -744,7 +746,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (!result && destVdi != null) { try { destVdi.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("destroy dest vdi failed", e); } } @@ -759,19 +761,19 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } @Override - public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO(); - VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO(); - int wait = cmd.getWait(); - DataStoreTO destStore = destVolume.getDataStore(); + public Answer copyVolumeFromPrimaryToSecondary(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final VolumeObjectTO srcVolume = (VolumeObjectTO) cmd.getSrcTO(); + final VolumeObjectTO destVolume = (VolumeObjectTO) cmd.getDestTO(); + final int wait = cmd.getWait(); + final DataStoreTO destStore = destVolume.getDataStore(); if (destStore instanceof NfsTO) { SR secondaryStorage = null; Task task = null; try { - NfsTO nfsStore = (NfsTO)destStore; - URI uri = new URI(nfsStore.getUrl()); + final NfsTO nfsStore = (NfsTO) destStore; + final URI uri = new URI(nfsStore.getUrl()); // Create the volume folder if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) { throw new InternalErrorException("Failed to create the volume folder."); @@ -780,27 +782,27 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { // Create a SR for the volume UUID folder secondaryStorage = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath()); // Look up the volume on the source primary storage pool - VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath()); + final VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath()); // Copy the volume to secondary storage task = srcVdi.copyAsync(conn, secondaryStorage, null, null); // poll every 1 seconds , hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); hypervisorResource.checkForSuccess(conn, task); - VDI destVdi = Types.toVDI(task, conn); - String destVolumeUUID = destVdi.getUuid(conn); + final VDI destVdi = Types.toVDI(task, conn); + final String destVolumeUUID = destVdi.getUuid(conn); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setPath(destVolume.getPath() + File.separator + destVolumeUUID + ".vhd"); newVol.setSize(srcVolume.getSize()); return new CopyCmdAnswer(newVol); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Failed to copy volume to secondary: " + e.toString()); return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString()); } finally { if (task != null) { try { task.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("unable to destroy task(" + task.toWireString() + ") due to " + e.toString()); } } @@ -811,21 +813,21 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } @Override - public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); - DataTO srcData = cmd.getSrcTO(); - DataTO destData = cmd.getDestTO(); - int wait = cmd.getWait(); - VolumeObjectTO srcVolume = (VolumeObjectTO)srcData; - VolumeObjectTO destVolume = (VolumeObjectTO)destData; - PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore(); - DataStoreTO srcStore = srcVolume.getDataStore(); + public Answer copyVolumeFromImageCacheToPrimary(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); + final DataTO srcData = cmd.getSrcTO(); + final DataTO destData = cmd.getDestTO(); + final int wait = cmd.getWait(); + final VolumeObjectTO srcVolume = (VolumeObjectTO) srcData; + final VolumeObjectTO destVolume = (VolumeObjectTO) destData; + final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) destVolume.getDataStore(); + final DataStoreTO srcStore = srcVolume.getDataStore(); if (srcStore instanceof NfsTO) { - NfsTO nfsStore = (NfsTO)srcStore; - String volumePath = srcVolume.getPath(); + final NfsTO nfsStore = (NfsTO) srcStore; + final String volumePath = srcVolume.getPath(); int index = volumePath.lastIndexOf("/"); - String volumeDirectory = volumePath.substring(0, index); + final String volumeDirectory = volumePath.substring(0, index); String volumeUuid = volumePath.substring(index + 1); index = volumeUuid.indexOf("."); if (index != -1) { @@ -834,33 +836,33 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { URI uri = null; try { uri = new URI(nfsStore.getUrl()); - } catch (Exception e) { + } catch (final Exception e) { return new CopyCmdAnswer(e.toString()); } - SR srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory); + final SR srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory); Task task = null; try { - SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid()); - VDI srcVdi = VDI.getByUuid(conn, volumeUuid); + final SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid()); + final VDI srcVdi = VDI.getByUuid(conn, volumeUuid); task = srcVdi.copyAsync(conn, primaryStoragePool, null, null); // poll every 1 seconds , hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); hypervisorResource.checkForSuccess(conn, task); - VDI destVdi = Types.toVDI(task, conn); - VolumeObjectTO newVol = new VolumeObjectTO(); + final VDI destVdi = Types.toVDI(task, conn); + final VolumeObjectTO newVol = new VolumeObjectTO(); newVol.setPath(destVdi.getUuid(conn)); newVol.setSize(srcVolume.getSize()); return new CopyCmdAnswer(newVol); - } catch (Exception e) { - String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + } catch (final Exception e) { + final String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); s_logger.warn(msg, e); return new CopyCmdAnswer(e.toString()); } finally { if (task != null) { try { task.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.warn("unable to destroy task(" + task.toString() + ") due to " + e.toString()); } } @@ -875,23 +877,23 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } @Override - public Answer createTemplateFromSnapshot(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); + public Answer createTemplateFromSnapshot(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); - DataTO srcData = cmd.getSrcTO(); - DataTO destData = cmd.getDestTO(); + final DataTO srcData = cmd.getSrcTO(); + final DataTO destData = cmd.getDestTO(); if (srcData.getDataStore() instanceof PrimaryDataStoreTO && destData.getDataStore() instanceof NfsTO) { return createTemplateFromSnapshot2(cmd); } - int wait = cmd.getWait(); + final int wait = cmd.getWait(); - SnapshotObjectTO srcObj = (SnapshotObjectTO)srcData; - TemplateObjectTO destObj = (TemplateObjectTO)destData; + final SnapshotObjectTO srcObj = (SnapshotObjectTO) srcData; + final TemplateObjectTO destObj = (TemplateObjectTO) destData; - NfsTO srcStore = (NfsTO)srcObj.getDataStore(); - NfsTO destStore = (NfsTO)destObj.getDataStore(); + final NfsTO srcStore = (NfsTO) srcObj.getDataStore(); + final NfsTO destStore = (NfsTO) destObj.getDataStore(); URI srcUri = null; URI destUri = null; @@ -899,16 +901,16 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { try { srcUri = new URI(srcStore.getUrl()); destUri = new URI(destStore.getUrl()); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("incorrect url", e); return new CopyCmdAnswer("incorrect url" + e.toString()); } - String srcPath = srcObj.getPath(); - int index = srcPath.lastIndexOf("/"); - String srcDir = srcPath.substring(0, index); - String destDir = destObj.getPath(); + final String srcPath = srcObj.getPath(); + final int index = srcPath.lastIndexOf("/"); + final String srcDir = srcPath.substring(0, index); + final String destDir = destObj.getPath(); SR srcSr = null; SR destSr = null; @@ -920,42 +922,42 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { try { srcSr = createFileSr(conn, srcUri.getHost() + ":" + srcUri.getPath(), srcDir); - String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); - String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(destNfsPath.getBytes()); + final String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); + final String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(destNfsPath.getBytes()); mountNfs(conn, destUri.getHost() + ":" + destUri.getPath(), localDir); makeDirectory(conn, localDir + "/" + destDir); destSr = createFileSR(conn, localDir + "/" + destDir); - String nameLabel = "cloud-" + UUID.randomUUID().toString(); + final String nameLabel = "cloud-" + UUID.randomUUID().toString(); - String[] parents = srcObj.getParents(); - List snapshotChains = new ArrayList(); + final String[] parents = srcObj.getParents(); + final List snapshotChains = new ArrayList(); if (parents != null) { for (int i = 0; i < parents.length; i++) { - String snChainPath = parents[i]; - String uuid = getSnapshotUuid(snChainPath); - VDI chain = VDI.getByUuid(conn, uuid); + final String snChainPath = parents[i]; + final String uuid = getSnapshotUuid(snChainPath); + final VDI chain = VDI.getByUuid(conn, uuid); snapshotChains.add(chain); } } - String snapshotUuid = getSnapshotUuid(srcPath); - VDI snapshotVdi = VDI.getByUuid(conn, snapshotUuid); + final String snapshotUuid = getSnapshotUuid(srcPath); + final VDI snapshotVdi = VDI.getByUuid(conn, snapshotUuid); snapshotChains.add(snapshotVdi); - long templateVirtualSize = snapshotChains.get(0).getVirtualSize(conn); + final long templateVirtualSize = snapshotChains.get(0).getVirtualSize(conn); destVdi = createVdi(conn, nameLabel, destSr, templateVirtualSize); - String destVdiUuid = destVdi.getUuid(conn); + final String destVdiUuid = destVdi.getUuid(conn); - for (VDI snapChain : snapshotChains) { - Task task = snapChain.copyAsync(conn, null, null, destVdi); + for (final VDI snapChain : snapshotChains) { + final Task task = snapChain.copyAsync(conn, null, null, destVdi); // poll every 1 seconds , hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); hypervisorResource.checkForSuccess(conn, task); @@ -968,23 +970,22 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { // scan makes XenServer pick up VDI physicalSize destSr.scan(conn); - String templateUuid = destVdi.getUuid(conn); - String templateFilename = templateUuid + ".vhd"; - long virtualSize = destVdi.getVirtualSize(conn); - long physicalSize = destVdi.getPhysicalUtilisation(conn); + final String templateUuid = destVdi.getUuid(conn); + final String templateFilename = templateUuid + ".vhd"; + final long virtualSize = destVdi.getVirtualSize(conn); + final long physicalSize = destVdi.getPhysicalUtilisation(conn); String templatePath = destNfsPath + "/" + destDir; - templatePath = templatePath.replaceAll("//","/"); + templatePath = templatePath.replaceAll("//", "/"); - result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, - physicalSize, virtualSize, destObj.getId()); + result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, physicalSize, virtualSize, destObj.getId()); if (!result) { throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir"); } - TemplateObjectTO newTemplate = new TemplateObjectTO(); + final TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(destDir + "/" + templateFilename); newTemplate.setFormat(Storage.ImageFormat.VHD); @@ -995,7 +996,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { result = true; return new CopyCmdAnswer(newTemplate); - } catch (Exception e) { + } catch (final Exception e) { s_logger.error("Failed create template from snapshot", e); return new CopyCmdAnswer("Failed create template from snapshot " + e.toString()); @@ -1004,7 +1005,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (destVdi != null) { try { destVdi.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Clean up left over on dest storage failed: ", e); } } @@ -1020,11 +1021,11 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { } } - public Answer createTemplateFromSnapshot2(CopyCommand cmd) { - Connection conn = hypervisorResource.getConnection(); + public Answer createTemplateFromSnapshot2(final CopyCommand cmd) { + final Connection conn = hypervisorResource.getConnection(); - SnapshotObjectTO snapshotObjTO = (SnapshotObjectTO)cmd.getSrcTO(); - TemplateObjectTO templateObjTO = (TemplateObjectTO)cmd.getDestTO(); + final SnapshotObjectTO snapshotObjTO = (SnapshotObjectTO) cmd.getSrcTO(); + final TemplateObjectTO templateObjTO = (TemplateObjectTO) cmd.getDestTO(); if (!(snapshotObjTO.getDataStore() instanceof PrimaryDataStoreTO) || !(templateObjTO.getDataStore() instanceof NfsTO)) { return null; @@ -1034,10 +1035,10 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { URI destUri = null; try { - destStore = (NfsTO)templateObjTO.getDataStore(); + destStore = (NfsTO) templateObjTO.getDataStore(); destUri = new URI(destStore.getUrl()); - } catch (Exception ex) { + } catch (final Exception ex) { s_logger.debug("Invalid URI", ex); return new CopyCmdAnswer("Invalid URI: " + ex.toString()); @@ -1046,23 +1047,23 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { SR srcSr = null; SR destSr = null; - String destDir = templateObjTO.getPath(); + final String destDir = templateObjTO.getPath(); VDI destVdi = null; boolean result = false; try { - Map srcDetails = cmd.getOptions(); + final Map srcDetails = cmd.getOptions(); - String iScsiName = srcDetails.get(DiskTO.IQN); - String storageHost = srcDetails.get(DiskTO.STORAGE_HOST); - String chapInitiatorUsername = srcDetails.get(DiskTO.CHAP_INITIATOR_USERNAME); - String chapInitiatorSecret = srcDetails.get(DiskTO.CHAP_INITIATOR_SECRET); + final String iScsiName = srcDetails.get(DiskTO.IQN); + final String storageHost = srcDetails.get(DiskTO.STORAGE_HOST); + final String chapInitiatorUsername = srcDetails.get(DiskTO.CHAP_INITIATOR_USERNAME); + final String chapInitiatorSecret = srcDetails.get(DiskTO.CHAP_INITIATOR_SECRET); srcSr = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true); - String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); - String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(destNfsPath.getBytes()); + final String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); + final String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(destNfsPath.getBytes()); mountNfs(conn, destNfsPath, localDir); makeDirectory(conn, localDir + "/" + destDir); @@ -1070,35 +1071,35 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { destSr = createFileSR(conn, localDir + "/" + destDir); // there should only be one VDI in this SR - VDI srcVdi = srcSr.getVDIs(conn).iterator().next(); + final VDI srcVdi = srcSr.getVDIs(conn).iterator().next(); destVdi = srcVdi.copy(conn, destSr); - String nameLabel = "cloud-" + UUID.randomUUID().toString(); + final String nameLabel = "cloud-" + UUID.randomUUID().toString(); destVdi.setNameLabel(conn, nameLabel); // scan makes XenServer pick up VDI physicalSize destSr.scan(conn); - String templateUuid = destVdi.getUuid(conn); - String templateFilename = templateUuid + ".vhd"; - long virtualSize = destVdi.getVirtualSize(conn); - long physicalSize = destVdi.getPhysicalUtilisation(conn); + final String templateUuid = destVdi.getUuid(conn); + final String templateFilename = templateUuid + ".vhd"; + final long virtualSize = destVdi.getVirtualSize(conn); + final long physicalSize = destVdi.getPhysicalUtilisation(conn); // create the template.properties file String templatePath = destNfsPath + "/" + destDir; templatePath = templatePath.replaceAll("//", "/"); - result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, - physicalSize, virtualSize, templateObjTO.getId()); + result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, physicalSize, virtualSize, + templateObjTO.getId()); if (!result) { throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir"); } - TemplateObjectTO newTemplate = new TemplateObjectTO(); + final TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(destDir + "/" + templateFilename); newTemplate.setFormat(Storage.ImageFormat.VHD); @@ -1110,19 +1111,22 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { result = true; return new CopyCmdAnswer(newTemplate); -// } catch (Exception ex) { -// s_logger.error("Failed to create a template from a snapshot", ex); -// -// return new CopyCmdAnswer("Failed to create a template from a snapshot: " + ex.toString()); - } catch (BadServerResponse e) { - s_logger.error("Failed to create a template from a snapshot due to incomprehensible server response", e); + // } catch (Exception ex) { + // s_logger.error("Failed to create a template from a snapshot", + // ex); + // + // return new + // CopyCmdAnswer("Failed to create a template from a snapshot: " + + // ex.toString()); + } catch (final BadServerResponse e) { + s_logger.error("Failed to create a template from a snapshot due to incomprehensible server response", e); - return new CopyCmdAnswer("Failed to create a template from a snapshot: " + e.toString()); - } catch (XenAPIException e) { - s_logger.error("Failed to create a template from a snapshot due to xenapi error", e); + return new CopyCmdAnswer("Failed to create a template from a snapshot: " + e.toString()); + } catch (final XenAPIException e) { + s_logger.error("Failed to create a template from a snapshot due to xenapi error", e); - return new CopyCmdAnswer("Failed to create a template from a snapshot: " + e.toString()); - } catch (XmlRpcException e) { + return new CopyCmdAnswer("Failed to create a template from a snapshot: " + e.toString()); + } catch (final XmlRpcException e) { s_logger.error("Failed to create a template from a snapshot due to rpc error", e); return new CopyCmdAnswer("Failed to create a template from a snapshot: " + e.toString()); @@ -1131,7 +1135,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor { if (destVdi != null) { try { destVdi.destroy(conn); - } catch (Exception e) { + } catch (final Exception e) { s_logger.debug("Cleaned up leftover VDI on destination storage due to failure: ", e); } } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XsHost.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XsHost.java new file mode 100644 index 00000000000..e17a017e6f4 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XsHost.java @@ -0,0 +1,212 @@ +// 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; + +import com.xensource.xenapi.Network; + +/** + * A list of UUIDs that are gathered from the XenServer when the resource first + * connects to XenServer. These UUIDs do not change over time. + */ +public class XsHost { + + private String systemvmisouuid; + private String uuid; + private String ip; + private String publicNetwork; + private String privateNetwork; + private String linkLocalNetwork; + private Network vswitchNetwork; + private String storageNetwork1; + private String guestNetwork; + private String guestPif; + private String publicPif; + private String privatePif; + private String storagePif1; + private String storagePif2; + private String pool; + private int speed; + private Integer cpuSockets; + private int cpus; + private String productVersion; + private String localSRuuid; + + public String getSystemvmisouuid() { + return systemvmisouuid; + } + + public void setSystemvmisouuid(final String systemvmisouuid) { + this.systemvmisouuid = systemvmisouuid; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(final String uuid) { + this.uuid = uuid; + } + + public String getIp() { + return ip; + } + + public void setIp(final String ip) { + this.ip = ip; + } + + public String getPublicNetwork() { + return publicNetwork; + } + + public void setPublicNetwork(final String publicNetwork) { + this.publicNetwork = publicNetwork; + } + + public String getPrivateNetwork() { + return privateNetwork; + } + + public void setPrivateNetwork(final String privateNetwork) { + this.privateNetwork = privateNetwork; + } + + public String getLinkLocalNetwork() { + return linkLocalNetwork; + } + + public void setLinkLocalNetwork(final String linkLocalNetwork) { + this.linkLocalNetwork = linkLocalNetwork; + } + + public Network getVswitchNetwork() { + return vswitchNetwork; + } + + public void setVswitchNetwork(final Network vswitchNetwork) { + this.vswitchNetwork = vswitchNetwork; + } + + public String getStorageNetwork1() { + return storageNetwork1; + } + + public void setStorageNetwork1(final String storageNetwork1) { + this.storageNetwork1 = storageNetwork1; + } + + public String getGuestNetwork() { + return guestNetwork; + } + + public void setGuestNetwork(final String guestNetwork) { + this.guestNetwork = guestNetwork; + } + + public String getGuestPif() { + return guestPif; + } + + public void setGuestPif(final String guestPif) { + this.guestPif = guestPif; + } + + public String getPublicPif() { + return publicPif; + } + + public void setPublicPif(final String publicPif) { + this.publicPif = publicPif; + } + + public String getPrivatePif() { + return privatePif; + } + + public void setPrivatePif(final String privatePif) { + this.privatePif = privatePif; + } + + public String getStoragePif1() { + return storagePif1; + } + + public void setStoragePif1(final String storagePif1) { + this.storagePif1 = storagePif1; + } + + public String getStoragePif2() { + return storagePif2; + } + + public void setStoragePif2(final String storagePif2) { + this.storagePif2 = storagePif2; + } + + public String getPool() { + return pool; + } + + public void setPool(final String pool) { + this.pool = pool; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(final int speed) { + this.speed = speed; + } + + public Integer getCpuSockets() { + return cpuSockets; + } + + public void setCpuSockets(final Integer cpuSockets) { + this.cpuSockets = cpuSockets; + } + + public int getCpus() { + return cpus; + } + + public void setCpus(final int cpus) { + this.cpus = cpus; + } + + public String getProductVersion() { + return productVersion; + } + + public void setProductVersion(final String productVersion) { + this.productVersion = productVersion; + } + + public String getLocalSRuuid() { + return localSRuuid; + } + + public void setLocalSRuuid(final String localSRuuid) { + this.localSRuuid = localSRuuid; + } + + @Override + public String toString() { + return new StringBuilder("XS[").append(uuid).append("-").append(ip).append("]").toString(); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixReadyCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixReadyCommandWrapper.java new file mode 100644 index 00000000000..d4c73ebb272 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixReadyCommandWrapper.java @@ -0,0 +1,75 @@ +// +// 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.ReadyAnswer; +import com.cloud.agent.api.ReadyCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VM; + +public final class CitrixReadyCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixReadyCommandWrapper.class); + + @Override + public Answer execute(final ReadyCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final Long dcId = command.getDataCenterId(); + // Ignore the result of the callHostPlugin. Even if unmounting the + // snapshots dir fails, let Ready command + // succeed. + citrixResourceBase.umountSnapshotDir(conn, dcId); + + citrixResourceBase.setupLinkLocalNetwork(conn); + // try to destroy CD-ROM device for all system VMs on this host + try { + final Host host = Host.getByUuid(conn, citrixResourceBase.getHost().getUuid()); + final Set vms = host.getResidentVMs(conn); + for (final VM vm : vms) { + citrixResourceBase.destroyPatchVbd(conn, vm.getNameLabel(conn)); + } + } catch (final Exception e) { + } + try { + final boolean result = citrixResourceBase.cleanupHaltedVms(conn); + if (!result) { + return new ReadyAnswer(command, "Unable to cleanup halted vms"); + } + } catch (final XenAPIException e) { + s_logger.warn("Unable to cleanup halted vms", e); + return new ReadyAnswer(command, "Unable to cleanup halted vms"); + } catch (final XmlRpcException e) { + s_logger.warn("Unable to cleanup halted vms", e); + return new ReadyAnswer(command, "Unable to cleanup halted vms"); + } + + return new ReadyAnswer(command); + } +} \ 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 5495f60c7a6..f2a921c0f72 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 @@ -23,6 +23,7 @@ import java.util.Hashtable; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; @@ -53,6 +54,7 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(CreateCommand.class, new CitrixCreateCommandWrapper()); map.put(CheckConsoleProxyLoadCommand.class, new CitrixCheckConsoleProxyLoadCommandWrapper()); map.put(WatchConsoleProxyLoadCommand.class, new CitrixWatchConsoleProxyLoadCommandWrapper()); + map.put(ReadyCommand.class, new CitrixReadyCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenServerResourceNewBase.java b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenServerResourceNewBase.java index 161a7b22abf..4971eb38593 100644 --- a/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenServerResourceNewBase.java +++ b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenServerResourceNewBase.java @@ -25,6 +25,11 @@ import java.util.concurrent.TimeoutException; import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; +import com.cloud.agent.api.StartupCommand; +import com.cloud.hypervisor.xenserver.resource.XenServer620SP1Resource; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Event; import com.xensource.xenapi.EventBatch; @@ -35,12 +40,6 @@ import com.xensource.xenapi.Types; import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VM; -import com.cloud.agent.api.StartupCommand; -import com.cloud.hypervisor.xenserver.resource.XenServer620SP1Resource; -import com.cloud.utils.Pair; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.VirtualMachine; - /** * * XenServerResourceNewBase is an abstract base class that encapsulates how @@ -67,16 +66,16 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { @Override public StartupCommand[] initialize() throws IllegalArgumentException { - StartupCommand[] cmds = super.initialize(); + final StartupCommand[] cmds = super.initialize(); - Connection conn = getConnection(); + final Connection conn = getConnection(); Pool pool; try { - pool = Pool.getByUuid(conn, _host.pool); - Pool.Record poolr = pool.getRecord(conn); + pool = Pool.getByUuid(conn, _host.getPool()); + final Pool.Record poolr = pool.getRecord(conn); - Host.Record masterRecord = poolr.master.getRecord(conn); - if (_host.uuid.equals(masterRecord.uuid)) { + final Host.Record masterRecord = poolr.master.getRecord(conn); + if (_host.getUuid().equals(masterRecord.uuid)) { _listener = new VmEventListener(true); // @@ -87,36 +86,37 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { } else { _listener = new VmEventListener(false); } - } catch (XenAPIException e) { + } catch (final XenAPIException e) { throw new CloudRuntimeException("Unable to determine who is the master", e); - } catch (XmlRpcException e) { + } catch (final XmlRpcException e) { throw new CloudRuntimeException("Unable to determine who is the master", e); } return cmds; } - protected void waitForTask2(Connection c, Task task, long pollInterval, long timeout) throws XenAPIException, XmlRpcException, TimeoutException { - long beginTime = System.currentTimeMillis(); + protected void waitForTask2(final Connection c, final Task task, final long pollInterval, final long timeout) throws XenAPIException, XmlRpcException, TimeoutException { + final long beginTime = System.currentTimeMillis(); if (s_logger.isTraceEnabled()) { s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getType(c) + ") sent to " + c.getSessionReference() + " is pending completion with a " + timeout + - "ms timeout"); + "ms timeout"); } - Set classes = new HashSet(); + final Set classes = new HashSet(); classes.add("Task/" + task.toWireString()); String token = ""; - Double t = new Double(timeout / 1000); + final Double t = new Double(timeout / 1000); while (true) { - EventBatch map = Event.from(c, classes, token, t); + final EventBatch map = Event.from(c, classes, token, t); token = map.token; @SuppressWarnings("unchecked") + final Set events = map.events; if (events.size() == 0) { - String msg = "No event for task " + task.toWireString(); + final String msg = "No event for task " + task.toWireString(); s_logger.warn(msg); task.cancel(c); throw new TimeoutException(msg); } - for (Event.Record rec : events) { + for (final Event.Record rec : events) { if (!(rec.snapshot instanceof Task.Record)) { if (s_logger.isDebugEnabled()) { s_logger.debug("Skipping over " + rec); @@ -124,7 +124,7 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { continue; } - Task.Record taskRecord = (Task.Record)rec.snapshot; + final Task.Record taskRecord = (Task.Record)rec.snapshot; if (taskRecord.status != Types.TaskStatusType.PENDING) { if (s_logger.isDebugEnabled()) { @@ -139,7 +139,7 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { } } if (System.currentTimeMillis() - beginTime > timeout) { - String msg = "Async " + timeout / 1000 + " seconds timeout for task " + task.toString(); + final String msg = "Async " + timeout / 1000 + " seconds timeout for task " + task.toString(); s_logger.warn(msg); task.cancel(c); throw new TimeoutException(msg); @@ -155,7 +155,7 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { Set _classes; String _token = ""; - public VmEventListener(boolean isMaster) { + public VmEventListener(final boolean isMaster) { _isMaster = isMaster; _classes = new HashSet(); _classes.add("VM"); @@ -163,22 +163,23 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { @Override public void run() { - setName("XS-Listener-" + _host.ip); + setName("XS-Listener-" + _host.getIp()); while (!_stop) { try { - Connection conn = getConnection(); + final Connection conn = getConnection(); EventBatch results; try { results = Event.from(conn, _classes, _token, new Double(30)); - } catch (Exception e) { + } catch (final Exception e) { s_logger.error("Retrying the waiting on VM events due to: ", e); continue; } _token = results.token; @SuppressWarnings("unchecked") + final Set events = results.events; - for (Event.Record event : events) { + for (final Event.Record event : events) { try { if (!(event.snapshot instanceof VM.Record)) { if (s_logger.isDebugEnabled()) { @@ -186,24 +187,24 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { } continue; } - VM.Record vm = (VM.Record)event.snapshot; + final VM.Record vm = (VM.Record)event.snapshot; String hostUuid = null; if (vm.residentOn != null && !vm.residentOn.toWireString().contains("OpaqueRef:NULL")) { hostUuid = vm.residentOn.getUuid(conn); } recordChanges(conn, vm, hostUuid); - } catch (Exception e) { + } catch (final Exception e) { s_logger.error("Skipping over " + event, e); } } - } catch (Throwable th) { + } catch (final Throwable th) { s_logger.error("Exception caught in eventlistener thread: ", th); } } } - protected void recordChanges(Connection conn, VM.Record rec, String hostUuid) { + protected void recordChanges(final Connection conn, final VM.Record rec, final String hostUuid) { } @@ -211,16 +212,16 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { public void start() { if (_isMaster) { // Throw away the initial set of events because they're history - Connection conn = getConnection(); + final Connection conn = getConnection(); EventBatch results; try { results = Event.from(conn, _classes, _token, new Double(30)); - } catch (Exception e) { + } catch (final Exception e) { s_logger.error("Retrying the waiting on VM events due to: ", e); throw new CloudRuntimeException("Unable to start a listener thread to listen to VM events", e); } _token = results.token; - s_logger.debug("Starting the event listener thread for " + _host.uuid); + s_logger.debug("Starting the event listener thread for " + _host.getUuid()); super.start(); } } @@ -234,7 +235,7 @@ public class XenServerResourceNewBase extends XenServer620SP1Resource { if (_changes.size() == 0) { return null; } - HashMap> diff = _changes; + final HashMap> diff = _changes; _changes = new HashMap>(); return diff; } 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 0c2944c8d8f..e79e8af5039 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 @@ -39,6 +39,10 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import com.cloud.agent.api.ScaleVmAnswer; +import com.cloud.agent.api.ScaleVmCommand; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.VirtualMachineTO; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.Types; @@ -46,35 +50,29 @@ import com.xensource.xenapi.VIF; import com.xensource.xenapi.VM; import com.xensource.xenapi.XenAPIObject; -import com.cloud.agent.api.ScaleVmAnswer; -import com.cloud.agent.api.ScaleVmCommand; -import com.cloud.agent.api.to.IpAddressTO; -import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase.XsHost; - public class CitrixResourceBaseTest { @Spy CitrixResourceBase _resource = new CitrixResourceBase() { @Override - public ScaleVmAnswer execute(ScaleVmCommand cmd) { + public ScaleVmAnswer execute(final ScaleVmCommand cmd) { return super.execute(cmd); } @Override - public String callHostPlugin(Connection conn, String plugin, String cmd, String... params) { + public String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) { return "Success"; } @Override - protected void scaleVM(Connection conn, VM vm, VirtualMachineTO vmSpec, Host host) throws Types.XenAPIException, XmlRpcException { - _host.speed = 500; + protected 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(Connection conn, Host host) throws Types.XenAPIException, XmlRpcException { + protected boolean isDmcEnabled(final Connection conn, final Host host) throws Types.XenAPIException, XmlRpcException { return true; } }; @@ -105,18 +103,18 @@ public class CitrixResourceBaseTest { @Test(expected = XmlRpcException.class) public void testScaleVMF1() throws Types.BadServerResponse, Types.XenAPIException, XmlRpcException { doReturn(conn).when(_resource).getConnection(); - Set vms = mock(Set.class); + final Set vms = mock(Set.class); - Iterator iter = mock(Iterator.class); + final Iterator iter = mock(Iterator.class); doReturn(iter).when(vms).iterator(); when(iter.hasNext()).thenReturn(true).thenReturn(false); doReturn(vm).when(iter).next(); - VM.Record vmr = mock(VM.Record.class); + final VM.Record vmr = mock(VM.Record.class); when(vm.getRecord(conn)).thenThrow(new XmlRpcException("XmlRpcException")); when(vm.getRecord(conn)).thenReturn(vmr); vmr.powerState = Types.VmPowerState.RUNNING; vmr.residentOn = mock(Host.class); - XenAPIObject object = mock(XenAPIObject.class); + final XenAPIObject object = mock(XenAPIObject.class); doReturn(new String("OpaqueRef:NULL")).when(object).toWireString(); doNothing().when(_resource).scaleVM(conn, vm, vmSpec, host); @@ -139,7 +137,7 @@ public class CitrixResourceBaseTest { doNothing().when(vm).setVCPUsNumberLive(conn, 1L); doReturn(500).when(vmSpec).getMinSpeed(); doReturn(false).when(vmSpec).getLimitCpuUse(); - Map args = mock(HashMap.class); + final Map args = mock(HashMap.class); when(host.callPlugin(conn, "vmops", "add_to_VCPUs_params_live", args)).thenReturn("Success"); doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); @@ -164,7 +162,7 @@ public class CitrixResourceBaseTest { doReturn(500).when(vmSpec).getMaxSpeed(); doReturn(true).when(vmSpec).getLimitCpuUse(); doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", "99", "vmname", "i-2-3-VM"); - Map args = mock(HashMap.class); + final Map args = mock(HashMap.class); when(host.callPlugin(conn, "vmops", "add_to_VCPUs_params_live", args)).thenReturn("Success"); doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); @@ -178,12 +176,12 @@ public class CitrixResourceBaseTest { @Test public void testSetNicDevIdIfCorrectVifIsNotNull() throws Exception { - IpAddressTO ip = mock(IpAddressTO.class); + final IpAddressTO ip = mock(IpAddressTO.class); when(ip.isAdd()).thenReturn(false); - VIF correctVif = null; + final VIF correctVif = null; try { _resource.setNicDevIdIfCorrectVifIsNotNull(conn, ip, correctVif); - } catch (NullPointerException e) { + } catch (final NullPointerException e) { fail("this test is meant to show that null pointer is not thrown"); } } 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 f8af54336e7..3e7fb574bcc 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 @@ -14,6 +14,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; @@ -96,4 +97,16 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testReadyCommandCommand() { + final ReadyCommand readyCommand = new ReadyCommand(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(readyCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } } \ No newline at end of file From 0e51379da72257e34fd24ae8d46df64981458347 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 10:16:16 +0100 Subject: [PATCH 05/30] Refactoring the GetHostStatsCommand - Added basic tests - Added test for when the key (Command) does not exist in the Map --- .../resource/CitrixResourceBase.java | 2 +- .../wrapper/CitrixRequestWrapper.java | 6 +++ .../wrapper/GetHostStatsCommandWrapper.java | 48 +++++++++++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 36 ++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetHostStatsCommandWrapper.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 850cbb39aa9..42d37d5f220 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 @@ -2250,7 +2250,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected HostStatsEntry getHostStats(final Connection conn, final GetHostStatsCommand cmd, final String hostGuid, final long hostId) { + public HostStatsEntry getHostStats(final Connection conn, final GetHostStatsCommand cmd, final String hostGuid, final long hostId) { final HostStatsEntry hostStats = new HostStatsEntry(hostId, 0, 0, 0, "host", 0, 0, 0, 0); final Object[] rrdData = getRRDData(conn, 1); // call rrd method with 1 for host 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 f2a921c0f72..98989ab006f 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 @@ -23,6 +23,7 @@ import java.util.Hashtable; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; @@ -55,6 +56,7 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(CheckConsoleProxyLoadCommand.class, new CitrixCheckConsoleProxyLoadCommandWrapper()); map.put(WatchConsoleProxyLoadCommand.class, new CitrixWatchConsoleProxyLoadCommandWrapper()); map.put(ReadyCommand.class, new CitrixReadyCommandWrapper()); + map.put(GetHostStatsCommand.class, new GetHostStatsCommandWrapper()); } public static CitrixRequestWrapper getInstance() { @@ -66,6 +68,10 @@ public class CitrixRequestWrapper extends RequestWrapper { @SuppressWarnings("unchecked") final CommandWrapper commandWrapper = map.get(command.getClass()); + if (commandWrapper == null) { + throw new NullPointerException("No key found for '" + command.getClass() + "' in the Map!"); + } + return commandWrapper.execute(command, serverResource); } } \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetHostStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetHostStatsCommandWrapper.java new file mode 100644 index 00000000000..d6053676c63 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetHostStatsCommandWrapper.java @@ -0,0 +1,48 @@ +// +// 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.GetHostStatsAnswer; +import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.HostStatsEntry; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class GetHostStatsCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(GetHostStatsCommandWrapper.class); + + @Override + public Answer execute(final GetHostStatsCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + try { + final HostStatsEntry hostStats = citrixResourceBase.getHostStats(conn, command, command.getHostGuid(), command.getHostId()); + return new GetHostStatsAnswer(command, hostStats); + } catch (final Exception e) { + final String msg = "Unable to get Host stats" + e.toString(); + s_logger.warn(msg, e); + return new GetHostStatsAnswer(command, null); + } + } +} \ No newline at end of file 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 3e7fb574bcc..027a5fdae7f 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 @@ -3,6 +3,7 @@ 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.assertTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -14,6 +15,8 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; @@ -41,6 +44,18 @@ public class CitrixRequestWrapperTest { assertNotNull(wrapper); } + @Test + public void testUnknownCommand() { + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + try { + wrapper.execute(new NotAValidCommand(), citrixResourceBase); + } catch (final Exception e) { + assertTrue(e instanceof NullPointerException); + } + } + @Test public void testExecuteRebootRouterCommand() { final RebootRouterCommand rebootCommand = new RebootRouterCommand("", ""); @@ -109,4 +124,25 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testGetHostStatsCommandCommand() { + final GetHostStatsCommand statsCommand = new GetHostStatsCommand(null, null, 0); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + + assertTrue(answer.getResult()); + } +} + +class NotAValidCommand extends Command { + + @Override + public boolean executeInSequence() { + return false; + } + } \ No newline at end of file From 8f04108e23dffc3f7930bdbe111eb11f2653b453 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 10:52:31 +0100 Subject: [PATCH 06/30] Refactoring the GetVmStatsCommand - Added basic tests --- .../resource/CitrixResourceBase.java | 4 +- .../wrapper/CitrixRequestWrapper.java | 2 + .../wrapper/GetVmStatsCommandWrapper.java | 82 +++++++++++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 15 ++++ 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmStatsCommandWrapper.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 42d37d5f220..024307d95b3 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 @@ -2358,7 +2358,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected HashMap getVmStats(final Connection conn, final GetVmStatsCommand cmd, final List vmUUIDs, final String hostGuid) { + public HashMap getVmStats(final Connection conn, final GetVmStatsCommand cmd, final List vmUUIDs, final String hostGuid) { final HashMap vmResponseMap = new HashMap(); for (final String vmUUID : vmUUIDs) { @@ -6674,7 +6674,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return false; } - protected VM getVM(final Connection conn, final String vmName) { + public VM getVM(final Connection conn, final String vmName) { // Look up VMs with the specified name Set vms; try { 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 98989ab006f..9c2f08dc0e0 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 @@ -24,6 +24,7 @@ import java.util.Hashtable; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; @@ -57,6 +58,7 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(WatchConsoleProxyLoadCommand.class, new CitrixWatchConsoleProxyLoadCommandWrapper()); map.put(ReadyCommand.class, new CitrixReadyCommandWrapper()); map.put(GetHostStatsCommand.class, new GetHostStatsCommandWrapper()); + map.put(GetVmStatsCommand.class, new GetVmStatsCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmStatsCommandWrapper.java new file mode 100644 index 00000000000..1b4863a99ab --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmStatsCommandWrapper.java @@ -0,0 +1,82 @@ +// +// 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.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.GetVmStatsAnswer; +import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.VmStatsEntry; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VM; + +public final class GetVmStatsCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(GetVmStatsCommandWrapper.class); + + @Override + public Answer execute(final GetVmStatsCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final List vmNames = command.getVmNames(); + final HashMap vmStatsNameMap = new HashMap(); + if (vmNames.size() == 0) { + return new GetVmStatsAnswer(command, vmStatsNameMap); + } + try { + + // Determine the UUIDs of the requested VMs + final List vmUUIDs = new ArrayList(); + + for (final String vmName : vmNames) { + final VM vm = citrixResourceBase.getVM(conn, vmName); + vmUUIDs.add(vm.getUuid(conn)); + } + + final HashMap vmStatsUUIDMap = citrixResourceBase.getVmStats(conn, command, vmUUIDs, command.getHostGuid()); + if (vmStatsUUIDMap == null) { + return new GetVmStatsAnswer(command, vmStatsNameMap); + } + + for (final Map.Entryentry : vmStatsUUIDMap.entrySet()) { + vmStatsNameMap.put(vmNames.get(vmUUIDs.indexOf(entry.getKey())), entry.getValue()); + } + + return new GetVmStatsAnswer(command, vmStatsNameMap); + } catch (final XenAPIException e) { + final String msg = "Unable to get VM stats" + e.toString(); + s_logger.warn(msg, e); + return new GetVmStatsAnswer(command, vmStatsNameMap); + } catch (final XmlRpcException e) { + final String msg = "Unable to get VM stats" + e.getMessage(); + s_logger.warn(msg, e); + return new GetVmStatsAnswer(command, vmStatsNameMap); + } + } +} \ No newline at end of file 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 027a5fdae7f..e54e809bac7 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 @@ -8,6 +8,8 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import java.util.ArrayList; + import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.junit.Test; import org.junit.runner.RunWith; @@ -17,6 +19,7 @@ import org.mockito.runners.MockitoJUnitRunner; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; @@ -136,6 +139,18 @@ public class CitrixRequestWrapperTest { assertTrue(answer.getResult()); } + + @Test + public void testGetVmStatsCommandCommand() { + final GetVmStatsCommand statsCommand = new GetVmStatsCommand(new ArrayList(), null, null); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + + assertTrue(answer.getResult()); + } } class NotAValidCommand extends Command { From c7830efef5d168adf37e64da639908f4186a01c2 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 11:05:43 +0100 Subject: [PATCH 07/30] Refactor the CheckHealthCommand and GetVmDiskStatsCommand classes in CitrixResourceBase - Added basic tests for both wrappers --- .../resource/CitrixResourceBase.java | 2 +- .../wrapper/CheckHealthCommandWrapper.java | 35 +++++++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 4 +++ .../wrapper/GetVmDiskStatsCommandWrapper.java | 34 ++++++++++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 26 ++++++++++++++ 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CheckHealthCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmDiskStatsCommandWrapper.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 024307d95b3..c7405fc942f 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 @@ -394,7 +394,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - protected boolean pingXAPI() { + public boolean pingXAPI() { final Connection conn = getConnection(); try { final Host host = Host.getByUuid(conn, _host.getUuid()); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CheckHealthCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CheckHealthCommandWrapper.java new file mode 100644 index 00000000000..fa2e0cad54a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CheckHealthCommandWrapper.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.CheckHealthAnswer; +import com.cloud.agent.api.CheckHealthCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; + +public final class CheckHealthCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final CheckHealthCommand command, final CitrixResourceBase citrixResourceBase) { + final boolean result = citrixResourceBase.pingXAPI(); + return new CheckHealthAnswer(command, 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 9c2f08dc0e0..b3996c19e06 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 @@ -22,8 +22,10 @@ package com.cloud.hypervisor.xenserver.resource.wrapper; import java.util.Hashtable; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootRouterCommand; @@ -59,6 +61,8 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(ReadyCommand.class, new CitrixReadyCommandWrapper()); map.put(GetHostStatsCommand.class, new GetHostStatsCommandWrapper()); map.put(GetVmStatsCommand.class, new GetVmStatsCommandWrapper()); + map.put(GetVmDiskStatsCommand.class, new GetVmDiskStatsCommandWrapper()); + map.put(CheckHealthCommand.class, new CheckHealthCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmDiskStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmDiskStatsCommandWrapper.java new file mode 100644 index 00000000000..a403322b625 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmDiskStatsCommandWrapper.java @@ -0,0 +1,34 @@ +// +// 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.GetVmDiskStatsAnswer; +import com.cloud.agent.api.GetVmDiskStatsCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; + +public final class GetVmDiskStatsCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final GetVmDiskStatsCommand command, final CitrixResourceBase citrixResourceBase) { + return new GetVmDiskStatsAnswer(command, null, null, null); + } +} \ No newline at end of file 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 e54e809bac7..69071c0e074 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 @@ -17,8 +17,10 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; @@ -151,6 +153,30 @@ public class CitrixRequestWrapperTest { assertTrue(answer.getResult()); } + + @Test + public void testGetVmDiskStatsCommandCommand() { + final GetVmDiskStatsCommand statsCommand = new GetVmDiskStatsCommand(new ArrayList(), null, null); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + + assertTrue(answer.getResult()); + } + + @Test + public void testCheckHealthCommandCommand() { + final CheckHealthCommand statsCommand = new CheckHealthCommand(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 6b80c79986cf5012ea951bb88040a747dd8f2556 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 11:15:37 +0100 Subject: [PATCH 08/30] Refactoring the StopCommand on CitrixResourceBase to cope with new design - Added basic tests --- .../resource/CitrixResourceBase.java | 18 +- .../wrapper/CitrixRequestWrapper.java | 2 + .../resource/wrapper/StopCommandWrapper.java | 173 ++++++++++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 13 ++ 4 files changed, 199 insertions(+), 7 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/StopCommandWrapper.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 c7405fc942f..7c80f645c8b 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 @@ -339,6 +339,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return _host; } + public boolean canBridgeFirewall() { + return _canBridgeFirewall; + } + private static boolean isAlienVm(final VM vm, final Connection conn) throws XenAPIException, XmlRpcException { // TODO : we need a better way to tell whether or not the VM belongs to CloudStack final String vmName = vm.getNameLabel(conn); @@ -374,7 +378,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return success; } - protected boolean isRefNull(final XenAPIObject object) { + public boolean isRefNull(final XenAPIObject object) { return object == null || object.toWireString().equals("OpaqueRef:NULL") || object.toWireString().equals(""); } @@ -1311,7 +1315,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - protected HashMap> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException { + public HashMap> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException { return null; } @@ -2877,7 +2881,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - protected void removeSR(final Connection conn, final SR sr) { + public void removeSR(final Connection conn, final SR sr) { if (sr == null) { return; } @@ -3272,7 +3276,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - void shutdownVM(final Connection conn, final VM vm, final String vmName) throws XmlRpcException { + public void shutdownVM(final Connection conn, final VM vm, final String vmName) throws XmlRpcException { Task task = null; try { task = vm.cleanShutdownAsync(conn); @@ -3672,7 +3676,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("Could not find an available slot in VM with name to attach a new disk."); } - protected String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) { + public String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) { final Map args = new HashMap(); String msg; try { @@ -4056,7 +4060,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vlanNetwork; } - protected void disableVlanNetwork(final Connection conn, final Network network) { + public void disableVlanNetwork(final Connection conn, final Network network) { } protected SR getLocalLVMSR(final Connection conn) { @@ -5736,7 +5740,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected SR getISOSRbyVmName(final Connection conn, final String vmName) { + public SR getISOSRbyVmName(final Connection conn, final String vmName) { try { final Set srs = SR.getByNameLabel(conn, vmName + "-ISO"); if (srs.size() == 0) { 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 b3996c19e06..5eb3882f627 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 @@ -29,6 +29,7 @@ import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateCommand; @@ -63,6 +64,7 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(GetVmStatsCommand.class, new GetVmStatsCommandWrapper()); map.put(GetVmDiskStatsCommand.class, new GetVmDiskStatsCommandWrapper()); map.put(CheckHealthCommand.class, new CheckHealthCommandWrapper()); + map.put(StopCommand.class, new StopCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/StopCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/StopCommandWrapper.java new file mode 100644 index 00000000000..bca90b54661 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/StopCommandWrapper.java @@ -0,0 +1,173 @@ +// +// 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.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.StopAnswer; +import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.VgpuTypesInfo; +import com.cloud.agent.api.to.GPUDeviceTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.StringUtils; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Types.VmPowerState; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VGPU; +import com.xensource.xenapi.VIF; +import com.xensource.xenapi.VM; + +public final class StopCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(StopCommandWrapper.class); + + @Override + public Answer execute(final StopCommand command, final CitrixResourceBase citrixResourceBase) { + final String vmName = command.getVmName(); + String platformstring = null; + try { + final Connection conn = citrixResourceBase.getConnection(); + final Set vms = VM.getByNameLabel(conn, vmName); + // 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.RUNNING) { + continue; + } + if (citrixResourceBase.isRefNull(vmr.residentOn)) { + continue; + } + if (vmr.residentOn.getUuid(conn).equals(citrixResourceBase.getHost().getUuid())) { + continue; + } + iter.remove(); + } + + if (vms.size() == 0) { + return new StopAnswer(command, "VM does not exist", true); + } + for (final VM vm : vms) { + final VM.Record vmr = vm.getRecord(conn); + platformstring = StringUtils.mapToString(vmr.platform); + if (vmr.isControlDomain) { + final String msg = "Tring to Shutdown control domain"; + s_logger.warn(msg); + return new StopAnswer(command, msg, false); + } + + if (vmr.powerState == VmPowerState.RUNNING && !citrixResourceBase.isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(citrixResourceBase.getHost().getUuid())) { + final String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + citrixResourceBase.getHost().getUuid() + " but host:" + vmr.residentOn.getUuid(conn); + s_logger.warn(msg); + return new StopAnswer(command, msg, platformstring, false); + } + + if (command.checkBeforeCleanup() && vmr.powerState == VmPowerState.RUNNING) { + final String msg = "Vm " + vmName + " is running on host and checkBeforeCleanup flag is set, so bailing out"; + s_logger.debug(msg); + return new StopAnswer(command, msg, false); + } + + s_logger.debug("9. The VM " + vmName + " is in Stopping state"); + + try { + if (vmr.powerState == VmPowerState.RUNNING) { + /* when stop a vm, set affinity to current xenserver */ + vm.setAffinity(conn, vm.getResidentOn(conn)); + + if (citrixResourceBase.canBridgeFirewall()) { + final String result = citrixResourceBase.callHostPlugin(conn, "vmops", "destroy_network_rules_for_vm", "vmName", command.getVmName()); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to remove network rules for vm " + command.getVmName()); + } else { + s_logger.info("Removed network rules for vm " + command.getVmName()); + } + } + citrixResourceBase.shutdownVM(conn, vm, vmName); + } + } catch (final Exception e) { + final String msg = "Catch exception " + e.getClass().getName() + " when stop VM:" + command.getVmName() + " due to " + e.toString(); + s_logger.debug(msg); + return new StopAnswer(command, msg, platformstring, false); + } finally { + + try { + if (vm.getPowerState(conn) == VmPowerState.HALTED) { + Set vGPUs = null; + // Get updated GPU details + try { + vGPUs = vm.getVGPUs(conn); + } catch (final XenAPIException e2) { + s_logger.debug("VM " + vmName + " does not have GPU support."); + } + if (vGPUs != null && !vGPUs.isEmpty()) { + final HashMap> groupDetails = citrixResourceBase.getGPUGroupDetails(conn); + command.setGpuDevice(new GPUDeviceTO(null, null, groupDetails)); + } + + final Set vifs = vm.getVIFs(conn); + final List networks = new ArrayList(); + for (final VIF vif : vifs) { + networks.add(vif.getNetwork(conn)); + } + vm.destroy(conn); + final SR sr = citrixResourceBase.getISOSRbyVmName(conn, command.getVmName()); + citrixResourceBase.removeSR(conn, sr); + // Disable any VLAN networks that aren't used + // anymore + for (final Network network : networks) { + try { + if (network.getNameLabel(conn).startsWith("VLAN")) { + citrixResourceBase.disableVlanNetwork(conn, network); + } + } catch (final Exception e) { + // network might be destroyed by other host + } + } + return new StopAnswer(command, "Stop VM " + vmName + " Succeed", platformstring, true); + } + } catch (final Exception e) { + final String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.getMessage(); + s_logger.warn(msg, e); + } finally { + s_logger.debug("10. The VM " + vmName + " is in Stopped state"); + } + } + } + + } catch (final Exception e) { + final String msg = "Stop Vm " + vmName + " fail due to " + e.toString(); + s_logger.warn(msg, e); + return new StopAnswer(command, msg, platformstring, false); + } + return new StopAnswer(command, "Stop VM failed", platformstring, false); + } +} \ No newline at end of file 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 69071c0e074..74f7cdc091a 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 @@ -26,6 +26,7 @@ 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.StopCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateAnswer; @@ -177,6 +178,18 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testStopCommandCommand() { + final StopCommand statsCommand = new StopCommand("Test", false, false); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 9e41b8051e4a0f41e8867b2b311cf7762cf66ad8 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 11:20:53 +0100 Subject: [PATCH 09/30] Renaming files - Forgot to add "Citrix" before the new command wrappers --- ...apper.java => CitrixCheckHealthCommandWrapper.java} | 2 +- ...pper.java => CitrixGetHostStatsCommandWrapper.java} | 4 ++-- ...er.java => CitrixGetVmDiskStatsCommandWrapper.java} | 2 +- ...rapper.java => CitrixGetVmStatsCommandWrapper.java} | 4 ++-- .../resource/wrapper/CitrixRequestWrapper.java | 10 +++++----- ...mmandWrapper.java => CitrixStopCommandWrapper.java} | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) rename plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/{CheckHealthCommandWrapper.java => CitrixCheckHealthCommandWrapper.java} (91%) rename plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/{GetHostStatsCommandWrapper.java => CitrixGetHostStatsCommandWrapper.java} (89%) rename plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/{GetVmDiskStatsCommandWrapper.java => CitrixGetVmDiskStatsCommandWrapper.java} (90%) rename plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/{GetVmStatsCommandWrapper.java => CitrixGetVmStatsCommandWrapper.java} (93%) rename plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/{StopCommandWrapper.java => CitrixStopCommandWrapper.java} (97%) diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CheckHealthCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckHealthCommandWrapper.java similarity index 91% rename from plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CheckHealthCommandWrapper.java rename to plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckHealthCommandWrapper.java index fa2e0cad54a..f77e3092ab7 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CheckHealthCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckHealthCommandWrapper.java @@ -25,7 +25,7 @@ import com.cloud.agent.api.CheckHealthCommand; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.resource.CommandWrapper; -public final class CheckHealthCommandWrapper extends CommandWrapper { +public final class CitrixCheckHealthCommandWrapper extends CommandWrapper { @Override public Answer execute(final CheckHealthCommand command, final CitrixResourceBase citrixResourceBase) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetHostStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetHostStatsCommandWrapper.java similarity index 89% rename from plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetHostStatsCommandWrapper.java rename to plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetHostStatsCommandWrapper.java index d6053676c63..21d9d3d9138 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetHostStatsCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetHostStatsCommandWrapper.java @@ -29,9 +29,9 @@ import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.resource.CommandWrapper; import com.xensource.xenapi.Connection; -public final class GetHostStatsCommandWrapper extends CommandWrapper { +public final class CitrixGetHostStatsCommandWrapper extends CommandWrapper { - private static final Logger s_logger = Logger.getLogger(GetHostStatsCommandWrapper.class); + private static final Logger s_logger = Logger.getLogger(CitrixGetHostStatsCommandWrapper.class); @Override public Answer execute(final GetHostStatsCommand command, final CitrixResourceBase citrixResourceBase) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmDiskStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVmDiskStatsCommandWrapper.java similarity index 90% rename from plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmDiskStatsCommandWrapper.java rename to plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVmDiskStatsCommandWrapper.java index a403322b625..682d2025056 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmDiskStatsCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVmDiskStatsCommandWrapper.java @@ -25,7 +25,7 @@ import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.resource.CommandWrapper; -public final class GetVmDiskStatsCommandWrapper extends CommandWrapper { +public final class CitrixGetVmDiskStatsCommandWrapper extends CommandWrapper { @Override public Answer execute(final GetVmDiskStatsCommand command, final CitrixResourceBase citrixResourceBase) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVmStatsCommandWrapper.java similarity index 93% rename from plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmStatsCommandWrapper.java rename to plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVmStatsCommandWrapper.java index 1b4863a99ab..2b535ea1c41 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/GetVmStatsCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVmStatsCommandWrapper.java @@ -37,9 +37,9 @@ import com.xensource.xenapi.Connection; import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VM; -public final class GetVmStatsCommandWrapper extends CommandWrapper { +public final class CitrixGetVmStatsCommandWrapper extends CommandWrapper { - private static final Logger s_logger = Logger.getLogger(GetVmStatsCommandWrapper.class); + private static final Logger s_logger = Logger.getLogger(CitrixGetVmStatsCommandWrapper.class); @Override public Answer execute(final GetVmStatsCommand command, final CitrixResourceBase citrixResourceBase) { 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 5eb3882f627..5e3e6e4b8e2 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 @@ -60,11 +60,11 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(CheckConsoleProxyLoadCommand.class, new CitrixCheckConsoleProxyLoadCommandWrapper()); map.put(WatchConsoleProxyLoadCommand.class, new CitrixWatchConsoleProxyLoadCommandWrapper()); map.put(ReadyCommand.class, new CitrixReadyCommandWrapper()); - map.put(GetHostStatsCommand.class, new GetHostStatsCommandWrapper()); - map.put(GetVmStatsCommand.class, new GetVmStatsCommandWrapper()); - map.put(GetVmDiskStatsCommand.class, new GetVmDiskStatsCommandWrapper()); - map.put(CheckHealthCommand.class, new CheckHealthCommandWrapper()); - map.put(StopCommand.class, new StopCommandWrapper()); + map.put(GetHostStatsCommand.class, new CitrixGetHostStatsCommandWrapper()); + map.put(GetVmStatsCommand.class, new CitrixGetVmStatsCommandWrapper()); + map.put(GetVmDiskStatsCommand.class, new CitrixGetVmDiskStatsCommandWrapper()); + map.put(CheckHealthCommand.class, new CitrixCheckHealthCommandWrapper()); + map.put(StopCommand.class, new CitrixStopCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/StopCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixStopCommandWrapper.java similarity index 97% rename from plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/StopCommandWrapper.java rename to plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixStopCommandWrapper.java index bca90b54661..ce8517f85c8 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/StopCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixStopCommandWrapper.java @@ -44,9 +44,9 @@ import com.xensource.xenapi.VGPU; import com.xensource.xenapi.VIF; import com.xensource.xenapi.VM; -public final class StopCommandWrapper extends CommandWrapper { +public final class CitrixStopCommandWrapper extends CommandWrapper { - private static final Logger s_logger = Logger.getLogger(StopCommandWrapper.class); + private static final Logger s_logger = Logger.getLogger(CitrixStopCommandWrapper.class); @Override public Answer execute(final StopCommand command, final CitrixResourceBase citrixResourceBase) { From f2fab5c8c367c73463320375a56d55abbe0c4a61 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 11:39:29 +0100 Subject: [PATCH 10/30] Refactoring the CitrixRebootCommand in order to have the new design applied - Added basic tests - Changed the way RebootCommand gets called from RebootRouterCommand - Made a couple of methods public in the CitrixResourceBase and its subclasses --- .../resource/CitrixResourceBase.java | 2 +- .../resource/XenServer56Resource.java | 2 +- .../resource/XenServer620SP1Resource.java | 2 +- .../wrapper/CitrixRebootCommandWrapper.java | 68 +++++++++++++++++++ .../CitrixRebootRouterCommandWrapper.java | 6 +- .../wrapper/CitrixRequestWrapper.java | 2 + .../wrapper/CitrixRequestWrapperTest.java | 16 ++--- 7 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootCommandWrapper.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 7c80f645c8b..7882b0e9feb 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 @@ -3228,7 +3228,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - void rebootVM(final Connection conn, final VM vm, final String vmName) throws Exception { + public void rebootVM(final Connection conn, final VM vm, final String vmName) throws Exception { Task task = null; try { task = vm.cleanRebootAsync(conn); 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 1de7b963be2..1bb2ff439b2 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 @@ -80,7 +80,7 @@ public class XenServer56Resource extends CitrixResourceBase { } @Override - protected void disableVlanNetwork(final Connection conn, final Network network) { + public void disableVlanNetwork(final Connection conn, final Network network) { try { final Network.Record networkr = network.getRecord(conn); if (!networkr.nameLabel.startsWith("VLAN")) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java index ac2b2a62f9d..e6c66a41c14 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java @@ -94,7 +94,7 @@ public class XenServer620SP1Resource extends XenServer620Resource { } @Override - protected HashMap> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException { + public HashMap> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException { final HashMap> groupDetails = new HashMap>(); final Host host = Host.getByUuid(conn, _host.getUuid()); final Set pgpus = host.getPGPUs(conn); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootCommandWrapper.java new file mode 100644 index 00000000000..f2cb54c3cc1 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootCommandWrapper.java @@ -0,0 +1,68 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.hypervisor.xenserver.resource.wrapper; + +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.RebootAnswer; +import com.cloud.agent.api.RebootCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VM; + +public final class CitrixRebootCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixRebootCommandWrapper.class); + + @Override + public Answer execute(final RebootCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + s_logger.debug("7. The VM " + command.getVmName() + " is in Starting state"); + try { + Set vms = null; + try { + vms = VM.getByNameLabel(conn, command.getVmName()); + } catch (final XenAPIException e0) { + s_logger.debug("getByNameLabel failed " + e0.toString()); + return new RebootAnswer(command, "getByNameLabel failed " + e0.toString(), false); + } catch (final Exception e0) { + s_logger.debug("getByNameLabel failed " + e0.getMessage()); + return new RebootAnswer(command, "getByNameLabel failed", false); + } + for (final VM vm : vms) { + try { + citrixResourceBase.rebootVM(conn, vm, vm.getNameLabel(conn)); + } catch (final Exception e) { + final String msg = e.toString(); + s_logger.warn(msg, e); + return new RebootAnswer(command, msg, false); + } + } + return new RebootAnswer(command, "reboot succeeded", true); + } finally { + s_logger.debug("8. The VM " + command.getVmName() + " is in Running state"); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootRouterCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootRouterCommandWrapper.java index c244335119c..5d860b9e633 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootRouterCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRebootRouterCommandWrapper.java @@ -20,7 +20,6 @@ package com.cloud.hypervisor.xenserver.resource.wrapper; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; @@ -33,7 +32,10 @@ public final class CitrixRebootRouterCommandWrapper extends CommandWrapper Date: Tue, 24 Mar 2015 11:54:21 +0100 Subject: [PATCH 11/30] Refactoring the CitrixCheckVirtualMachineCommand toc ope with new design - Added basic tests - Added tests for RebootRouterCommand - Removed the code from CitrixResourceBase that has already been refactored --- .../resource/CitrixResourceBase.java | 40 ++++++---------- ...trixCheckVirtualMachineCommandWrapper.java | 48 +++++++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 2 + .../wrapper/CitrixRequestWrapperTest.java | 28 +++++++++++ 4 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckVirtualMachineCommandWrapper.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 7882b0e9feb..30c96ee5273 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 @@ -189,6 +189,7 @@ import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; import com.cloud.exception.InternalErrorException; import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.xenserver.resource.wrapper.CitrixRequestWrapper; import com.cloud.network.Networks; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; @@ -426,33 +427,20 @@ 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. + } + final Class clazz = cmd.getClass(); - if (clazz == CreateCommand.class) { - return execute((CreateCommand)cmd); - } else if (cmd instanceof NetworkElementCommand) { + + if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == CheckConsoleProxyLoadCommand.class) { - return execute((CheckConsoleProxyLoadCommand)cmd); - } else if (clazz == WatchConsoleProxyLoadCommand.class) { - return execute((WatchConsoleProxyLoadCommand)cmd); - } else if (clazz == ReadyCommand.class) { - return execute((ReadyCommand)cmd); - } else if (clazz == GetHostStatsCommand.class) { - return execute((GetHostStatsCommand)cmd); - } else if (clazz == GetVmStatsCommand.class) { - return execute((GetVmStatsCommand)cmd); - } else if (clazz == GetVmDiskStatsCommand.class) { - return execute((GetVmDiskStatsCommand)cmd); - } else if (clazz == CheckHealthCommand.class) { - return execute((CheckHealthCommand)cmd); - } else if (clazz == StopCommand.class) { - return execute((StopCommand)cmd); - } else if (clazz == RebootRouterCommand.class) { - return execute((RebootRouterCommand)cmd); - } else if (clazz == RebootCommand.class) { - return execute((RebootCommand)cmd); - } else if (clazz == CheckVirtualMachineCommand.class) { - return execute((CheckVirtualMachineCommand)cmd); } else if (clazz == PrepareForMigrationCommand.class) { return execute((PrepareForMigrationCommand)cmd); } else if (clazz == MigrateCommand.class) { @@ -2621,7 +2609,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vmStates; } - protected PowerState getVmState(final Connection conn, final String vmName) { + public PowerState getVmState(final Connection conn, final String vmName) { int retry = 3; while (retry-- > 0) { try { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckVirtualMachineCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckVirtualMachineCommandWrapper.java new file mode 100644 index 00000000000..1ae20c1bcfb --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckVirtualMachineCommandWrapper.java @@ -0,0 +1,48 @@ +// +// 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.CheckVirtualMachineAnswer; +import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.vm.VirtualMachine.PowerState; +import com.xensource.xenapi.Connection; + +public final class CitrixCheckVirtualMachineCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixCheckVirtualMachineCommandWrapper.class); + + @Override + public Answer execute(final CheckVirtualMachineCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final String vmName = command.getVmName(); + final PowerState powerState = citrixResourceBase.getVmState(conn, vmName); + final Integer vncPort = null; + if (powerState == PowerState.PowerOn) { + s_logger.debug("3. The VM " + vmName + " is in Running state"); + } + + return new CheckVirtualMachineAnswer(command, powerState, vncPort); + } +} \ 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 f83218bc7b5..77879f988ec 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 @@ -23,6 +23,7 @@ import java.util.Hashtable; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckHealthCommand; +import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; @@ -67,6 +68,7 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(CheckHealthCommand.class, new CitrixCheckHealthCommandWrapper()); map.put(StopCommand.class, new CitrixStopCommandWrapper()); map.put(RebootCommand.class, new CitrixRebootCommandWrapper()); + map.put(CheckVirtualMachineCommand.class, new CitrixCheckVirtualMachineCommandWrapper()); } 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 98023f76382..2237cf11aa1 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 @@ -16,12 +16,14 @@ import org.mockito.runners.MockitoJUnitRunner; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckHealthCommand; +import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; 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.StopCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; @@ -182,6 +184,32 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testRebootCommand() { + final RebootCommand rebootCommand = new RebootCommand("Test"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(rebootCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testCheckVirtualMachineCommandCommand() { + final CheckVirtualMachineCommand statsCommand = new CheckVirtualMachineCommand("Test"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + + assertTrue(answer.getResult()); + } } class NotAValidCommand extends Command { From a70d80dfd690b6cda2dde0eff163da31f55c24ee Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 13:51:48 +0100 Subject: [PATCH 12/30] Refactoring PrepareForMigrationCommand and MigrateCommand in order to cope with the new design - Basic tests added --- .../resource/CitrixResourceBase.java | 6 +- .../wrapper/CitrixMigrateCommandWrapper.java | 84 +++++++++++++++++++ ...trixPrepareForMigrationCommandWrapper.java | 61 ++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 4 + .../wrapper/CitrixRequestWrapperTest.java | 49 ++++++++--- 5 files changed, 190 insertions(+), 14 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixMigrateCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPrepareForMigrationCommandWrapper.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 30c96ee5273..2f7ba8b8398 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 @@ -1013,7 +1013,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected Network getNetwork(final Connection conn, final NicTO nic) throws XenAPIException, XmlRpcException { + public Network getNetwork(final Connection conn, final NicTO nic) throws XenAPIException, XmlRpcException { final String name = nic.getName(); final XsLocalNetwork network = getNativeNetworkForTraffic(conn, nic.getType(), name); if (network == null) { @@ -1125,7 +1125,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vif; } - protected void prepareISO(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException { + public void prepareISO(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException { final Set vms = VM.getByNameLabel(conn, vmName); if (vms == null || vms.size() != 1) { @@ -3355,7 +3355,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - private void migrateVM(final Connection conn, final Host destHost, final VM vm, final String vmName) throws Exception { + public void migrateVM(final Connection conn, final Host destHost, final VM vm, final String vmName) throws Exception { Task task = null; try { final Map other = new HashMap(); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixMigrateCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixMigrateCommandWrapper.java new file mode 100644 index 00000000000..6c5e55c071a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixMigrateCommandWrapper.java @@ -0,0 +1,84 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.MigrateAnswer; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VM; + +public final class CitrixMigrateCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixMigrateCommandWrapper.class); + + @Override + public Answer execute(final MigrateCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final String vmName = command.getVmName(); + + try { + final Set vms = VM.getByNameLabel(conn, vmName); + + final String ipaddr = command.getDestinationIp(); + + final Set hosts = Host.getAll(conn); + Host dsthost = null; + if(hosts != null) { + for (final Host host : hosts) { + if (host.getAddress(conn).equals(ipaddr)) { + dsthost = host; + break; + } + } + } + if (dsthost == null) { + final String msg = "Migration failed due to unable to find host " + ipaddr + " in XenServer pool " + citrixResourceBase.getHost().getPool(); + s_logger.warn(msg); + return new MigrateAnswer(command, false, msg, null); + } + for (final VM vm : vms) { + final Set vbds = vm.getVBDs(conn); + for (final VBD vbd : vbds) { + final VBD.Record vbdRec = vbd.getRecord(conn); + if (vbdRec.type.equals(Types.VbdType.CD) && !vbdRec.empty) { + vbd.eject(conn); + break; + } + } + citrixResourceBase.migrateVM(conn, dsthost, vm, vmName); + vm.setAffinity(conn, dsthost); + } + return new MigrateAnswer(command, true, "migration succeeded", null); + } catch (final Exception e) { + s_logger.warn(e.getMessage(), e); + return new MigrateAnswer(command, false, e.getMessage(), null); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPrepareForMigrationCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPrepareForMigrationCommandWrapper.java new file mode 100644 index 00000000000..a8bc18248be --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPrepareForMigrationCommandWrapper.java @@ -0,0 +1,61 @@ +// +// 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.PrepareForMigrationAnswer; +import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixPrepareForMigrationCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixPrepareForMigrationCommandWrapper.class); + + @Override + public Answer execute(final PrepareForMigrationCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + + final VirtualMachineTO vm = command.getVirtualMachine(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Preparing host for migrating " + vm); + } + + final NicTO[] nics = vm.getNics(); + try { + citrixResourceBase.prepareISO(conn, vm.getName()); + + for (final NicTO nic : nics) { + citrixResourceBase.getNetwork(conn, nic); + } + s_logger.debug("4. The VM " + vm.getName() + " is in Migrating state"); + + return new PrepareForMigrationAnswer(command); + } catch (final Exception e) { + s_logger.warn("Catch Exception " + e.getClass().getName() + " prepare for migration failed due to " + e.toString(), e); + return new PrepareForMigrationAnswer(command, e); + } + } +} \ 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 77879f988ec..ca0b7d03114 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 @@ -28,6 +28,8 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; @@ -69,6 +71,8 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(StopCommand.class, new CitrixStopCommandWrapper()); map.put(RebootCommand.class, new CitrixRebootCommandWrapper()); map.put(CheckVirtualMachineCommand.class, new CitrixCheckVirtualMachineCommandWrapper()); + map.put(PrepareForMigrationCommand.class, new CitrixPrepareForMigrationCommandWrapper()); + map.put(MigrateCommand.class, new CitrixMigrateCommandWrapper()); } 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 2237cf11aa1..e895581767f 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 @@ -21,6 +21,8 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; @@ -30,6 +32,7 @@ import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.vm.DiskProfile; @@ -37,11 +40,11 @@ import com.cloud.vm.DiskProfile; public class CitrixRequestWrapperTest { @Mock - protected CitrixResourceBase citrixResourceBase; + private CitrixResourceBase citrixResourceBase; @Mock - protected RebootAnswer rebootAnswer; + private RebootAnswer rebootAnswer; @Mock - protected CreateAnswer createAnswer; + private CreateAnswer createAnswer; @Test public void testWrapperInstance() { @@ -114,7 +117,7 @@ public class CitrixRequestWrapperTest { } @Test - public void testReadyCommandCommand() { + public void testReadyCommand() { final ReadyCommand readyCommand = new ReadyCommand(); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); @@ -126,7 +129,7 @@ public class CitrixRequestWrapperTest { } @Test - public void testGetHostStatsCommandCommand() { + public void testGetHostStatsCommand() { final GetHostStatsCommand statsCommand = new GetHostStatsCommand(null, null, 0); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); @@ -138,7 +141,7 @@ public class CitrixRequestWrapperTest { } @Test - public void testGetVmStatsCommandCommand() { + public void testGetVmStatsCommand() { final GetVmStatsCommand statsCommand = new GetVmStatsCommand(new ArrayList(), null, null); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); @@ -150,7 +153,7 @@ public class CitrixRequestWrapperTest { } @Test - public void testGetVmDiskStatsCommandCommand() { + public void testGetVmDiskStatsCommand() { final GetVmDiskStatsCommand statsCommand = new GetVmDiskStatsCommand(new ArrayList(), null, null); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); @@ -162,7 +165,7 @@ public class CitrixRequestWrapperTest { } @Test - public void testCheckHealthCommandCommand() { + public void testCheckHealthCommand() { final CheckHealthCommand statsCommand = new CheckHealthCommand(); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); @@ -200,16 +203,40 @@ public class CitrixRequestWrapperTest { } @Test - public void testCheckVirtualMachineCommandCommand() { - final CheckVirtualMachineCommand statsCommand = new CheckVirtualMachineCommand("Test"); + public void testCheckVirtualMachineCommand() { + final CheckVirtualMachineCommand virtualMachineCommand = new CheckVirtualMachineCommand("Test"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + final Answer answer = wrapper.execute(virtualMachineCommand, citrixResourceBase); assertTrue(answer.getResult()); } + + @Test + public void testPrepareForMigrationCommand() { + final PrepareForMigrationCommand prepareCommand = new PrepareForMigrationCommand(new VirtualMachineTO(0, "Test", null, 2, 200, 256, 512, null, "CentOS", true, false, "123")); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(prepareCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } + + @Test + public void testMigrateCommand() { + final MigrateCommand migrateCommand = new MigrateCommand("Test", "127.0.0.1", false, new VirtualMachineTO(0, "Test", null, 2, 200, 256, 512, null, "CentOS", true, false, "123"), false); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(migrateCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From a06958f46927cc5e1555f45d0678977b37c9261e Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 14:31:19 +0100 Subject: [PATCH 13/30] Refactoring DestroyCommand and CreateStoragePoolCommand wrappers to cope with the new design - Basic tests added s Please enter the commit message for your changes. Lines starting --- .../resource/CitrixResourceBase.java | 10 +-- ...CitrixCreateStoragePoolCommandWrapper.java | 57 +++++++++++++ .../wrapper/CitrixDestroyCommandWrapper.java | 83 +++++++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 4 + .../wrapper/CitrixRequestWrapperTest.java | 49 ++++++++++- 5 files changed, 192 insertions(+), 11 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateStoragePoolCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDestroyCommandWrapper.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 2f7ba8b8398..e9353034875 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 @@ -441,12 +441,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == PrepareForMigrationCommand.class) { - return execute((PrepareForMigrationCommand)cmd); - } else if (clazz == MigrateCommand.class) { - return execute((MigrateCommand)cmd); - } else if (clazz == DestroyCommand.class) { - return execute((DestroyCommand)cmd); } else if (clazz == CreateStoragePoolCommand.class) { return execute((CreateStoragePoolCommand)cmd); } else if (clazz == ModifyStoragePoolCommand.class) { @@ -5863,7 +5857,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected SR getIscsiSR(final Connection conn, final String srNameLabel, final String target, String path, final String chapInitiatorUsername, final String chapInitiatorPassword, + public SR getIscsiSR(final Connection conn, final String srNameLabel, final String target, String path, final String chapInitiatorUsername, final String chapInitiatorPassword, final boolean ignoreIntroduceException) { synchronized (srNameLabel.intern()) { final Map deviceConfig = new HashMap(); @@ -6007,7 +6001,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected SR getNfsSR(final Connection conn, final String poolid, final String uuid, final String server, String serverpath, final String pooldesc) { + public SR getNfsSR(final Connection conn, final String poolid, final String uuid, final String server, String serverpath, final String pooldesc) { final Map deviceConfig = new HashMap(); try { serverpath = serverpath.replace("//", "/"); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateStoragePoolCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateStoragePoolCommandWrapper.java new file mode 100644 index 00000000000..f749abb04a9 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateStoragePoolCommandWrapper.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.CreateStoragePoolCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.storage.Storage.StoragePoolType; +import com.xensource.xenapi.Connection; + +public final class CitrixCreateStoragePoolCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixCreateStoragePoolCommandWrapper.class); + + @Override + public Answer execute(final CreateStoragePoolCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final StorageFilerTO pool = command.getPool(); + try { + if (pool.getType() == StoragePoolType.NetworkFilesystem) { + citrixResourceBase.getNfsSR(conn, Long.toString(pool.getId()), pool.getUuid(), pool.getHost(), pool.getPath(), pool.toString()); + } else if (pool.getType() == StoragePoolType.IscsiLUN) { + citrixResourceBase.getIscsiSR(conn, pool.getUuid(), pool.getHost(), pool.getPath(), null, null, false); + } else if (pool.getType() == StoragePoolType.PreSetup) { + } else { + return new Answer(command, false, "The pool type: " + pool.getType().name() + " is not supported."); + } + return new Answer(command, true, "success"); + } catch (final Exception e) { + final String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + + citrixResourceBase.getHost().getUuid() + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDestroyCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDestroyCommandWrapper.java new file mode 100644 index 00000000000..0685a1b8eb9 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDestroyCommandWrapper.java @@ -0,0 +1,83 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; + +public final class CitrixDestroyCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixDestroyCommandWrapper.class); + + @Override + public Answer execute(final DestroyCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final VolumeTO vol = command.getVolume(); + // Look up the VDI + final String volumeUUID = vol.getPath(); + VDI vdi = null; + try { + vdi = citrixResourceBase.getVDIbyUuid(conn, volumeUUID); + } catch (final Exception e) { + return new Answer(command, true, "Success"); + } + Set vbds = null; + try { + vbds = vdi.getVBDs(conn); + } catch (final Exception e) { + final String msg = "VDI getVBDS for " + volumeUUID + " failed due to " + e.toString(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } + for (final VBD vbd : vbds) { + try { + vbd.unplug(conn); + vbd.destroy(conn); + } catch (final Exception e) { + final String msg = "VM destroy for " + volumeUUID + " failed due to " + e.toString(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } + } + try { + final Set snapshots = vdi.getSnapshots(conn); + for (final VDI snapshot : snapshots) { + snapshot.destroy(conn); + } + vdi.destroy(conn); + } catch (final Exception e) { + final String msg = "VDI destroy for " + volumeUUID + " failed due to " + e.toString(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } + + return new Answer(command, true, "Success"); + } +} \ 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 ca0b7d03114..af5e5b40c30 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 @@ -25,6 +25,7 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; +import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; @@ -37,6 +38,7 @@ import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateCommand; +import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; import com.cloud.resource.ServerResource; @@ -73,6 +75,8 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(CheckVirtualMachineCommand.class, new CitrixCheckVirtualMachineCommandWrapper()); map.put(PrepareForMigrationCommand.class, new CitrixPrepareForMigrationCommandWrapper()); map.put(MigrateCommand.class, new CitrixMigrateCommandWrapper()); + map.put(DestroyCommand.class, new CitrixDestroyCommandWrapper()); + map.put(CreateStoragePoolCommand.class, new CitrixCreateStoragePoolCommandWrapper()); } 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 e895581767f..baf7a55517f 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 @@ -5,6 +5,7 @@ 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 java.util.ArrayList; @@ -12,12 +13,14 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; +import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; @@ -32,8 +35,11 @@ import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; 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.to.VirtualMachineTO; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.hypervisor.xenserver.resource.XsHost; +import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.vm.DiskProfile; @RunWith(MockitoJUnitRunner.class) @@ -80,7 +86,9 @@ public class CitrixRequestWrapperTest { @Test public void testExecuteCreateCommand() { - final CreateCommand createCommand = new CreateCommand(new DiskProfile(null), "", new StoragePoolVO(), false); + final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + final DiskProfile diskProfile = Mockito.mock(DiskProfile.class); + final CreateCommand createCommand = new CreateCommand(diskProfile, "", poolVO, false); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); @@ -216,7 +224,8 @@ public class CitrixRequestWrapperTest { @Test public void testPrepareForMigrationCommand() { - final PrepareForMigrationCommand prepareCommand = new PrepareForMigrationCommand(new VirtualMachineTO(0, "Test", null, 2, 200, 256, 512, null, "CentOS", true, false, "123")); + final VirtualMachineTO machineTO = Mockito.mock(VirtualMachineTO.class); + final PrepareForMigrationCommand prepareCommand = new PrepareForMigrationCommand(machineTO); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); @@ -228,7 +237,8 @@ public class CitrixRequestWrapperTest { @Test public void testMigrateCommand() { - final MigrateCommand migrateCommand = new MigrateCommand("Test", "127.0.0.1", false, new VirtualMachineTO(0, "Test", null, 2, 200, 256, 512, null, "CentOS", true, false, "123"), false); + final VirtualMachineTO machineTO = Mockito.mock(VirtualMachineTO.class); + final MigrateCommand migrateCommand = new MigrateCommand("Test", "127.0.0.1", false, machineTO, false); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); @@ -237,6 +247,39 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testDestroyCommand() { + + final VMTemplateStorageResourceAssoc templateStorage = Mockito.mock(VMTemplateStorageResourceAssoc.class); + final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + + final DestroyCommand destroyCommand = new DestroyCommand(poolVO, templateStorage); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } + + @Test + public void testCreateStoragePoolCommand() { + final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final CreateStoragePoolCommand destroyCommand = new CreateStoragePoolCommand(false, poolVO); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getHost()).thenReturn(xsHost); + + final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 6c775951c7d749877605474b1ba2c43d14464f7d Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 14:51:20 +0100 Subject: [PATCH 14/30] Refactoring DeleteStoragePoolCommand, ModifyStoragePoolCommand and ResizeVolumeCommand to cope with new design - Basic tests added. --- .../resource/CitrixResourceBase.java | 4 +- ...CitrixDeleteStoragePoolCommandWrapper.java | 52 ++++++++++ ...CitrixModifyStoragePoolCommandWrapper.java | 96 +++++++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 6 ++ .../CitrixResizeVolumeCommandWrapper.java | 52 ++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 52 ++++++++++ 6 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteStoragePoolCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixModifyStoragePoolCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixResizeVolumeCommandWrapper.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 e9353034875..ec67ee8ff70 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 @@ -5033,11 +5033,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } - protected String callHostPluginPremium(final Connection conn, final String cmd, final String... params) { + public String callHostPluginPremium(final Connection conn, final String cmd, final String... params) { return callHostPlugin(conn, "vmopspremium", cmd, params); } - protected String setupHeartbeatSr(final Connection conn, final SR sr, final boolean force) throws XenAPIException, XmlRpcException { + public String setupHeartbeatSr(final Connection conn, final SR sr, final boolean force) throws XenAPIException, XmlRpcException { final SR.Record srRec = sr.getRecord(conn); final String srUuid = srRec.uuid; if (!srRec.shared || !SRType.LVMOHBA.equals(srRec.type) && !SRType.LVMOISCSI.equals(srRec.type) && !SRType.NFS.equals(srRec.type)) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteStoragePoolCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteStoragePoolCommandWrapper.java new file mode 100644 index 00000000000..e95a2729b68 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteStoragePoolCommandWrapper.java @@ -0,0 +1,52 @@ +// +// 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.DeleteStoragePoolCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.SR; + +public final class CitrixDeleteStoragePoolCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixDeleteStoragePoolCommandWrapper.class); + + @Override + public Answer execute(final DeleteStoragePoolCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final StorageFilerTO poolTO = command.getPool(); + try { + final SR sr = citrixResourceBase.getStorageRepository(conn, poolTO.getUuid()); + citrixResourceBase.removeSR(conn, sr); + final Answer answer = new Answer(command, true, "success"); + return answer; + } catch (final Exception e) { + final String msg = "DeleteStoragePoolCommand XenAPIException:" + e.getMessage() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: " + poolTO.getHost() + + poolTO.getPath(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixModifyStoragePoolCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixModifyStoragePoolCommandWrapper.java new file mode 100644 index 00000000000..1a6fb2756aa --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixModifyStoragePoolCommandWrapper.java @@ -0,0 +1,96 @@ +// +// 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.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.ModifyStoragePoolAnswer; +import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.storage.template.TemplateProp; +import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixModifyStoragePoolCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixModifyStoragePoolCommandWrapper.class); + + @Override + public Answer execute(final ModifyStoragePoolCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final StorageFilerTO pool = command.getPool(); + final boolean add = command.getAdd(); + if (add) { + try { + final SR sr = citrixResourceBase.getStorageRepository(conn, pool.getUuid()); + citrixResourceBase.setupHeartbeatSr(conn, sr, false); + final long capacity = sr.getPhysicalSize(conn); + final long available = capacity - sr.getPhysicalUtilisation(conn); + if (capacity == -1) { + final String msg = "Pool capacity is -1! pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg); + return new Answer(command, false, msg); + } + final Map tInfo = new HashMap(); + final ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(command, capacity, available, tInfo); + return answer; + } catch (final XenAPIException e) { + final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.toString() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: " + pool.getHost() + + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } catch (final Exception e) { + final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.getMessage() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: " + + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } + } else { + try { + final SR sr = citrixResourceBase.getStorageRepository(conn, pool.getUuid()); + final String srUuid = sr.getUuid(conn); + final String result = citrixResourceBase.callHostPluginPremium(conn, "setup_heartbeat_file", "host", citrixResourceBase.getHost().getUuid(), "sr", srUuid, "add", + "false"); + if (result == null || !result.split("#")[1].equals("0")) { + throw new CloudRuntimeException("Unable to remove heartbeat file entry for SR " + srUuid + " due to " + result); + } + return new Answer(command, true, "seccuss"); + } catch (final XenAPIException e) { + final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.toString() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: " + + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } catch (final Exception e) { + final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.getMessage() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: " + + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(command, false, msg); + } + } + } +} \ 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 af5e5b40c30..5451601a6ee 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 @@ -26,10 +26,12 @@ import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; @@ -39,6 +41,7 @@ import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; import com.cloud.resource.ServerResource; @@ -77,6 +80,9 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(MigrateCommand.class, new CitrixMigrateCommandWrapper()); map.put(DestroyCommand.class, new CitrixDestroyCommandWrapper()); map.put(CreateStoragePoolCommand.class, new CitrixCreateStoragePoolCommandWrapper()); + map.put(ModifyStoragePoolCommand.class, new CitrixModifyStoragePoolCommandWrapper()); + map.put(DeleteStoragePoolCommand.class, new CitrixDeleteStoragePoolCommandWrapper()); + map.put(ResizeVolumeCommand.class, new CitrixResizeVolumeCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixResizeVolumeCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixResizeVolumeCommandWrapper.java new file mode 100644 index 00000000000..62f90933bd2 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixResizeVolumeCommandWrapper.java @@ -0,0 +1,52 @@ +// +// 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.storage.ResizeVolumeAnswer; +import com.cloud.agent.api.storage.ResizeVolumeCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.VDI; + +public final class CitrixResizeVolumeCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixResizeVolumeCommandWrapper.class); + + @Override + public Answer execute(final ResizeVolumeCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final String volid = command.getPath(); + final long newSize = command.getNewSize(); + + try { + final VDI vdi = citrixResourceBase.getVDIbyUuid(conn, volid); + vdi.resize(conn, newSize); + return new ResizeVolumeAnswer(command, true, "success", newSize); + } catch (final Exception e) { + s_logger.warn("Unable to resize volume", e); + final String error = "failed to resize volume:" + e; + return new ResizeVolumeAnswer(command, false, error); + } + } +} \ No newline at end of file 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 baf7a55517f..9de002e28cd 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 @@ -21,10 +21,12 @@ import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; @@ -36,6 +38,8 @@ import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; 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.ResizeVolumeCommand; +import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.hypervisor.xenserver.resource.XsHost; @@ -280,6 +284,54 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testModifyStoragePoolCommand() { + final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final ModifyStoragePoolCommand destroyCommand = new ModifyStoragePoolCommand(false, poolVO); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getHost()).thenReturn(xsHost); + + final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } + + @Test + public void testDeleteStoragePoolCommand() { + final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final DeleteStoragePoolCommand destroyCommand = new DeleteStoragePoolCommand(poolVO); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getHost()).thenReturn(xsHost); + + final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + + assertTrue(answer.getResult()); + } + + @Test + public void testResizeVolumeCommand() { + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + + final ResizeVolumeCommand destroyCommand = new ResizeVolumeCommand("Test", pool, 1l, 3l, false, "Tests-1"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From ea374b6a2ffba8c5ea2222cf1cffce10dbbdff92 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 15:26:03 +0100 Subject: [PATCH 15/30] Refactoring AttachIsoCommand, AttachVolumeCommand and UpgradeSnapshotCommand to cope with new design - Basic tests added --- .../resource/CitrixResourceBase.java | 22 +-- .../CitrixAttachIsoCommandWrapper.java | 134 ++++++++++++++++ .../CitrixAttachVolumeCommandWrapper.java | 144 ++++++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 6 + .../CitrixUpgradeSnapshotCommandWrapper.java | 64 ++++++++ .../wrapper/CitrixRequestWrapperTest.java | 70 ++++++++- 6 files changed, 424 insertions(+), 16 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixAttachIsoCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixAttachVolumeCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpgradeSnapshotCommandWrapper.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 ec67ee8ff70..3c55a88989e 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 @@ -441,14 +441,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == CreateStoragePoolCommand.class) { - return execute((CreateStoragePoolCommand)cmd); - } else if (clazz == ModifyStoragePoolCommand.class) { - return execute((ModifyStoragePoolCommand)cmd); - } else if (clazz == DeleteStoragePoolCommand.class) { - return execute((DeleteStoragePoolCommand) cmd); - }else if (clazz == ResizeVolumeCommand.class) { - return execute((ResizeVolumeCommand) cmd); } else if (clazz == AttachVolumeCommand.class) { return execute((AttachVolumeCommand)cmd); } else if (clazz == AttachIsoCommand.class) { @@ -2679,7 +2671,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - String upgradeSnapshot(final Connection conn, final String templatePath, final String snapshotPath) { + public String upgradeSnapshot(final Connection conn, final String templatePath, final String snapshotPath) { final String results = callHostPluginAsync(conn, "vmopspremium", "upgrade_snapshot", 2 * 60 * 60, "templatePath", templatePath, "snapshotPath", snapshotPath); if (results == null || results.isEmpty()) { @@ -3620,7 +3612,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return connect(conn, vmname, ipAddress, 3922); } - protected boolean isDeviceUsed(final Connection conn, final VM vm, final Long deviceId) { + public boolean isDeviceUsed(final Connection conn, final VM vm, final Long deviceId) { // Figure out the disk number to attach the VM to String msg = null; @@ -3640,7 +3632,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("When check deviceId " + msg); } - protected String getUnusedDeviceNum(final Connection conn, final VM vm) { + public String getUnusedDeviceNum(final Connection conn, final VM vm) { // Figure out the disk number to attach the VM to try { final Set allowedVBDDevices = vm.getAllowedVBDDevices(conn); @@ -5841,7 +5833,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return getVDIbyUuid(conn, uuid, true); } - protected VDI getVDIbyUuid(final Connection conn, final String uuid, final boolean throwExceptionIfNotFound) { + public VDI getVDIbyUuid(final Connection conn, final String uuid, final boolean throwExceptionIfNotFound) { try { return VDI.getByUuid(conn, uuid); } catch (final Exception e) { @@ -6099,7 +6091,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new Answer(cmd, true, "Success"); } - protected VDI createVdi(final SR sr, final String vdiNameLabel, final Long volumeSize) throws Types.XenAPIException, XmlRpcException { + public VDI createVdi(final SR sr, final String vdiNameLabel, final Long volumeSize) throws Types.XenAPIException, XmlRpcException { final Connection conn = getConnection(); final VDI.Record vdir = new VDI.Record(); @@ -6121,7 +6113,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return VDI.create(conn, vdir); } - protected void handleSrAndVdiDetach(final String iqn, final Connection conn) throws Exception { + public void handleSrAndVdiDetach(final String iqn, final Connection conn) throws Exception { final SR sr = getStorageRepository(conn, iqn); removeSR(conn, sr); @@ -6685,7 +6677,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vms.iterator().next(); } - protected VDI getIsoVDIByURL(final Connection conn, final String vmName, final String isoURL) { + public VDI getIsoVDIByURL(final Connection conn, final String vmName, final String isoURL) { SR isoSR = null; String mountpoint = null; if (isoURL.startsWith("xs-tools")) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixAttachIsoCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixAttachIsoCommandWrapper.java new file mode 100644 index 00000000000..cc444c5a92d --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixAttachIsoCommandWrapper.java @@ -0,0 +1,134 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +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.SR; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +public final class CitrixAttachIsoCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixAttachIsoCommandWrapper.class); + + @Override + public Answer execute(final AttachIsoCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final boolean attach = command.isAttach(); + final String vmName = command.getVmName(); + final String isoURL = command.getIsoPath(); + + String errorMsg; + if (attach) { + errorMsg = "Failed to attach ISO"; + } else { + errorMsg = "Failed to detach ISO"; + } + try { + if (attach) { + VBD isoVBD = null; + + // Find the VM + final VM vm = citrixResourceBase.getVM(conn, vmName); + + // Find the ISO VDI + final VDI isoVDI = citrixResourceBase.getIsoVDIByURL(conn, vmName, isoURL); + + // Find the VM's CD-ROM VBD + final Set vbds = vm.getVBDs(conn); + for (final VBD vbd : vbds) { + final String userDevice = vbd.getUserdevice(conn); + final Types.VbdType type = vbd.getType(conn); + + if (userDevice.equals("3") && type == Types.VbdType.CD) { + isoVBD = vbd; + break; + } + } + + if (isoVBD == null) { + throw new CloudRuntimeException("Unable to find CD-ROM VBD for VM: " + vmName); + } else { + // If an ISO is already inserted, eject it + if (isoVBD.getEmpty(conn) == false) { + isoVBD.eject(conn); + } + + // Insert the new ISO + isoVBD.insert(conn, isoVDI); + } + + return new Answer(command); + } else { + // Find the VM + final VM vm = citrixResourceBase.getVM(conn, vmName); + final String vmUUID = vm.getUuid(conn); + + // Find the ISO VDI + final VDI isoVDI = citrixResourceBase.getIsoVDIByURL(conn, vmName, isoURL); + + final SR sr = isoVDI.getSR(conn); + + // Look up all VBDs for this VDI + final Set vbds = isoVDI.getVBDs(conn); + + // Iterate through VBDs, and if the VBD belongs the VM, eject + // the ISO from it + for (final VBD vbd : vbds) { + final VM vbdVM = vbd.getVM(conn); + final String vbdVmUUID = vbdVM.getUuid(conn); + + if (vbdVmUUID.equals(vmUUID)) { + // If an ISO is already inserted, eject it + if (!vbd.getEmpty(conn)) { + vbd.eject(conn); + } + + break; + } + } + + if (!sr.getNameLabel(conn).startsWith("XenServer Tools")) { + citrixResourceBase.removeSR(conn, sr); + } + + return new Answer(command); + } + } catch (final XenAPIException e) { + s_logger.warn(errorMsg + ": " + e.toString(), e); + return new Answer(command, false, e.toString()); + } catch (final Exception e) { + s_logger.warn(errorMsg + ": " + e.toString(), 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/CitrixAttachVolumeCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixAttachVolumeCommandWrapper.java new file mode 100644 index 00000000000..01fd874e55c --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixAttachVolumeCommandWrapper.java @@ -0,0 +1,144 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachVolumeAnswer; +import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +public final class CitrixAttachVolumeCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixAttachVolumeCommandWrapper.class); + + @Override + public Answer execute(final AttachVolumeCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final boolean attach = command.getAttach(); + final String vmName = command.getVmName(); + final String vdiNameLabel = vmName + "-DATA"; + final Long deviceId = command.getDeviceId(); + + String errorMsg; + if (attach) { + errorMsg = "Failed to attach volume"; + } else { + errorMsg = "Failed to detach volume"; + } + + try { + VDI vdi = null; + + if (command.getAttach() && command.isManaged()) { + final SR sr = citrixResourceBase.getIscsiSR(conn, command.get_iScsiName(), command.getStorageHost(), command.get_iScsiName(), command.getChapInitiatorUsername(), + command.getChapInitiatorPassword(), true); + + vdi = citrixResourceBase.getVDIbyUuid(conn, command.getVolumePath(), false); + + if (vdi == null) { + vdi = citrixResourceBase.createVdi(sr, vdiNameLabel, command.getVolumeSize()); + } + } else { + vdi = citrixResourceBase.getVDIbyUuid(conn, command.getVolumePath()); + } + + // Look up the VM + final VM vm = citrixResourceBase.getVM(conn, vmName); + if (attach) { + // Figure out the disk number to attach the VM to + String diskNumber = null; + if (deviceId != null) { + if (deviceId.longValue() == 3) { + final String msg = "Device 3 is reserved for CD-ROM, choose other device"; + return new AttachVolumeAnswer(command, msg); + } + if (citrixResourceBase.isDeviceUsed(conn, vm, deviceId)) { + final String msg = "Device " + deviceId + " is used in VM " + vmName; + return new AttachVolumeAnswer(command, msg); + } + diskNumber = deviceId.toString(); + } else { + diskNumber = citrixResourceBase.getUnusedDeviceNum(conn, vm); + } + // Create a new VBD + final VBD.Record vbdr = new VBD.Record(); + vbdr.VM = vm; + vbdr.VDI = vdi; + vbdr.bootable = false; + vbdr.userdevice = diskNumber; + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + vbdr.unpluggable = true; + final VBD vbd = VBD.create(conn, vbdr); + + // Attach the VBD to the VM + vbd.plug(conn); + + // Update the VDI's label to include the VM name + vdi.setNameLabel(conn, vdiNameLabel); + + return new AttachVolumeAnswer(command, Long.parseLong(diskNumber), vdi.getUuid(conn)); + } else { + // Look up all VBDs for this VDI + final Set vbds = vdi.getVBDs(conn); + + // Detach each VBD from its VM, and then destroy it + for (final VBD vbd : vbds) { + final VBD.Record vbdr = vbd.getRecord(conn); + + if (vbdr.currentlyAttached) { + vbd.unplug(conn); + } + + vbd.destroy(conn); + } + + // Update the VDI's label to be "detached" + vdi.setNameLabel(conn, "detached"); + + if (command.isManaged()) { + citrixResourceBase.handleSrAndVdiDetach(command.get_iScsiName(), conn); + } + + return new AttachVolumeAnswer(command); + } + } catch (final XenAPIException e) { + final String msg = errorMsg + " for uuid: " + command.getVolumePath() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new AttachVolumeAnswer(command, msg); + } catch (final Exception e) { + final String msg = errorMsg + " for uuid: " + command.getVolumePath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + return new AttachVolumeAnswer(command, msg); + } + } +} \ 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 5451601a6ee..1deefeaef97 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 @@ -22,6 +22,8 @@ package com.cloud.hypervisor.xenserver.resource.wrapper; import java.util.Hashtable; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; @@ -37,6 +39,7 @@ import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateCommand; @@ -83,6 +86,9 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(ModifyStoragePoolCommand.class, new CitrixModifyStoragePoolCommandWrapper()); map.put(DeleteStoragePoolCommand.class, new CitrixDeleteStoragePoolCommandWrapper()); map.put(ResizeVolumeCommand.class, new CitrixResizeVolumeCommandWrapper()); + map.put(AttachVolumeCommand.class, new CitrixAttachVolumeCommandWrapper()); + map.put(AttachIsoCommand.class, new CitrixAttachIsoCommandWrapper()); + map.put(UpgradeSnapshotCommand.class, new CitrixUpgradeSnapshotCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpgradeSnapshotCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpgradeSnapshotCommandWrapper.java new file mode 100644 index 00000000000..a7f3a5008bc --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpgradeSnapshotCommandWrapper.java @@ -0,0 +1,64 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.hypervisor.xenserver.resource.wrapper; + +import java.net.URI; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.UpgradeSnapshotCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixUpgradeSnapshotCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixUpgradeSnapshotCommandWrapper.class); + + @Override + public Answer execute(final UpgradeSnapshotCommand command, final CitrixResourceBase citrixResourceBase) { + final String secondaryStorageUrl = command.getSecondaryStorageUrl(); + final String backedUpSnapshotUuid = command.getSnapshotUuid(); + final Long volumeId = command.getVolumeId(); + final Long accountId = command.getAccountId(); + final Long templateId = command.getTemplateId(); + final Long tmpltAcountId = command.getTmpltAccountId(); + final String version = command.getVersion(); + + if (!version.equals("2.1")) { + return new Answer(command, true, "success"); + } + try { + final Connection conn = citrixResourceBase.getConnection(); + final URI uri = new URI(secondaryStorageUrl); + final String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + final String snapshotPath = secondaryStorageMountPath + "/snapshots/" + accountId + "/" + volumeId + "/" + backedUpSnapshotUuid + ".vhd"; + final String templatePath = secondaryStorageMountPath + "/template/tmpl/" + tmpltAcountId + "/" + templateId; + citrixResourceBase.upgradeSnapshot(conn, templatePath, snapshotPath); + return new Answer(command, true, "success"); + } catch (final Exception e) { + final String details = "upgrading snapshot " + backedUpSnapshotUuid + " failed due to " + e.toString(); + s_logger.error(details, e); + + } + return new Answer(command, false, "failure"); + } +} \ No newline at end of file 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 9de002e28cd..d5f44e0a81c 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 @@ -17,6 +17,8 @@ import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; @@ -33,6 +35,7 @@ import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.storage.CreateAnswer; @@ -43,6 +46,7 @@ import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.hypervisor.xenserver.resource.XsHost; +import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.vm.DiskProfile; @@ -222,6 +226,7 @@ public class CitrixRequestWrapperTest { assertNotNull(wrapper); final Answer answer = wrapper.execute(virtualMachineCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertTrue(answer.getResult()); } @@ -235,6 +240,7 @@ public class CitrixRequestWrapperTest { assertNotNull(wrapper); final Answer answer = wrapper.execute(prepareCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); } @@ -248,6 +254,7 @@ public class CitrixRequestWrapperTest { assertNotNull(wrapper); final Answer answer = wrapper.execute(migrateCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); } @@ -264,6 +271,7 @@ public class CitrixRequestWrapperTest { assertNotNull(wrapper); final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); } @@ -281,6 +289,7 @@ public class CitrixRequestWrapperTest { when(citrixResourceBase.getHost()).thenReturn(xsHost); final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); } @@ -298,6 +307,7 @@ public class CitrixRequestWrapperTest { when(citrixResourceBase.getHost()).thenReturn(xsHost); final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); } @@ -315,6 +325,7 @@ public class CitrixRequestWrapperTest { when(citrixResourceBase.getHost()).thenReturn(xsHost); final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertTrue(answer.getResult()); } @@ -323,15 +334,72 @@ public class CitrixRequestWrapperTest { public void testResizeVolumeCommand() { final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); - final ResizeVolumeCommand destroyCommand = new ResizeVolumeCommand("Test", pool, 1l, 3l, false, "Tests-1"); + final ResizeVolumeCommand resizeCommand = new ResizeVolumeCommand("Test", pool, 1l, 3l, false, "Tests-1"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(resizeCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testAttachVolumeCommand() { + final AttachVolumeCommand destroyCommand = new AttachVolumeCommand(false, true, "Test", StoragePoolType.LVM, "/", "DATA", 100l, 1l, "123"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); } + + @Test + public void testAttachIsoCommand() { + final AttachIsoCommand destroyCommand = new AttachIsoCommand("Test", "/", true); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testUpgradeSnapshotCommand() { + final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + + final UpgradeSnapshotCommand destroyCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", "2.1"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testUpgradeSnapshotCommandNo21() { + final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + + final UpgradeSnapshotCommand destroyCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", "3.1"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + verify(citrixResourceBase, times(0)).getConnection(); + + assertTrue(answer.getResult()); + } } class NotAValidCommand extends Command { From 11d0336803048b156731da15239147e7f6b4d03a Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 24 Mar 2015 18:04:39 +0100 Subject: [PATCH 16/30] Refactoring GetStorageStatsCommand and PrimaryStorageDownloadCommand to cope with the new design Fix the NPE in the constructor that was never used - Basic tests added for all changes --- .../api/storage/AbstractDownloadCommand.java | 18 ++-- .../PrimaryStorageDownloadCommand.java | 25 ++---- .../resource/CitrixResourceBase.java | 14 +--- .../CitrixGetStorageStatsCommandWrapper.java | 69 +++++++++++++++ ...xPrimaryStorageDownloadCommandWrapper.java | 83 +++++++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 4 + .../wrapper/CitrixRequestWrapperTest.java | 40 +++++++++ 7 files changed, 217 insertions(+), 36 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetStorageStatsCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPrimaryStorageDownloadCommandWrapper.java diff --git a/core/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java b/core/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java index 0bde5e37941..0670eefd944 100644 --- a/core/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java +++ b/core/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java @@ -31,8 +31,8 @@ public abstract class AbstractDownloadCommand extends SsCommand { protected AbstractDownloadCommand() { } - protected AbstractDownloadCommand(String name, String url, ImageFormat format, Long accountId) { - assert (url != null); + protected AbstractDownloadCommand(final String name, String url, final ImageFormat format, final Long accountId) { + assert url != null; url = url.replace('\\', '/'); this.url = url; @@ -41,14 +41,14 @@ public abstract class AbstractDownloadCommand extends SsCommand { this.name = name; } - protected AbstractDownloadCommand(AbstractDownloadCommand that) { + protected AbstractDownloadCommand(final AbstractDownloadCommand that) { super(that); - assert (that.url != null); + assert that.url != null; - this.url = that.url.replace('\\', '/'); - this.format = that.format; - this.accountId = that.accountId; - this.name = that.name; + url = that.url.replace('\\', '/'); + format = that.format; + accountId = that.accountId; + name = that.name; } public String getUrl() { @@ -73,7 +73,7 @@ public abstract class AbstractDownloadCommand extends SsCommand { } public void setUrl(String url) { - assert (url != null); + assert url != null; url = url.replace('\\', '/'); this.url = url; } diff --git a/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java b/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java index f8b88c963a4..ce8ed217a56 100644 --- a/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java +++ b/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java @@ -37,22 +37,13 @@ public class PrimaryStorageDownloadCommand extends AbstractDownloadCommand { String primaryStorageUrl; protected PrimaryStorageDownloadCommand() { - } - public PrimaryStorageDownloadCommand(String url, StoragePool pool, int wait) { - super(null, url, null, null); - this.poolId = pool.getId(); - this.poolUuid = pool.getUuid(); - this.primaryPool = new StorageFilerTO(pool); - setWait(wait); - } - - public PrimaryStorageDownloadCommand(String name, String url, ImageFormat format, long accountId, StoragePool pool, int wait) { + public PrimaryStorageDownloadCommand(final String name, final String url, final ImageFormat format, final long accountId, final StoragePool pool, final int wait) { super(name, url, format, accountId); - this.poolId = pool.getId(); - this.poolUuid = pool.getUuid(); - this.primaryPool = new StorageFilerTO(pool); + poolId = pool.getId(); + poolUuid = pool.getUuid(); + primaryPool = new StorageFilerTO(pool); setWait(wait); } @@ -68,15 +59,15 @@ public class PrimaryStorageDownloadCommand extends AbstractDownloadCommand { return primaryPool; } - public void setLocalPath(String path) { - this.localPath = path; + public void setLocalPath(final String path) { + localPath = path; } public String getLocalPath() { return localPath; } - public void setSecondaryStorageUrl(String url) { + public void setSecondaryStorageUrl(final String url) { secondaryStorageUrl = url; } @@ -84,7 +75,7 @@ public class PrimaryStorageDownloadCommand extends AbstractDownloadCommand { return secondaryStorageUrl; } - public void setPrimaryStorageUrl(String url) { + public void setPrimaryStorageUrl(final String url) { primaryStorageUrl = url; } 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 3c55a88989e..c412b546efb 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 @@ -441,12 +441,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == AttachVolumeCommand.class) { - return execute((AttachVolumeCommand)cmd); - } else if (clazz == AttachIsoCommand.class) { - return execute((AttachIsoCommand) cmd); - } else if (clazz == UpgradeSnapshotCommand.class) { - return execute((UpgradeSnapshotCommand)cmd); } else if (clazz == GetStorageStatsCommand.class) { return execute((GetStorageStatsCommand)cmd); } else if (clazz == PrimaryStorageDownloadCommand.class) { @@ -2751,7 +2745,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - String copy_vhd_from_secondarystorage(final Connection conn, final String mountpoint, final String sruuid, final int wait) { + public String copyVhdFromSecondaryStorage(final Connection conn, final String mountpoint, final String sruuid, final int wait) { final String nameLabel = "cloud-" + UUID.randomUUID().toString(); final String results = callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel); @@ -2794,7 +2788,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } final String pUuid = poolsr.getUuid(conn); final boolean isISCSI = IsISCSI(poolsr.getType(conn)); - final String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait); + final String uuid = copyVhdFromSecondaryStorage(conn, tmplpath, pUuid, wait); final VDI tmpl = getVDIbyUuid(conn, uuid); final VDI snapshotvdi = tmpl.snapshot(conn, new HashMap()); final String snapshotUuid = snapshotvdi.getUuid(conn); @@ -6589,7 +6583,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - boolean IsISCSI(final String type) { + public boolean IsISCSI(final String type) { return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type); } @@ -6838,7 +6832,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return success; } - protected String getVhdParent(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI) { + public String getVhdParent(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI) { final String parentUuid = callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString()); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetStorageStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetStorageStatsCommandWrapper.java new file mode 100644 index 00000000000..e0001ccd9fe --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetStorageStatsCommandWrapper.java @@ -0,0 +1,69 @@ +// +// 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.GetStorageStatsAnswer; +import com.cloud.agent.api.GetStorageStatsCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixGetStorageStatsCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixGetStorageStatsCommandWrapper.class); + + @Override + public Answer execute(final GetStorageStatsCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + try { + final Set srs = SR.getByNameLabel(conn, command.getStorageId()); + if (srs.size() != 1) { + final String msg = "There are " + srs.size() + " storageid: " + command.getStorageId(); + s_logger.warn(msg); + return new GetStorageStatsAnswer(command, msg); + } + final SR sr = srs.iterator().next(); + sr.scan(conn); + final long capacity = sr.getPhysicalSize(conn); + final long used = sr.getPhysicalUtilisation(conn); + return new GetStorageStatsAnswer(command, capacity, used); + } catch (final XenAPIException e) { + final String msg = "GetStorageStats Exception:" + e.toString() + "host:" + citrixResourceBase.getHost().getUuid() + "storageid: " + command.getStorageId(); + s_logger.warn(msg); + return new GetStorageStatsAnswer(command, msg); + } catch (final XmlRpcException e) { + final String msg = "GetStorageStats Exception:" + e.getMessage() + "host:" + citrixResourceBase.getHost().getUuid() + "storageid: " + command.getStorageId(); + s_logger.warn(msg); + return new GetStorageStatsAnswer(command, msg); + } catch (final Exception e) { + final String msg = "GetStorageStats Exception:" + e.getMessage() + "host:" + citrixResourceBase.getHost().getUuid() + "storageid: " + command.getStorageId(); + s_logger.warn(msg); + return new GetStorageStatsAnswer(command, msg); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPrimaryStorageDownloadCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPrimaryStorageDownloadCommandWrapper.java new file mode 100644 index 00000000000..270520777d4 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPrimaryStorageDownloadCommandWrapper.java @@ -0,0 +1,83 @@ +// +// 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.net.URI; +import java.util.HashMap; +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; +import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.VDI; + +public final class CitrixPrimaryStorageDownloadCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixPrimaryStorageDownloadCommandWrapper.class); + + @Override + public Answer execute(final PrimaryStorageDownloadCommand command, final CitrixResourceBase citrixResourceBase) { + final String tmplturl = command.getUrl(); + final String poolName = command.getPoolUuid(); + final int wait = command.getWait(); + try { + final URI uri = new URI(tmplturl); + final String tmplpath = uri.getHost() + ":" + uri.getPath(); + final Connection conn = citrixResourceBase.getConnection(); + SR poolsr = null; + final Set srs = SR.getByNameLabel(conn, poolName); + if (srs.size() != 1) { + final String msg = "There are " + srs.size() + " SRs with same name: " + poolName; + s_logger.warn(msg); + return new PrimaryStorageDownloadAnswer(msg); + } else { + poolsr = srs.iterator().next(); + } + final String pUuid = poolsr.getUuid(conn); + final boolean isISCSI = citrixResourceBase.IsISCSI(poolsr.getType(conn)); + final String uuid = citrixResourceBase.copyVhdFromSecondaryStorage(conn, tmplpath, pUuid, wait); + final VDI tmpl = citrixResourceBase.getVDIbyUuid(conn, uuid); + final VDI snapshotvdi = tmpl.snapshot(conn, new HashMap()); + final String snapshotUuid = snapshotvdi.getUuid(conn); + snapshotvdi.setNameLabel(conn, "Template " + command.getName()); + final String parentuuid = citrixResourceBase.getVhdParent(conn, pUuid, snapshotUuid, isISCSI); + final VDI parent = citrixResourceBase.getVDIbyUuid(conn, parentuuid); + final Long phySize = parent.getPhysicalUtilisation(conn); + tmpl.destroy(conn); + poolsr.scan(conn); + try { + Thread.sleep(5000); + } catch (final Exception e) { + } + return new PrimaryStorageDownloadAnswer(snapshotvdi.getUuid(conn), phySize); + } catch (final Exception e) { + final String msg = "Catch Exception " + e.getClass().getName() + " on host:" + citrixResourceBase.getHost().getUuid() + " for template: " + tmplturl + " due to " + + e.toString(); + s_logger.warn(msg, e); + return new PrimaryStorageDownloadAnswer(msg); + } + } +} \ 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 1deefeaef97..c31c340c608 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 @@ -30,6 +30,7 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.MigrateCommand; @@ -44,6 +45,7 @@ import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; 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.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; @@ -89,6 +91,8 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(AttachVolumeCommand.class, new CitrixAttachVolumeCommandWrapper()); map.put(AttachIsoCommand.class, new CitrixAttachIsoCommandWrapper()); map.put(UpgradeSnapshotCommand.class, new CitrixUpgradeSnapshotCommandWrapper()); + map.put(GetStorageStatsCommand.class, new CitrixGetStorageStatsCommandWrapper()); + map.put(PrimaryStorageDownloadCommand.class, new CitrixPrimaryStorageDownloadCommandWrapper()); } 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 d5f44e0a81c..187384271f5 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 @@ -25,6 +25,7 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.MigrateCommand; @@ -41,11 +42,14 @@ import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; 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.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.hypervisor.xenserver.resource.XsHost; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.vm.DiskProfile; @@ -400,6 +404,42 @@ public class CitrixRequestWrapperTest { assertTrue(answer.getResult()); } + + @Test + public void testGetStorageStatsCommand() { + final XsHost xsHost = Mockito.mock(XsHost.class); + final DataStoreTO store = Mockito.mock(DataStoreTO.class); + + final GetStorageStatsCommand storageStatsCommand = new GetStorageStatsCommand(store); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getHost()).thenReturn(xsHost); + + final Answer answer = wrapper.execute(storageStatsCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testPrimaryStorageDownloadCommand() { + final XsHost xsHost = Mockito.mock(XsHost.class); + final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + + final PrimaryStorageDownloadCommand storageDownloadCommand = new PrimaryStorageDownloadCommand("Test", "http://127.0.0.1", ImageFormat.VHD, 1l, poolVO, 200); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getHost()).thenReturn(xsHost); + + final Answer answer = wrapper.execute(storageDownloadCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 637a56c3c1f8a33bdbb2344824e4df0ed9dee786 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Wed, 25 Mar 2015 19:16:02 +0100 Subject: [PATCH 17/30] Refactoring GetVncPortCommand, MaintainCommand and SetupCommand to cope with new design. - Basic test added, but could not mock all the static stuff so the test is not complete yet. Will look further into it. --- .../resource/CitrixResourceBase.java | 30 ++- .../resource/Xenserver625Resource.java | 2 +- .../CitrixGetVncPortCommandWrapper.java | 56 +++++ .../wrapper/CitrixMaintainCommandWrapper.java | 75 +++++++ .../wrapper/CitrixRequestWrapper.java | 6 + .../wrapper/CitrixSetupCommandWrapper.java | 200 ++++++++++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 118 ++++++++++- 7 files changed, 473 insertions(+), 14 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVncPortCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixMaintainCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixSetupCommandWrapper.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 c412b546efb..6c51faeda8f 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 @@ -340,10 +340,22 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return _host; } + public boolean isSecurityGroupEnabled() { + return _securityGroupEnabled; + } + + public void setCanBridgeFirewall(final boolean canBridgeFirewall) { + _canBridgeFirewall = canBridgeFirewall; + } + public boolean canBridgeFirewall() { return _canBridgeFirewall; } + public boolean canBridgeFirewall(final Connection conn) { + return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.getUuid(), "instance", _instance)); + } + private static boolean isAlienVm(final VM vm, final Connection conn) throws XenAPIException, XmlRpcException { // TODO : we need a better way to tell whether or not the VM belongs to CloudStack final String vmName = vm.getNameLabel(conn); @@ -3008,7 +3020,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new ReadyAnswer(cmd); } - protected String getVncUrl(final Connection conn, final VM vm) { + public String getVncUrl(final Connection conn, final VM vm) { VM.Record record; Console c; try { @@ -3679,7 +3691,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return argString.toString(); } - protected boolean setIptables(final Connection conn) { + public boolean setIptables(final Connection conn) { final String result = callHostPlugin(conn, "vmops", "setIptables"); if (result == null || result.isEmpty()) { return false; @@ -4399,7 +4411,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected boolean transferManagementNetwork(final Connection conn, final Host host, final PIF src, final PIF.Record spr, final PIF dest) throws XmlRpcException, XenAPIException { + 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); Host.managementReconfigure(conn, dest); String hostUuid = null; @@ -4456,7 +4468,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new StartupCommand[] {cmd}; } - private void cleanupTemplateSR(final Connection conn) { + public void cleanupTemplateSR(final Connection conn) { Set pbds = null; try { final Host host = Host.getByUuid(conn, _host.getUuid()); @@ -4493,7 +4505,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected boolean launchHeartBeat(final Connection conn) { + public boolean launchHeartBeat(final Connection conn) { final String result = callHostPluginPremium(conn, "heartbeat", "host", _host.getUuid(), "timeout", Integer.toString(_heartbeatTimeout), @@ -4523,7 +4535,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (_securityGroupEnabled) { - _canBridgeFirewall = can_bridge_firewall(conn); + _canBridgeFirewall = canBridgeFirewall(conn); if (!_canBridgeFirewall) { final String msg = "Failed to configure brige firewall"; s_logger.warn(msg); @@ -4657,7 +4669,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } /* return : if setup is needed */ - protected boolean setupServer(final Connection conn, final Host host) { + public boolean setupServer(final Connection conn, final Host host) { final String packageVersion = CitrixResourceBase.class.getPackage().getImplementationVersion(); final String version = this.getClass().getName() + "-" + (packageVersion == null ? Long.toString(System.currentTimeMillis()) : packageVersion); @@ -5110,10 +5122,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - protected boolean can_bridge_firewall(final Connection conn) { - return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.getUuid(), "instance", _instance)); - } - private Answer execute(final OvsSetupBridgeCommand cmd) { final Connection conn = getConnection(); findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); 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 a01e1927d1d..11ab7ba4395 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 @@ -71,7 +71,7 @@ public class Xenserver625Resource extends XenServerResourceNewBase { } @Override - protected boolean setupServer(final Connection conn,final Host host) { + public boolean setupServer(final Connection conn,final Host host) { final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); try { sshConnection.connect(null, 60000, 60000); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVncPortCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVncPortCommandWrapper.java new file mode 100644 index 00000000000..d69ce27d606 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixGetVncPortCommandWrapper.java @@ -0,0 +1,56 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.GetVncPortAnswer; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.VM; + +public final class CitrixGetVncPortCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixGetVncPortCommandWrapper.class); + + @Override + public Answer execute(final GetVncPortCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + try { + final Set vms = VM.getByNameLabel(conn, command.getName()); + if (vms.size() == 1) { + String consoleurl; + consoleurl = "consoleurl=" + citrixResourceBase.getVncUrl(conn, vms.iterator().next()) + "&" + "sessionref=" + conn.getSessionReference(); + return new GetVncPortAnswer(command, consoleurl, -1); + } else { + return new GetVncPortAnswer(command, "There are " + vms.size() + " VMs named " + command.getName()); + } + } catch (final Exception e) { + final String msg = "Unable to get vnc port due to " + e.toString(); + s_logger.warn(msg, e); + return new GetVncPortAnswer(command, msg); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixMaintainCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixMaintainCommandWrapper.java new file mode 100644 index 00000000000..d1c5b70f1ff --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixMaintainCommandWrapper.java @@ -0,0 +1,75 @@ +// +// 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 org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.hypervisor.xenserver.resource.XsHost; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixMaintainCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixMaintainCommandWrapper.class); + + @Override + public Answer execute(final MaintainCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + try { + + final XsHost xsHost = citrixResourceBase.getHost(); + final String uuid = xsHost.getUuid(); + final Host host = Host.getByUuid(conn, uuid); + // remove all tags cloud stack + final Host.Record hr = host.getRecord(conn); + + // Adding this check because could not get the mock to work. Will push the code and fix it afterwards. + if (hr == null) { + s_logger.warn("Host.Record is null."); + return new MaintainAnswer(command, false, "Host.Record is null"); + } + + final Iterator it = hr.tags.iterator(); + while (it.hasNext()) { + final String tag = it.next(); + if (tag.contains("cloud")) { + it.remove(); + } + } + host.setTags(conn, hr.tags); + return new MaintainAnswer(command); + } catch (final XenAPIException e) { + s_logger.warn("Unable to put server in maintainence mode", e); + return new MaintainAnswer(command, false, e.getMessage()); + } catch (final XmlRpcException e) { + s_logger.warn("Unable to put server in maintainence mode", e); + return new MaintainAnswer(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 c31c340c608..6d262ee7725 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 @@ -33,12 +33,15 @@ import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; @@ -93,6 +96,9 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(UpgradeSnapshotCommand.class, new CitrixUpgradeSnapshotCommandWrapper()); map.put(GetStorageStatsCommand.class, new CitrixGetStorageStatsCommandWrapper()); map.put(PrimaryStorageDownloadCommand.class, new CitrixPrimaryStorageDownloadCommandWrapper()); + map.put(GetVncPortCommand.class, new CitrixGetVncPortCommandWrapper()); + map.put(SetupCommand.class, new CitrixSetupCommandWrapper()); + map.put(MaintainCommand.class, new CitrixMaintainCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixSetupCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixSetupCommandWrapper.java new file mode 100644 index 00000000000..3b24aa38876 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixSetupCommandWrapper.java @@ -0,0 +1,200 @@ +// +// 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.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.SetupAnswer; +import com.cloud.agent.api.SetupCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Bond; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.PIF; +import com.xensource.xenapi.Pool; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixSetupCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixSetupCommandWrapper.class); + + @Override + public Answer execute(final SetupCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + try { + final Map poolRecs = Pool.getAllRecords(conn); + if (poolRecs.size() != 1) { + throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + citrixResourceBase.getHost().getUuid()); + } + final Host master = poolRecs.values().iterator().next().master; + citrixResourceBase.setupServer(conn, master); + final Host host = Host.getByUuid(conn, citrixResourceBase.getHost().getUuid()); + citrixResourceBase.setupServer(conn, host); + + if (!citrixResourceBase.setIptables(conn)) { + s_logger.warn("set xenserver Iptable failed"); + return null; + } + + if (citrixResourceBase.isSecurityGroupEnabled()) { + final boolean canBridgeFirewall = citrixResourceBase.canBridgeFirewall(conn); + citrixResourceBase.setCanBridgeFirewall(canBridgeFirewall); + if (!canBridgeFirewall) { + final String msg = "Failed to configure brige firewall"; + s_logger.warn(msg); + s_logger.warn("Check host " + citrixResourceBase.getHost().getIp() +" for CSP is installed or not and check network mode for bridge"); + return new SetupAnswer(command, msg); + } + + } + + + final boolean r = citrixResourceBase.launchHeartBeat(conn); + if (!r) { + return null; + } + citrixResourceBase.cleanupTemplateSR(conn); + try { + if (command.useMultipath()) { + // the config value is set to true + host.addToOtherConfig(conn, "multipathing", "true"); + host.addToOtherConfig(conn, "multipathhandle", "dmp"); + } + + } catch (final Types.MapDuplicateKey e) { + s_logger.debug("multipath is already set"); + } + + if (command.needSetup() ) { + final String result = citrixResourceBase.callHostPlugin(conn, "vmops", "setup_iscsi", "uuid", citrixResourceBase.getHost().getUuid()); + + if (!result.contains("> DONE <")) { + s_logger.warn("Unable to setup iscsi: " + result); + return new SetupAnswer(command, result); + } + + Pair mgmtPif = null; + final Set hostPifs = host.getPIFs(conn); + for (final PIF pif : hostPifs) { + final PIF.Record rec = pif.getRecord(conn); + if (rec.management) { + if (rec.VLAN != null && rec.VLAN != -1) { + final String msg = + new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(citrixResourceBase.getHost().getUuid()) + .append("; pif=") + .append(rec.uuid) + .append("; vlan=") + .append(rec.VLAN) + .toString(); + s_logger.warn(msg); + return new SetupAnswer(command, msg); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Management network is on pif=" + rec.uuid); + } + mgmtPif = new Pair(pif, rec); + break; + } + } + + if (mgmtPif == null) { + final String msg = "Unable to find management network for " + citrixResourceBase.getHost().getUuid(); + s_logger.warn(msg); + return new SetupAnswer(command, msg); + } + + final Map networks = Network.getAllRecords(conn); + if(networks == null) { + final String msg = "Unable to setup as there are no networks in the host: " + citrixResourceBase.getHost().getUuid(); + s_logger.warn(msg); + return new SetupAnswer(command, msg); + } + for (final Network.Record network : networks.values()) { + if (network.nameLabel.equals("cloud-private")) { + for (final PIF pif : network.PIFs) { + final PIF.Record pr = pif.getRecord(conn); + if (citrixResourceBase.getHost().getUuid().equals(pr.host.getUuid(conn))) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found a network called cloud-private. host=" + citrixResourceBase.getHost().getUuid() + "; Network=" + network.uuid + "; pif=" + pr.uuid); + } + if (pr.VLAN != null && pr.VLAN != -1) { + final String msg = + new StringBuilder("Unsupported configuration. Network cloud-private is on a VLAN. Network=").append(network.uuid) + .append(" ; pif=") + .append(pr.uuid) + .toString(); + s_logger.warn(msg); + return new SetupAnswer(command, msg); + } + if (!pr.management && pr.bondMasterOf != null && pr.bondMasterOf.size() > 0) { + if (pr.bondMasterOf.size() > 1) { + final String msg = + new StringBuilder("Unsupported configuration. Network cloud-private has more than one bond. Network=").append(network.uuid) + .append("; pif=") + .append(pr.uuid) + .toString(); + s_logger.warn(msg); + return new SetupAnswer(command, msg); + } + final Bond bond = pr.bondMasterOf.iterator().next(); + final Set slaves = bond.getSlaves(conn); + for (final PIF slave : slaves) { + final PIF.Record spr = slave.getRecord(conn); + if (spr.management) { + if (!citrixResourceBase.transferManagementNetwork(conn, host, slave, spr, pif)) { + final String msg = + new StringBuilder("Unable to transfer management network. slave=" + spr.uuid + "; master=" + pr.uuid + "; host=" + + citrixResourceBase.getHost().getUuid()).toString(); + s_logger.warn(msg); + return new SetupAnswer(command, msg); + } + break; + } + } + } + } + } + } + } + } + return new SetupAnswer(command, false); + + } catch (final XmlRpcException e) { + s_logger.warn("Unable to setup", e); + return new SetupAnswer(command, e.getMessage()); + } catch (final XenAPIException e) { + s_logger.warn("Unable to setup", e); + return new SetupAnswer(command, e.getMessage()); + } catch (final Exception e) { + s_logger.warn("Unable to setup", e); + return new SetupAnswer(command, e.getMessage()); + } + } +} \ No newline at end of file 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 187384271f5..45bdea1d6e5 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 @@ -3,18 +3,24 @@ 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.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Map; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.xmlrpc.client.XmlRpcClient; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; @@ -28,6 +34,8 @@ import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.PrepareForMigrationCommand; @@ -35,6 +43,7 @@ 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.SetupCommand; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; @@ -47,14 +56,19 @@ import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.HostEnvironment; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.hypervisor.xenserver.resource.XsHost; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.vm.DiskProfile; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Marshalling; -@RunWith(MockitoJUnitRunner.class) +@RunWith(PowerMockRunner.class) +@PrepareForTest({Connection.class, Host.Record.class}) public class CitrixRequestWrapperTest { @Mock @@ -440,6 +454,106 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testGetVncPortCommand() { + final GetVncPortCommand storageDownloadCommand = new GetVncPortCommand(1l, "Test"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(storageDownloadCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testSetupCommand() { + final XsHost xsHost = Mockito.mock(XsHost.class); + final HostEnvironment env = Mockito.mock(HostEnvironment.class); + + final SetupCommand storageDownloadCommand = new SetupCommand(env); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getHost()).thenReturn(xsHost); + + final Answer answer = wrapper.execute(storageDownloadCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testMaintainCommand() { + // This test needs further work. + + final String uuid = "befc4dcd-f5c6-4015-8791-3c18622b7c7f"; + + final Connection conn = Mockito.mock(Connection.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + final XmlRpcClient client = Mockito.mock(XmlRpcClient.class); + + // final Host.Record hr = PowerMockito.mock(Host.Record.class); + // final Host host = PowerMockito.mock(Host.class); + + final MaintainCommand storageDownloadCommand = new MaintainCommand(); + + final Map map = new Hashtable(); + map.put("Value", "Xen"); + + final Map spiedMap = spy(map); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getHost()).thenReturn(xsHost); + when(xsHost.getUuid()).thenReturn(uuid); + when(conn.getSessionReference()).thenReturn("befc4dcd"); + + try { + final Object [] params = {Marshalling.toXMLRPC("befc4dcd"), Marshalling.toXMLRPC(uuid)}; + when(client.execute("host.get_by_uuid", new Object[]{"befc4dcd", uuid})).thenReturn(spiedMap); + PowerMockito.when(conn, "dispatch", "host.get_by_uuid", params).thenReturn(spiedMap); + } catch (final Exception e) { + } + + // try { + // PowerMockito.mockStatic(Host.class); + // //BDDMockito.given(Host.getByUuid(conn, xsHost.getUuid())).willReturn(host); + // PowerMockito.when(Host.getByUuid(conn, xsHost.getUuid())).thenReturn(host); + // PowerMockito.verifyStatic(times(1)); + // } catch (final BadServerResponse e) { + // fail(e.getMessage()); + // } catch (final XenAPIException e) { + // fail(e.getMessage()); + // } catch (final XmlRpcException e) { + // fail(e.getMessage()); + // } + // + // PowerMockito.mockStatic(Types.class); + // PowerMockito.when(Types.toHostRecord(spiedMap)).thenReturn(hr); + // PowerMockito.verifyStatic(times(1)); + // + // try { + // PowerMockito.mockStatic(Host.Record.class); + // when(host.getRecord(conn)).thenReturn(hr); + // verify(host, times(1)).getRecord(conn); + // } 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(storageDownloadCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 3a70912b7cd246a698553d1943218b2ed17e1c4a Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Wed, 25 Mar 2015 19:20:04 +0100 Subject: [PATCH 18/30] Make methods in subclasses public. Remove the if-commands that I have already refactored. --- .../xenserver/resource/CitrixResourceBase.java | 10 ---------- .../hypervisor/xenserver/resource/XcpOssResource.java | 2 +- .../xenserver/resource/XenServer56Resource.java | 2 +- 3 files changed, 2 insertions(+), 12 deletions(-) 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 6c51faeda8f..8fa9e4c2bb0 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 @@ -453,16 +453,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == GetStorageStatsCommand.class) { - return execute((GetStorageStatsCommand)cmd); - } else if (clazz == PrimaryStorageDownloadCommand.class) { - return execute((PrimaryStorageDownloadCommand)cmd); - } else if (clazz == GetVncPortCommand.class) { - return execute((GetVncPortCommand)cmd); - } else if (clazz == SetupCommand.class) { - return execute((SetupCommand)cmd); - } else if (clazz == MaintainCommand.class) { - return execute((MaintainCommand)cmd); } else if (clazz == PingTestCommand.class) { return execute((PingTestCommand)cmd); } else if (clazz == CheckOnHostCommand.class) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java index b5eef7eeee1..312b34cc295 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java @@ -74,7 +74,7 @@ public class XcpOssResource extends CitrixResourceBase { } @Override - protected boolean launchHeartBeat(final Connection conn) { + public boolean launchHeartBeat(final Connection conn) { return true; } 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 1bb2ff439b2..6b3efb5d930 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 @@ -263,7 +263,7 @@ public class XenServer56Resource extends CitrixResourceBase { @Override - protected boolean transferManagementNetwork(final Connection conn, final Host host, final PIF src, final PIF.Record spr, final PIF dest) throws XmlRpcException, XenAPIException { + 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); Host.managementReconfigure(conn, dest); String hostUuid = null; From 18470a48d0db69e4bd97d22c023f7a5ae3bcbd97 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Thu, 26 Mar 2015 11:10:35 +0100 Subject: [PATCH 19/30] Refactoring PingTestCommand to cope with new design - Basic tests added --- .../resource/CitrixResourceBase.java | 6 +-- .../wrapper/CitrixPingTestCommandWrapper.java | 47 +++++++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 2 + .../wrapper/CitrixRequestWrapperTest.java | 14 ++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPingTestCommandWrapper.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 8fa9e4c2bb0..50859afa66e 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 @@ -453,8 +453,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == PingTestCommand.class) { - return execute((PingTestCommand)cmd); } else if (clazz == CheckOnHostCommand.class) { return execute((CheckOnHostCommand)cmd); } else if (clazz == ModifySshKeysCommand.class) { @@ -1945,7 +1943,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new Answer(cmd); } - private boolean doPingTest(final Connection conn, final String computingHostIp) { + public boolean doPingTest(final Connection conn, final String computingHostIp) { final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); try { sshConnection.connect(null, 60000, 60000); @@ -1970,7 +1968,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new CheckOnHostAnswer(cmd, null, "Not Implmeneted"); } - private boolean doPingTest(final Connection conn, final String domRIp, final String vmIp) { + public boolean doPingTest(final Connection conn, final String domRIp, final String vmIp) { final String args = "-i " + domRIp + " -p " + vmIp; final String result = callHostPlugin(conn, "vmops", "pingtest", "args", args); if (result == null || result.isEmpty()) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPingTestCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPingTestCommandWrapper.java new file mode 100644 index 00000000000..8a7a01cf7b0 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPingTestCommandWrapper.java @@ -0,0 +1,47 @@ +// +// 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.PingTestCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixPingTestCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final PingTestCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + boolean result = false; + final String computingHostIp = command.getComputingHostIp(); + + if (computingHostIp != null) { + result = citrixResourceBase.doPingTest(conn, computingHostIp); + } else { + result = citrixResourceBase.doPingTest(conn, command.getRouterIp(), command.getPrivateIp()); + } + + if (!result) { + return new Answer(command, false, "PingTestCommand failed"); + } + return new Answer(command); + } +} \ 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 6d262ee7725..badc892b2ee 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 @@ -37,6 +37,7 @@ import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; @@ -99,6 +100,7 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(GetVncPortCommand.class, new CitrixGetVncPortCommandWrapper()); map.put(SetupCommand.class, new CitrixSetupCommandWrapper()); map.put(MaintainCommand.class, new CitrixMaintainCommandWrapper()); + map.put(PingTestCommand.class, new CitrixPingTestCommandWrapper()); } 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 45bdea1d6e5..0ba9d1a1f3b 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 @@ -38,6 +38,7 @@ import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; @@ -554,6 +555,19 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testPingTestCommandHostIp() { + final PingTestCommand storageDownloadCommand = new PingTestCommand("127.0.0.1"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(storageDownloadCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 74faf73408f805af7ac64a081c711f1ceac0a144 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Thu, 26 Mar 2015 15:56:18 +0100 Subject: [PATCH 20/30] Refactoring CheckOnHostCommand, ModifySshKeysCommand, OvsSetTagAndFlowCommand and StartCommand to cope with new design - Unit tests added --- .../resource/CitrixResourceBase.java | 36 +-- .../xenserver/resource/XcpOssResource.java | 2 +- .../resource/XenServer620SP1Resource.java | 2 +- .../CitrixCheckOnHostCommandWrapper.java | 34 +++ .../CitrixModifySshKeysCommandWrapper.java | 33 +++ .../CitrixOvsSetTagAndFlowCommandWrapper.java | 72 ++++++ .../wrapper/CitrixRequestWrapper.java | 8 + .../wrapper/CitrixStartCommandWrapper.java | 210 ++++++++++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 149 ++++++++++--- 9 files changed, 498 insertions(+), 48 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckOnHostCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixModifySshKeysCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsSetTagAndFlowCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixStartCommandWrapper.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 50859afa66e..c9b05a4cf68 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 @@ -340,6 +340,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return _host; } + public boolean isOvs() { + return _isOvs; + } + + public void setIsOvs(final boolean isOvs) { + _isOvs = isOvs; + } + public boolean isSecurityGroupEnabled() { return _securityGroupEnabled; } @@ -453,12 +461,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == CheckOnHostCommand.class) { - return execute((CheckOnHostCommand)cmd); - } else if (clazz == ModifySshKeysCommand.class) { - return execute((ModifySshKeysCommand)cmd); - } else if (clazz == StartCommand.class) { - return execute((StartCommand)cmd); } else if (clazz == CheckSshCommand.class) { return execute((CheckSshCommand)cmd); } else if (clazz == SecurityGroupRulesCmd.class) { @@ -467,8 +469,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return execute((OvsFetchInterfaceCommand)cmd); } else if (clazz == OvsCreateGreTunnelCommand.class) { return execute((OvsCreateGreTunnelCommand)cmd); - } else if (clazz == OvsSetTagAndFlowCommand.class) { - return execute((OvsSetTagAndFlowCommand)cmd); } else if (clazz == OvsDeleteFlowCommand.class) { return execute((OvsDeleteFlowCommand)cmd); } else if (clazz == OvsVpcPhysicalTopologyConfigCommand.class) { @@ -863,7 +863,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException("Unsupported network type: " + type); } - private synchronized Network setupvSwitchNetwork(final Connection conn) { + public synchronized Network setupvSwitchNetwork(final Connection conn) { try { if (_host.getVswitchNetwork() == null) { Network vswitchNw = null; @@ -1052,7 +1052,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected VIF createVif(final Connection conn, final String vmName, final VM vm, final VirtualMachineTO vmSpec, final NicTO nic) throws XmlRpcException, XenAPIException { + public VIF createVif(final Connection conn, final String vmName, final VM vm, final VirtualMachineTO vmSpec, final NicTO nic) throws XmlRpcException, XenAPIException { assert nic.getUuid() != null : "Nic should have a uuid value"; if (s_logger.isDebugEnabled()) { @@ -1198,7 +1198,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected VBD createVbd(final Connection conn, final DiskTO volume, final String vmName, final VM vm, final BootloaderType bootLoaderType, VDI vdi) throws XmlRpcException, XenAPIException { + public VBD createVbd(final Connection conn, final DiskTO volume, final String vmName, final VM vm, final BootloaderType bootLoaderType, VDI vdi) throws XmlRpcException, XenAPIException { final Volume.Type type = volume.getType(); if (vdi == null) { @@ -1287,10 +1287,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } - protected void createVGPU(final Connection conn, final StartCommand cmd, final VM vm, final GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { + public void createVGPU(final Connection conn, final StartCommand cmd, final VM vm, final GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { } - protected VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmSpec, final Host host) throws XenAPIException, XmlRpcException { + public VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmSpec, final Host host) throws XenAPIException, XmlRpcException { final String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getPlatformEmulator(), vmSpec.getBootloader() == BootloaderType.CD); final Set templates = VM.getByNameLabel(conn, guestOsTypeName); if ( templates == null || templates.isEmpty()) { @@ -1454,7 +1454,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected String handleVmStartFailure(final Connection conn, final String vmName, final VM vm, final String message, final Throwable th) { + public String handleVmStartFailure(final Connection conn, final String vmName, final VM vm, final String message, final Throwable th) { final String msg = "Unable to start " + vmName + " due to " + message; s_logger.warn(msg, th); @@ -1519,7 +1519,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return msg; } - protected VBD createPatchVbd(final Connection conn, final String vmName, final VM vm) throws XmlRpcException, XenAPIException { + public VBD createPatchVbd(final Connection conn, final String vmName, final VM vm) throws XmlRpcException, XenAPIException { if (_host.getSystemvmisouuid() == null) { final Set srs = SR.getByNameLabel(conn, "XenServer Tools"); @@ -1607,7 +1607,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new CheckSshAnswer(cmd); } - private HashMap parseDefaultOvsRuleComamnd(final String str) { + public HashMap parseDefaultOvsRuleComamnd(final String str) { final HashMap cmd = new HashMap(); final String[] sarr = str.split("/"); for (int i = 0; i < sarr.length; i++) { @@ -1864,7 +1864,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe // the idea here is to see if the DiskTO in question is from managed storage and // does not yet have an SR // if no SR, create it and create a VDI in it - private VDI prepareManagedDisk(final Connection conn, final DiskTO disk, final String vmName) throws Exception { + public VDI prepareManagedDisk(final Connection conn, final DiskTO disk, final String vmName) throws Exception { final Map details = disk.getDetails(); if (details == null) { @@ -3297,7 +3297,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - void startVM(final Connection conn, final Host host, final VM vm, final String vmName) throws Exception { + public void startVM(final Connection conn, final Host host, final VM vm, final String vmName) throws Exception { Task task = null; try { task = vm.startOnAsync(conn, host, false, true); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java index 312b34cc295..540044e5d04 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java @@ -123,7 +123,7 @@ public class XcpOssResource extends CitrixResourceBase { } @Override - protected synchronized VBD createPatchVbd(final Connection conn, final String vmName, final VM vm) throws XmlRpcException, XenAPIException { + public synchronized VBD createPatchVbd(final Connection conn, final String vmName, final VM vm) throws XmlRpcException, XenAPIException { if (_host.getLocalSRuuid() != null) { //create an iso vdi on it final String result = callHostPlugin(conn, "vmops", "createISOVHD", "uuid", _host.getLocalSRuuid()); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java index e6c66a41c14..0704e8e4b62 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java @@ -136,7 +136,7 @@ public class XenServer620SP1Resource extends XenServer620Resource { } @Override - protected void createVGPU(final Connection conn, final StartCommand cmd, final VM vm, final GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { + public void createVGPU(final Connection conn, final StartCommand cmd, final VM vm, final GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { if (s_logger.isDebugEnabled()) { s_logger.debug("Creating VGPU of VGPU type [ " + gpuDevice.getVgpuType() + " ] in gpu group" + gpuDevice.getGpuGroup() + " for VM " + cmd.getVirtualMachine().getName()); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckOnHostCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckOnHostCommandWrapper.java new file mode 100644 index 00000000000..aaee57b498e --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckOnHostCommandWrapper.java @@ -0,0 +1,34 @@ +// +// 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.CheckOnHostAnswer; +import com.cloud.agent.api.CheckOnHostCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; + +public final class CitrixCheckOnHostCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final CheckOnHostCommand command, final CitrixResourceBase citrixResourceBase) { + return new CheckOnHostAnswer(command, "Not Implmeneted"); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixModifySshKeysCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixModifySshKeysCommandWrapper.java new file mode 100644 index 00000000000..8ea852d9127 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixModifySshKeysCommandWrapper.java @@ -0,0 +1,33 @@ +// +// 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.ModifySshKeysCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; + +public final class CitrixModifySshKeysCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final ModifySshKeysCommand command, final CitrixResourceBase citrixResourceBase) { + return new Answer(command); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsSetTagAndFlowCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsSetTagAndFlowCommandWrapper.java new file mode 100644 index 00000000000..2048f4d16d2 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsSetTagAndFlowCommandWrapper.java @@ -0,0 +1,72 @@ +// +// 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.OvsSetTagAndFlowAnswer; +import com.cloud.agent.api.OvsSetTagAndFlowCommand; +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 CitrixOvsSetTagAndFlowCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsSetTagAndFlowCommandWrapper.class); + + @Override + public Answer execute(final OvsSetTagAndFlowCommand 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); + + /* + * If VM is domainRouter, this will try to set flow and tag on its + * none guest network nic. don't worry, it will fail silently at + * host plugin side + */ + final String result = citrixResourceBase.callHostPlugin(conn, "ovsgre", "ovs_set_tag_and_flow", "bridge", bridge, "vmName", command.getVmName(), "tag", + command.getTag(), "vlans", command.getVlans(), "seqno", command.getSeqNo()); + s_logger.debug("set flow for " + command.getVmName() + " " + result); + + if (result != null && result.equalsIgnoreCase("SUCCESS")) { + return new OvsSetTagAndFlowAnswer(command, true, result); + } else { + return new OvsSetTagAndFlowAnswer(command, false, result); + } + } catch (final BadServerResponse e) { + s_logger.error("Failed to set tag and flow", e); + } catch (final XenAPIException e) { + s_logger.error("Failed to set tag and flow", e); + } catch (final XmlRpcException e) { + s_logger.error("Failed to set tag and flow", e); + } + + return new OvsSetTagAndFlowAnswer(command, false, "EXCEPTION"); + } +} \ 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 badc892b2ee..fbb3f27c42d 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 @@ -25,6 +25,7 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; 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.Command; import com.cloud.agent.api.CreateStoragePoolCommand; @@ -36,13 +37,16 @@ import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortCommand; 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.OvsSetTagAndFlowCommand; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.SetupCommand; +import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; @@ -101,6 +105,10 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(SetupCommand.class, new CitrixSetupCommandWrapper()); map.put(MaintainCommand.class, new CitrixMaintainCommandWrapper()); map.put(PingTestCommand.class, new CitrixPingTestCommandWrapper()); + map.put(CheckOnHostCommand.class, new CitrixCheckOnHostCommandWrapper()); + map.put(ModifySshKeysCommand.class, new CitrixModifySshKeysCommandWrapper()); + map.put(StartCommand.class, new CitrixStartCommandWrapper()); + map.put(OvsSetTagAndFlowCommand.class, new CitrixOvsSetTagAndFlowCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixStartCommandWrapper.java new file mode 100644 index 00000000000..ceaaf3498d6 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixStartCommandWrapper.java @@ -0,0 +1,210 @@ +// +// 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.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.OvsSetTagAndFlowAnswer; +import com.cloud.agent.api.OvsSetTagAndFlowCommand; +import com.cloud.agent.api.StartAnswer; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.GPUDeviceTO; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.network.Networks; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.IsolationType; +import com.cloud.resource.CommandWrapper; +import com.cloud.vm.VirtualMachine; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types.VmPowerState; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +public final class CitrixStartCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixStartCommandWrapper.class); + + @Override + public Answer execute(final StartCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final VirtualMachineTO vmSpec = command.getVirtualMachine(); + final String vmName = vmSpec.getName(); + VmPowerState state = VmPowerState.HALTED; + VM vm = null; + // if a VDI is created, record its UUID to send back to the CS MS + final Map iqnToPath = new HashMap(); + try { + final Set vms = VM.getByNameLabel(conn, vmName); + if (vms != null) { + for (final VM v : vms) { + final VM.Record vRec = v.getRecord(conn); + if (vRec.powerState == VmPowerState.HALTED) { + v.destroy(conn); + } else if (vRec.powerState == VmPowerState.RUNNING) { + final String host = vRec.residentOn.getUuid(conn); + final String msg = "VM " + vmName + " is runing on host " + host; + s_logger.debug(msg); + return new StartAnswer(command, msg, host); + } else { + final String msg = "There is already a VM having the same name " + vmName + " vm record " + vRec.toString(); + s_logger.warn(msg); + return new StartAnswer(command, msg); + } + } + } + s_logger.debug("1. The VM " + vmName + " is in Starting state."); + + final Host host = Host.getByUuid(conn, citrixResourceBase.getHost().getUuid()); + vm = citrixResourceBase.createVmFromTemplate(conn, vmSpec, host); + + final GPUDeviceTO gpuDevice = vmSpec.getGpuDevice(); + if (gpuDevice != null) { + s_logger.debug("Creating VGPU for of VGPU type: " + gpuDevice.getVgpuType() + " in GPU group " + gpuDevice.getGpuGroup() + " for VM " + vmName); + citrixResourceBase.createVGPU(conn, command, vm, gpuDevice); + } + + for (final DiskTO disk : vmSpec.getDisks()) { + final VDI newVdi = citrixResourceBase.prepareManagedDisk(conn, disk, vmName); + + if (newVdi != null) { + final String path = newVdi.getUuid(conn); + + iqnToPath.put(disk.getDetails().get(DiskTO.IQN), path); + } + + citrixResourceBase.createVbd(conn, disk, vmName, vm, vmSpec.getBootloader(), newVdi); + } + + if (vmSpec.getType() != VirtualMachine.Type.User) { + citrixResourceBase.createPatchVbd(conn, vmName, vm); + } + + for (final NicTO nic : vmSpec.getNics()) { + citrixResourceBase.createVif(conn, vmName, vm, vmSpec, nic); + } + + citrixResourceBase.startVM(conn, host, vm, vmName); + + if (citrixResourceBase.isOvs()) { + // TODO(Salvatore-orlando): This code should go + for (final NicTO nic : vmSpec.getNics()) { + if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vswitch) { + final HashMap args = citrixResourceBase.parseDefaultOvsRuleComamnd(BroadcastDomainType.getValue(nic.getBroadcastUri())); + final OvsSetTagAndFlowCommand flowCmd = new OvsSetTagAndFlowCommand(args.get("vmName"), args.get("tag"), args.get("vlans"), args.get("seqno"), + Long.parseLong(args.get("vmId"))); + + final CitrixRequestWrapper citrixRequestWrapper = CitrixRequestWrapper.getInstance(); + + final OvsSetTagAndFlowAnswer r = (OvsSetTagAndFlowAnswer) citrixRequestWrapper.execute(flowCmd, citrixResourceBase); + + if (!r.getResult()) { + s_logger.warn("Failed to set flow for VM " + r.getVmId()); + } else { + s_logger.info("Success to set flow for VM " + r.getVmId()); + } + } + } + } + + if (citrixResourceBase.canBridgeFirewall()) { + String result = null; + if (vmSpec.getType() != VirtualMachine.Type.User) { + final NicTO[] nics = vmSpec.getNics(); + boolean secGrpEnabled = false; + for (final NicTO nic : nics) { + if (nic.isSecurityGroupEnabled() || nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { + secGrpEnabled = true; + break; + } + } + if (secGrpEnabled) { + result = citrixResourceBase.callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", vmName); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program default network rules for " + vmName); + } else { + s_logger.info("Programmed default network rules for " + vmName); + } + } + + } else { + // For user vm, program the rules for each nic if the + // isolation uri scheme is ec2 + final NicTO[] nics = vmSpec.getNics(); + for (final NicTO nic : nics) { + if (nic.isSecurityGroupEnabled() || nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { + final List nicSecIps = nic.getNicSecIps(); + String secIpsStr; + final StringBuilder sb = new StringBuilder(); + if (nicSecIps != null) { + for (final String ip : nicSecIps) { + sb.append(ip).append(":"); + } + secIpsStr = sb.toString(); + } else { + secIpsStr = "0:"; + } + result = citrixResourceBase.callHostPlugin(conn, "vmops", "default_network_rules", "vmName", vmName, "vmIP", nic.getIp(), "vmMAC", nic.getMac(), + "vmID", Long.toString(vmSpec.getId()), "secIps", secIpsStr); + + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program default network rules for " + vmName + " on nic with ip:" + nic.getIp() + " mac:" + nic.getMac()); + } else { + s_logger.info("Programmed default network rules for " + vmName + " on nic with ip:" + nic.getIp() + " mac:" + nic.getMac()); + } + } + } + } + } + + state = VmPowerState.RUNNING; + + final StartAnswer startAnswer = new StartAnswer(command); + + startAnswer.setIqnToPath(iqnToPath); + + return startAnswer; + } catch (final Exception e) { + s_logger.warn("Catch Exception: " + e.getClass().toString() + " due to " + e.toString(), e); + final String msg = citrixResourceBase.handleVmStartFailure(conn, vmName, vm, "", e); + + final StartAnswer startAnswer = new StartAnswer(command, msg); + + startAnswer.setIqnToPath(iqnToPath); + + return startAnswer; + } finally { + if (state != VmPowerState.HALTED) { + s_logger.debug("2. The VM " + vmName + " is in " + state + " state."); + } else { + s_logger.debug("The VM is in stopped state, detected problem during startup : " + vmName); + } + } + } +} \ No newline at end of file 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 0ba9d1a1f3b..0ffa7f4f92e 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 @@ -3,6 +3,7 @@ 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.junit.Assert.fail; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -13,6 +14,7 @@ import java.util.Hashtable; import java.util.Map; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClient; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,6 +28,7 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; 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.Command; import com.cloud.agent.api.CreateStoragePoolCommand; @@ -37,7 +40,9 @@ import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortCommand; 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.OvsSetTagAndFlowCommand; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; @@ -45,6 +50,7 @@ import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.SetupCommand; +import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; @@ -67,6 +73,9 @@ import com.cloud.vm.DiskProfile; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.Marshalling; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.Types.BadServerResponse; +import com.xensource.xenapi.Types.XenAPIException; @RunWith(PowerMockRunner.class) @PrepareForTest({Connection.class, Host.Record.class}) @@ -189,36 +198,36 @@ public class CitrixRequestWrapperTest { @Test public void testGetVmDiskStatsCommand() { - final GetVmDiskStatsCommand statsCommand = new GetVmDiskStatsCommand(new ArrayList(), null, null); + final GetVmDiskStatsCommand diskStatsCommand = new GetVmDiskStatsCommand(new ArrayList(), null, null); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + final Answer answer = wrapper.execute(diskStatsCommand, citrixResourceBase); assertTrue(answer.getResult()); } @Test public void testCheckHealthCommand() { - final CheckHealthCommand statsCommand = new CheckHealthCommand(); + final CheckHealthCommand checkHealthCommand = new CheckHealthCommand(); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + final Answer answer = wrapper.execute(checkHealthCommand, citrixResourceBase); assertFalse(answer.getResult()); } @Test public void testStopCommandCommand() { - final StopCommand statsCommand = new StopCommand("Test", false, false); + final StopCommand stopCommand = new StopCommand("Test", false, false); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(statsCommand, citrixResourceBase); + final Answer answer = wrapper.execute(stopCommand, citrixResourceBase); assertFalse(answer.getResult()); } @@ -300,14 +309,14 @@ public class CitrixRequestWrapperTest { final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); final XsHost xsHost = Mockito.mock(XsHost.class); - final CreateStoragePoolCommand destroyCommand = new CreateStoragePoolCommand(false, poolVO); + final CreateStoragePoolCommand createStorageCommand = new CreateStoragePoolCommand(false, poolVO); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); when(citrixResourceBase.getHost()).thenReturn(xsHost); - final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + final Answer answer = wrapper.execute(createStorageCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); @@ -318,14 +327,14 @@ public class CitrixRequestWrapperTest { final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); final XsHost xsHost = Mockito.mock(XsHost.class); - final ModifyStoragePoolCommand destroyCommand = new ModifyStoragePoolCommand(false, poolVO); + final ModifyStoragePoolCommand modifyStorageCommand = new ModifyStoragePoolCommand(false, poolVO); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); when(citrixResourceBase.getHost()).thenReturn(xsHost); - final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + final Answer answer = wrapper.execute(modifyStorageCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); @@ -336,14 +345,14 @@ public class CitrixRequestWrapperTest { final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); final XsHost xsHost = Mockito.mock(XsHost.class); - final DeleteStoragePoolCommand destroyCommand = new DeleteStoragePoolCommand(poolVO); + final DeleteStoragePoolCommand deleteStorageCommand = new DeleteStoragePoolCommand(poolVO); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); when(citrixResourceBase.getHost()).thenReturn(xsHost); - final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + final Answer answer = wrapper.execute(deleteStorageCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertTrue(answer.getResult()); @@ -366,12 +375,12 @@ public class CitrixRequestWrapperTest { @Test public void testAttachVolumeCommand() { - final AttachVolumeCommand destroyCommand = new AttachVolumeCommand(false, true, "Test", StoragePoolType.LVM, "/", "DATA", 100l, 1l, "123"); + final AttachVolumeCommand attachCommand = new AttachVolumeCommand(false, true, "Test", StoragePoolType.LVM, "/", "DATA", 100l, 1l, "123"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + final Answer answer = wrapper.execute(attachCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); @@ -379,12 +388,12 @@ public class CitrixRequestWrapperTest { @Test public void testAttachIsoCommand() { - final AttachIsoCommand destroyCommand = new AttachIsoCommand("Test", "/", true); + final AttachIsoCommand attachCommand = new AttachIsoCommand("Test", "/", true); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + final Answer answer = wrapper.execute(attachCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); @@ -394,12 +403,12 @@ public class CitrixRequestWrapperTest { public void testUpgradeSnapshotCommand() { final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); - final UpgradeSnapshotCommand destroyCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", "2.1"); + final UpgradeSnapshotCommand upgradeSnapshotCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", "2.1"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + final Answer answer = wrapper.execute(upgradeSnapshotCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertTrue(answer.getResult()); @@ -409,12 +418,12 @@ public class CitrixRequestWrapperTest { public void testUpgradeSnapshotCommandNo21() { final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); - final UpgradeSnapshotCommand destroyCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", "3.1"); + final UpgradeSnapshotCommand upgradeSnapshotCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", "3.1"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(destroyCommand, citrixResourceBase); + final Answer answer = wrapper.execute(upgradeSnapshotCommand, citrixResourceBase); verify(citrixResourceBase, times(0)).getConnection(); assertTrue(answer.getResult()); @@ -458,12 +467,12 @@ public class CitrixRequestWrapperTest { @Test public void testGetVncPortCommand() { - final GetVncPortCommand storageDownloadCommand = new GetVncPortCommand(1l, "Test"); + final GetVncPortCommand vncPortCommand = new GetVncPortCommand(1l, "Test"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(storageDownloadCommand, citrixResourceBase); + final Answer answer = wrapper.execute(vncPortCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); @@ -474,14 +483,14 @@ public class CitrixRequestWrapperTest { final XsHost xsHost = Mockito.mock(XsHost.class); final HostEnvironment env = Mockito.mock(HostEnvironment.class); - final SetupCommand storageDownloadCommand = new SetupCommand(env); + final SetupCommand setupCommand = new SetupCommand(env); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); when(citrixResourceBase.getHost()).thenReturn(xsHost); - final Answer answer = wrapper.execute(storageDownloadCommand, citrixResourceBase); + final Answer answer = wrapper.execute(setupCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); @@ -500,7 +509,7 @@ public class CitrixRequestWrapperTest { // final Host.Record hr = PowerMockito.mock(Host.Record.class); // final Host host = PowerMockito.mock(Host.class); - final MaintainCommand storageDownloadCommand = new MaintainCommand(); + final MaintainCommand maintainCommand = new MaintainCommand(); final Map map = new Hashtable(); map.put("Value", "Xen"); @@ -551,23 +560,107 @@ public class CitrixRequestWrapperTest { // fail(e.getMessage()); // } - final Answer answer = wrapper.execute(storageDownloadCommand, citrixResourceBase); + final Answer answer = wrapper.execute(maintainCommand, citrixResourceBase); assertFalse(answer.getResult()); } @Test public void testPingTestCommandHostIp() { - final PingTestCommand storageDownloadCommand = new PingTestCommand("127.0.0.1"); + final PingTestCommand pingTestCommand = new PingTestCommand("127.0.0.1"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); - final Answer answer = wrapper.execute(storageDownloadCommand, citrixResourceBase); + final Answer answer = wrapper.execute(pingTestCommand, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); } + + @Test + public void testPingTestCommandRouterPvtIps() { + final PingTestCommand pingTestCommand = new PingTestCommand("127.0.0.1", "192.168.0.1"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(pingTestCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testCheckOnHostCommand() { + final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class); + final CheckOnHostCommand onHostCommand = new CheckOnHostCommand(host); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(onHostCommand, citrixResourceBase); + + assertFalse(answer.getResult()); + } + + @Test + public void testModifySshKeysCommand() { + final ModifySshKeysCommand sshKeysCommand = new ModifySshKeysCommand("", ""); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(sshKeysCommand, citrixResourceBase); + + assertTrue(answer.getResult()); + } + + @Test + public void testStartCommand() { + final VirtualMachineTO vm = Mockito.mock(VirtualMachineTO.class); + final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class); + + final StartCommand startCommand = new StartCommand(vm, host, false); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(startCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testOvsSetTagAndFlowCommand() { + final Network network = Mockito.mock(Network.class); + final Connection conn = Mockito.mock(Connection.class); + + final OvsSetTagAndFlowCommand tagAndFlowCommand = new OvsSetTagAndFlowCommand("Test", "tag", "vlan://1", "123", 1l); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.setupvSwitchNetwork(conn)).thenReturn(network); + try { + when(network.getBridge(conn)).thenReturn("br0"); + } 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(tagAndFlowCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + verify(citrixResourceBase, times(1)).setupvSwitchNetwork(conn); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 30b770aeab9c1efeaf84c4f5274ab2cb044a896c Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Thu, 26 Mar 2015 16:52:00 +0100 Subject: [PATCH 21/30] Refactoring CheckSshCommand, OvsFetchInterfaceCommand and SecurityGroupRulesCommand to cope with new design. - Unit Tests added --- .../resource/CitrixResourceBase.java | 95 +++---------------- .../xenserver/resource/XsLocalNetwork.java | 91 ++++++++++++++++++ .../wrapper/CitrixCheckSshCommandWrapper.java | 63 ++++++++++++ ...CitrixOvsFetchInterfaceCommandWrapper.java | 71 ++++++++++++++ .../wrapper/CitrixRequestWrapper.java | 6 ++ ...itrixSecurityGroupRulesCommandWrapper.java | 61 ++++++++++++ .../wrapper/CitrixRequestWrapperTest.java | 73 ++++++++++++++ 7 files changed, 379 insertions(+), 81 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XsLocalNetwork.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckSshCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsFetchInterfaceCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixSecurityGroupRulesCommandWrapper.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 c9b05a4cf68..4477a701e54 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 @@ -461,12 +461,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == CheckSshCommand.class) { - return execute((CheckSshCommand)cmd); - } else if (clazz == SecurityGroupRulesCmd.class) { - return execute((SecurityGroupRulesCmd)cmd); - } else if (clazz == OvsFetchInterfaceCommand.class) { - return execute((OvsFetchInterfaceCommand)cmd); } else if (clazz == OvsCreateGreTunnelCommand.class) { return execute((OvsCreateGreTunnelCommand)cmd); } else if (clazz == OvsDeleteFlowCommand.class) { @@ -847,17 +841,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (type == TrafficType.Guest) { - return new XsLocalNetwork(Network.getByUuid(conn, _host.getGuestNetwork()), null, PIF.getByUuid(conn, _host.getGuestPif()), null); + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getGuestNetwork()), null, PIF.getByUuid(conn, _host.getGuestPif()), null); } else if (type == TrafficType.Control) { setupLinkLocalNetwork(conn); - return new XsLocalNetwork(Network.getByUuid(conn, _host.getLinkLocalNetwork())); + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getLinkLocalNetwork())); } else if (type == TrafficType.Management) { - return new XsLocalNetwork(Network.getByUuid(conn, _host.getPrivateNetwork()), null, PIF.getByUuid(conn, _host.getPrivatePif()), null); + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPrivateNetwork()), null, PIF.getByUuid(conn, _host.getPrivatePif()), null); } else if (type == TrafficType.Public) { - return new XsLocalNetwork(Network.getByUuid(conn, _host.getPublicNetwork()), null, PIF.getByUuid(conn, _host.getPublicPif()), null); + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPublicNetwork()), null, PIF.getByUuid(conn, _host.getPublicPif()), null); } else if (type == TrafficType.Storage) { /* TrafficType.Storage is for secondary storage, while storageNetwork1 is for primary storage, we need better name here */ - return new XsLocalNetwork(Network.getByUuid(conn, _host.getStorageNetwork1()), null, PIF.getByUuid(conn, _host.getStoragePif1()), null); + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getStorageNetwork1()), null, PIF.getByUuid(conn, _host.getStoragePif1()), null); } throw new CloudRuntimeException("Unsupported network type: " + type); @@ -3571,7 +3565,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vdis; } - protected String connect(final Connection conn, final String vmName, final String ipAddress, final int port) { + public String connect(final Connection conn, final String vmName, final String ipAddress, final int port) { for (int i = 0; i <= _retry; i++) { try { final Set vms = VM.getByNameLabel(conn, vmName); @@ -3729,7 +3723,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } final Network nk = mgmtPifRec.network; final Network.Record nkRec = nk.getRecord(conn); - return new XsLocalNetwork(nk, nkRec, mgmtPif, mgmtPifRec); + return new XsLocalNetwork(this, nk, nkRec, mgmtPif, mgmtPifRec); } protected VIF getCorrectVif(final Connection conn, final VM router, final Network network) throws XmlRpcException, XenAPIException { @@ -3864,10 +3858,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe * * @see CitrixResourceBase#enableVlanNetwork */ - protected XsLocalNetwork getNetworkByName(final Connection conn, final String name) throws XenAPIException, XmlRpcException { + public XsLocalNetwork getNetworkByName(final Connection conn, final String name) throws XenAPIException, XmlRpcException { final Set networks = Network.getByNameLabel(conn, name); if (networks.size() == 1) { - return new XsLocalNetwork(networks.iterator().next(), null, null, null); + return new XsLocalNetwork(this, networks.iterator().next(), null, null, null); } if (networks.size() == 0) { @@ -3882,7 +3876,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe long earliestTimestamp = Long.MAX_VALUE; int earliestRandom = Integer.MAX_VALUE; for (final Network network : networks) { - final XsLocalNetwork nic = new XsLocalNetwork(network); + final XsLocalNetwork nic = new XsLocalNetwork(this, network); if (nic.getPif(conn) != null) { return nic; @@ -3906,7 +3900,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - return earliestNetwork != null ? new XsLocalNetwork(earliestNetwork, earliestNetworkRecord, null, null) : null; + return earliestNetwork != null ? new XsLocalNetwork(this, earliestNetwork, earliestNetworkRecord, null, null) : null; } protected String generateTimeStamp() { @@ -5314,7 +5308,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String label = cmd.getLabel(); //FIXME: this is a tricky to pass the network checking in XCP. I temporary get default label from Host. - if (is_xcp()) { + if (isXcp()) { label = getLabel(); } s_logger.debug("Will look for network with name-label:" + label + " on host " + _host.getIp()); @@ -6894,67 +6888,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new Answer(cmd, true, result); } - /** - * XsNic represents a network and the host's specific PIF. - */ - protected class XsLocalNetwork { - private final Network _n; - private Network.Record _nr; - private PIF _p; - private PIF.Record _pr; - - public XsLocalNetwork(final Network n) { - this(n, null, null, null); - } - - public XsLocalNetwork(final Network n, final Network.Record nr, final PIF p, final PIF.Record pr) { - _n = n; - _nr = nr; - _p = p; - _pr = pr; - } - - public Network getNetwork() { - return _n; - } - - public Network.Record getNetworkRecord(final Connection conn) throws XenAPIException, XmlRpcException { - if (_nr == null) { - _nr = _n.getRecord(conn); - } - - return _nr; - } - - public PIF getPif(final Connection conn) throws XenAPIException, XmlRpcException { - if (_p == null) { - final Network.Record nr = getNetworkRecord(conn); - for (final PIF pif : nr.PIFs) { - final PIF.Record pr = pif.getRecord(conn); - if (_host.getUuid().equals(pr.host.getUuid(conn))) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found a network called " + nr.nameLabel + " on host=" + _host.getIp() + "; Network=" + nr.uuid + "; pif=" + pr.uuid); - } - _p = pif; - _pr = pr; - break; - } - } - } - return _p; - } - - public PIF.Record getPifRecord(final Connection conn) throws XenAPIException, XmlRpcException { - if (_pr == null) { - final PIF p = getPif(conn); - if (_pr == null) { - _pr = p.getRecord(conn); - } - } - return _pr; - } - } - protected String getGuestOsType(final String stdType, String platformEmulator, final boolean bootFromCD) { if (platformEmulator == null) { s_logger.debug("no guest OS type, start it as HVM guest"); @@ -7259,7 +7192,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public void setRunLevel(final int level) { } - private boolean is_xcp() { + public boolean isXcp() { final Connection conn = getConnection(); final String result = callHostPlugin(conn, "ovstunnel", "is_xcp"); if (result.equals("XCP")) { @@ -7268,7 +7201,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return false; } - private String getLabel() { + public String getLabel() { final Connection conn = getConnection(); final String result = callHostPlugin(conn, "ovstunnel", "getLabel"); return result; diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XsLocalNetwork.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XsLocalNetwork.java new file mode 100644 index 00000000000..c7f4f8369ea --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XsLocalNetwork.java @@ -0,0 +1,91 @@ +// 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; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.PIF; +import com.xensource.xenapi.Types.XenAPIException; + +/** + * XsNic represents a network and the host's specific PIF. + */ +public class XsLocalNetwork { + + private static final Logger s_logger = Logger.getLogger(XsLocalNetwork.class); + + private final CitrixResourceBase _citrixResourceBase; + private final Network _n; + private Network.Record _nr; + private PIF _p; + private PIF.Record _pr; + + public XsLocalNetwork(final CitrixResourceBase citrixResourceBase, final Network n) { + this(citrixResourceBase, n, null, null, null); + } + + public XsLocalNetwork(final CitrixResourceBase citrixResourceBase, final Network n, final Network.Record nr, final PIF p, final PIF.Record pr) { + _citrixResourceBase = citrixResourceBase; + _n = n; + _nr = nr; + _p = p; + _pr = pr; + } + + public Network getNetwork() { + return _n; + } + + public Network.Record getNetworkRecord(final Connection conn) throws XenAPIException, XmlRpcException { + if (_nr == null) { + _nr = _n.getRecord(conn); + } + + return _nr; + } + + public PIF getPif(final Connection conn) throws XenAPIException, XmlRpcException { + if (_p == null) { + final Network.Record nr = getNetworkRecord(conn); + for (final PIF pif : nr.PIFs) { + final PIF.Record pr = pif.getRecord(conn); + if (_citrixResourceBase.getHost().getUuid().equals(pr.host.getUuid(conn))) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found a network called " + nr.nameLabel + " on host=" + _citrixResourceBase.getHost().getIp() + "; Network=" + nr.uuid + "; pif=" + pr.uuid); + } + _p = pif; + _pr = pr; + break; + } + } + } + return _p; + } + + public PIF.Record getPifRecord(final Connection conn) throws XenAPIException, XmlRpcException { + if (_pr == null) { + final PIF p = getPif(conn); + if (_pr == null) { + _pr = p.getRecord(conn); + } + } + return _pr; + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckSshCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckSshCommandWrapper.java new file mode 100644 index 00000000000..4437641d405 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckSshCommandWrapper.java @@ -0,0 +1,63 @@ +// +// 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.check.CheckSshAnswer; +import com.cloud.agent.api.check.CheckSshCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixCheckSshCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixCheckSshCommandWrapper.class); + + @Override + public Answer execute(final CheckSshCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final String vmName = command.getName(); + final String privateIp = command.getIp(); + final int cmdPort = command.getPort(); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort); + } + + try { + final String result = citrixResourceBase.connect(conn, command.getName(), privateIp, cmdPort); + if (result != null) { + return new CheckSshAnswer(command, "Can not ping System vm " + vmName + "due to:" + result); + } + //Do not destroy the disk here! It will stio the patching process. Please, don't! + //destroyPatchVbd(conn, vmName); + } catch (final Exception e) { + return new CheckSshAnswer(command, e); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port succeeded for vm " + vmName); + } + + return new CheckSshAnswer(command); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsFetchInterfaceCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsFetchInterfaceCommandWrapper.java new file mode 100644 index 00000000000..1f211a48494 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsFetchInterfaceCommandWrapper.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 org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.OvsFetchInterfaceAnswer; +import com.cloud.agent.api.OvsFetchInterfaceCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.hypervisor.xenserver.resource.XsLocalNetwork; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.PIF; +import com.xensource.xenapi.Types.BadServerResponse; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixOvsFetchInterfaceCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsFetchInterfaceCommandWrapper.class); + + @Override + public Answer execute(final OvsFetchInterfaceCommand command, final CitrixResourceBase citrixResourceBase) { + String label = command.getLabel(); + //FIXME: this is a tricky to pass the network checking in XCP. I temporary get default label from Host. + if (citrixResourceBase.isXcp()) { + label = citrixResourceBase.getLabel(); + } + s_logger.debug("Will look for network with name-label:" + label + " on host " + citrixResourceBase.getHost().getIp()); + final Connection conn = citrixResourceBase.getConnection(); + try { + final XsLocalNetwork nw = citrixResourceBase.getNetworkByName(conn, label); + if(nw == null) { + throw new CloudRuntimeException("Unable to locate the network with name-label: " + label + " on host: " + citrixResourceBase.getHost().getIp()); + } + s_logger.debug("Network object:" + nw.getNetwork().getUuid(conn)); + final PIF pif = nw.getPif(conn); + final PIF.Record pifRec = pif.getRecord(conn); + s_logger.debug("PIF object:" + pifRec.uuid + "(" + pifRec.device + ")"); + return new OvsFetchInterfaceAnswer(command, true, "Interface " + pifRec.device + " retrieved successfully", pifRec.IP, pifRec.netmask, pifRec.MAC); + } catch (final BadServerResponse e) { + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + citrixResourceBase.getHost().getIp(), e); + return new OvsFetchInterfaceAnswer(command, false, "EXCEPTION:" + e.getMessage()); + } catch (final XenAPIException e) { + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + citrixResourceBase.getHost().getIp(), e); + return new OvsFetchInterfaceAnswer(command, false, "EXCEPTION:" + e.getMessage()); + } catch (final XmlRpcException e) { + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + citrixResourceBase.getHost().getIp(), e); + return new OvsFetchInterfaceAnswer(command, false, "EXCEPTION:" + 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 fbb3f27c42d..be7aec66485 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 @@ -39,16 +39,19 @@ 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.OvsFetchInterfaceCommand; import com.cloud.agent.api.OvsSetTagAndFlowCommand; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StopCommand; 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.storage.CreateCommand; @@ -109,6 +112,9 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(ModifySshKeysCommand.class, new CitrixModifySshKeysCommandWrapper()); map.put(StartCommand.class, new CitrixStartCommandWrapper()); map.put(OvsSetTagAndFlowCommand.class, new CitrixOvsSetTagAndFlowCommandWrapper()); + map.put(CheckSshCommand.class, new CitrixCheckSshCommandWrapper()); + map.put(SecurityGroupRulesCmd.class, new CitrixSecurityGroupRulesCommandWrapper()); + map.put(OvsFetchInterfaceCommand.class, new CitrixOvsFetchInterfaceCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixSecurityGroupRulesCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixSecurityGroupRulesCommandWrapper.java new file mode 100644 index 00000000000..0cf4a8ab29b --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixSecurityGroupRulesCommandWrapper.java @@ -0,0 +1,61 @@ +// +// 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.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixSecurityGroupRulesCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixSecurityGroupRulesCommandWrapper.class); + + @Override + public Answer execute(final SecurityGroupRulesCmd command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + if (s_logger.isTraceEnabled()) { + s_logger.trace("Sending network rules command to " + citrixResourceBase.getHost().getIp()); + } + + if (!citrixResourceBase.canBridgeFirewall()) { + s_logger.warn("Host " + citrixResourceBase.getHost().getIp() + " cannot do bridge firewalling"); + return new SecurityGroupRuleAnswer(command, false, "Host " + citrixResourceBase.getHost().getIp() + " cannot do bridge firewalling", + SecurityGroupRuleAnswer.FailureReason.CANNOT_BRIDGE_FIREWALL); + } + + final String result = citrixResourceBase.callHostPlugin(conn, "vmops", "network_rules", "vmName", command.getVmName(), "vmIP", command.getGuestIp(), "vmMAC", + command.getGuestMac(), "vmID", Long.toString(command.getVmId()), "signature", command.getSignature(), "seqno", Long.toString(command.getSeqNum()), "deflated", + "true", "rules", command.compressStringifiedRules(), "secIps", command.getSecIpsString()); + + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program network rules for vm " + command.getVmName()); + return new SecurityGroupRuleAnswer(command, false, "programming network rules failed"); + } else { + s_logger.info("Programmed network rules for vm " + command.getVmName() + " guestIp=" + command.getGuestIp() + ", ingress numrules=" + + command.getIngressRuleSet().length + ", egress numrules=" + command.getEgressRuleSet().length); + return new SecurityGroupRuleAnswer(command); + } + } +} \ No newline at end of file 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 0ffa7f4f92e..75dd051ffcf 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 @@ -49,10 +49,12 @@ 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.SecurityGroupRulesCmd; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StopCommand; 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.storage.CreateAnswer; @@ -66,6 +68,7 @@ import com.cloud.agent.api.to.VirtualMachineTO; 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.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.VMTemplateStorageResourceAssoc; @@ -586,6 +589,7 @@ public class CitrixRequestWrapperTest { assertNotNull(wrapper); final Answer answer = wrapper.execute(pingTestCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); @@ -627,6 +631,7 @@ public class CitrixRequestWrapperTest { assertNotNull(wrapper); final Answer answer = wrapper.execute(startCommand, citrixResourceBase); + verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); @@ -661,6 +666,74 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testCheckSshCommand() { + final CheckSshCommand sshCommand = new CheckSshCommand("Test", "127.0.0.1", 22); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(sshCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testSecurityGroupRulesCommand() { + final Connection conn = Mockito.mock(Connection.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final SecurityGroupRulesCmd sshCommand = new SecurityGroupRulesCmd(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getHost()).thenReturn(xsHost); + + final Answer answer = wrapper.execute(sshCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testOvsFetchInterfaceCommand() { + final String label = "[abc]"; + + final Connection conn = Mockito.mock(Connection.class); + final XsLocalNetwork network = Mockito.mock(XsLocalNetwork.class); + + final XsHost xsHost = Mockito.mock(XsHost.class); + + final SecurityGroupRulesCmd sshCommand = new SecurityGroupRulesCmd(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.isXcp()).thenReturn(true); + when(citrixResourceBase.getLabel()).thenReturn("[abc]"); + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getHost()).thenReturn(xsHost); + + try { + when(citrixResourceBase.getNetworkByName(conn, label)).thenReturn(network); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + final Answer answer = wrapper.execute(sshCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 751c14b929c1f9a7e703f2a1fa0d46ca0ca8fe6f Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Mon, 30 Mar 2015 15:18:46 +0200 Subject: [PATCH 22/30] 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 { From fbcae54a5b21cdf5c77dc3676415112ecb3b25cd Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Mon, 30 Mar 2015 16:05:42 +0200 Subject: [PATCH 23/30] Refactoring NetworkRulesSystemVmCommand, OvsCreateTunnelCommand, OvsDestroyBridgeCommand, OvsDestroyTunnelCommand, OvsSetupBridgeCommand in order to cope with new design. - Meny unit ests added. --- .../resource/CitrixResourceBase.java | 16 +- ...rixNetworkRulesSystemVmCommandWrapper.java | 45 +++ .../CitrixOvsCreateTunnelCommandWrapper.java | 67 ++++ .../CitrixOvsDestroyBridgeCommandWrapper.java | 53 +++ .../CitrixOvsDestroyTunnelCommandWrapper.java | 58 +++ .../CitrixOvsSetupBridgeCommandWrapper.java | 45 +++ .../wrapper/CitrixRequestWrapper.java | 10 + .../wrapper/CitrixRequestWrapperTest.java | 357 ++++++++++++++++-- 8 files changed, 597 insertions(+), 54 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkRulesSystemVmCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsCreateTunnelCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDestroyBridgeCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDestroyTunnelCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsSetupBridgeCommandWrapper.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 c1705c0ce8e..c495b75e1a7 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 @@ -467,16 +467,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == NetworkRulesSystemVmCommand.class) { - return execute((NetworkRulesSystemVmCommand)cmd); - } else if (clazz == OvsCreateTunnelCommand.class) { - return execute((OvsCreateTunnelCommand)cmd); - } else if (clazz == OvsSetupBridgeCommand.class) { - return execute((OvsSetupBridgeCommand)cmd); - } else if (clazz == OvsDestroyBridgeCommand.class) { - return execute((OvsDestroyBridgeCommand)cmd); - } else if (clazz == OvsDestroyTunnelCommand.class) { - return execute((OvsDestroyTunnelCommand)cmd); } else if (clazz == UpdateHostPasswordCommand.class) { return execute((UpdateHostPasswordCommand)cmd); } else if (cmd instanceof ClusterVMMetaDataSyncCommand) { @@ -917,7 +907,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe /** * This method creates a XenServer network and configures it for being used as a L2-in-L3 tunneled network */ - private synchronized Network configureTunnelNetwork(final Connection conn, final Long networkId, final long hostId, final String bridgeName) { + public synchronized Network configureTunnelNetwork(final Connection conn, final Long networkId, final long hostId, final String bridgeName) { try { final Network nw = findOrCreateTunnelNetwork(conn, bridgeName); final String nwName = bridgeName; @@ -964,7 +954,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - private synchronized void destroyTunnelNetwork(final Connection conn, final Network nw, final long hostId) { + public synchronized void destroyTunnelNetwork(final Connection conn, final Network nw, final long hostId) { try { final String bridge = nw.getBridge(conn); final String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge, @@ -1617,7 +1607,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return cmd; } - private void cleanUpTmpDomVif(final Connection conn, final Network nw) throws XenAPIException, XmlRpcException { + public void cleanUpTmpDomVif(final Connection conn, final Network nw) throws XenAPIException, XmlRpcException { final Pair vm = getControlDomain(conn); final VM dom0 = vm.first(); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkRulesSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkRulesSystemVmCommandWrapper.java new file mode 100644 index 00000000000..cdd93ae665b --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkRulesSystemVmCommandWrapper.java @@ -0,0 +1,45 @@ +// +// 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.NetworkRulesSystemVmCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.vm.VirtualMachine; +import com.xensource.xenapi.Connection; + +public final class CitrixNetworkRulesSystemVmCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final NetworkRulesSystemVmCommand command, final CitrixResourceBase citrixResourceBase) { + boolean success = true; + final Connection conn = citrixResourceBase.getConnection(); + if (command.getType() != VirtualMachine.Type.User) { + + final String result = citrixResourceBase.callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", command.getVmName()); + 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/CitrixOvsCreateTunnelCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsCreateTunnelCommandWrapper.java new file mode 100644 index 00000000000..3e25a743822 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsCreateTunnelCommandWrapper.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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.OvsCreateTunnelAnswer; +import com.cloud.agent.api.OvsCreateTunnelCommand; +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 CitrixOvsCreateTunnelCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsCreateTunnelCommandWrapper.class); + + @Override + public Answer execute(final OvsCreateTunnelCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + String bridge = "unknown"; + try { + final Network nw = citrixResourceBase.findOrCreateTunnelNetwork(conn, command.getNetworkName()); + if (nw == null) { + s_logger.debug("Error during bridge setup"); + return new OvsCreateTunnelAnswer(command, false, "Cannot create network", bridge); + } + + citrixResourceBase.configureTunnelNetwork(conn, command.getNetworkId(), command.getFrom(), command.getNetworkName()); + bridge = nw.getBridge(conn); + final String result = + citrixResourceBase.callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", command.getRemoteIp(), + "key", command.getKey().toString(), "from", + command.getFrom().toString(), "to", command.getTo().toString(), "cloudstack-network-id", + command.getNetworkUuid()); + final String[] res = result.split(":"); + + if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) { + return new OvsCreateTunnelAnswer(command, true, result, res[1], bridge); + } else { + return new OvsCreateTunnelAnswer(command, false, result, bridge); + } + } catch (final Exception e) { + s_logger.debug("Error during tunnel setup"); + s_logger.warn("Caught execption when creating ovs tunnel", e); + return new OvsCreateTunnelAnswer(command, false, e.getMessage(), bridge); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDestroyBridgeCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDestroyBridgeCommandWrapper.java new file mode 100644 index 00000000000..ee6e4dd9c0e --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDestroyBridgeCommandWrapper.java @@ -0,0 +1,53 @@ +// +// 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.OvsDestroyBridgeCommand; +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 CitrixOvsDestroyBridgeCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsDestroyBridgeCommandWrapper.class); + + @Override + public Answer execute(final OvsDestroyBridgeCommand command, final CitrixResourceBase citrixResourceBase) { + try { + final Connection conn = citrixResourceBase.getConnection(); + + final Network nw = citrixResourceBase.findOrCreateTunnelNetwork(conn, command.getBridgeName()); + citrixResourceBase.cleanUpTmpDomVif(conn, nw); + + citrixResourceBase.destroyTunnelNetwork(conn, nw, command.getHostId()); + + s_logger.debug("OVS Bridge destroyed"); + + return new Answer(command, true, null); + } catch (final Exception e) { + s_logger.warn("caught execption when destroying ovs bridge", 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/CitrixOvsDestroyTunnelCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDestroyTunnelCommandWrapper.java new file mode 100644 index 00000000000..da0fd1f2f91 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDestroyTunnelCommandWrapper.java @@ -0,0 +1,58 @@ +// +// 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.OvsDestroyTunnelCommand; +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 CitrixOvsDestroyTunnelCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsDestroyTunnelCommandWrapper.class); + + @Override + public Answer execute(final OvsDestroyTunnelCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + try { + final Network nw = citrixResourceBase.findOrCreateTunnelNetwork(conn, command.getBridgeName()); + if (nw == null) { + s_logger.warn("Unable to find tunnel network for GRE key:" + command.getBridgeName()); + return new Answer(command, false, "No network found"); + } + + final String bridge = nw.getBridge(conn); + final String result = citrixResourceBase.callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", command.getInPortName()); + + if (result.equalsIgnoreCase("SUCCESS")) { + return new Answer(command, true, result); + } else { + return new Answer(command, false, result); + } + } catch (final Exception e) { + s_logger.warn("caught execption when destroy ovs tunnel", 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/CitrixOvsSetupBridgeCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsSetupBridgeCommandWrapper.java new file mode 100644 index 00000000000..0c553b4981a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsSetupBridgeCommandWrapper.java @@ -0,0 +1,45 @@ +// +// 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.OvsSetupBridgeCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixOvsSetupBridgeCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsSetupBridgeCommandWrapper.class); + + @Override + public Answer execute(final OvsSetupBridgeCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + + citrixResourceBase.findOrCreateTunnelNetwork(conn, command.getBridgeName()); + citrixResourceBase.configureTunnelNetwork(conn, command.getNetworkId(), command.getHostId(), command.getBridgeName()); + + s_logger.debug("OVS Bridge configured"); + + return new Answer(command, true, null); + } +} \ 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 eb179bb4a0c..eff580a61b2 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 @@ -40,10 +40,15 @@ 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.NetworkRulesSystemVmCommand; import com.cloud.agent.api.OvsCreateGreTunnelCommand; +import com.cloud.agent.api.OvsCreateTunnelCommand; import com.cloud.agent.api.OvsDeleteFlowCommand; +import com.cloud.agent.api.OvsDestroyBridgeCommand; +import com.cloud.agent.api.OvsDestroyTunnelCommand; import com.cloud.agent.api.OvsFetchInterfaceCommand; 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.PingTestCommand; @@ -125,6 +130,11 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(OvsVpcPhysicalTopologyConfigCommand.class, new CitrixOvsVpcPhysicalTopologyConfigCommandWrapper()); map.put(OvsVpcRoutingPolicyConfigCommand.class, new CitrixOvsVpcRoutingPolicyConfigCommandWrapper()); map.put(CleanupNetworkRulesCmd.class, new CitrixCleanupNetworkRulesCmdWrapper()); + map.put(NetworkRulesSystemVmCommand.class, new CitrixNetworkRulesSystemVmCommandWrapper()); + map.put(OvsCreateTunnelCommand.class, new CitrixOvsCreateTunnelCommandWrapper()); + map.put(OvsSetupBridgeCommand.class, new CitrixOvsSetupBridgeCommandWrapper()); + map.put(OvsDestroyBridgeCommand.class, new CitrixOvsDestroyBridgeCommandWrapper()); + map.put(OvsDestroyTunnelCommand.class, new CitrixOvsDestroyTunnelCommandWrapper()); } 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 5fde596c720..8b8c9ce6f73 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 @@ -45,10 +45,15 @@ 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.NetworkRulesSystemVmCommand; import com.cloud.agent.api.OvsCreateGreTunnelCommand; +import com.cloud.agent.api.OvsCreateTunnelCommand; import com.cloud.agent.api.OvsDeleteFlowCommand; +import com.cloud.agent.api.OvsDestroyBridgeCommand; +import com.cloud.agent.api.OvsDestroyTunnelCommand; import com.cloud.agent.api.OvsFetchInterfaceCommand; 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.PingTestCommand; @@ -81,6 +86,7 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.vm.DiskProfile; +import com.cloud.vm.VirtualMachine; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.Marshalling; @@ -90,7 +96,7 @@ import com.xensource.xenapi.Types.BadServerResponse; import com.xensource.xenapi.Types.XenAPIException; @RunWith(PowerMockRunner.class) -@PrepareForTest({Connection.class, Host.Record.class}) +@PrepareForTest({ Connection.class, Host.Record.class }) public class CitrixRequestWrapperTest { @Mock @@ -415,7 +421,8 @@ public class CitrixRequestWrapperTest { public void testUpgradeSnapshotCommand() { final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); - final UpgradeSnapshotCommand upgradeSnapshotCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", "2.1"); + final UpgradeSnapshotCommand upgradeSnapshotCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", + "2.1"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); @@ -430,7 +437,8 @@ public class CitrixRequestWrapperTest { public void testUpgradeSnapshotCommandNo21() { final StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); - final UpgradeSnapshotCommand upgradeSnapshotCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", "3.1"); + final UpgradeSnapshotCommand upgradeSnapshotCommand = new UpgradeSnapshotCommand(poolVO, "http", 1l, 1l, 1l, 1l, 1l, "/", "58c5778b-7dd1-47cc-a7b5-f768541bf278", "Test", + "3.1"); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); @@ -518,8 +526,8 @@ public class CitrixRequestWrapperTest { final XsHost xsHost = Mockito.mock(XsHost.class); final XmlRpcClient client = Mockito.mock(XmlRpcClient.class); - // final Host.Record hr = PowerMockito.mock(Host.Record.class); - // final Host host = PowerMockito.mock(Host.class); + // final Host.Record hr = PowerMockito.mock(Host.Record.class); + // final Host host = PowerMockito.mock(Host.class); final MaintainCommand maintainCommand = new MaintainCommand(); @@ -537,40 +545,42 @@ public class CitrixRequestWrapperTest { when(conn.getSessionReference()).thenReturn("befc4dcd"); try { - final Object [] params = {Marshalling.toXMLRPC("befc4dcd"), Marshalling.toXMLRPC(uuid)}; - when(client.execute("host.get_by_uuid", new Object[]{"befc4dcd", uuid})).thenReturn(spiedMap); + final Object[] params = { Marshalling.toXMLRPC("befc4dcd"), Marshalling.toXMLRPC(uuid) }; + when(client.execute("host.get_by_uuid", new Object[] { "befc4dcd", uuid })).thenReturn(spiedMap); PowerMockito.when(conn, "dispatch", "host.get_by_uuid", params).thenReturn(spiedMap); } catch (final Exception e) { } - // try { - // PowerMockito.mockStatic(Host.class); - // //BDDMockito.given(Host.getByUuid(conn, xsHost.getUuid())).willReturn(host); - // PowerMockito.when(Host.getByUuid(conn, xsHost.getUuid())).thenReturn(host); - // PowerMockito.verifyStatic(times(1)); - // } catch (final BadServerResponse e) { - // fail(e.getMessage()); - // } catch (final XenAPIException e) { - // fail(e.getMessage()); - // } catch (final XmlRpcException e) { - // fail(e.getMessage()); - // } + // try { + // PowerMockito.mockStatic(Host.class); + // //BDDMockito.given(Host.getByUuid(conn, + // xsHost.getUuid())).willReturn(host); + // PowerMockito.when(Host.getByUuid(conn, + // xsHost.getUuid())).thenReturn(host); + // PowerMockito.verifyStatic(times(1)); + // } catch (final BadServerResponse e) { + // fail(e.getMessage()); + // } catch (final XenAPIException e) { + // fail(e.getMessage()); + // } catch (final XmlRpcException e) { + // fail(e.getMessage()); + // } // - // PowerMockito.mockStatic(Types.class); - // PowerMockito.when(Types.toHostRecord(spiedMap)).thenReturn(hr); - // PowerMockito.verifyStatic(times(1)); + // PowerMockito.mockStatic(Types.class); + // PowerMockito.when(Types.toHostRecord(spiedMap)).thenReturn(hr); + // PowerMockito.verifyStatic(times(1)); // - // try { - // PowerMockito.mockStatic(Host.Record.class); - // when(host.getRecord(conn)).thenReturn(hr); - // verify(host, times(1)).getRecord(conn); - // } catch (final BadServerResponse e) { - // fail(e.getMessage()); - // } catch (final XenAPIException e) { - // fail(e.getMessage()); - // } catch (final XmlRpcException e) { - // fail(e.getMessage()); - // } + // try { + // PowerMockito.mockStatic(Host.Record.class); + // when(host.getRecord(conn)).thenReturn(hr); + // verify(host, times(1)).getRecord(conn); + // } 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(maintainCommand, citrixResourceBase); @@ -771,8 +781,9 @@ public class CitrixRequestWrapperTest { 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"); + 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()); @@ -876,9 +887,9 @@ public class CitrixRequestWrapperTest { 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"); + 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()); @@ -914,9 +925,9 @@ public class CitrixRequestWrapperTest { 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"); + 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()); @@ -994,6 +1005,270 @@ public class CitrixRequestWrapperTest { assertTrue(answer.getResult()); assertNull(answer.getDetails()); } + + @Test + public void testNetworkRulesSystemVmCommand() { + final Connection conn = Mockito.mock(Connection.class); + + final NetworkRulesSystemVmCommand netRules = new NetworkRulesSystemVmCommand("Test", VirtualMachine.Type.User); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + + final Answer answer = wrapper.execute(netRules, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testNetworkRulesSystemVmCommandNonUser() { + final Connection conn = Mockito.mock(Connection.class); + + final NetworkRulesSystemVmCommand netRules = new NetworkRulesSystemVmCommand("Test", VirtualMachine.Type.DomainRouter); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", netRules.getVmName())).thenReturn("true"); + + final Answer answer = wrapper.execute(netRules, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testNetworkRulesSystemVmCommandNonUserFalse() { + final Connection conn = Mockito.mock(Connection.class); + + final NetworkRulesSystemVmCommand netRules = new NetworkRulesSystemVmCommand("Test", VirtualMachine.Type.DomainRouter); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", netRules.getVmName())).thenReturn("false"); + + final Answer answer = wrapper.execute(netRules, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testOvsCreateTunnelCommandSuccess() { + final String bridge = "tunnel"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsCreateTunnelCommand createTunnel = new OvsCreateTunnelCommand("127.0.0.1", 1, 1l, 2l, 1l, "127.0.1.1", "net01", "cd84c713-f448-48c9-ba25-e6740d4a9003"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.findOrCreateTunnelNetwork(conn, createTunnel.getNetworkName())).thenReturn(network); + when(network.getBridge(conn)).thenReturn(bridge); + + when(citrixResourceBase.callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", createTunnel.getRemoteIp(), + "key", createTunnel.getKey().toString(), "from", + createTunnel.getFrom().toString(), "to", createTunnel.getTo().toString(), "cloudstack-network-id", + createTunnel.getNetworkUuid())).thenReturn("SUCCESS:0"); + + } 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(createTunnel, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + verify(citrixResourceBase, times(1)).configureTunnelNetwork(conn, createTunnel.getNetworkId(), createTunnel.getFrom(), createTunnel.getNetworkName()); + + assertTrue(answer.getResult()); + } + + @Test + public void testOvsCreateTunnelCommandFail() { + final String bridge = "tunnel"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsCreateTunnelCommand createTunnel = new OvsCreateTunnelCommand("127.0.0.1", 1, 1l, 2l, 1l, "127.0.1.1", "net01", "cd84c713-f448-48c9-ba25-e6740d4a9003"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.findOrCreateTunnelNetwork(conn, createTunnel.getNetworkName())).thenReturn(network); + when(network.getBridge(conn)).thenReturn(bridge); + + when(citrixResourceBase.callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", createTunnel.getRemoteIp(), + "key", createTunnel.getKey().toString(), "from", + createTunnel.getFrom().toString(), "to", createTunnel.getTo().toString(), "cloudstack-network-id", + createTunnel.getNetworkUuid())).thenReturn("FAIL:1"); + + } 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(createTunnel, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + verify(citrixResourceBase, times(1)).configureTunnelNetwork(conn, createTunnel.getNetworkId(), createTunnel.getFrom(), createTunnel.getNetworkName()); + + assertFalse(answer.getResult()); + } + + @Test + public void testOvsCreateTunnelCommandNoNet() { + final Connection conn = Mockito.mock(Connection.class); + + final OvsCreateTunnelCommand createTunnel = new OvsCreateTunnelCommand("127.0.0.1", 1, 1l, 2l, 1l, "127.0.1.1", "net01", "cd84c713-f448-48c9-ba25-e6740d4a9003"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.findOrCreateTunnelNetwork(conn, createTunnel.getNetworkName())).thenReturn(null); + + final Answer answer = wrapper.execute(createTunnel, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testOvsSetupBridgeCommand() { + final Connection conn = Mockito.mock(Connection.class); + + final OvsSetupBridgeCommand setupBridge = new OvsSetupBridgeCommand("Test", 1l, 1l); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + + + final Answer answer = wrapper.execute(setupBridge, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + verify(citrixResourceBase, times(1)).findOrCreateTunnelNetwork(conn, setupBridge.getBridgeName()); + verify(citrixResourceBase, times(1)).configureTunnelNetwork(conn, setupBridge.getNetworkId(), setupBridge.getHostId(), setupBridge.getBridgeName()); + + assertTrue(answer.getResult()); + } + + @Test + public void testOvsDestroyBridgeCommand() { + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsDestroyBridgeCommand destroyBridge = new OvsDestroyBridgeCommand(1l, "bridge", 1l); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.findOrCreateTunnelNetwork(conn, destroyBridge.getBridgeName())).thenReturn(network); + + final Answer answer = wrapper.execute(destroyBridge, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + try { + verify(citrixResourceBase, times(1)).cleanUpTmpDomVif(conn, network); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + verify(citrixResourceBase, times(1)).destroyTunnelNetwork(conn, network, destroyBridge.getHostId()); + + assertTrue(answer.getResult()); + } + + @Test + public void testOvsDestroyTunnelCommandSuccess() { + final String bridge = "tunnel"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsDestroyTunnelCommand destroyTunnel = new OvsDestroyTunnelCommand(1l, "net01", "port11"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.findOrCreateTunnelNetwork(conn, destroyTunnel.getBridgeName())).thenReturn(network); + when(network.getBridge(conn)).thenReturn(bridge); + + when(citrixResourceBase.callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", destroyTunnel.getInPortName())).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(destroyTunnel, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testOvsDestroyTunnelCommandFailed() { + final String bridge = "tunnel"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsDestroyTunnelCommand destroyTunnel = new OvsDestroyTunnelCommand(1l, "net01", "port11"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.findOrCreateTunnelNetwork(conn, destroyTunnel.getBridgeName())).thenReturn(network); + when(network.getBridge(conn)).thenReturn(bridge); + + when(citrixResourceBase.callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", destroyTunnel.getInPortName())).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(destroyTunnel, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 24bbfbc1e6608aff56b66a6678a8a876842945eb Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Mon, 30 Mar 2015 17:31:09 +0200 Subject: [PATCH 24/30] Refactoring other 8 command wrapper in order to cope with the new design - Advanced unit tests added for half of the commands - Basic unit tests added for the other half --- .../resource/CitrixResourceBase.java | 38 ++-- .../CitrixCheckNetworkCommandWrapper.java | 94 ++++++++ ...ixClusterVMMetaDataSyncCommandWrapper.java | 57 +++++ .../CitrixCreateVMSnapshotCommandWrapper.java | 188 ++++++++++++++++ .../CitrixDeleteVMSnapshotCommandWrapper.java | 90 ++++++++ .../wrapper/CitrixPlugNicCommandWrapper.java | 92 ++++++++ .../wrapper/CitrixRequestWrapper.java | 16 ++ ...itrixRevertToVMSnapshotCommandWrapper.java | 110 ++++++++++ .../CitrixUnPlugNicCommandWrapper.java | 72 +++++++ ...itrixUpdateHostPasswordCommandWrapper.java | 34 +++ .../wrapper/CitrixRequestWrapperTest.java | 202 ++++++++++++++++++ 11 files changed, 968 insertions(+), 25 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckNetworkCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixClusterVMMetaDataSyncCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateVMSnapshotCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteVMSnapshotCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPlugNicCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRevertToVMSnapshotCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUnPlugNicCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpdateHostPasswordCommandWrapper.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 c495b75e1a7..aa9268105ee 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 @@ -346,6 +346,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return _instance; } + public void addToPwdQueue(final String password) { + _password.add(password); + } + public boolean isOvs() { return _isOvs; } @@ -467,24 +471,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == UpdateHostPasswordCommand.class) { - return execute((UpdateHostPasswordCommand)cmd); - } else if (cmd instanceof ClusterVMMetaDataSyncCommand) { - return execute((ClusterVMMetaDataSyncCommand)cmd); - } else if (clazz == CheckNetworkCommand.class) { - return execute((CheckNetworkCommand)cmd); - } else if (clazz == PlugNicCommand.class) { - return execute((PlugNicCommand)cmd); - } else if (clazz == UnPlugNicCommand.class) { - return execute((UnPlugNicCommand) cmd); } else if (cmd instanceof StorageSubSystemCommand) { return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); - } else if (clazz == CreateVMSnapshotCommand.class) { - return execute((CreateVMSnapshotCommand) cmd); - } else if (clazz == DeleteVMSnapshotCommand.class) { - return execute((DeleteVMSnapshotCommand) cmd); - } else if (clazz == RevertToVMSnapshotCommand.class) { - return execute((RevertToVMSnapshotCommand) cmd); } else if (clazz == NetworkRulesVmSecondaryIpCommand.class) { return execute((NetworkRulesVmSecondaryIpCommand) cmd); } else if (clazz == ScaleVmCommand.class) { @@ -798,7 +786,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected String revertToSnapshot(final Connection conn, final VM vmSnapshot, final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) throws XenAPIException, + public String revertToSnapshot(final Connection conn, final VM vmSnapshot, final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) throws XenAPIException, XmlRpcException { final String results = @@ -3137,7 +3125,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return false; } - protected void waitForTask(final Connection c, final Task task, final long pollInterval, final long timeout) throws XenAPIException, XmlRpcException, TimeoutException { + public void waitForTask(final Connection c, final Task task, final long pollInterval, final long timeout) throws XenAPIException, XmlRpcException, TimeoutException { final long beginTime = System.currentTimeMillis(); if (s_logger.isTraceEnabled()) { s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") sent to " + c.getSessionReference() + " is pending completion with a " + timeout + @@ -3161,7 +3149,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected void checkForSuccess(final Connection c, final Task task) throws XenAPIException, XmlRpcException { + public void checkForSuccess(final Connection c, final Task task) throws XenAPIException, XmlRpcException { if (task.getStatus(c) == Types.TaskStatusType.SUCCESS) { if (s_logger.isTraceEnabled()) { s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") completed"); @@ -3748,7 +3736,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } - protected VIF getVifByMac(final Connection conn, final VM router, String mac) throws XmlRpcException, XenAPIException { + public VIF getVifByMac(final Connection conn, final VM router, String mac) throws XmlRpcException, XenAPIException { final Set routerVIFs = router.getVIFs(conn); mac = mac.trim(); for (final VIF vif : routerVIFs) { @@ -3760,7 +3748,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } - protected String getLowestAvailableVIFDeviceNum(final Connection conn, final VM vm) { + public String getLowestAvailableVIFDeviceNum(final Connection conn, final VM vm) { String vmName = ""; try { vmName = vm.getNameLabel(conn); @@ -4811,7 +4799,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected boolean isNetworkSetupByName(final String nameTag) throws XenAPIException, XmlRpcException { + public boolean isNetworkSetupByName(final String nameTag) throws XenAPIException, XmlRpcException { if (nameTag != null) { if (s_logger.isDebugEnabled()) { s_logger.debug("Looking for network setup by name " + nameTag); @@ -6194,7 +6182,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - private long getVMSnapshotChainSize(final Connection conn, final VolumeObjectTO volumeTo, final String vmName) throws BadServerResponse, XenAPIException, XmlRpcException { + public long getVMSnapshotChainSize(final Connection conn, final VolumeObjectTO volumeTo, final String vmName) throws BadServerResponse, XenAPIException, XmlRpcException { final Set allvolumeVDIs = VDI.getByNameLabel(conn, volumeTo.getName()); long size = 0; for (final VDI vdi : allvolumeVDIs) { @@ -6378,7 +6366,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - private VM createWorkingVM(final Connection conn, final String vmName, final String guestOSType, final String platformEmulator, final List listVolumeTo) throws BadServerResponse, + public VM createWorkingVM(final Connection conn, final String vmName, final String guestOSType, final String platformEmulator, final List listVolumeTo) throws BadServerResponse, Types.VmBadPowerState, Types.SrFull, Types.OperationNotAllowed, XenAPIException, XmlRpcException { //below is redundant but keeping for consistency and code readabilty @@ -6928,7 +6916,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new ClusterVMMetaDataSyncAnswer(cmd.getClusterId(), vmMetadatum); } - protected HashMap clusterVMMetaDataSync(final Connection conn) { + public HashMap clusterVMMetaDataSync(final Connection conn) { final HashMap vmMetaDatum = new HashMap(); try { final Map vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckNetworkCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckNetworkCommandWrapper.java new file mode 100644 index 00000000000..fb62fcebbc3 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckNetworkCommandWrapper.java @@ -0,0 +1,94 @@ +// +// 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.List; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckNetworkAnswer; +import com.cloud.agent.api.CheckNetworkCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.network.PhysicalNetworkSetupInfo; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixCheckNetworkCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixCheckNetworkCommandWrapper.class); + + @Override + public Answer execute(final CheckNetworkCommand command, final CitrixResourceBase citrixResourceBase) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Checking if network name setup is done on the resource"); + } + + final List infoList = command.getPhysicalNetworkInfoList(); + + try { + boolean errorout = false; + String msg = ""; + for (final PhysicalNetworkSetupInfo info : infoList) { + if (!citrixResourceBase.isNetworkSetupByName(info.getGuestNetworkName())) { + msg = + "For Physical Network id:" + info.getPhysicalNetworkId() + ", Guest Network is not configured on the backend by name " + + info.getGuestNetworkName(); + errorout = true; + break; + } + if (!citrixResourceBase.isNetworkSetupByName(info.getPrivateNetworkName())) { + msg = + "For Physical Network id:" + info.getPhysicalNetworkId() + ", Private Network is not configured on the backend by name " + + info.getPrivateNetworkName(); + errorout = true; + break; + } + if (!citrixResourceBase.isNetworkSetupByName(info.getPublicNetworkName())) { + msg = + "For Physical Network id:" + info.getPhysicalNetworkId() + ", Public Network is not configured on the backend by name " + + info.getPublicNetworkName(); + errorout = true; + break; + } + /*if(!isNetworkSetupByName(info.getStorageNetworkName())){ + msg = "For Physical Network id:"+ info.getPhysicalNetworkId() + ", Storage Network is not configured on the backend by name " + info.getStorageNetworkName(); + errorout = true; + break; + }*/ + } + if (errorout) { + s_logger.error(msg); + return new CheckNetworkAnswer(command, false, msg); + } else { + return new CheckNetworkAnswer(command, true, "Network Setup check by names is done"); + } + + } catch (final XenAPIException e) { + final String msg = "CheckNetworkCommand failed with XenAPIException:" + e.toString() + " host:" + citrixResourceBase.getHost().getUuid(); + s_logger.warn(msg, e); + return new CheckNetworkAnswer(command, false, msg); + } catch (final Exception e) { + final String msg = "CheckNetworkCommand failed with Exception:" + e.getMessage() + " host:" + citrixResourceBase.getHost().getUuid(); + s_logger.warn(msg, e); + return new CheckNetworkAnswer(command, false, msg); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixClusterVMMetaDataSyncCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixClusterVMMetaDataSyncCommandWrapper.java new file mode 100644 index 00000000000..fb7384be75e --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixClusterVMMetaDataSyncCommandWrapper.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 java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.ClusterVMMetaDataSyncAnswer; +import com.cloud.agent.api.ClusterVMMetaDataSyncCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Pool; + +public final class CitrixClusterVMMetaDataSyncCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixClusterVMMetaDataSyncCommandWrapper.class); + + @Override + public Answer execute(final ClusterVMMetaDataSyncCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + //check if this is master + try { + final Pool pool = Pool.getByUuid(conn, citrixResourceBase.getHost().getPool()); + final Pool.Record poolr = pool.getRecord(conn); + final Host.Record hostr = poolr.master.getRecord(conn); + if (!citrixResourceBase.getHost().getUuid().equals(hostr.uuid)) { + return new ClusterVMMetaDataSyncAnswer(command.getClusterId(), null); + } + } catch (final Throwable e) { + s_logger.warn("Check for master failed, failing the Cluster sync VMMetaData command"); + return new ClusterVMMetaDataSyncAnswer(command.getClusterId(), null); + } + final HashMap vmMetadatum = citrixResourceBase.clusterVMMetaDataSync(conn); + return new ClusterVMMetaDataSyncAnswer(command.getClusterId(), vmMetadatum); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateVMSnapshotCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateVMSnapshotCommandWrapper.java new file mode 100644 index 00000000000..7ccf9279b04 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateVMSnapshotCommandWrapper.java @@ -0,0 +1,188 @@ +// +// 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.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CreateVMSnapshotAnswer; +import com.cloud.agent.api.CreateVMSnapshotCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.vm.snapshot.VMSnapshot; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Pool; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Task; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.VmPowerState; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +public final class CitrixCreateVMSnapshotCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixCreateVMSnapshotCommandWrapper.class); + + @Override + public Answer execute(final CreateVMSnapshotCommand command, final CitrixResourceBase citrixResourceBase) { + final String vmName = command.getVmName(); + final String vmSnapshotName = command.getTarget().getSnapshotName(); + final List listVolumeTo = command.getVolumeTOs(); + + VmPowerState vmState = VmPowerState.HALTED; + + final String guestOSType = command.getGuestOSType(); + final String platformEmulator = command.getPlatformEmulator(); + + final boolean snapshotMemory = command.getTarget().getType() == VMSnapshot.Type.DiskAndMemory; + final long timeout = command.getWait(); + + final Connection conn = citrixResourceBase.getConnection(); + VM vm = null; + VM vmSnapshot = null; + boolean success = false; + + try { + // check if VM snapshot already exists + final Set vmSnapshots = VM.getByNameLabel(conn, command.getTarget().getSnapshotName()); + if (vmSnapshots == null || vmSnapshots.size() > 0) { + return new CreateVMSnapshotAnswer(command, command.getTarget(), command.getVolumeTOs()); + } + + // check if there is already a task for this VM snapshot + Task task = null; + Set tasks = Task.getByNameLabel(conn, "Async.VM.snapshot"); + if(tasks == null) { + tasks = new LinkedHashSet<>(); + } + final Set tasksByName = Task.getByNameLabel(conn, "Async.VM.checkpoint"); + if(tasksByName != null) { + tasks.addAll(tasksByName); + } + for (final Task taskItem : tasks) { + if (taskItem.getOtherConfig(conn).containsKey("CS_VM_SNAPSHOT_KEY")) { + final String vmSnapshotTaskName = taskItem.getOtherConfig(conn).get("CS_VM_SNAPSHOT_KEY"); + if (vmSnapshotTaskName != null && vmSnapshotTaskName.equals(command.getTarget().getSnapshotName())) { + task = taskItem; + } + } + } + + // create a new task if there is no existing task for this VM snapshot + if (task == null) { + try { + vm = citrixResourceBase.getVM(conn, vmName); + vmState = vm.getPowerState(conn); + } catch (final Exception e) { + if (!snapshotMemory) { + vm = citrixResourceBase.createWorkingVM(conn, vmName, guestOSType, platformEmulator, listVolumeTo); + } + } + + if (vm == null) { + return new CreateVMSnapshotAnswer(command, false, "Creating VM Snapshot Failed due to can not find vm: " + vmName); + } + + // call Xenserver API + if (!snapshotMemory) { + task = vm.snapshotAsync(conn, vmSnapshotName); + } else { + final Set vbds = vm.getVBDs(conn); + final Pool pool = Pool.getByUuid(conn, citrixResourceBase.getHost().getPool()); + for (final VBD vbd : vbds) { + final VBD.Record vbdr = vbd.getRecord(conn); + if (vbdr.userdevice.equals("0")) { + final VDI vdi = vbdr.VDI; + final SR sr = vdi.getSR(conn); + // store memory image on the same SR with ROOT volume + pool.setSuspendImageSR(conn, sr); + } + } + task = vm.checkpointAsync(conn, vmSnapshotName); + } + task.addToOtherConfig(conn, "CS_VM_SNAPSHOT_KEY", vmSnapshotName); + } + + citrixResourceBase.waitForTask(conn, task, 1000, timeout * 1000); + citrixResourceBase.checkForSuccess(conn, task); + final String result = task.getResult(conn); + + // extract VM snapshot ref from result + final String ref = result.substring("".length(), result.length() - "".length()); + vmSnapshot = Types.toVM(ref); + try { + Thread.sleep(5000); + } catch (final InterruptedException ex) { + + } + // calculate used capacity for this VM snapshot + for (final VolumeObjectTO volumeTo : command.getVolumeTOs()) { + final long size = citrixResourceBase.getVMSnapshotChainSize(conn, volumeTo, command.getVmName()); + volumeTo.setSize(size); + } + + success = true; + return new CreateVMSnapshotAnswer(command, command.getTarget(), command.getVolumeTOs()); + } catch (final Exception e) { + String msg = ""; + if (e instanceof Types.BadAsyncResult) { + final String licenseKeyWord = "LICENCE_RESTRICTION"; + final Types.BadAsyncResult errorResult = (Types.BadAsyncResult)e; + if (errorResult.shortDescription != null && errorResult.shortDescription.contains(licenseKeyWord)) { + msg = licenseKeyWord; + } + } else { + msg = e.toString(); + } + s_logger.warn("Creating VM Snapshot " + command.getTarget().getSnapshotName() + " failed due to: " + msg, e); + return new CreateVMSnapshotAnswer(command, false, msg); + } finally { + try { + if (!success) { + if (vmSnapshot != null) { + s_logger.debug("Delete exsisting VM Snapshot " + vmSnapshotName + " after making VolumeTO failed"); + final Set vbds = vmSnapshot.getVBDs(conn); + for (final VBD vbd : vbds) { + final VBD.Record vbdr = vbd.getRecord(conn); + if (vbdr.type == Types.VbdType.DISK) { + final VDI vdi = vbdr.VDI; + vdi.destroy(conn); + } + } + vmSnapshot.destroy(conn); + } + } + if (vmState == VmPowerState.HALTED) { + if (vm != null) { + vm.destroy(conn); + } + } + } catch (final Exception e2) { + s_logger.error("delete snapshot error due to " + e2.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteVMSnapshotCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteVMSnapshotCommandWrapper.java new file mode 100644 index 00000000000..10f409176ff --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteVMSnapshotCommandWrapper.java @@ -0,0 +1,90 @@ +// +// 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.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.DeleteVMSnapshotAnswer; +import com.cloud.agent.api.DeleteVMSnapshotCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.vm.snapshot.VMSnapshot; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +public final class CitrixDeleteVMSnapshotCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixDeleteVMSnapshotCommandWrapper.class); + + @Override + public Answer execute(final DeleteVMSnapshotCommand command, final CitrixResourceBase citrixResourceBase) { + final String snapshotName = command.getTarget().getSnapshotName(); + final Connection conn = citrixResourceBase.getConnection(); + + try { + final List vdiList = new ArrayList(); + final Set snapshots = VM.getByNameLabel(conn, snapshotName); + if (snapshots == null || snapshots.size() == 0) { + s_logger.warn("VM snapshot with name " + snapshotName + " does not exist, assume it is already deleted"); + return new DeleteVMSnapshotAnswer(command, command.getVolumeTOs()); + } + final VM snapshot = snapshots.iterator().next(); + final Set vbds = snapshot.getVBDs(conn); + for (final VBD vbd : vbds) { + if (vbd.getType(conn) == Types.VbdType.DISK) { + final VDI vdi = vbd.getVDI(conn); + vdiList.add(vdi); + } + } + if (command.getTarget().getType() == VMSnapshot.Type.DiskAndMemory) { + vdiList.add(snapshot.getSuspendVDI(conn)); + } + snapshot.destroy(conn); + for (final VDI vdi : vdiList) { + vdi.destroy(conn); + } + + try { + Thread.sleep(5000); + } catch (final InterruptedException ex) { + + } + // re-calculate used capacify for this VM snapshot + for (final VolumeObjectTO volumeTo : command.getVolumeTOs()) { + final long size = citrixResourceBase.getVMSnapshotChainSize(conn, volumeTo, command.getVmName()); + volumeTo.setSize(size); + } + + return new DeleteVMSnapshotAnswer(command, command.getVolumeTOs()); + } catch (final Exception e) { + s_logger.warn("Catch Exception: " + e.getClass().toString() + " due to " + e.toString(), e); + return new DeleteVMSnapshotAnswer(command, false, e.getMessage()); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPlugNicCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPlugNicCommandWrapper.java new file mode 100644 index 00000000000..a3edfbe13f1 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPlugNicCommandWrapper.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.Set; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.PlugNicAnswer; +import com.cloud.agent.api.PlugNicCommand; +import com.cloud.agent.api.to.NicTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.VIF; +import com.xensource.xenapi.VM; + +public final class CitrixPlugNicCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixPlugNicCommandWrapper.class); + + @Override + public Answer execute(final PlugNicCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final String vmName = command.getVmName(); + try { + final Set vms = VM.getByNameLabel(conn, vmName); + if (vms == null || vms.isEmpty()) { + return new PlugNicAnswer(command, false, "Can not find VM " + vmName); + } + final VM vm = vms.iterator().next(); + final NicTO nic = command.getNic(); + + String mac = nic.getMac(); + final Set routerVIFs = vm.getVIFs(conn); + mac = mac.trim(); + + int counter = 0; + for (final VIF vif : routerVIFs) { + final String lmac = vif.getMAC(conn); + if (lmac.trim().equals(mac)) { + counter++; + } + } + // We allow 2 routers with the same mac. It's needed for the redundant vpc routers. + // [FIXME] Find a way to identify the type of the router or if it's + // redundant. + if (counter > 2) { + final String msg = " Plug Nic failed due to a VIF with the same mac " + nic.getMac() + " exists in more than 2 routers."; + s_logger.error(msg); + return new PlugNicAnswer(command, false, msg); + } + + // Wilder Rodrigues - replaced this code with the code above. + // VIF vif = getVifByMac(conn, vm, nic.getMac()); + // if (vif != null) { + // final String msg = " Plug Nic failed due to a VIF with the same mac " + nic.getMac() + " exists"; + // s_logger.warn(msg); + // return new PlugNicAnswer(cmd, false, msg); + // } + + final String deviceId = citrixResourceBase.getLowestAvailableVIFDeviceNum(conn, vm); + nic.setDeviceId(Integer.parseInt(deviceId)); + final VIF vif = citrixResourceBase.createVif(conn, vmName, vm, null, nic); + // vif = createVif(conn, vmName, vm, null, nic); + vif.plug(conn); + return new PlugNicAnswer(command, true, "success"); + } catch (final Exception e) { + final String msg = " Plug Nic failed due to " + e.toString(); + s_logger.error(msg, e); + return new PlugNicAnswer(command, false, msg); + } + } +} \ 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 eff580a61b2..289fff9f596 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 @@ -25,12 +25,16 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.CheckHealthCommand; +import com.cloud.agent.api.CheckNetworkCommand; import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.ClusterVMMetaDataSyncCommand; import com.cloud.agent.api.Command; 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.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; @@ -52,14 +56,18 @@ import com.cloud.agent.api.OvsSetupBridgeCommand; import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand; import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.PlugNicCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.RevertToVMSnapshotCommand; import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.UpdateHostPasswordCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; @@ -135,6 +143,14 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(OvsSetupBridgeCommand.class, new CitrixOvsSetupBridgeCommandWrapper()); map.put(OvsDestroyBridgeCommand.class, new CitrixOvsDestroyBridgeCommandWrapper()); map.put(OvsDestroyTunnelCommand.class, new CitrixOvsDestroyTunnelCommandWrapper()); + map.put(UpdateHostPasswordCommand.class, new CitrixUpdateHostPasswordCommandWrapper()); + map.put(ClusterVMMetaDataSyncCommand.class, new CitrixClusterVMMetaDataSyncCommandWrapper()); + map.put(CheckNetworkCommand.class, new CitrixCheckNetworkCommandWrapper()); + map.put(PlugNicCommand.class, new CitrixPlugNicCommandWrapper()); + map.put(UnPlugNicCommand.class, new CitrixUnPlugNicCommandWrapper()); + map.put(CreateVMSnapshotCommand.class, new CitrixCreateVMSnapshotCommandWrapper()); + map.put(DeleteVMSnapshotCommand.class, new CitrixDeleteVMSnapshotCommandWrapper()); + map.put(RevertToVMSnapshotCommand.class, new CitrixRevertToVMSnapshotCommandWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRevertToVMSnapshotCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRevertToVMSnapshotCommandWrapper.java new file mode 100644 index 00000000000..a9291322ad8 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRevertToVMSnapshotCommandWrapper.java @@ -0,0 +1,110 @@ +// +// 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.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.RevertToVMSnapshotAnswer; +import com.cloud.agent.api.RevertToVMSnapshotCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.vm.VirtualMachine.PowerState; +import com.cloud.vm.snapshot.VMSnapshot; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +public final class CitrixRevertToVMSnapshotCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixRevertToVMSnapshotCommandWrapper.class); + + @Override + public Answer execute(final RevertToVMSnapshotCommand command, final CitrixResourceBase citrixResourceBase) { + final String vmName = command.getVmName(); + final List listVolumeTo = command.getVolumeTOs(); + final VMSnapshot.Type vmSnapshotType = command.getTarget().getType(); + final Boolean snapshotMemory = vmSnapshotType == VMSnapshot.Type.DiskAndMemory; + final Connection conn = citrixResourceBase.getConnection(); + PowerState vmState = null; + VM vm = null; + try { + + final Set vmSnapshots = VM.getByNameLabel(conn, command.getTarget().getSnapshotName()); + if (vmSnapshots == null || vmSnapshots.size() == 0) { + return new RevertToVMSnapshotAnswer(command, false, "Cannot find vmSnapshot with name: " + command.getTarget().getSnapshotName()); + } + + final VM vmSnapshot = vmSnapshots.iterator().next(); + + // find target VM or creating a work VM + try { + vm = citrixResourceBase.getVM(conn, vmName); + } catch (final Exception e) { + vm = citrixResourceBase.createWorkingVM(conn, vmName, command.getGuestOSType(), command.getPlatformEmulator(), listVolumeTo); + } + + if (vm == null) { + return new RevertToVMSnapshotAnswer(command, false, "Revert to VM Snapshot Failed due to can not find vm: " + vmName); + } + + // call plugin to execute revert + citrixResourceBase.revertToSnapshot(conn, vmSnapshot, vmName, vm.getUuid(conn), snapshotMemory, citrixResourceBase.getHost().getUuid()); + vm = citrixResourceBase.getVM(conn, vmName); + final Set vbds = vm.getVBDs(conn); + final Map vdiMap = new HashMap(); + // get vdi:vbdr to a map + for (final VBD vbd : vbds) { + final VBD.Record vbdr = vbd.getRecord(conn); + if (vbdr.type == Types.VbdType.DISK) { + final VDI vdi = vbdr.VDI; + vdiMap.put(vbdr.userdevice, vdi); + } + } + + if (!snapshotMemory) { + vm.destroy(conn); + vmState = PowerState.PowerOff; + } else { + vmState = PowerState.PowerOn; + } + + // after revert, VM's volumes path have been changed, need to report to manager + for (final VolumeObjectTO volumeTo : listVolumeTo) { + final Long deviceId = volumeTo.getDeviceId(); + final VDI vdi = vdiMap.get(deviceId.toString()); + volumeTo.setPath(vdi.getUuid(conn)); + } + + return new RevertToVMSnapshotAnswer(command, listVolumeTo, vmState); + } catch (final Exception e) { + s_logger.error("revert vm " + vmName + " to snapshot " + command.getTarget().getSnapshotName() + " failed due to " + e.getMessage()); + return new RevertToVMSnapshotAnswer(command, false, e.getMessage()); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUnPlugNicCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUnPlugNicCommandWrapper.java new file mode 100644 index 00000000000..625083504de --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUnPlugNicCommandWrapper.java @@ -0,0 +1,72 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.UnPlugNicAnswer; +import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.to.NicTO; +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.VIF; +import com.xensource.xenapi.VM; + +public final class CitrixUnPlugNicCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixUnPlugNicCommandWrapper.class); + + @Override + public Answer execute(final UnPlugNicCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final String vmName = command.getVmName(); + try { + final Set vms = VM.getByNameLabel(conn, vmName); + if (vms == null || vms.isEmpty()) { + return new UnPlugNicAnswer(command, false, "Can not find VM " + vmName); + } + final VM vm = vms.iterator().next(); + final NicTO nic = command.getNic(); + final String mac = nic.getMac(); + final VIF vif = citrixResourceBase.getVifByMac(conn, vm, mac); + if (vif != null) { + vif.unplug(conn); + final Network network = vif.getNetwork(conn); + vif.destroy(conn); + try { + if (network.getNameLabel(conn).startsWith("VLAN")) { + citrixResourceBase.disableVlanNetwork(conn, network); + } + } catch (final Exception e) { + } + } + return new UnPlugNicAnswer(command, true, "success"); + } catch (final Exception e) { + final String msg = " UnPlug Nic failed due to " + e.toString(); + s_logger.warn(msg, e); + return new UnPlugNicAnswer(command, false, msg); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpdateHostPasswordCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpdateHostPasswordCommandWrapper.java new file mode 100644 index 00000000000..f2f1fb5fce9 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpdateHostPasswordCommandWrapper.java @@ -0,0 +1,34 @@ +// +// 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.UpdateHostPasswordCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; + +public final class CitrixUpdateHostPasswordCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final UpdateHostPasswordCommand command, final CitrixResourceBase citrixResourceBase) { + citrixResourceBase.addToPwdQueue(command.getNewPassword()); + return new Answer(command, true, null); + } +} \ No newline at end of file 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 8b8c9ce6f73..72d5c1a3017 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 @@ -13,9 +13,11 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Hashtable; +import java.util.List; import java.util.Map; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClient; import org.junit.Test; @@ -30,12 +32,16 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.CheckHealthCommand; +import com.cloud.agent.api.CheckNetworkCommand; import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.ClusterVMMetaDataSyncCommand; import com.cloud.agent.api.Command; 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.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; @@ -57,16 +63,21 @@ import com.cloud.agent.api.OvsSetupBridgeCommand; import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand; import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.PlugNicCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.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.SecurityGroupRulesCmd; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.UpdateHostPasswordCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; +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; @@ -76,12 +87,14 @@ 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.NicTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; 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.PhysicalNetworkSetupInfo; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.VMTemplateStorageResourceAssoc; @@ -92,6 +105,7 @@ import com.xensource.xenapi.Host; import com.xensource.xenapi.Marshalling; import com.xensource.xenapi.Network; import com.xensource.xenapi.PIF; +import com.xensource.xenapi.Pool; import com.xensource.xenapi.Types.BadServerResponse; import com.xensource.xenapi.Types.XenAPIException; @@ -1269,6 +1283,194 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testUpdateHostPasswordCommand() { + final UpdateHostPasswordCommand updatePwd = new UpdateHostPasswordCommand("test", "123"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(updatePwd, citrixResourceBase); + + assertTrue(answer.getResult()); + } + + @Test + public void testClusterVMMetaDataSyncCommand() { + final String uuid = "6172d8b7-ba10-4a70-93f9-ecaf41f51d53"; + + final Connection conn = Mockito.mock(Connection.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final Pool pool = PowerMockito.mock(Pool.class); + final Pool.Record poolr = Mockito.mock(Pool.Record.class); + final Host.Record hostr = Mockito.mock(Host.Record.class); + final Host master = Mockito.mock(Host.class); + + final ClusterVMMetaDataSyncCommand vmDataSync = new ClusterVMMetaDataSyncCommand(10, 1l); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.getHost()).thenReturn(xsHost); + when(citrixResourceBase.getHost().getUuid()).thenReturn(uuid); + + PowerMockito.mockStatic(Pool.Record.class); + + when(pool.getRecord(conn)).thenReturn(poolr); + poolr.master = master; + when(poolr.master.getRecord(conn)).thenReturn(hostr); + hostr.uuid = uuid; + + } 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(vmDataSync, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testCheckNetworkCommandSuccess() { + final List setupInfos = new ArrayList(); + + final CheckNetworkCommand checkNet = new CheckNetworkCommand(setupInfos); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(checkNet, citrixResourceBase); + + assertTrue(answer.getResult()); + } + + @Test + public void testCheckNetworkCommandFailure() { + final PhysicalNetworkSetupInfo info = new PhysicalNetworkSetupInfo(); + + final List setupInfos = new ArrayList(); + setupInfos.add(info); + + final CheckNetworkCommand checkNet = new CheckNetworkCommand(setupInfos); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(checkNet, citrixResourceBase); + + assertFalse(answer.getResult()); + } + + @Test + public void testPlugNicCommand() { + final NicTO nicTO = Mockito.mock(NicTO.class); + final Connection conn = Mockito.mock(Connection.class); + + final PlugNicCommand plugNic = new PlugNicCommand(nicTO, "Test", VirtualMachine.Type.User); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + + final Answer answer = wrapper.execute(plugNic, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testUnPlugNicCommand() { + final NicTO nicTO = Mockito.mock(NicTO.class); + final Connection conn = Mockito.mock(Connection.class); + + final UnPlugNicCommand unplugNic = new UnPlugNicCommand(nicTO, "Test"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + + final Answer answer = wrapper.execute(unplugNic, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testCreateVMSnapshotCommand() { + final Connection conn = Mockito.mock(Connection.class); + + final VMSnapshotTO snapshotTO = Mockito.mock(VMSnapshotTO.class); + final List volumeTOs = new ArrayList(); + + final CreateVMSnapshotCommand vmSnapshot = new CreateVMSnapshotCommand("Test", snapshotTO, volumeTOs, "Debian"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + + final Answer answer = wrapper.execute(vmSnapshot, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testDeleteVMSnapshotCommand() { + final Connection conn = Mockito.mock(Connection.class); + + final VMSnapshotTO snapshotTO = Mockito.mock(VMSnapshotTO.class); + final List volumeTOs = new ArrayList(); + + final DeleteVMSnapshotCommand vmSnapshot = new DeleteVMSnapshotCommand("Test", snapshotTO, volumeTOs, "Debian"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + + final Answer answer = wrapper.execute(vmSnapshot, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testRevertToVMSnapshotCommand() { + final Connection conn = Mockito.mock(Connection.class); + + final VMSnapshotTO snapshotTO = Mockito.mock(VMSnapshotTO.class); + final List volumeTOs = new ArrayList(); + + final RevertToVMSnapshotCommand vmSnapshot = new RevertToVMSnapshotCommand("Test", snapshotTO, volumeTOs, "Debian"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + + final Answer answer = wrapper.execute(vmSnapshot, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } } class NotAValidCommand extends Command { From 02571728c61e64399bea77af3d6ac2d6d87d0404 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Mon, 30 Mar 2015 19:01:46 +0200 Subject: [PATCH 25/30] 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 { From 4600eef87c435598e5d3f1fbe2910d58803c0029 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 31 Mar 2015 00:27:06 +0200 Subject: [PATCH 26/30] Removing all private/protected/public execute() methods from CitrixResourceBase class Started the refactor of the XenServer56Resource class - Unit test added Changing the CitrixRequestWrapper in order to cope with multiple resources classes and commands Still have to remove few methods form CitrixResourceBase --- .../resource/CitrixResourceBase.java | 9436 +++++++---------- .../resource/XenServer56FP1Resource.java | 2 +- .../resource/XenServer56Resource.java | 53 +- .../wrapper/CitrixRequestWrapper.java | 158 +- .../XenServer56CheckOnHostCommandWrapper.java | 48 + .../resource/CitrixResourceBaseTest.java | 188 - .../wrapper/XenServer56WrapperTest.java | 38 + 7 files changed, 3958 insertions(+), 5965 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56CheckOnHostCommandWrapper.java delete mode 100644 plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java create mode 100644 plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56WrapperTest.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 6ef756cb81e..ee9fd2b6f8a 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 @@ -19,7 +19,6 @@ package com.cloud.hypervisor.xenserver.resource; import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URI; @@ -32,7 +31,6 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -61,87 +59,19 @@ import org.xml.sax.SAXException; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.AttachIsoCommand; -import com.cloud.agent.api.AttachVolumeAnswer; -import com.cloud.agent.api.AttachVolumeCommand; -import com.cloud.agent.api.CheckHealthAnswer; -import com.cloud.agent.api.CheckHealthCommand; -import com.cloud.agent.api.CheckNetworkAnswer; -import com.cloud.agent.api.CheckNetworkCommand; -import com.cloud.agent.api.CheckOnHostAnswer; -import com.cloud.agent.api.CheckOnHostCommand; -import com.cloud.agent.api.CheckVirtualMachineAnswer; -import com.cloud.agent.api.CheckVirtualMachineCommand; -import com.cloud.agent.api.CleanupNetworkRulesCmd; -import com.cloud.agent.api.ClusterVMMetaDataSyncAnswer; -import com.cloud.agent.api.ClusterVMMetaDataSyncCommand; import com.cloud.agent.api.Command; -import com.cloud.agent.api.CreateStoragePoolCommand; -import com.cloud.agent.api.CreateVMSnapshotAnswer; -import com.cloud.agent.api.CreateVMSnapshotCommand; -import com.cloud.agent.api.DeleteStoragePoolCommand; -import com.cloud.agent.api.DeleteVMSnapshotAnswer; -import com.cloud.agent.api.DeleteVMSnapshotCommand; -import com.cloud.agent.api.GetHostStatsAnswer; import com.cloud.agent.api.GetHostStatsCommand; -import com.cloud.agent.api.GetStorageStatsAnswer; -import com.cloud.agent.api.GetStorageStatsCommand; -import com.cloud.agent.api.GetVmDiskStatsAnswer; -import com.cloud.agent.api.GetVmDiskStatsCommand; -import com.cloud.agent.api.GetVmStatsAnswer; import com.cloud.agent.api.GetVmStatsCommand; -import com.cloud.agent.api.GetVncPortAnswer; -import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.HostStatsEntry; import com.cloud.agent.api.HostVmStateReportEntry; -import com.cloud.agent.api.MaintainAnswer; -import com.cloud.agent.api.MaintainCommand; -import com.cloud.agent.api.MigrateAnswer; -import com.cloud.agent.api.MigrateCommand; -import com.cloud.agent.api.ModifySshKeysCommand; -import com.cloud.agent.api.ModifyStoragePoolAnswer; -import com.cloud.agent.api.ModifyStoragePoolCommand; -import com.cloud.agent.api.NetworkRulesSystemVmCommand; -import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; -import com.cloud.agent.api.OvsCreateGreTunnelAnswer; -import com.cloud.agent.api.OvsCreateGreTunnelCommand; -import com.cloud.agent.api.OvsCreateTunnelAnswer; -import com.cloud.agent.api.OvsCreateTunnelCommand; -import com.cloud.agent.api.OvsDeleteFlowCommand; -import com.cloud.agent.api.OvsDestroyBridgeCommand; -import com.cloud.agent.api.OvsDestroyTunnelCommand; -import com.cloud.agent.api.OvsFetchInterfaceAnswer; -import com.cloud.agent.api.OvsFetchInterfaceCommand; import com.cloud.agent.api.OvsSetTagAndFlowAnswer; 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.PerformanceMonitorAnswer; -import com.cloud.agent.api.PerformanceMonitorCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; import com.cloud.agent.api.PingRoutingWithOvsCommand; -import com.cloud.agent.api.PingTestCommand; -import com.cloud.agent.api.PlugNicAnswer; -import com.cloud.agent.api.PlugNicCommand; -import com.cloud.agent.api.PrepareForMigrationAnswer; -import com.cloud.agent.api.PrepareForMigrationCommand; -import com.cloud.agent.api.PvlanSetupCommand; -import com.cloud.agent.api.ReadyAnswer; -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.RevertToVMSnapshotAnswer; -import com.cloud.agent.api.RevertToVMSnapshotCommand; -import com.cloud.agent.api.ScaleVmAnswer; -import com.cloud.agent.api.ScaleVmCommand; -import com.cloud.agent.api.SecurityGroupRuleAnswer; -import com.cloud.agent.api.SecurityGroupRulesCmd; -import com.cloud.agent.api.SetupAnswer; -import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; @@ -151,29 +81,13 @@ import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.StoragePoolInfo; -import com.cloud.agent.api.UnPlugNicAnswer; -import com.cloud.agent.api.UnPlugNicCommand; -import com.cloud.agent.api.UpdateHostPasswordCommand; -import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.VmStatsEntry; -import com.cloud.agent.api.check.CheckSshAnswer; -import com.cloud.agent.api.check.CheckSshCommand; -import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; -import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer; -import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.routing.IpAssocCommand; import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.SetNetworkACLCommand; import com.cloud.agent.api.routing.SetSourceNatCommand; -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.PrimaryStorageDownloadAnswer; -import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; -import com.cloud.agent.api.storage.ResizeVolumeAnswer; -import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DiskTO; @@ -181,9 +95,7 @@ import com.cloud.agent.api.to.GPUDeviceTO; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.NfsTO; 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.api.to.VolumeTO; import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer; import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; import com.cloud.exception.InternalErrorException; @@ -194,7 +106,6 @@ import com.cloud.network.Networks; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.TrafficType; -import com.cloud.network.PhysicalNetworkSetupInfo; import com.cloud.resource.ServerResource; import com.cloud.resource.hypervisor.HypervisorResource; import com.cloud.storage.Storage; @@ -203,7 +114,6 @@ import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; import com.cloud.storage.resource.StorageSubsystemCommandHandler; import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase; -import com.cloud.storage.template.TemplateProp; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.ExecutionResult; import com.cloud.utils.NumbersUtil; @@ -215,10 +125,8 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.utils.ssh.SSHCmdHelper; import com.cloud.utils.ssh.SshHelper; -import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.PowerState; -import com.cloud.vm.snapshot.VMSnapshot; import com.trilead.ssh2.SCPClient; import com.xensource.xenapi.Bond; import com.xensource.xenapi.Connection; @@ -260,57 +168,8 @@ 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(); - protected final int _retry = 100; - protected final int _sleep = 10000; - protected long _dcId; - protected String _pod; - protected String _cluster; - protected String _privateNetworkName; - protected String _linkLocalPrivateNetworkName; - protected String _publicNetworkName; - protected String _storageNetworkName1; - protected String _storageNetworkName2; - protected String _guestNetworkName; - protected int _wait; - protected int _migratewait; - protected String _instance; //instance name (default is usually "VM") - protected boolean _securityGroupEnabled; - protected IAgentControl _agentControl; - - final int _maxWeight = 256; - protected int _heartbeatTimeout = 120; - protected int _heartbeatInterval = 60; - protected final XsHost _host = new XsHost(); - - // Guest and Host Performance Statistics - protected String _consolidationFunction = "AVERAGE"; - protected int _pollingIntervalInSeconds = 60; - - //Hypervisor specific params with generic value, may need to be overridden for specific versions - long _xsMemoryUsed = 128 * 1024 * 1024L; // xenserver hypervisor used 128 M - double _xsVirtualizationFactor = 63.0 / 64.0; // 1 - virtualization overhead - - //static min values for guests on xenserver - private static final long mem_128m = 134217728L; - - protected boolean _canBridgeFirewall = false; - protected boolean _isOvs = false; - protected List _tmpDom0Vif = new ArrayList(); - protected StorageSubsystemCommandHandler storageHandler; - protected int _maxNics = 7; - - protected VirtualRoutingResource _vrResource; - public enum SRType { - NFS, LVM, ISCSI, ISO, LVMOISCSI, LVMOHBA, EXT, FILE; + EXT, FILE, ISCSI, ISO, LVM, LVMOHBA, LVMOISCSI, NFS; String _str; @@ -318,17 +177,24 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe _str = super.toString().toLowerCase(); } + public boolean equals(final String type) { + return _str.equalsIgnoreCase(type); + } + @Override public String toString() { return _str; } - - public boolean equals(final String type) { - return _str.equalsIgnoreCase(type); - } } + protected static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance(); + //static min values for guests on xenserver + private static final long mem_128m = 134217728L; + + static final Random Rand = new Random(System.currentTimeMillis()); + private static final Logger s_logger = Logger.getLogger(CitrixResourceBase.class); protected static final HashMap s_powerStatesTable; + static { s_powerStatesTable = new HashMap(); s_powerStatesTable.put(VmPowerState.HALTED, PowerState.PowerOff); @@ -338,44 +204,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_powerStatesTable.put(VmPowerState.UNRECOGNIZED, PowerState.PowerUnknown); } - public XsHost getHost() { - return _host; - } - - public String getVMInstanceName() { - return _instance; - } - - public void addToPwdQueue(final String password) { - _password.add(password); - } - - public VirtualRoutingResource getVirtualRoutingResource() { - return _vrResource; - } - - public boolean isOvs() { - return _isOvs; - } - - public void setIsOvs(final boolean isOvs) { - _isOvs = isOvs; - } - - public boolean isSecurityGroupEnabled() { - return _securityGroupEnabled; - } - - public void setCanBridgeFirewall(final boolean canBridgeFirewall) { - _canBridgeFirewall = canBridgeFirewall; - } - - public boolean canBridgeFirewall() { - return _canBridgeFirewall; - } - - public boolean canBridgeFirewall(final Connection conn) { - return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.getUuid(), "instance", _instance)); + private static PowerState convertToPowerState(final VmPowerState ps) { + final PowerState powerState = s_powerStatesTable.get(ps); + return powerState == null ? PowerState.PowerUnknown : powerState; } private static boolean isAlienVm(final VM vm, final Connection conn) throws XenAPIException, XmlRpcException { @@ -388,184 +219,89 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return true; } - public boolean cleanupHaltedVms(final Connection conn) throws XenAPIException, XmlRpcException { - final Host host = Host.getByUuid(conn, _host.getUuid()); - final Map vms = VM.getAllRecords(conn); - boolean success = true; - if(vms != null && !vms.isEmpty()) { - for (final Map.Entry entry : vms.entrySet()) { - final VM vm = entry.getKey(); - final VM.Record vmRec = entry.getValue(); - if (vmRec.isATemplate || vmRec.isControlDomain) { - continue; - } + protected IAgentControl _agentControl; + protected boolean _canBridgeFirewall = false; + protected String _cluster; + // Guest and Host Performance Statistics + protected String _consolidationFunction = "AVERAGE"; + protected long _dcId; + protected String _guestNetworkName; + protected int _heartbeatInterval = 60; + protected int _heartbeatTimeout = 120; + protected final XsHost _host = new XsHost(); + protected String _instance; //instance name (default is usually "VM") + protected boolean _isOvs = false; + protected String _linkLocalPrivateNetworkName; + protected int _maxNics = 7; - if (VmPowerState.HALTED.equals(vmRec.powerState) && vmRec.affinity.equals(host) && !isAlienVm(vm, conn)) { - try { - vm.destroy(conn); - } catch (final Exception e) { - s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to ", e); - success = false; - } - } - } - } - return success; + final int _maxWeight = 256; + protected int _migratewait; + protected String _name; + protected Queue _password = new LinkedList(); + + protected String _pod; + protected int _pollingIntervalInSeconds = 60; + + protected String _privateNetworkName; + protected String _publicNetworkName; + + protected final int _retry = 100; + + protected boolean _securityGroupEnabled; + protected final int _sleep = 10000; + protected String _storageNetworkName1; + protected String _storageNetworkName2; + protected List _tmpDom0Vif = new ArrayList(); + + protected String _username; + + protected VirtualRoutingResource _vrResource; + + protected int _wait; + //Hypervisor specific params with generic value, may need to be overridden for specific versions + long _xsMemoryUsed = 128 * 1024 * 1024L; // xenserver hypervisor used 128 M + + double _xsVirtualizationFactor = 63.0 / 64.0; // 1 - virtualization overhead + + protected StorageSubsystemCommandHandler storageHandler; + + public CitrixResourceBase() { } - public boolean isRefNull(final XenAPIObject object) { - return object == null || object.toWireString().equals("OpaqueRef:NULL") || object.toWireString().equals(""); + public void addToPwdQueue(final String password) { + _password.add(password); } - @Override - public void disconnected() { + protected StorageSubsystemCommandHandler buildStorageHandler() { + final XenServerStorageProcessor processor = new XenServerStorageProcessor(this); + return new StorageSubsystemCommandHandlerBase(processor); } - protected boolean pingdomr(final Connection conn, final String host, final String port) { - String status; - status = callHostPlugin(conn, "vmops", "pingdomr", "host", host, "port", port); - - if (status == null || status.isEmpty()) { - return false; - } - - return true; - - } - - public boolean pingXAPI() { - final Connection conn = getConnection(); + public String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) { + final Map args = new HashMap(); + String msg; try { + for (int i = 0; i < params.length; i += 2) { + args.put(params[i], params[i + 1]); + } + + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); + } final Host host = Host.getByUuid(conn, _host.getUuid()); - if( !host.getEnabled(conn) ) { - s_logger.debug("Host " + _host.getIp() + " is not enabled!"); - return false; + final String result = host.callPlugin(conn, plugin, cmd, args); + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin Result: " + result); } - } catch (final Exception e) { - s_logger.debug("cannot get host enabled status, host " + _host.getIp() + " due to " + e.toString(), e); - return false; + return result.replace("\n", ""); + } catch (final XenAPIException e) { + msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(); + s_logger.warn(msg); + } catch (final XmlRpcException e) { + msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(); + s_logger.debug(msg); } - try { - callHostPlugin(conn, "echo", "main"); - } catch (final Exception e) { - s_logger.debug("cannot ping host " + _host.getIp() + " due to " + e.toString(), e); - return false; - } - return true; - } - - - protected String logX(final XenAPIObject obj, final String msg) { - return new StringBuilder("Host ").append(_host.getIp()).append(" ").append(obj.toWireString()).append(": ").append(msg).toString(); - } - - @Override - public Answer executeRequest(final Command cmd) { - - // We need this one because the StorageSubSystemCommand is from another hierarchy. - if (cmd instanceof StorageSubSystemCommand) { - return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); - } - - final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); - try { - return wrapper.execute(cmd, this); - } catch (final Exception e) { - return Answer.createUnsupportedCommandAnswer(cmd); - } - } - - @Override - public ExecutionResult executeInVR(final String routerIP, final String script, final String args, final int timeout) { - Pair result; - String cmdline = "/opt/cloud/bin/router_proxy.sh " + script + " " + routerIP + " " + args; - // semicolon need to be escape for bash - cmdline = cmdline.replaceAll(";", "\\\\;"); - try { - s_logger.debug("Executing command in VR: " + cmdline); - result = SshHelper.sshExecute(_host.getIp(), 22, _username, null, _password.peek(), cmdline, - 60000, 60000, timeout * 1000); - } catch (final Exception e) { - return new ExecutionResult(false, e.getMessage()); - } - return new ExecutionResult(result.first(), result.second()); - } - - @Override - public ExecutionResult executeInVR(final String routerIP, final String script, final String args) { - // Timeout is 120 seconds by default - return executeInVR(routerIP, script, args, 120); - } - - @Override - public ExecutionResult createFileInVR(final String routerIp, final String path, final String filename, final String content) { - final Connection conn = getConnection(); - final String hostPath = "/tmp/"; - - s_logger.debug("Copying VR with ip " + routerIp +" config file into host "+ _host.getIp() ); - try { - SshHelper.scpTo(_host.getIp(), 22, _username, null, _password.peek(), hostPath, content.getBytes(Charset.defaultCharset()), filename, null); - } catch (final Exception e) { - s_logger.warn("scp VR config file into host " + _host.getIp() + " failed with exception " + e.getMessage().toString()); - } - - final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path); - s_logger.debug ("VR Config file " + filename + " got created in VR, ip " + routerIp + " with content \n" + content); - - return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); - } - - @Override - public ExecutionResult prepareCommand(final NetworkElementCommand cmd) { - //Update IP used to access router - cmd.setRouterAccessIp(cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP)); - assert cmd.getRouterAccessIp() != null; - - if (cmd instanceof IpAssocVpcCommand) { - return prepareNetworkElementCommand((IpAssocVpcCommand)cmd); - } else if (cmd instanceof IpAssocCommand) { - return prepareNetworkElementCommand((IpAssocCommand)cmd); - } else if (cmd instanceof SetupGuestNetworkCommand) { - return prepareNetworkElementCommand((SetupGuestNetworkCommand)cmd); - } else if (cmd instanceof SetSourceNatCommand) { - return prepareNetworkElementCommand((SetSourceNatCommand)cmd); - } else if (cmd instanceof SetNetworkACLCommand) { - return prepareNetworkElementCommand((SetNetworkACLCommand)cmd); - } - return new ExecutionResult(true, null); - } - - @Override - public ExecutionResult cleanupCommand(final NetworkElementCommand cmd) { - if (cmd instanceof IpAssocCommand && !(cmd instanceof IpAssocVpcCommand)) { - return cleanupNetworkElementCommand((IpAssocCommand)cmd); - } - return new ExecutionResult(true, null); - } - - private Answer execute(final PerformanceMonitorCommand cmd) { - final Connection conn = getConnection(); - final String perfMon = getPerfMon(conn, cmd.getParams(), cmd.getWait()); - if (perfMon == null) { - return new PerformanceMonitorAnswer(cmd, false, perfMon); - } else { - return new PerformanceMonitorAnswer(cmd, true, perfMon); - } - } - - public String getPerfMon(final Connection conn, final Map params, - final int wait) { - String result = null; - try { - result = callHostPluginAsync(conn, "vmopspremium", "asmonitor", 60, - params); - if (result != null) { - return result; - } - } catch (final Exception e) { - s_logger.error("Can not get performance monitor for AS due to ", e); - } - return null; + throw new CloudRuntimeException(msg); } protected String callHostPluginAsync(final Connection conn, final String plugin, @@ -614,271 +350,466 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } - 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); - final Long newDynamicMemoryMin = vmSpec.getMinRam(); - final Long newDynamicMemoryMax = vmSpec.getMaxRam(); - if (staticMemoryMin > newDynamicMemoryMin || newDynamicMemoryMax > staticMemoryMax) { - throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: " + "0 <= memory-static-min(" + staticMemoryMin + - ") <= memory-dynamic-min(" + newDynamicMemoryMin + ") <= memory-dynamic-max(" + newDynamicMemoryMax + ") <= memory-static-max(" + staticMemoryMax + ")"); - } - - vm.setMemoryDynamicRange(conn, newDynamicMemoryMin, newDynamicMemoryMax); - vm.setVCPUsNumberLive(conn, (long)vmSpec.getCpus()); - - final Integer speed = vmSpec.getMinSpeed(); - if (speed != null) { - - int cpuWeight = _maxWeight; //cpu_weight - - // weight based allocation - - cpuWeight = (int)(speed * 0.99 / _host.getSpeed() * _maxWeight); - if (cpuWeight > _maxWeight) { - cpuWeight = _maxWeight; - } - - if (vmSpec.getLimitCpuUse()) { - long utilization = 0; // max CPU cap, default is unlimited - utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100); - //vm.addToVCPUsParamsLive(conn, "cap", Long.toString(utilization)); currently xenserver doesnot support Xapi to add VCPUs params live. - callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", Long.toString(utilization), "vmname", vmSpec.getName()); - } - //vm.addToVCPUsParamsLive(conn, "weight", Integer.toString(cpuWeight)); - callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", Integer.toString(cpuWeight), "vmname", vmSpec.getName()); - } - } - - public ScaleVmAnswer execute(final ScaleVmCommand cmd) { - final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - final String vmName = vmSpec.getName(); + protected String callHostPluginAsync(final Connection conn, final String plugin, final String cmd, final int wait, final String... params) { + final int timeout = wait * 1000; + final Map args = new HashMap(); + Task task = null; try { - final Connection conn = getConnection(); - final Set vms = VM.getByNameLabel(conn, vmName); + for (int i = 0; i < params.length; i += 2) { + args.put(params[i], params[i + 1]); + } + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); + } final Host host = Host.getByUuid(conn, _host.getUuid()); - - // If DMC is not enable then don't execute this command. - if (!isDmcEnabled(conn, host)) { - throw new CloudRuntimeException("Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.getUuid() + - " ,check your license and hypervisor version."); + task = host.callPluginAsync(conn, plugin, cmd, args); + // poll every 1 seconds + waitForTask(conn, task, 1000, timeout); + checkForSuccess(conn, task); + final String result = task.getResult(conn); + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin Result: " + result); } - - // 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 && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.getUuid())) { - iter.remove(); - } - } - - if (vms.size() == 0) { - s_logger.info("No running VM " + vmName + " exists on XenServer" + _host.getUuid()); - return new ScaleVmAnswer(cmd, false, "VM does not exist"); - } - - for (final VM vm : vms) { - vm.getRecord(conn); + return result.replace("", "").replace("", "").replace("\n", ""); + } catch (final Types.HandleInvalid e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + + e.handle); + } catch (final XenAPIException e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); + } catch (final Exception e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(), e); + } finally { + if (task != null) { try { - 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(cmd, false, msg); - } - - } - final String msg = "scaling VM " + vmName + " is successful on host " + host; - s_logger.debug(msg); - return new ScaleVmAnswer(cmd, 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(cmd, 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(cmd, 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(cmd, false, msg); - } - } - - private Answer execute(final RevertToVMSnapshotCommand cmd) { - final String vmName = cmd.getVmName(); - final List listVolumeTo = cmd.getVolumeTOs(); - final VMSnapshot.Type vmSnapshotType = cmd.getTarget().getType(); - final Boolean snapshotMemory = vmSnapshotType == VMSnapshot.Type.DiskAndMemory; - final Connection conn = getConnection(); - PowerState vmState = null; - VM vm = null; - try { - - final Set vmSnapshots = VM.getByNameLabel(conn, cmd.getTarget().getSnapshotName()); - if (vmSnapshots.size() == 0) { - return new RevertToVMSnapshotAnswer(cmd, false, "Cannot find vmSnapshot with name: " + cmd.getTarget().getSnapshotName()); - } - - final VM vmSnapshot = vmSnapshots.iterator().next(); - - // find target VM or creating a work VM - try { - vm = getVM(conn, vmName); - } catch (final Exception e) { - vm = createWorkingVM(conn, vmName, cmd.getGuestOSType(), cmd.getPlatformEmulator(), listVolumeTo); - } - - if (vm == null) { - return new RevertToVMSnapshotAnswer(cmd, false, "Revert to VM Snapshot Failed due to can not find vm: " + vmName); - } - - // call plugin to execute revert - revertToSnapshot(conn, vmSnapshot, vmName, vm.getUuid(conn), snapshotMemory, _host.getUuid()); - vm = getVM(conn, vmName); - final Set vbds = vm.getVBDs(conn); - final Map vdiMap = new HashMap(); - // get vdi:vbdr to a map - for (final VBD vbd : vbds) { - final VBD.Record vbdr = vbd.getRecord(conn); - if (vbdr.type == Types.VbdType.DISK) { - final VDI vdi = vbdr.VDI; - vdiMap.put(vbdr.userdevice, vdi); + task.destroy(conn); + } catch (final Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } - - if (!snapshotMemory) { - vm.destroy(conn); - vmState = PowerState.PowerOff; - } else { - vmState = PowerState.PowerOn; - } - - // after revert, VM's volumes path have been changed, need to report to manager - for (final VolumeObjectTO volumeTo : listVolumeTo) { - final Long deviceId = volumeTo.getDeviceId(); - final VDI vdi = vdiMap.get(deviceId.toString()); - volumeTo.setPath(vdi.getUuid(conn)); - } - - return new RevertToVMSnapshotAnswer(cmd, listVolumeTo, vmState); - } catch (final Exception e) { - s_logger.error("revert vm " + vmName + " to snapshot " + cmd.getTarget().getSnapshotName() + " failed due to " + e.getMessage()); - return new RevertToVMSnapshotAnswer(cmd, false, e.getMessage()); } - } - - public String revertToSnapshot(final Connection conn, final VM vmSnapshot, final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) throws XenAPIException, - XmlRpcException { - - final String results = - callHostPluginAsync(conn, "vmopsSnapshot", "revert_memory_snapshot", 10 * 60 * 1000, "snapshotUUID", vmSnapshot.getUuid(conn), "vmName", vmName, "oldVmUuid", - oldVmUuid, "snapshotMemory", snapshotMemory.toString(), "hostUUID", hostUUID); - String errMsg = null; - if (results == null || results.isEmpty()) { - errMsg = "revert_memory_snapshot return null"; - } else { - if (results.equals("0")) { - return results; - } else { - errMsg = "revert_memory_snapshot exception"; - } - } - s_logger.warn(errMsg); - throw new CloudRuntimeException(errMsg); - } - - 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); - } - return getNetworkByName(conn, name); - } - - if (type == TrafficType.Guest) { - return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getGuestNetwork()), null, PIF.getByUuid(conn, _host.getGuestPif()), null); - } else if (type == TrafficType.Control) { - setupLinkLocalNetwork(conn); - return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getLinkLocalNetwork())); - } else if (type == TrafficType.Management) { - return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPrivateNetwork()), null, PIF.getByUuid(conn, _host.getPrivatePif()), null); - } else if (type == TrafficType.Public) { - return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPublicNetwork()), null, PIF.getByUuid(conn, _host.getPublicPif()), null); - } else if (type == TrafficType.Storage) { - /* TrafficType.Storage is for secondary storage, while storageNetwork1 is for primary storage, we need better name here */ - return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getStorageNetwork1()), null, PIF.getByUuid(conn, _host.getStoragePif1()), null); - } - - throw new CloudRuntimeException("Unsupported network type: " + type); - } - - public synchronized Network setupvSwitchNetwork(final Connection conn) { - try { - if (_host.getVswitchNetwork() == null) { - Network vswitchNw = null; - final Network.Record rec = new Network.Record(); - final String nwName = Networks.BroadcastScheme.VSwitch.toString(); - final Set networks = Network.getByNameLabel(conn, nwName); - - if (networks.size() == 0) { - rec.nameDescription = "vswitch network for " + nwName; - rec.nameLabel = nwName; - vswitchNw = Network.create(conn, rec); - } else { - vswitchNw = networks.iterator().next(); - } - _host.setVswitchNetwork(vswitchNw); - } - return _host.getVswitchNetwork(); - } catch (final BadServerResponse e) { - s_logger.error("Failed to setup vswitch network", e); - } catch (final XenAPIException e) { - s_logger.error("Failed to setup vswitch network", e); - } catch (final XmlRpcException e) { - s_logger.error("Failed to setup vswitch network", e); - } - return null; } - /** - * This method just creates a XenServer network following the tunnel network naming convention - */ - public synchronized Network findOrCreateTunnelNetwork(final Connection conn, final String nwName) { - try { - Network nw = null; - final Network.Record rec = new Network.Record(); - final Set networks = Network.getByNameLabel(conn, nwName); + public String callHostPluginPremium(final Connection conn, final String cmd, final String... params) { + return callHostPlugin(conn, "vmopspremium", cmd, params); + } - if (networks.size() == 0) { - rec.nameDescription = "tunnel network id# " + nwName; - rec.nameLabel = nwName; - //Initialize the ovs-host-setup to avoid error when doing get-param in plugin - final Map otherConfig = new HashMap(); - otherConfig.put("ovs-host-setup", ""); - // Mark 'internal network' as shared so bridge gets automatically created on each host in the cluster - // when VM with vif connected to this internal network is started - otherConfig.put("assume_network_is_shared", "true"); - rec.otherConfig = otherConfig; - nw = Network.create(conn, rec); - s_logger.debug("### XenServer network for tunnels created:" + nwName); - } else { - nw = networks.iterator().next(); - s_logger.debug("XenServer network for tunnels found:" + nwName); + protected String callHostPluginThroughMaster(final Connection conn, final String plugin, final String cmd, final String... params) { + final Map args = new HashMap(); + + try { + final Map poolRecs = Pool.getAllRecords(conn); + if (poolRecs.size() != 1) { + throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.getUuid()); } - return nw; - } catch (final Exception e) { - s_logger.warn("createTunnelNetwork failed", e); - return null; + final Host master = poolRecs.values().iterator().next().master; + for (int i = 0; i < params.length; i += 2) { + args.put(params[i], params[i + 1]); + } + + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); + } + final String result = master.callPlugin(conn, plugin, cmd, args); + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin Result: " + result); + } + return result.replace("\n", ""); + } catch (final Types.HandleInvalid e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + + e.handle); + } catch (final XenAPIException e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); + } catch (final XmlRpcException e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(), e); } + return null; + } + + public boolean canBridgeFirewall() { + return _canBridgeFirewall; + } + + public boolean canBridgeFirewall(final Connection conn) { + return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.getUuid(), "instance", _instance)); + } + + public void checkForSuccess(final Connection c, final Task task) throws XenAPIException, XmlRpcException { + if (task.getStatus(c) == Types.TaskStatusType.SUCCESS) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") completed"); + } + return; + } else { + final String msg = "Task failed! Task record: " + task.getRecord(c); + s_logger.warn(msg); + task.cancel(c); + task.destroy(c); + throw new Types.BadAsyncResult(msg); + } + } + + protected boolean checkSR(final Connection conn, final SR sr) { + try { + final SR.Record srr = sr.getRecord(conn); + final Set pbds = sr.getPBDs(conn); + if (pbds.size() == 0) { + final String msg = "There is no PBDs for this SR: " + srr.nameLabel + " on host:" + _host.getUuid(); + s_logger.warn(msg); + return false; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Checking " + srr.nameLabel + " or SR " + srr.uuid + " on " + _host); + } + if (srr.shared) { + if (SRType.NFS.equals(srr.type) ){ + final Map smConfig = srr.smConfig; + if( !smConfig.containsKey("nosubdir")) { + smConfig.put("nosubdir", "true"); + sr.setSmConfig(conn,smConfig); + } + } + + final Host host = Host.getByUuid(conn, _host.getUuid()); + boolean found = false; + for (final PBD pbd : pbds) { + final PBD.Record pbdr = pbd.getRecord(conn); + if (host.equals(pbdr.host)) { + if (!pbdr.currentlyAttached) { + pbdPlug(conn, pbd, pbdr.uuid); + } + found = true; + break; + } + } + if (!found) { + final PBD.Record pbdr = srr.PBDs.iterator().next().getRecord(conn); + pbdr.host = host; + pbdr.uuid = ""; + final PBD pbd = PBD.create(conn, pbdr); + pbdPlug(conn, pbd, pbd.getUuid(conn)); + } + } else { + for (final PBD pbd : pbds) { + final PBD.Record pbdr = pbd.getRecord(conn); + if (!pbdr.currentlyAttached) { + pbdPlug(conn, pbd, pbdr.uuid); + } + } + } + + } catch (final Exception e) { + final String msg = "checkSR failed host:" + _host + " due to " + e.toString(); + s_logger.warn(msg, e); + return false; + } + return true; + } + + private void CheckXenHostInfo() throws ConfigurationException { + final Connection conn = ConnPool.getConnect(_host.getIp(), _username, _password); + if( conn == null ) { + throw new ConfigurationException("Can not create connection to " + _host.getIp()); + } + try { + Host.Record hostRec = null; + try { + final Host host = Host.getByUuid(conn, _host.getUuid()); + hostRec = host.getRecord(conn); + final Pool.Record poolRec = Pool.getAllRecords(conn).values().iterator().next(); + _host.setPool(poolRec.uuid); + + } catch (final Exception e) { + throw new ConfigurationException("Can not get host information from " + _host.getIp()); + } + if (!hostRec.address.equals(_host.getIp())) { + final String msg = "Host " + _host.getIp() + " seems be reinstalled, please remove this host and readd"; + s_logger.error(msg); + throw new ConfigurationException(msg); + } + } finally { + try { + Session.logout(conn); + } catch (final Exception e) { + } + } + } + + @Override + public ExecutionResult cleanupCommand(final NetworkElementCommand cmd) { + if (cmd instanceof IpAssocCommand && !(cmd instanceof IpAssocVpcCommand)) { + return cleanupNetworkElementCommand((IpAssocCommand)cmd); + } + return new ExecutionResult(true, null); + } + + + public boolean cleanupHaltedVms(final Connection conn) throws XenAPIException, XmlRpcException { + final Host host = Host.getByUuid(conn, _host.getUuid()); + final Map vms = VM.getAllRecords(conn); + boolean success = true; + if(vms != null && !vms.isEmpty()) { + for (final Map.Entry entry : vms.entrySet()) { + final VM vm = entry.getKey(); + final VM.Record vmRec = entry.getValue(); + if (vmRec.isATemplate || vmRec.isControlDomain) { + continue; + } + + if (VmPowerState.HALTED.equals(vmRec.powerState) && vmRec.affinity.equals(host) && !isAlienVm(vm, conn)) { + try { + vm.destroy(conn); + } catch (final Exception e) { + s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to ", e); + success = false; + } + } + } + } + return success; + } + + protected ExecutionResult cleanupNetworkElementCommand(final IpAssocCommand cmd) { + final Connection conn = getConnection(); + final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + final String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + try { + final IpAddressTO[] ips = cmd.getIpAddresses(); + final int ipsCount = ips.length; + for (final IpAddressTO ip : ips) { + + final VM router = getVM(conn, routerName); + + final NicTO nic = new NicTO(); + nic.setMac(ip.getVifMacAddress()); + nic.setType(ip.getTrafficType()); + if (ip.getBroadcastUri()== null) { + nic.setBroadcastType(BroadcastDomainType.Native); + } else { + final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); + nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); + nic.setBroadcastUri(uri); + } + nic.setDeviceId(0); + nic.setNetworkRateMbps(ip.getNetworkRate()); + nic.setName(ip.getNetworkName()); + + Network network = getNetwork(conn, nic); + + + // If we are disassociating the last IP address in the VLAN, we need + // to remove a VIF + boolean removeVif = false; + + //there is only one ip in this public vlan and removing it, so remove the nic + if (ipsCount == 1 && !ip.isAdd()) { + removeVif = true; + } + + if (removeVif) { + + // Determine the correct VIF on DomR to associate/disassociate the + // IP address with + final VIF correctVif = getCorrectVif(conn, router, network); + if (correctVif != null) { + network = correctVif.getNetwork(conn); + + // Mark this vif to be removed from network usage + networkUsage(conn, routerIp, "deleteVif", "eth" + correctVif.getDevice(conn)); + + // Remove the VIF from DomR + correctVif.unplug(conn); + correctVif.destroy(conn); + + // Disable the VLAN network if necessary + disableVlanNetwork(conn, network); + } + } + } + } catch (final Exception e) { + s_logger.debug("Ip Assoc failure on applying one ip due to exception: ", e); + return new ExecutionResult(false, e.getMessage()); + } + return new ExecutionResult(true, null); + } + + public void cleanupTemplateSR(final Connection conn) { + Set pbds = null; + try { + final Host host = Host.getByUuid(conn, _host.getUuid()); + pbds = host.getPBDs(conn); + } catch (final XenAPIException e) { + s_logger.warn("Unable to get the SRs " + e.toString(), e); + throw new CloudRuntimeException("Unable to get SRs " + e.toString(), e); + } catch (final Exception e) { + throw new CloudRuntimeException("Unable to get SRs " + e.getMessage(), e); + } + for (final PBD pbd : pbds) { + SR sr = null; + SR.Record srRec = null; + try { + sr = pbd.getSR(conn); + srRec = sr.getRecord(conn); + } catch (final Exception e) { + s_logger.warn("pbd.getSR get Exception due to ", e); + continue; + } + final String type = srRec.type; + if (srRec.shared) { + continue; + } + if (SRType.NFS.equals(type) || SRType.ISO.equals(type) && srRec.nameDescription.contains("template")) { + try { + pbd.unplug(conn); + pbd.destroy(conn); + sr.forget(conn); + } catch (final Exception e) { + s_logger.warn("forget SR catch Exception due to ", e); + } + } + } + } + + public void cleanUpTmpDomVif(final Connection conn, final Network nw) throws XenAPIException, XmlRpcException { + + final Pair vm = getControlDomain(conn); + final VM dom0 = vm.first(); + final Set dom0Vifs = dom0.getVIFs(conn); + for (final VIF v : dom0Vifs) { + String vifName = "unknown"; + try { + final VIF.Record vifr = v.getRecord(conn); + if (v.getNetwork(conn).getUuid(conn).equals(nw.getUuid(conn))) { + if(vifr != null) { + final Map config = vifr.otherConfig; + vifName = config.get("nameLabel"); + } + s_logger.debug("A VIF in dom0 for the network is found - so destroy the vif"); + v.destroy(conn); + s_logger.debug("Destroy temp dom0 vif" + vifName + " success"); + } + } catch (final Exception e) { + s_logger.warn("Destroy temp dom0 vif " + vifName + "failed", e); + } + } + } + + protected VDI cloudVDIcopy(final Connection conn, final VDI vdi, final SR sr, int wait) throws Exception { + Task task = null; + if (wait == 0) { + wait = 2 * 60 * 60; + } + try { + task = vdi.copyAsync(conn, sr); + // poll every 1 seconds , timeout after 2 hours + waitForTask(conn, task, 1000, (long)wait * 1000); + checkForSuccess(conn, task); + final VDI dvdi = Types.toVDI(task, conn); + return dvdi; + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (final Exception e) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e.toString()); + } + } + } + } + + public HashMap clusterVMMetaDataSync(final Connection conn) { + final HashMap vmMetaDatum = new HashMap(); + try { + final Map vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER + if(vm_map != null) { + for (final VM.Record record : vm_map.values()) { + if (record.isControlDomain || record.isASnapshot || record.isATemplate) { + continue; // Skip DOM0 + } + vmMetaDatum.put(record.nameLabel, StringUtils.mapToString(record.platform)); + } + } + } catch (final Throwable e) { + final String msg = "Unable to get vms through host " + _host.getUuid() + " due to to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } + return vmMetaDatum; + } + + @Override + public boolean configure(final String name, final Map params) throws ConfigurationException { + _name = name; + + try { + _dcId = Long.parseLong((String)params.get("zone")); + } catch (final NumberFormatException e) { + throw new ConfigurationException("Unable to get the zone " + params.get("zone")); + } + + _host.setUuid((String)params.get("guid")); + + _name = _host.getUuid(); + _host.setIp((String)params.get("ipaddress")); + + _username = (String)params.get("username"); + _password.add((String)params.get("password")); + _pod = (String)params.get("pod"); + _cluster = (String)params.get("cluster"); + _privateNetworkName = (String)params.get("private.network.device"); + _publicNetworkName = (String)params.get("public.network.device"); + _guestNetworkName = (String)params.get("guest.network.device"); + _instance = (String)params.get("instance.name"); + _securityGroupEnabled = Boolean.parseBoolean((String)params.get("securitygroupenabled")); + + _linkLocalPrivateNetworkName = (String)params.get("private.linkLocal.device"); + if (_linkLocalPrivateNetworkName == null) { + _linkLocalPrivateNetworkName = "cloud_link_local_network"; + } + + _storageNetworkName1 = (String)params.get("storage.network.device1"); + _storageNetworkName2 = (String)params.get("storage.network.device2"); + + _heartbeatTimeout = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.timeout"), 120); + _heartbeatInterval = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.interval"), 60); + + String value = (String)params.get("wait"); + _wait = NumbersUtil.parseInt(value, 600); + + value = (String)params.get("migratewait"); + _migratewait = NumbersUtil.parseInt(value, 3600); + + _maxNics = NumbersUtil.parseInt((String)params.get("xenserver.nics.max"), 7); + + if (_pod == null) { + throw new ConfigurationException("Unable to get the pod"); + } + + if (_host.getIp() == null) { + throw new ConfigurationException("Unable to get the host address"); + } + + if (_username == null) { + throw new ConfigurationException("Unable to get the username"); + } + + if (_password.peek() == null) { + throw new ConfigurationException("Unable to get the password"); + } + + if (_host.getUuid() == null) { + throw new ConfigurationException("Unable to get the uuid"); + } + + CheckXenHostInfo(); + + storageHandler = buildStorageHandler(); + + _vrResource = new VirtualRoutingResource(this); + if (!_vrResource.configure(name, params)) { + throw new ConfigurationException("Unable to configure VirtualRoutingResource"); + } + return true; } /** @@ -887,7 +818,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public synchronized Network configureTunnelNetwork(final Connection conn, final Long networkId, final long hostId, final String bridgeName) { try { final Network nw = findOrCreateTunnelNetwork(conn, bridgeName); - final String nwName = bridgeName; //Invoke plugin to setup the bridge which will be used by this network final String bridge = nw.getBridge(conn); final Map nwOtherConfig = nw.getOtherConfig(conn); @@ -931,228 +861,218 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - public synchronized void destroyTunnelNetwork(final Connection conn, final Network nw, final long hostId) { - try { - final String bridge = nw.getBridge(conn); - final String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge, - "cs_host_id", ((Long)hostId).toString()); - final String[] res = result.split(":"); - if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) { - //TODO: Should make this error not fatal? - //Can Concurrent VM shutdown/migration/reboot events can cause this method - //to be executed on a bridge which has already been removed? - throw new CloudRuntimeException("Unable to remove OVS bridge " + bridge + ":" + result); - } - return; - } catch (final Exception e) { - s_logger.warn("destroyTunnelNetwork failed:", e); - return; - } + public String connect(final Connection conn, final String vmname, final String ipAddress) { + return connect(conn, vmname, ipAddress, 3922); } - public Network getNetwork(final Connection conn, final NicTO nic) throws XenAPIException, XmlRpcException { - final String name = nic.getName(); - final XsLocalNetwork network = getNativeNetworkForTraffic(conn, nic.getType(), name); - if (network == null) { - s_logger.error("Network is not configured on the backend for nic " + nic.toString()); - throw new CloudRuntimeException("Network for the backend is not configured correctly for network broadcast domain: " + nic.getBroadcastUri()); - } - final URI uri = nic.getBroadcastUri(); - final BroadcastDomainType type = nic.getBroadcastType(); - if (uri != null && uri.toString().contains("untagged")) { - return network.getNetwork(); - } else if (uri != null && type == BroadcastDomainType.Vlan) { - assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Vlan; - final long vlan = Long.parseLong(BroadcastDomainType.getValue(uri)); - return enableVlanNetwork(conn, vlan, network); - } else if (type == BroadcastDomainType.Native || type == BroadcastDomainType.LinkLocal || - type == BroadcastDomainType.Vsp) { - return network.getNetwork(); - } else if (uri != null && type == BroadcastDomainType.Vswitch) { - final String header = uri.toString().substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length()); - if (header.startsWith("vlan")) { - _isOvs = true; - return setupvSwitchNetwork(conn); - } else { - return findOrCreateTunnelNetwork(conn, getOvsTunnelNetworkName(uri.getAuthority())); - } - } else if (type == BroadcastDomainType.Storage) { - if (uri == null) { - return network.getNetwork(); - } else { - final long vlan = Long.parseLong(BroadcastDomainType.getValue(uri)); - return enableVlanNetwork(conn, vlan, network); - } - } else if (type == BroadcastDomainType.Lswitch) { - // Nicira Logical Switch - return network.getNetwork(); - } else if (uri != null && type == BroadcastDomainType.Pvlan) { - assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Pvlan; - // should we consider moving this NetUtils method to BroadcastDomainType? - final long vlan = Long.parseLong(NetUtils.getPrimaryPvlanFromUri(uri)); - return enableVlanNetwork(conn, vlan, network); - } - - throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri()); - } - - private String getOvsTunnelNetworkName(final String broadcastUri) { - if (broadcastUri.contains(".")) { - final String[] parts = broadcastUri.split("\\."); - return "OVS-DR-VPC-Bridge"+parts[0]; - } else { + public String connect(final Connection conn, final String vmName, final String ipAddress, final int port) { + for (int i = 0; i <= _retry; i++) { try { - return "OVSTunnel" + broadcastUri; + final Set vms = VM.getByNameLabel(conn, vmName); + if (vms.size() < 1) { + final String msg = "VM " + vmName + " is not running"; + s_logger.warn(msg); + return msg; + } } catch (final Exception e) { + final String msg = "VM.getByNameLabel " + vmName + " failed due to " + e.toString(); + s_logger.warn(msg, e); + return msg; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Trying to connect to " + ipAddress + " attempt " + i + " of " + _retry); + } + if (pingdomr(conn, ipAddress, Integer.toString(port))) { return null; } - } - } - - public VIF createVif(final Connection conn, final String vmName, final VM vm, final VirtualMachineTO vmSpec, final NicTO nic) throws XmlRpcException, XenAPIException { - assert nic.getUuid() != null : "Nic should have a uuid value"; - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating VIF for " + vmName + " on nic " + nic); - } - VIF.Record vifr = new VIF.Record(); - vifr.VM = vm; - vifr.device = Integer.toString(nic.getDeviceId()); - vifr.MAC = nic.getMac(); - - // Nicira needs these IDs to find the NIC - vifr.otherConfig = new HashMap(); - vifr.otherConfig.put("nicira-iface-id", nic.getUuid()); - vifr.otherConfig.put("nicira-vm-id", vm.getUuid(conn)); - // Provide XAPI with the cloudstack vm and nic uids. - vifr.otherConfig.put("cloudstack-nic-id", nic.getUuid()); - if (vmSpec != null) { - vifr.otherConfig.put("cloudstack-vm-id", vmSpec.getUuid()); - } - - // OVS plugin looks at network UUID in the vif 'otherconfig' details to group VIF's & tunnel ports as part of tier - // when bridge is setup for distributed routing - vifr.otherConfig.put("cloudstack-network-id", nic.getNetworkUuid()); - - // Nuage Vsp needs Virtual Router IP to be passed in the otherconfig - // get the virtual router IP information from broadcast uri - final URI broadcastUri = nic.getBroadcastUri(); - if (broadcastUri != null && broadcastUri.getScheme().equalsIgnoreCase(Networks.BroadcastDomainType.Vsp.scheme())) { - final String path = broadcastUri.getPath(); - vifr.otherConfig.put("vsp-vr-ip", path.substring(1)); - } - vifr.network = getNetwork(conn, nic); - - if (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) { - vifr.qosAlgorithmType = "ratelimit"; - vifr.qosAlgorithmParams = new HashMap(); - // convert mbs to kilobyte per second - vifr.qosAlgorithmParams.put("kbps", Integer.toString(nic.getNetworkRateMbps() * 128)); - } - - vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT; - final VIF vif = VIF.create(conn, vifr); - if (s_logger.isDebugEnabled()) { - vifr = vif.getRecord(conn); - if(vifr != null) { - s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId()); - } - } - - return vif; - } - - public void prepareISO(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException { - - final Set vms = VM.getByNameLabel(conn, vmName); - if (vms == null || vms.size() != 1) { - throw new CloudRuntimeException("There are " + (vms == null ? "0" : vms.size()) + " VMs named " + vmName); - } - final VM vm = vms.iterator().next(); - final Set vbds = vm.getVBDs(conn); - for (final VBD vbd : vbds) { - final VBD.Record vbdr = vbd.getRecord(conn); - if (vbdr.type == Types.VbdType.CD && vbdr.empty == false) { - final VDI vdi = vbdr.VDI; - final SR sr = vdi.getSR(conn); - final Set pbds = sr.getPBDs(conn); - if (pbds == null) { - throw new CloudRuntimeException("There is no pbd for sr " + sr); - } - for (final PBD pbd : pbds) { - final PBD.Record pbdr = pbd.getRecord(conn); - if (pbdr.host.getUuid(conn).equals(_host.getUuid())) { - return; - } - } - sr.setShared(conn, true); - final Host host = Host.getByUuid(conn, _host.getUuid()); - final PBD.Record pbdr = pbds.iterator().next().getRecord(conn); - pbdr.host = host; - pbdr.uuid = ""; - final PBD pbd = PBD.create(conn, pbdr); - pbdPlug(conn, pbd, pbd.getUuid(conn)); - break; - } - } - } - - protected VDI mount(final Connection conn, final String vmName, final DiskTO volume) throws XmlRpcException, XenAPIException { - final DataTO data = volume.getData(); - final Volume.Type type = volume.getType(); - if (type == Volume.Type.ISO) { - final TemplateObjectTO iso = (TemplateObjectTO)data; - final DataStoreTO store = iso.getDataStore(); - - if (store == null) { - //It's a fake iso - return null; - } - - //corer case, xenserver pv driver iso - final String templateName = iso.getName(); - if (templateName.startsWith("xs-tools")) { - try { - final Set vdis = VDI.getByNameLabel(conn, templateName); - if (vdis.isEmpty()) { - throw new CloudRuntimeException("Could not find ISO with URL: " + templateName); - } - return vdis.iterator().next(); - } catch (final XenAPIException e) { - throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString()); - } catch (final Exception e) { - throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString()); - } - } - - if (!(store instanceof NfsTO)) { - throw new CloudRuntimeException("only support mount iso on nfs"); - } - final NfsTO nfsStore = (NfsTO)store; - final String isoPath = nfsStore.getUrl() + File.separator + iso.getPath(); - final int index = isoPath.lastIndexOf("/"); - - final String mountpoint = isoPath.substring(0, index); - URI uri; try { - uri = new URI(mountpoint); - } catch (final URISyntaxException e) { - throw new CloudRuntimeException("Incorrect uri " + mountpoint, e); + Thread.sleep(_sleep); + } catch (final InterruptedException e) { } - final SR isoSr = createIsoSRbyURI(conn, uri, vmName, false); - - final String isoname = isoPath.substring(index + 1); - - final VDI isoVdi = getVDIbyLocationandSR(conn, isoname, isoSr); - - if (isoVdi == null) { - throw new CloudRuntimeException("Unable to find ISO " + isoPath); - } - return isoVdi; - } else { - final VolumeObjectTO vol = (VolumeObjectTO)data; - return VDI.getByUuid(conn, vol.getPath()); } + final String msg = "Timeout, Unable to logon to " + ipAddress; + s_logger.debug(msg); + + return msg; + } + + public String copyVhdFromSecondaryStorage(final Connection conn, final String mountpoint, final String sruuid, final int wait) { + final String nameLabel = "cloud-" + UUID.randomUUID().toString(); + final String results = + callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "copy_vhd_from_secondarystorage return null"; + } else { + final String[] tmp = results.split("#"); + final String status = tmp[0]; + if (status.equals("0")) { + return tmp[1]; + } else { + errMsg = tmp[1]; + } + } + final String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1); + if (killCopyProcess(conn, source)) { + destroyVDIbyNameLabel(conn, nameLabel); + } + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + + @Override + public ExecutionResult createFileInVR(final String routerIp, final String path, final String filename, final String content) { + final Connection conn = getConnection(); + final String hostPath = "/tmp/"; + + s_logger.debug("Copying VR with ip " + routerIp +" config file into host "+ _host.getIp() ); + try { + SshHelper.scpTo(_host.getIp(), 22, _username, null, _password.peek(), hostPath, content.getBytes(Charset.defaultCharset()), filename, null); + } catch (final Exception e) { + s_logger.warn("scp VR config file into host " + _host.getIp() + " failed with exception " + e.getMessage().toString()); + } + + final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path); + s_logger.debug ("VR Config file " + filename + " got created in VR, ip " + routerIp + " with content \n" + content); + + return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); + } + + protected SR createIsoSRbyURI(final Connection conn, final URI uri, final String vmName, final boolean shared) { + try { + final Map deviceConfig = new HashMap(); + String path = uri.getPath(); + path = path.replace("//", "/"); + deviceConfig.put("location", uri.getHost() + ":" + path); + final Host host = Host.getByUuid(conn, _host.getUuid()); + final SR sr = SR.create(conn, host, deviceConfig, new Long(0), uri.getHost() + path, "iso", "iso", "iso", shared, new HashMap()); + sr.setNameLabel(conn, vmName + "-ISO"); + sr.setNameDescription(conn, deviceConfig.get("location")); + + sr.scan(conn); + return sr; + } catch (final XenAPIException e) { + final String msg = "createIsoSRbyURI failed! mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (final Exception e) { + final String msg = "createIsoSRbyURI failed! mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + + protected SR createNfsSRbyURI(final Connection conn, final URI uri, final boolean shared) { + try { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating a " + (shared ? "shared SR for " : "not shared SR for ") + uri); + } + + final Map deviceConfig = new HashMap(); + String path = uri.getPath(); + path = path.replace("//", "/"); + deviceConfig.put("server", uri.getHost()); + deviceConfig.put("serverpath", path); + final String name = UUID.nameUUIDFromBytes(new String(uri.getHost() + path).getBytes()).toString(); + if (!shared) { + final Set srs = SR.getByNameLabel(conn, name); + for (final SR sr : srs) { + final SR.Record record = sr.getRecord(conn); + if (SRType.NFS.equals(record.type) && record.contentType.equals("user") && !record.shared) { + removeSRSync(conn, sr); + } + } + } + + final Host host = Host.getByUuid(conn, _host.getUuid()); + final Map smConfig = new HashMap(); + smConfig.put("nosubdir", "true"); + final SR sr = SR.create(conn, host, deviceConfig, new Long(0), name, uri.getHost() + uri.getPath(), SRType.NFS.toString(), "user", shared, smConfig); + + if (!checkSR(conn, sr)) { + throw new Exception("no attached PBD"); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "Created a SR; UUID is " + sr.getUuid(conn) + " device config is " + deviceConfig)); + } + sr.scan(conn); + return sr; + } catch (final XenAPIException e) { + final String msg = "Can not create second storage SR mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (final Exception e) { + final String msg = "Can not create second storage SR mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + + public VBD createPatchVbd(final Connection conn, final String vmName, final VM vm) throws XmlRpcException, XenAPIException { + + if (_host.getSystemvmisouuid() == null) { + final Set srs = SR.getByNameLabel(conn, "XenServer Tools"); + if (srs.size() != 1) { + throw new CloudRuntimeException("There are " + srs.size() + " SRs with name XenServer Tools"); + } + final SR sr = srs.iterator().next(); + sr.scan(conn); + + final SR.Record srr = sr.getRecord(conn); + + if (_host.getSystemvmisouuid() == null) { + for (final VDI vdi : srr.VDIs) { + final VDI.Record vdir = vdi.getRecord(conn); + if (vdir.nameLabel.contains("systemvm.iso")) { + _host.setSystemvmisouuid(vdir.uuid); + break; + } + } + } + if (_host.getSystemvmisouuid() == null) { + throw new CloudRuntimeException("can not find systemvmiso"); + } + } + + final VBD.Record cdromVBDR = new VBD.Record(); + cdromVBDR.VM = vm; + cdromVBDR.empty = true; + cdromVBDR.bootable = false; + cdromVBDR.userdevice = "3"; + cdromVBDR.mode = Types.VbdMode.RO; + cdromVBDR.type = Types.VbdType.CD; + final VBD cdromVBD = VBD.create(conn, cdromVBDR); + cdromVBD.insert(conn, VDI.getByUuid(conn, _host.getSystemvmisouuid())); + + return cdromVBD; + } + + protected boolean createSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String newFolder) { + final String result = callHostPlugin(conn, "vmopsSnapshot", "create_secondary_storage_folder", "remoteMountPath", remoteMountPath, "newFolder", newFolder); + return result != null; + } + + String createTemplateFromSnapshot(final Connection conn, final String templatePath, final String snapshotPath, final int wait) { + final String tmpltLocalDir = UUID.randomUUID().toString(); + final String results = + callHostPluginAsync(conn, "vmopspremium", "create_privatetemplate_from_snapshot", wait, "templatePath", templatePath, "snapshotPath", snapshotPath, + "tmpltLocalDir", tmpltLocalDir); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "create_privatetemplate_from_snapshot return null"; + } else { + final String[] tmp = results.split("#"); + final String status = tmp[0]; + if (status.equals("0")) { + return results; + } else { + errMsg = "create_privatetemplate_from_snapshot failed due to " + tmp[1]; + } + } + final String source = "cloud_mount/" + tmpltLocalDir; + killCopyProcess(conn, source); + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); } public VBD createVbd(final Connection conn, final DiskTO volume, final String vmName, final VM vm, final BootloaderType bootLoaderType, VDI vdi) throws XmlRpcException, XenAPIException { @@ -1210,43 +1130,84 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vbd; } + public VDI createVdi(final SR sr, final String vdiNameLabel, final Long volumeSize) throws Types.XenAPIException, XmlRpcException { + final Connection conn = getConnection(); - private long getStaticMax(final String os, final boolean b, final long dynamicMinRam, final long dynamicMaxRam){ - final long recommendedValue = CitrixHelper.getXenServerStaticMax(os, b); - if(recommendedValue == 0){ - s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); - return dynamicMaxRam; - } - final long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability - if (dynamicMaxRam > staticMax){ // XS contraint that dynamic max <= static max - s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + ", can lead to stability issues. Setting static max as much as dynamic max "); - return dynamicMaxRam; - } - return staticMax; - } + final VDI.Record vdir = new VDI.Record(); + vdir.nameLabel = vdiNameLabel; + vdir.SR = sr; + vdir.type = Types.VdiType.USER; - private long getStaticMin(final String os, final boolean b, final long dynamicMinRam, final long dynamicMaxRam) { - final long recommendedValue = CitrixHelper.getXenServerStaticMin(os, b); - if (recommendedValue == 0) { - s_logger.warn("No recommended value found for dynamic min"); - return dynamicMinRam; + final long totalSrSpace = sr.getPhysicalSize(conn); + final long unavailableSrSpace = sr.getPhysicalUtilisation(conn); + final long availableSrSpace = totalSrSpace - unavailableSrSpace; + + if (availableSrSpace < volumeSize) { + throw new CloudRuntimeException("Available space for SR cannot be less than " + volumeSize + "."); } - if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min - s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); - } - return dynamicMinRam; - } + vdir.virtualSize = volumeSize; - - public HashMap> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException { - return null; + return VDI.create(conn, vdir); } public void createVGPU(final Connection conn, final StartCommand cmd, final VM vm, final GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { } + public VIF createVif(final Connection conn, final String vmName, final VM vm, final VirtualMachineTO vmSpec, final NicTO nic) throws XmlRpcException, XenAPIException { + assert nic.getUuid() != null : "Nic should have a uuid value"; + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating VIF for " + vmName + " on nic " + nic); + } + VIF.Record vifr = new VIF.Record(); + vifr.VM = vm; + vifr.device = Integer.toString(nic.getDeviceId()); + vifr.MAC = nic.getMac(); + + // Nicira needs these IDs to find the NIC + vifr.otherConfig = new HashMap(); + vifr.otherConfig.put("nicira-iface-id", nic.getUuid()); + vifr.otherConfig.put("nicira-vm-id", vm.getUuid(conn)); + // Provide XAPI with the cloudstack vm and nic uids. + vifr.otherConfig.put("cloudstack-nic-id", nic.getUuid()); + if (vmSpec != null) { + vifr.otherConfig.put("cloudstack-vm-id", vmSpec.getUuid()); + } + + // OVS plugin looks at network UUID in the vif 'otherconfig' details to group VIF's & tunnel ports as part of tier + // when bridge is setup for distributed routing + vifr.otherConfig.put("cloudstack-network-id", nic.getNetworkUuid()); + + // Nuage Vsp needs Virtual Router IP to be passed in the otherconfig + // get the virtual router IP information from broadcast uri + final URI broadcastUri = nic.getBroadcastUri(); + if (broadcastUri != null && broadcastUri.getScheme().equalsIgnoreCase(Networks.BroadcastDomainType.Vsp.scheme())) { + final String path = broadcastUri.getPath(); + vifr.otherConfig.put("vsp-vr-ip", path.substring(1)); + } + vifr.network = getNetwork(conn, nic); + + if (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) { + vifr.qosAlgorithmType = "ratelimit"; + vifr.qosAlgorithmParams = new HashMap(); + // convert mbs to kilobyte per second + vifr.qosAlgorithmParams.put("kbps", Integer.toString(nic.getNetworkRateMbps() * 128)); + } + + vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT; + final VIF vif = VIF.create(conn, vifr); + if (s_logger.isDebugEnabled()) { + vifr = vif.getRecord(conn); + if(vifr != null) { + s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId()); + } + } + + return vif; + } + public VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmSpec, final Host host) throws XenAPIException, XmlRpcException { final String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getPlatformEmulator(), vmSpec.getBootloader() == BootloaderType.CD); final Set templates = VM.getByNameLabel(conn, guestOsTypeName); @@ -1377,142 +1338,66 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vm; } - - protected void finalizeVmMetaData(final VM vm, final Connection conn, final VirtualMachineTO vmSpec) throws Exception { - - final Map details = vmSpec.getDetails(); - if (details != null) { - final String platformstring = details.get("platform"); - if (platformstring != null && !platformstring.isEmpty()) { - final Map platform = StringUtils.stringToMap(platformstring); - vm.setPlatform(conn, platform); + public VM createWorkingVM(final Connection conn, final String vmName, final String guestOSType, final String platformEmulator, final List listVolumeTo) throws BadServerResponse, + Types.VmBadPowerState, Types.SrFull, + Types.OperationNotAllowed, XenAPIException, XmlRpcException { + //below is redundant but keeping for consistency and code readabilty + final String guestOsTypeName = platformEmulator; + if (guestOsTypeName == null) { + final String msg = + " Hypervisor " + this.getClass().getName() + " doesn't support guest OS type " + guestOSType + ". you can choose 'Other install media' to run it as HVM"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + final VM template = getVM(conn, guestOsTypeName); + final VM vm = template.createClone(conn, vmName); + vm.setIsATemplate(conn, false); + final Map vdiMap = new HashMap(); + for (final VolumeObjectTO volume : listVolumeTo) { + final String vdiUuid = volume.getPath(); + try { + final VDI vdi = VDI.getByUuid(conn, vdiUuid); + vdiMap.put(vdi, volume); + } catch (final Types.UuidInvalid e) { + s_logger.warn("Unable to find vdi by uuid: " + vdiUuid + ", skip it"); + } + } + for (final Map.Entryentry : vdiMap.entrySet()) { + final VDI vdi = entry.getKey(); + final VolumeObjectTO volumeTO = entry.getValue(); + final VBD.Record vbdr = new VBD.Record(); + vbdr.VM = vm; + vbdr.VDI = vdi; + if (volumeTO.getVolumeType() == Volume.Type.ROOT) { + vbdr.bootable = true; + vbdr.unpluggable = false; } else { - final String timeoffset = details.get("timeoffset"); - if (timeoffset != null) { - final Map platform = vm.getPlatform(conn); - platform.put("timeoffset", timeoffset); - vm.setPlatform(conn, platform); - } - final String coresPerSocket = details.get("cpu.corespersocket"); - if (coresPerSocket != null) { - final Map platform = vm.getPlatform(conn); - platform.put("cores-per-socket", coresPerSocket); - vm.setPlatform(conn, platform); - } - } - if ( !BootloaderType.CD.equals(vmSpec.getBootloader())) { - final String xenservertoolsversion = details.get("hypervisortoolsversion"); - if ((xenservertoolsversion == null || !xenservertoolsversion.equalsIgnoreCase("xenserver61")) && vmSpec.getGpuDevice() == null) { - final Map platform = vm.getPlatform(conn); - platform.remove("device_id"); - vm.setPlatform(conn, platform); - } + vbdr.bootable = false; + vbdr.unpluggable = true; } + vbdr.userdevice = Long.toString(volumeTO.getDeviceId()); + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + VBD.create(conn, vbdr); } + return vm; } - public String handleVmStartFailure(final Connection conn, final String vmName, final VM vm, final String message, final Throwable th) { - final String msg = "Unable to start " + vmName + " due to " + message; - s_logger.warn(msg, th); - if (vm == null) { - return msg; - } - - try { - final VM.Record vmr = vm.getRecord(conn); - final List networks = new ArrayList(); - for (final VIF vif : vmr.VIFs) { - try { - final VIF.Record rec = vif.getRecord(conn); - if(rec != null) { - networks.add(rec.network); - } else { - s_logger.warn("Unable to cleanup VIF: " + vif.toWireString() + " As vif record is null"); - } - } catch (final Exception e) { - s_logger.warn("Unable to cleanup VIF", e); - } - } - if (vmr.powerState == VmPowerState.RUNNING) { - try { - vm.hardShutdown(conn); - } catch (final Exception e) { - s_logger.warn("VM hardshutdown failed due to ", e); - } - } - if (vm.getPowerState(conn) == VmPowerState.HALTED) { - try { - vm.destroy(conn); - } catch (final Exception e) { - s_logger.warn("VM destroy failed due to ", e); - } - } - for (final VBD vbd : vmr.VBDs) { - try { - vbd.unplug(conn); - vbd.destroy(conn); - } catch (final Exception e) { - s_logger.warn("Unable to clean up VBD due to ", e); - } - } - for (final VIF vif : vmr.VIFs) { - try { - vif.unplug(conn); - vif.destroy(conn); - } catch (final Exception e) { - s_logger.warn("Unable to cleanup VIF", e); - } - } - for (final Network network : networks) { - if (network.getNameLabel(conn).startsWith("VLAN")) { - disableVlanNetwork(conn, network); - } - } - } catch (final Exception e) { - s_logger.warn("VM getRecord failed due to ", e); - } - - return msg; + protected boolean deleteSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String folder) { + final String details = callHostPlugin(conn, "vmopsSnapshot", "delete_secondary_storage_folder", "remoteMountPath", remoteMountPath, "folder", folder); + return details != null && details.equals("1"); } - public VBD createPatchVbd(final Connection conn, final String vmName, final VM vm) throws XmlRpcException, XenAPIException { - if (_host.getSystemvmisouuid() == null) { - final Set srs = SR.getByNameLabel(conn, "XenServer Tools"); - if (srs.size() != 1) { - throw new CloudRuntimeException("There are " + srs.size() + " SRs with name XenServer Tools"); - } - final SR sr = srs.iterator().next(); - sr.scan(conn); + protected String deleteSnapshotBackup(final Connection conn, final Long dcId, final Long accountId, final Long volumeId, final String secondaryStorageMountPath, final String backupUUID) { - final SR.Record srr = sr.getRecord(conn); + // If anybody modifies the formatting below again, I'll skin them + final String result = + callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "dcId", dcId.toString(), "accountId", accountId.toString(), + "volumeId", volumeId.toString(), "secondaryStorageMountPath", secondaryStorageMountPath); - if (_host.getSystemvmisouuid() == null) { - for (final VDI vdi : srr.VDIs) { - final VDI.Record vdir = vdi.getRecord(conn); - if (vdir.nameLabel.contains("systemvm.iso")) { - _host.setSystemvmisouuid(vdir.uuid); - break; - } - } - } - if (_host.getSystemvmisouuid() == null) { - throw new CloudRuntimeException("can not find systemvmiso"); - } - } - - final VBD.Record cdromVBDR = new VBD.Record(); - cdromVBDR.VM = vm; - cdromVBDR.empty = true; - cdromVBDR.bootable = false; - cdromVBDR.userdevice = "3"; - cdromVBDR.mode = Types.VbdMode.RO; - cdromVBDR.type = Types.VbdType.CD; - final VBD cdromVBD = VBD.create(conn, cdromVBDR); - cdromVBD.insert(conn, VDI.getByUuid(conn, _host.getSystemvmisouuid())); - - return cdromVBD; + return result; } public void destroyPatchVbd(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException { @@ -1536,130 +1421,253 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected CheckSshAnswer execute(final CheckSshCommand cmd) { - final Connection conn = getConnection(); - final String vmName = cmd.getName(); - final String privateIp = cmd.getIp(); - final int cmdPort = cmd.getPort(); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort); - } - + public synchronized void destroyTunnelNetwork(final Connection conn, final Network nw, final long hostId) { try { - final String result = connect(conn, cmd.getName(), privateIp, cmdPort); - if (result != null) { - return new CheckSshAnswer(cmd, "Can not ping System vm " + vmName + "due to:" + result); + final String bridge = nw.getBridge(conn); + final String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge, + "cs_host_id", ((Long)hostId).toString()); + final String[] res = result.split(":"); + if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) { + //TODO: Should make this error not fatal? + //Can Concurrent VM shutdown/migration/reboot events can cause this method + //to be executed on a bridge which has already been removed? + throw new CloudRuntimeException("Unable to remove OVS bridge " + bridge + ":" + result); } - //Do not destroy the disk here! It will stio the patching process. Please, don't! - //destroyPatchVbd(conn, vmName); + return; } catch (final Exception e) { - return new CheckSshAnswer(cmd, e); + s_logger.warn("destroyTunnelNetwork failed:", e); + return; + } + } + + + void destroyVDIbyNameLabel(final Connection conn, final String nameLabel) { + try { + final Set vdis = VDI.getByNameLabel(conn, nameLabel); + if (vdis.size() != 1) { + s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel); + return; + } + for (final VDI vdi : vdis) { + try { + vdi.destroy(conn); + } catch (final Exception e) { + final String msg = "Failed to destroy VDI : " + nameLabel + "due to " + e.toString() + "\n Force deleting VDI using system 'rm' command"; + s_logger.warn(msg); + try { + final String srUUID = vdi.getSR(conn).getUuid(conn); + final String vdiUUID = vdi.getUuid(conn); + final String vdifile = "/var/run/sr-mount/" + srUUID + "/" + vdiUUID + ".vhd"; + callHostPluginAsync(conn, "vmopspremium", "remove_corrupt_vdi", 10, "vdifile", vdifile); + } catch (final Exception e2) { + s_logger.warn(e2); + } + } + } + } catch (final Exception e) { + } + } + + public void disableVlanNetwork(final Connection conn, final Network network) { + } + + @Override + public void disconnected() { + } + + public boolean doPingTest(final Connection conn, final String computingHostIp) { + final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); + try { + sshConnection.connect(null, 60000, 60000); + if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { + throw new CloudRuntimeException("Unable to authenticate"); + } + + final String cmd = "ping -c 2 " + computingHostIp; + if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { + throw new CloudRuntimeException("Cannot ping host " + computingHostIp + " from host " + _host.getIp()); + } + return true; + } catch (final Exception e) { + s_logger.warn("Catch exception " + e.toString(), e); + return false; + } finally { + sshConnection.close(); + } + } + + public boolean doPingTest(final Connection conn, final String domRIp, final String vmIp) { + final String args = "-i " + domRIp + " -p " + vmIp; + final String result = callHostPlugin(conn, "vmops", "pingtest", "args", args); + if (result == null || result.isEmpty()) { + return false; + } + return true; + } + + /** + * enableVlanNetwork creates a Network object, Vlan object, and thereby + * a tagged PIF object in Xapi. + * + * In XenServer, VLAN is added by + * - Create a network, which is unique cluster wide. + * - Find the PIF that you want to create the VLAN on. + * - Create a VLAN using the network and the PIF. As a result of this + * operation, a tagged PIF object is also created. + * + * Here is a list of problems with clustered Xapi implementation that + * we are trying to circumvent. + * - There can be multiple Networks with the same name-label so searching + * using name-label is not unique. + * - There are no other ways to search for Networks other than listing + * all of them which is not efficient in our implementation because + * we can have over 4000 VLAN networks. + * - In a clustered situation, it's possible for both hosts to detect + * that the Network is missing and both creates it. This causes a + * lot of problems as one host may be using one Network and another + * may be using a different network for their VMs. This causes + * problems in migration because the VMs are logically attached + * to different networks in Xapi's database but in reality, they + * are attached to the same network. + * + * To work around these problems, we do the following. + * + * - When creating the VLAN network, we name it as VLAN-UUID of the + * Network it is created on-VLAN Tag. Because VLAN tags is unique with + * one particular network, this is a unique name-label to quickly + * retrieve the the VLAN network with when we need it again. + * - When we create the VLAN network, we add a timestamp and a random + * number as a tag into the network. Then instead of creating + * VLAN on that network, we actually retrieve the Network again + * and this time uses the VLAN network with lowest timestamp or + * lowest random number as the VLAN network. This allows VLAN creation + * to happen on multiple hosts concurrently but even if two VLAN + * networks were created with the same name, only one of them is used. + * + * One cavaet about this approach is that it relies on the timestamp to + * be relatively accurate among different hosts. + * + * @param conn Xapi Connection + * @param tag VLAN tag + * @param network network on this host to create the VLAN on. + * @return VLAN Network created. + * @throws XenAPIException + * @throws XmlRpcException + */ + protected Network enableVlanNetwork(final Connection conn, final long tag, final XsLocalNetwork network) throws XenAPIException, XmlRpcException { + Network vlanNetwork = null; + final String oldName = "VLAN" + Long.toString(tag); + final String newName = "VLAN-" + network.getNetworkRecord(conn).uuid + "-" + tag; + XsLocalNetwork vlanNic = getNetworkByName(conn, newName); + if (vlanNic == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Couldn't find vlan network with the new name so trying old name: " + oldName); + } + vlanNic = getNetworkByName(conn, oldName); + if (vlanNic != null) { + s_logger.info("Renaming VLAN with old name " + oldName + " to " + newName); + vlanNic.getNetwork().setNameLabel(conn, newName); + } + } + if (vlanNic == null) { // Can't find it, then create it. + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.getIp()); + } + final Network.Record nwr = new Network.Record(); + nwr.nameLabel = newName; + nwr.tags = new HashSet(); + nwr.tags.add(generateTimeStamp()); + vlanNetwork = Network.create(conn, nwr); + vlanNic = getNetworkByName(conn, newName); + if(vlanNic == null) { //Still vlanNic is null means we could not create it for some reason and no exception capture happened. + throw new CloudRuntimeException("Could not find/create vlan network with name: " + newName); + } + } + + final PIF nPif = network.getPif(conn); + final PIF.Record nPifr = network.getPifRecord(conn); + + vlanNetwork = vlanNic.getNetwork(); + if (vlanNic.getPif(conn) != null) { + return vlanNetwork; } if (s_logger.isDebugEnabled()) { - s_logger.debug("Ping command port succeeded for vm " + vmName); + s_logger.debug("Creating VLAN " + tag + " on host " + _host.getIp() + " on device " + nPifr.device); } - - return new CheckSshAnswer(cmd); - } - - public HashMap parseDefaultOvsRuleComamnd(final String str) { - final HashMap cmd = new HashMap(); - final String[] sarr = str.split("/"); - for (int i = 0; i < sarr.length; i++) { - String c = sarr[i]; - c = c.startsWith("/") ? c.substring(1) : c; - c = c.endsWith("/") ? c.substring(0, c.length() - 1) : c; - final String[] p = c.split(";"); - if (p.length != 2) { - continue; - } - if (p[0].equalsIgnoreCase("vlans")) { - p[1] = p[1].replace("@", "["); - p[1] = p[1].replace("#", "]"); - } - cmd.put(p[0], p[1]); - } - return cmd; - } - - public void cleanUpTmpDomVif(final Connection conn, final Network nw) throws XenAPIException, XmlRpcException { - - final Pair vm = getControlDomain(conn); - final VM dom0 = vm.first(); - final Set dom0Vifs = dom0.getVIFs(conn); - for (final VIF v : dom0Vifs) { - String vifName = "unknown"; - try { - final VIF.Record vifr = v.getRecord(conn); - if (v.getNetwork(conn).getUuid(conn).equals(nw.getUuid(conn))) { - if(vifr != null) { - final Map config = vifr.otherConfig; - vifName = config.get("nameLabel"); - } - s_logger.debug("A VIF in dom0 for the network is found - so destroy the vif"); - v.destroy(conn); - s_logger.debug("Destroy temp dom0 vif" + vifName + " success"); + final VLAN vlan = VLAN.create(conn, nPif, tag, vlanNetwork); + if (vlan != null) { + final VLAN.Record vlanr = vlan.getRecord(conn); + if (vlanr != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("VLAN is created for " + tag + ". The uuid is " + vlanr.uuid); } - } catch (final Exception e) { - s_logger.warn("Destroy temp dom0 vif " + vifName + "failed", e); } } + return vlanNetwork; } - private Answer execute(final PvlanSetupCommand cmd) { + private OvsSetTagAndFlowAnswer execute(final OvsSetTagAndFlowCommand cmd) { + _isOvs = true; + final Connection conn = getConnection(); - - final String primaryPvlan = cmd.getPrimary(); - final String isolatedPvlan = cmd.getIsolated(); - final String op = cmd.getOp(); - final String dhcpName = cmd.getDhcpName(); - final String dhcpMac = cmd.getDhcpMac(); - final String dhcpIp = cmd.getDhcpIp(); - final String vmMac = cmd.getVmMac(); - final String networkTag = cmd.getNetworkTag(); - - XsLocalNetwork nw = null; - String nwNameLabel = null; try { - nw = 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); + final Network nw = setupvSwitchNetwork(conn); + final String bridge = nw.getBridge(conn); + + /* + * If VM is domainRouter, this will try to set flow and tag on its + * none guest network nic. don't worry, it will fail silently at + * host plugin side + */ + final String result = callHostPlugin(conn, "ovsgre", "ovs_set_tag_and_flow", "bridge", bridge, "vmName", cmd.getVmName(), "tag", cmd.getTag(), "vlans", + cmd.getVlans(), "seqno", cmd.getSeqNo()); + s_logger.debug("set flow for " + cmd.getVmName() + " " + result); + + if (result.equalsIgnoreCase("SUCCESS")) { + return new OvsSetTagAndFlowAnswer(cmd, true, result); + } else { + return new OvsSetTagAndFlowAnswer(cmd, false, result); } - nwNameLabel = nw.getNetwork().getNameLabel(conn); + } catch (final BadServerResponse e) { + s_logger.error("Failed to set tag and flow", e); } catch (final XenAPIException e) { - s_logger.warn("Fail to get network", e); - return new Answer(cmd, false, e.toString()); + s_logger.error("Failed to set tag and flow", e); } catch (final XmlRpcException e) { - s_logger.warn("Fail to get network", e); - return new Answer(cmd, false, e.toString()); + s_logger.error("Failed to set tag and flow", e); } - String result = null; - if (cmd.getType() == PvlanSetupCommand.Type.DHCP) { - result = - 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(cmd, false, result); - } else { - s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac); + return new OvsSetTagAndFlowAnswer(cmd, false, "EXCEPTION"); + } + + @Override + public RebootAnswer execute(final RebootCommand cmd) { + final Connection conn = getConnection(); + s_logger.debug("7. The VM " + cmd.getVmName() + " is in Starting state"); + try { + Set vms = null; + try { + vms = VM.getByNameLabel(conn, cmd.getVmName()); + } catch (final XenAPIException e0) { + s_logger.debug("getByNameLabel failed " + e0.toString()); + return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString(), false); + } catch (final Exception e0) { + s_logger.debug("getByNameLabel failed " + e0.getMessage()); + return new RebootAnswer(cmd, "getByNameLabel failed", false); } - } else if (cmd.getType() == PvlanSetupCommand.Type.VM) { - result = - 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(cmd, false, result); - } else { - s_logger.info("Programmed pvlan for vm with mac " + vmMac); + for (final VM vm : vms) { + try { + rebootVM(conn, vm, vm.getNameLabel(conn)); + } catch (final Exception e) { + final String msg = e.toString(); + s_logger.warn(msg, e); + return new RebootAnswer(cmd, msg, false); + } } + return new RebootAnswer(cmd, "reboot succeeded", true); + } finally { + s_logger.debug("8. The VM " + cmd.getVmName() + " is in Running state"); } - return new Answer(cmd, true, result); } @Override @@ -1818,1576 +1826,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - // the idea here is to see if the DiskTO in question is from managed storage and - // does not yet have an SR - // if no SR, create it and create a VDI in it - public VDI prepareManagedDisk(final Connection conn, final DiskTO disk, final String vmName) throws Exception { - final Map details = disk.getDetails(); - - if (details == null) { - return null; - } - - final boolean isManaged = new Boolean(details.get(DiskTO.MANAGED)).booleanValue(); - - if (!isManaged) { - return null; - } - - final String iqn = details.get(DiskTO.IQN); - - final Set srNameLabels = SR.getByNameLabel(conn, iqn); - - if (srNameLabels.size() != 0) { - return null; - } - - final String vdiNameLabel = vmName + "-DATA"; - - return prepareManagedStorage(conn, details, null, vdiNameLabel); - } - - protected SR prepareManagedSr(final Connection conn, final Map details) { - final String iScsiName = details.get(DiskTO.IQN); - final String storageHost = details.get(DiskTO.STORAGE_HOST); - final String chapInitiatorUsername = details.get(DiskTO.CHAP_INITIATOR_USERNAME); - final String chapInitiatorSecret = details.get(DiskTO.CHAP_INITIATOR_SECRET); - final String mountpoint = details.get(DiskTO.MOUNT_POINT); - final String protocoltype = details.get(DiskTO.PROTOCOL_TYPE); - - if (StoragePoolType.NetworkFilesystem.toString().equalsIgnoreCase(protocoltype)) { - final String poolid = storageHost + ":" + mountpoint; - final String namelable = mountpoint; - final String volumedesc = storageHost + ":" + mountpoint; - - return getNfsSR(conn, poolid, namelable, storageHost, mountpoint, volumedesc); - } else { - return getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true); - } - } - - protected VDI prepareManagedStorage(final Connection conn, final Map details, final String path, final String vdiNameLabel) throws Exception { - final SR sr = prepareManagedSr(conn, details); - - VDI vdi = getVDIbyUuid(conn, path, false); - final Long volumeSize = Long.parseLong(details.get(DiskTO.VOLUME_SIZE)); - - if (vdi == null) { - vdi = createVdi(sr, vdiNameLabel, volumeSize); - } else { - // if VDI is not null, it must have already been created, so check whether a resize of the volume was performed - // if true, resize the VDI to the volume size - - s_logger.info("checking for the resize of the datadisk"); - - final long vdiVirtualSize = vdi.getVirtualSize(conn); - - if (vdiVirtualSize != volumeSize) { - s_logger.info("resizing the data disk (vdi) from vdiVirtualsize: "+ vdiVirtualSize + " to volumeSize: " + volumeSize); - - try { - vdi.resize(conn, volumeSize); - } catch (final Exception e) { - s_logger.warn("Unable to resize volume", e); - } - } - } - - return vdi; - } - - protected Answer execute(final ModifySshKeysCommand cmd) { - return new Answer(cmd); - } - - public boolean doPingTest(final Connection conn, final String computingHostIp) { - final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); - try { - sshConnection.connect(null, 60000, 60000); - if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { - throw new CloudRuntimeException("Unable to authenticate"); - } - - final String cmd = "ping -c 2 " + computingHostIp; - if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { - throw new CloudRuntimeException("Cannot ping host " + computingHostIp + " from host " + _host.getIp()); - } - return true; - } catch (final Exception e) { - s_logger.warn("Catch exception " + e.toString(), e); - return false; - } finally { - sshConnection.close(); - } - } - - protected CheckOnHostAnswer execute(final CheckOnHostCommand cmd) { - return new CheckOnHostAnswer(cmd, null, "Not Implmeneted"); - } - - public boolean doPingTest(final Connection conn, final String domRIp, final String vmIp) { - final String args = "-i " + domRIp + " -p " + vmIp; - final String result = callHostPlugin(conn, "vmops", "pingtest", "args", args); - if (result == null || result.isEmpty()) { - return false; - } - return true; - } - - private Answer execute(final PingTestCommand cmd) { - final Connection conn = getConnection(); - boolean result = false; - final String computingHostIp = cmd.getComputingHostIp(); - - if (computingHostIp != null) { - result = doPingTest(conn, computingHostIp); - } else { - result = doPingTest(conn, cmd.getRouterIp(), cmd.getPrivateIp()); - } - - if (!result) { - return new Answer(cmd, false, "PingTestCommand failed"); - } - return new Answer(cmd); - } - - protected MaintainAnswer execute(final MaintainCommand cmd) { - final Connection conn = getConnection(); - try { - - final Host host = Host.getByUuid(conn, _host.getUuid()); - // remove all tags cloud stack - final Host.Record hr = host.getRecord(conn); - final Iterator it = hr.tags.iterator(); - while (it.hasNext()) { - final String tag = it.next(); - if (tag.contains("cloud")) { - it.remove(); - } - } - host.setTags(conn, hr.tags); - return new MaintainAnswer(cmd); - } catch (final XenAPIException e) { - s_logger.warn("Unable to put server in maintainence mode", e); - return new MaintainAnswer(cmd, false, e.getMessage()); - } catch (final XmlRpcException e) { - s_logger.warn("Unable to put server in maintainence mode", e); - return new MaintainAnswer(cmd, false, e.getMessage()); - } - } - - public String networkUsage(final Connection conn, final String privateIpAddress, final String option, final String vif) { - if (option.equals("get")) { - return "0:0"; - } - return null; - } - - protected ExecutionResult prepareNetworkElementCommand(final IpAssocCommand cmd) { - final Connection conn = getConnection(); - final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); - final String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); - - try { - final IpAddressTO[] ips = cmd.getIpAddresses(); - for (final IpAddressTO ip : ips) { - - final VM router = getVM(conn, routerName); - - final NicTO nic = new NicTO(); - nic.setMac(ip.getVifMacAddress()); - nic.setType(ip.getTrafficType()); - if (ip.getBroadcastUri()== null) { - nic.setBroadcastType(BroadcastDomainType.Native); - } else { - final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); - nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); - nic.setBroadcastUri(uri); - } - nic.setDeviceId(0); - nic.setNetworkRateMbps(ip.getNetworkRate()); - nic.setName(ip.getNetworkName()); - - final Network network = getNetwork(conn, nic); - - // Determine the correct VIF on DomR to associate/disassociate the - // IP address with - VIF correctVif = getCorrectVif(conn, router, network); - - // If we are associating an IP address and DomR doesn't have a VIF - // for the specified vlan ID, we need to add a VIF - // If we are disassociating the last IP address in the VLAN, we need - // to remove a VIF - boolean addVif = false; - if (ip.isAdd() && correctVif == null) { - addVif = true; - } - - if (addVif) { - // Add a new VIF to DomR - final String vifDeviceNum = getLowestAvailableVIFDeviceNum(conn, router); - - if (vifDeviceNum == null) { - throw new InternalErrorException("There were no more available slots for a new VIF on router: " + router.getNameLabel(conn)); - } - - nic.setDeviceId(Integer.valueOf(vifDeviceNum)); - - correctVif = createVif(conn, routerName, router, null, nic); - correctVif.plug(conn); - // Add iptables rule for network usage - networkUsage(conn, routerIp, "addVif", "eth" + correctVif.getDevice(conn)); - } - - if (ip.isAdd() && correctVif == null) { - throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with."); - } - if (correctVif != null ) { - ip.setNicDevId(Integer.valueOf(correctVif.getDevice(conn))); - ip.setNewNic(addVif); - } - } - } catch (final InternalErrorException e) { - s_logger.error("Ip Assoc failure on applying one ip due to exception: ", e); - return new ExecutionResult(false, e.getMessage()); - } catch (final Exception e) { - return new ExecutionResult(false, e.getMessage()); - } - return new ExecutionResult(true, null); - } - - protected ExecutionResult cleanupNetworkElementCommand(final IpAssocCommand cmd) { - final Connection conn = getConnection(); - final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); - final String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); - try { - final IpAddressTO[] ips = cmd.getIpAddresses(); - final int ipsCount = ips.length; - for (final IpAddressTO ip : ips) { - - final VM router = getVM(conn, routerName); - - final NicTO nic = new NicTO(); - nic.setMac(ip.getVifMacAddress()); - nic.setType(ip.getTrafficType()); - if (ip.getBroadcastUri()== null) { - nic.setBroadcastType(BroadcastDomainType.Native); - } else { - final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); - nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); - nic.setBroadcastUri(uri); - } - nic.setDeviceId(0); - nic.setNetworkRateMbps(ip.getNetworkRate()); - nic.setName(ip.getNetworkName()); - - Network network = getNetwork(conn, nic); - - - // If we are disassociating the last IP address in the VLAN, we need - // to remove a VIF - boolean removeVif = false; - - //there is only one ip in this public vlan and removing it, so remove the nic - if (ipsCount == 1 && !ip.isAdd()) { - removeVif = true; - } - - if (removeVif) { - - // Determine the correct VIF on DomR to associate/disassociate the - // IP address with - final VIF correctVif = getCorrectVif(conn, router, network); - if (correctVif != null) { - network = correctVif.getNetwork(conn); - - // Mark this vif to be removed from network usage - networkUsage(conn, routerIp, "deleteVif", "eth" + correctVif.getDevice(conn)); - - // Remove the VIF from DomR - correctVif.unplug(conn); - correctVif.destroy(conn); - - // Disable the VLAN network if necessary - disableVlanNetwork(conn, network); - } - } - } - } catch (final Exception e) { - s_logger.debug("Ip Assoc failure on applying one ip due to exception: ", e); - return new ExecutionResult(false, e.getMessage()); - } - return new ExecutionResult(true, null); - } - - protected GetVncPortAnswer execute(final GetVncPortCommand cmd) { - final Connection conn = getConnection(); - try { - final Set vms = VM.getByNameLabel(conn, cmd.getName()); - if (vms.size() == 1) { - String consoleurl; - consoleurl = "consoleurl=" + getVncUrl(conn, vms.iterator().next()) + "&" + "sessionref=" + conn.getSessionReference(); - return new GetVncPortAnswer(cmd, consoleurl, -1); - } else { - return new GetVncPortAnswer(cmd, "There are " + vms.size() + " VMs named " + cmd.getName()); - } - } catch (final Exception e) { - final String msg = "Unable to get vnc port due to " + e.toString(); - s_logger.warn(msg, e); - return new GetVncPortAnswer(cmd, msg); - } - } - - protected Storage.StorageResourceType getStorageResourceType() { - return Storage.StorageResourceType.STORAGE_POOL; - } - - protected CheckHealthAnswer execute(final CheckHealthCommand cmd) { - final boolean result = pingXAPI(); - return new CheckHealthAnswer(cmd, result); - } - - protected long[] getNetworkStats(final Connection conn, final String privateIP) { - final String result = networkUsage(conn, privateIP, "get", null); - final long[] stats = new long[2]; - if (result != null) { - final String[] splitResult = result.split(":"); - int i = 0; - while (i < splitResult.length - 1) { - stats[0] += new Long(splitResult[i++]).longValue(); - stats[1] += new Long(splitResult[i++]).longValue(); - } - } - return stats; - } - - /** - * This is the method called for getting the HOST stats - * - * @param cmd - * @return - */ - protected GetHostStatsAnswer execute(final GetHostStatsCommand cmd) { - final Connection conn = getConnection(); - try { - final HostStatsEntry hostStats = getHostStats(conn, cmd, cmd.getHostGuid(), cmd.getHostId()); - return new GetHostStatsAnswer(cmd, hostStats); - } catch (final Exception e) { - final String msg = "Unable to get Host stats" + e.toString(); - s_logger.warn(msg, e); - return new GetHostStatsAnswer(cmd, null); - } - } - - public HostStatsEntry getHostStats(final Connection conn, final GetHostStatsCommand cmd, final String hostGuid, final long hostId) { - - final HostStatsEntry hostStats = new HostStatsEntry(hostId, 0, 0, 0, "host", 0, 0, 0, 0); - final Object[] rrdData = getRRDData(conn, 1); // call rrd method with 1 for host - - if (rrdData == null) { - return null; - } - - final Integer numRows = (Integer)rrdData[0]; - final Integer numColumns = (Integer)rrdData[1]; - final Node legend = (Node)rrdData[2]; - final Node dataNode = (Node)rrdData[3]; - - final NodeList legendChildren = legend.getChildNodes(); - for (int col = 0; col < numColumns; col++) { - - if (legendChildren == null || legendChildren.item(col) == null) { - continue; - } - - final String columnMetadata = getXMLNodeValue(legendChildren.item(col)); - - if (columnMetadata == null) { - continue; - } - - final String[] columnMetadataList = columnMetadata.split(":"); - - if (columnMetadataList.length != 4) { - continue; - } - - final String type = columnMetadataList[1]; - final String param = columnMetadataList[3]; - - if (type.equalsIgnoreCase("host")) { - - if (param.matches("pif_eth0_rx")) { - hostStats.setNetworkReadKBs(getDataAverage(dataNode, col, numRows)/1000); - } else if (param.matches("pif_eth0_tx")) { - hostStats.setNetworkWriteKBs(getDataAverage(dataNode, col, numRows)/1000); - } else if (param.contains("memory_total_kib")) { - hostStats.setTotalMemoryKBs(getDataAverage(dataNode, col, numRows)); - } else if (param.contains("memory_free_kib")) { - hostStats.setFreeMemoryKBs(getDataAverage(dataNode, col, numRows)); - } else if (param.matches("cpu_avg")) { - // hostStats.setNumCpus(hostStats.getNumCpus() + 1); - hostStats.setCpuUtilization(hostStats.getCpuUtilization() + getDataAverage(dataNode, col, numRows)); - } - - /* - if (param.contains("loadavg")) { - hostStats.setAverageLoad((hostStats.getAverageLoad() + getDataAverage(dataNode, col, numRows))); - } - */ - } - } - - // add the host cpu utilization - /* - if (hostStats.getNumCpus() != 0) { - hostStats.setCpuUtilization(hostStats.getCpuUtilization() / hostStats.getNumCpus()); - s_logger.debug("Host cpu utilization " + hostStats.getCpuUtilization()); - } - */ - - return hostStats; - } - - protected GetVmStatsAnswer execute(final GetVmStatsCommand cmd) { - final Connection conn = getConnection(); - final List vmNames = cmd.getVmNames(); - final HashMap vmStatsNameMap = new HashMap(); - if (vmNames.size() == 0) { - return new GetVmStatsAnswer(cmd, vmStatsNameMap); - } - try { - - // Determine the UUIDs of the requested VMs - final List vmUUIDs = new ArrayList(); - - for (final String vmName : vmNames) { - final VM vm = getVM(conn, vmName); - vmUUIDs.add(vm.getUuid(conn)); - } - - final HashMap vmStatsUUIDMap = getVmStats(conn, cmd, vmUUIDs, cmd.getHostGuid()); - if (vmStatsUUIDMap == null) { - return new GetVmStatsAnswer(cmd, vmStatsNameMap); - } - - for (final Map.Entryentry : vmStatsUUIDMap.entrySet()) { - vmStatsNameMap.put(vmNames.get(vmUUIDs.indexOf(entry.getKey())), entry.getValue()); - } - - return new GetVmStatsAnswer(cmd, vmStatsNameMap); - } catch (final XenAPIException e) { - final String msg = "Unable to get VM stats" + e.toString(); - s_logger.warn(msg, e); - return new GetVmStatsAnswer(cmd, vmStatsNameMap); - } catch (final XmlRpcException e) { - final String msg = "Unable to get VM stats" + e.getMessage(); - s_logger.warn(msg, e); - return new GetVmStatsAnswer(cmd, vmStatsNameMap); - } - } - - public HashMap getVmStats(final Connection conn, final GetVmStatsCommand cmd, final List vmUUIDs, final String hostGuid) { - final HashMap vmResponseMap = new HashMap(); - - for (final String vmUUID : vmUUIDs) { - vmResponseMap.put(vmUUID, new VmStatsEntry(0, 0, 0, 0, "vm")); - } - - final Object[] rrdData = getRRDData(conn, 2); // call rrddata with 2 for vm - - if (rrdData == null) { - return null; - } - - final Integer numRows = (Integer)rrdData[0]; - final Integer numColumns = (Integer)rrdData[1]; - final Node legend = (Node)rrdData[2]; - final Node dataNode = (Node)rrdData[3]; - - final NodeList legendChildren = legend.getChildNodes(); - for (int col = 0; col < numColumns; col++) { - - if (legendChildren == null || legendChildren.item(col) == null) { - continue; - } - - final String columnMetadata = getXMLNodeValue(legendChildren.item(col)); - - if (columnMetadata == null) { - continue; - } - - final String[] columnMetadataList = columnMetadata.split(":"); - - if (columnMetadataList.length != 4) { - continue; - } - - final String type = columnMetadataList[1]; - final String uuid = columnMetadataList[2]; - final String param = columnMetadataList[3]; - - if (type.equals("vm") && vmResponseMap.keySet().contains(uuid)) { - final VmStatsEntry vmStatsAnswer = vmResponseMap.get(uuid); - - vmStatsAnswer.setEntityType("vm"); - - if (param.contains("cpu")) { - vmStatsAnswer.setNumCPUs(vmStatsAnswer.getNumCPUs() + 1); - vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() + getDataAverage(dataNode, col, numRows)); - } else if (param.matches("vif_\\d*_rx")) { - vmStatsAnswer.setNetworkReadKBs(vmStatsAnswer.getNetworkReadKBs() + getDataAverage(dataNode, col, numRows)/1000); - } else if (param.matches("vif_\\d*_tx")) { - vmStatsAnswer.setNetworkWriteKBs(vmStatsAnswer.getNetworkWriteKBs() + getDataAverage(dataNode, col, numRows)/1000); - } else if (param.matches("vbd_.*_read")) { - vmStatsAnswer.setDiskReadKBs(vmStatsAnswer.getDiskReadKBs() + getDataAverage(dataNode, col, numRows)/1000); - } else if (param.matches("vbd_.*_write")) { - vmStatsAnswer.setDiskWriteKBs(vmStatsAnswer.getDiskWriteKBs() + getDataAverage(dataNode, col, numRows)/1000); - } - } - } - - for (final Map.Entry entry: vmResponseMap.entrySet()) { - final VmStatsEntry vmStatsAnswer = entry.getValue(); - - if (vmStatsAnswer.getNumCPUs() != 0) { - vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() / vmStatsAnswer.getNumCPUs()); - } - - vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() * 100); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Vm cpu utilization " + vmStatsAnswer.getCPUUtilization()); - } - } - return vmResponseMap; - } - - protected GetVmDiskStatsAnswer execute(final GetVmDiskStatsCommand cmd) { - return new GetVmDiskStatsAnswer(cmd, null, null, null); - } - - - protected Document getStatsRawXML(final Connection conn, final boolean host) { - final Date currentDate = new Date(); - String urlStr = "http://" + _host.getIp() + "/rrd_updates?"; - urlStr += "session_id=" + conn.getSessionReference(); - urlStr += "&host=" + (host ? "true" : "false"); - urlStr += "&cf=" + _consolidationFunction; - urlStr += "&interval=" + _pollingIntervalInSeconds; - urlStr += "&start=" + (currentDate.getTime() / 1000 - 1000 - 100); - - URL url; - BufferedReader in = null; - try { - url = new URL(urlStr); - url.openConnection(); - final URLConnection uc = url.openConnection(); - in = new BufferedReader(new InputStreamReader(uc.getInputStream())); - final InputSource statsSource = new InputSource(in); - return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(statsSource); - } catch (final MalformedURLException e) { - s_logger.warn("Malformed URL? come on...." + urlStr); - return null; - } catch (final IOException e) { - s_logger.warn("Problems getting stats using " + urlStr, e); - return null; - } catch (final SAXException e) { - s_logger.warn("Problems getting stats using " + urlStr, e); - return null; - } catch (final ParserConfigurationException e) { - s_logger.warn("Problems getting stats using " + urlStr, e); - return null; - } finally { - if (in != null) { - try { - in.close(); - } catch (final IOException e) { - s_logger.warn("Unable to close the buffer ", e); - } - } - } - } - - - - protected Object[] getRRDData(final Connection conn, final int flag) { - - /* - * Note: 1 => called from host, hence host stats 2 => called from vm, hence vm stats - */ - Document doc = null; - - try { - doc = getStatsRawXML(conn, flag == 1 ? true : false); - } catch (final Exception e1) { - s_logger.warn("Error whilst collecting raw stats from plugin: ", e1); - return null; - } - - if (doc == null) { //stats are null when the host plugin call fails (host down state) - return null; - } - - final NodeList firstLevelChildren = doc.getChildNodes(); - final NodeList secondLevelChildren = firstLevelChildren.item(0).getChildNodes(); - final Node metaNode = secondLevelChildren.item(0); - final Node dataNode = secondLevelChildren.item(1); - - Integer numRows = 0; - Integer numColumns = 0; - Node legend = null; - final NodeList metaNodeChildren = metaNode.getChildNodes(); - for (int i = 0; i < metaNodeChildren.getLength(); i++) { - final Node n = metaNodeChildren.item(i); - if (n.getNodeName().equals("rows")) { - numRows = Integer.valueOf(getXMLNodeValue(n)); - } else if (n.getNodeName().equals("columns")) { - numColumns = Integer.valueOf(getXMLNodeValue(n)); - } else if (n.getNodeName().equals("legend")) { - legend = n; - } - } - - return new Object[] { numRows, numColumns, legend, dataNode }; - } - - protected String getXMLNodeValue(final Node n) { - return n.getChildNodes().item(0).getNodeValue(); - } - - protected double getDataAverage(final Node dataNode, final int col, final int numRows) { - double value = 0; - final double dummy = 0; - int numRowsUsed = 0; - for (int row = 0; row < numRows; row++) { - final Node data = dataNode.getChildNodes().item(numRows - 1 - row).getChildNodes().item(col + 1); - final Double currentDataAsDouble = Double.valueOf(getXMLNodeValue(data)); - if (!currentDataAsDouble.equals(Double.NaN)) { - numRowsUsed += 1; - value += currentDataAsDouble; - } - } - - if (numRowsUsed == 0) { - if (!Double.isInfinite(value) && !Double.isNaN(value)) { - return value; - } else { - s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows=0"); - return dummy; - } - } else { - if (!Double.isInfinite(value / numRowsUsed) && !Double.isNaN(value / numRowsUsed)) { - return value / numRowsUsed; - } else { - s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows>0"); - return dummy; - } - } - - } - - private static PowerState convertToPowerState(final VmPowerState ps) { - final PowerState powerState = s_powerStatesTable.get(ps); - return powerState == null ? PowerState.PowerUnknown : powerState; - } - - protected HashMap getHostVmStateReport(final Connection conn) { - - // TODO : new VM sync model does not require a cluster-scope report, we need to optimize - // the report accordingly - final HashMap vmStates = new HashMap(); - Map vm_map = null; - for (int i = 0; i < 2; i++) { - try { - vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER - break; - } catch (final Throwable e) { - s_logger.warn("Unable to get vms", e); - } - try { - Thread.sleep(1000); - } catch (final InterruptedException ex) { - - } - } - - if (vm_map == null) { - return vmStates; - } - for (final VM.Record record : vm_map.values()) { - if (record.isControlDomain || record.isASnapshot || record.isATemplate) { - continue; // Skip DOM0 - } - - final VmPowerState ps = record.powerState; - final Host host = record.residentOn; - String host_uuid = null; - if (!isRefNull(host)) { - try { - host_uuid = host.getUuid(conn); - } catch (final BadServerResponse e) { - s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); - } catch (final XenAPIException e) { - s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); - } catch (final XmlRpcException e) { - s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); - } - - if (host_uuid.equalsIgnoreCase(_host.getUuid())) { - vmStates.put( - record.nameLabel, - new HostVmStateReportEntry(convertToPowerState(ps), host_uuid) - ); - } - } - } - - return vmStates; - } - - public PowerState getVmState(final Connection conn, final String vmName) { - int retry = 3; - while (retry-- > 0) { - try { - final Set vms = VM.getByNameLabel(conn, vmName); - for (final VM vm : vms) { - return convertToPowerState(vm.getPowerState(conn)); - } - } catch (final BadServerResponse e) { - // There is a race condition within xenserver such that if a vm is - // deleted and we - // happen to ask for it, it throws this stupid response. So - // if this happens, - // we take a nap and try again which then avoids the race - // condition because - // the vm's information is now cleaned up by xenserver. The error - // is as follows - // com.xensource.xenapi.Types$BadServerResponse - // [HANDLE_INVALID, VM, - // 3dde93f9-c1df-55a7-2cde-55e1dce431ab] - s_logger.info("Unable to get a vm PowerState due to " + e.toString() + ". We are retrying. Count: " + retry); - try { - Thread.sleep(3000); - } catch (final InterruptedException ex) { - - } - } catch (final XenAPIException e) { - final String msg = "Unable to get a vm PowerState due to " + e.toString(); - s_logger.warn(msg, e); - break; - } catch (final XmlRpcException e) { - final String msg = "Unable to get a vm PowerState due to " + e.getMessage(); - s_logger.warn(msg, e); - break; - } - } - - return PowerState.PowerOff; - } - - protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) { - final Connection conn = getConnection(); - final String vmName = cmd.getVmName(); - final PowerState powerState = getVmState(conn, vmName); - final Integer vncPort = null; - if (powerState == PowerState.PowerOn) { - s_logger.debug("3. The VM " + vmName + " is in Running state"); - } - - return new CheckVirtualMachineAnswer(cmd, powerState, vncPort); - } - - protected PrepareForMigrationAnswer execute(final PrepareForMigrationCommand cmd) { - final Connection conn = getConnection(); - - final VirtualMachineTO vm = cmd.getVirtualMachine(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Preparing host for migrating " + vm); - } - - final NicTO[] nics = vm.getNics(); - try { - prepareISO(conn, vm.getName()); - - for (final NicTO nic : nics) { - getNetwork(conn, nic); - } - s_logger.debug("4. The VM " + vm.getName() + " is in Migrating state"); - - return new PrepareForMigrationAnswer(cmd); - } catch (final Exception e) { - s_logger.warn("Catch Exception " + e.getClass().getName() + " prepare for migration failed due to " + e.toString(), e); - return new PrepareForMigrationAnswer(cmd, e); - } - } - - public String upgradeSnapshot(final Connection conn, final String templatePath, final String snapshotPath) { - final String results = callHostPluginAsync(conn, "vmopspremium", "upgrade_snapshot", 2 * 60 * 60, "templatePath", templatePath, "snapshotPath", snapshotPath); - - if (results == null || results.isEmpty()) { - final String msg = "upgrade_snapshot return null"; - s_logger.warn(msg); - throw new CloudRuntimeException(msg); - } - final String[] tmp = results.split("#"); - final String status = tmp[0]; - if (status.equals("0")) { - return results; - } else { - s_logger.warn(results); - throw new CloudRuntimeException(results); - } - } - - String createTemplateFromSnapshot(final Connection conn, final String templatePath, final String snapshotPath, final int wait) { - final String tmpltLocalDir = UUID.randomUUID().toString(); - final String results = - callHostPluginAsync(conn, "vmopspremium", "create_privatetemplate_from_snapshot", wait, "templatePath", templatePath, "snapshotPath", snapshotPath, - "tmpltLocalDir", tmpltLocalDir); - String errMsg = null; - if (results == null || results.isEmpty()) { - errMsg = "create_privatetemplate_from_snapshot return null"; - } else { - final String[] tmp = results.split("#"); - final String status = tmp[0]; - if (status.equals("0")) { - return results; - } else { - errMsg = "create_privatetemplate_from_snapshot failed due to " + tmp[1]; - } - } - final String source = "cloud_mount/" + tmpltLocalDir; - killCopyProcess(conn, source); - s_logger.warn(errMsg); - throw new CloudRuntimeException(errMsg); - } - - boolean killCopyProcess(final Connection conn, final String nameLabel) { - final String results = callHostPluginAsync(conn, "vmops", "kill_copy_process", 60, "namelabel", nameLabel); - String errMsg = null; - if (results == null || results.equals("false")) { - errMsg = "kill_copy_process failed"; - s_logger.warn(errMsg); - return false; - } else { - return true; - } - } - - void destroyVDIbyNameLabel(final Connection conn, final String nameLabel) { - try { - final Set vdis = VDI.getByNameLabel(conn, nameLabel); - if (vdis.size() != 1) { - s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel); - return; - } - for (final VDI vdi : vdis) { - try { - vdi.destroy(conn); - } catch (final Exception e) { - final String msg = "Failed to destroy VDI : " + nameLabel + "due to " + e.toString() + "\n Force deleting VDI using system 'rm' command"; - s_logger.warn(msg); - try { - final String srUUID = vdi.getSR(conn).getUuid(conn); - final String vdiUUID = vdi.getUuid(conn); - final String vdifile = "/var/run/sr-mount/" + srUUID + "/" + vdiUUID + ".vhd"; - final String results = callHostPluginAsync(conn, "vmopspremium", "remove_corrupt_vdi", 10, "vdifile", vdifile); - } catch (final Exception e2) { - s_logger.warn(e2); - } - } - } - } catch (final Exception e) { - } - } - - public String copyVhdFromSecondaryStorage(final Connection conn, final String mountpoint, final String sruuid, final int wait) { - final String nameLabel = "cloud-" + UUID.randomUUID().toString(); - final String results = - callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel); - String errMsg = null; - if (results == null || results.isEmpty()) { - errMsg = "copy_vhd_from_secondarystorage return null"; - } else { - final String[] tmp = results.split("#"); - final String status = tmp[0]; - if (status.equals("0")) { - return tmp[1]; - } else { - errMsg = tmp[1]; - } - } - final String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1); - if (killCopyProcess(conn, source)) { - destroyVDIbyNameLabel(conn, nameLabel); - } - s_logger.warn(errMsg); - throw new CloudRuntimeException(errMsg); - } - - public PrimaryStorageDownloadAnswer execute(final PrimaryStorageDownloadCommand cmd) { - final String tmplturl = cmd.getUrl(); - final String poolName = cmd.getPoolUuid(); - final int wait = cmd.getWait(); - try { - final URI uri = new URI(tmplturl); - final String tmplpath = uri.getHost() + ":" + uri.getPath(); - final Connection conn = getConnection(); - SR poolsr = null; - final Set srs = SR.getByNameLabel(conn, poolName); - if (srs.size() != 1) { - final String msg = "There are " + srs.size() + " SRs with same name: " + poolName; - s_logger.warn(msg); - return new PrimaryStorageDownloadAnswer(msg); - } else { - poolsr = srs.iterator().next(); - } - final String pUuid = poolsr.getUuid(conn); - final boolean isISCSI = IsISCSI(poolsr.getType(conn)); - final String uuid = copyVhdFromSecondaryStorage(conn, tmplpath, pUuid, wait); - final VDI tmpl = getVDIbyUuid(conn, uuid); - final VDI snapshotvdi = tmpl.snapshot(conn, new HashMap()); - final String snapshotUuid = snapshotvdi.getUuid(conn); - snapshotvdi.setNameLabel(conn, "Template " + cmd.getName()); - final String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI); - final VDI parent = getVDIbyUuid(conn, parentuuid); - final Long phySize = parent.getPhysicalUtilisation(conn); - tmpl.destroy(conn); - poolsr.scan(conn); - try { - Thread.sleep(5000); - } catch (final Exception e) { - } - return new PrimaryStorageDownloadAnswer(snapshotvdi.getUuid(conn), phySize); - } catch (final Exception e) { - final String msg = "Catch Exception " + e.getClass().getName() + " on host:" + _host.getUuid() + " for template: " + tmplturl + " due to " + e.toString(); - s_logger.warn(msg, e); - return new PrimaryStorageDownloadAnswer(msg); - } - } - - protected String removeSRSync(final Connection conn, final SR sr) { - if (sr == null) { - return null; - } - if (s_logger.isDebugEnabled()) { - s_logger.debug(logX(sr, "Removing SR")); - } - long waittime = 0; - try { - final Set vdis = sr.getVDIs(conn); - for (final VDI vdi : vdis) { - final Map currentOperation = vdi.getCurrentOperations(conn); - if (currentOperation == null || currentOperation.size() == 0) { - continue; - } - if (waittime >= 1800000) { - final String msg = "This template is being used, try late time"; - s_logger.warn(msg); - return msg; - } - waittime += 30000; - try { - Thread.sleep(30000); - } catch (final InterruptedException ex) { - } - } - removeSR(conn, sr); - return null; - } catch (final XenAPIException e) { - s_logger.warn(logX(sr, "Unable to get current opertions " + e.toString()), e); - } catch (final XmlRpcException e) { - s_logger.warn(logX(sr, "Unable to get current opertions " + e.getMessage()), e); - } - final String msg = "Remove SR failed"; - s_logger.warn(msg); - return msg; - - } - - public void removeSR(final Connection conn, final SR sr) { - if (sr == null) { - return; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug(logX(sr, "Removing SR")); - } - - for (int i = 0; i < 2; i++) { - try { - final Set vdis = sr.getVDIs(conn); - for (final VDI vdi : vdis) { - vdi.forget(conn); - } - - Set pbds = sr.getPBDs(conn); - for (final PBD pbd : pbds) { - if (s_logger.isDebugEnabled()) { - s_logger.debug(logX(pbd, "Unplugging pbd")); - } - - // if (pbd.getCurrentlyAttached(conn)) { - pbd.unplug(conn); - //} - - pbd.destroy(conn); - } - - pbds = sr.getPBDs(conn); - - if (pbds.size() == 0) { - if (s_logger.isDebugEnabled()) { - s_logger.debug(logX(sr, "Forgetting")); - } - - sr.forget(conn); - - return; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug(logX(sr, "There is still one or more PBDs attached.")); - - if (s_logger.isTraceEnabled()) { - for (final PBD pbd : pbds) { - s_logger.trace(logX(pbd, " Still attached")); - } - } - } - } catch (final XenAPIException e) { - s_logger.debug(logX(sr, "Catch XenAPIException: " + e.toString())); - } catch (final XmlRpcException e) { - s_logger.debug(logX(sr, "Catch Exception: " + e.getMessage())); - } - } - - s_logger.warn(logX(sr, "Unable to remove SR")); - } - - protected MigrateAnswer execute(final MigrateCommand cmd) { - final Connection conn = getConnection(); - final String vmName = cmd.getVmName(); - - try { - final Set vms = VM.getByNameLabel(conn, vmName); - - final String ipaddr = cmd.getDestinationIp(); - - final Set hosts = Host.getAll(conn); - Host dsthost = null; - if(hosts != null) { - for (final Host host : hosts) { - if (host.getAddress(conn).equals(ipaddr)) { - dsthost = host; - break; - } - } - } - if (dsthost == null) { - final String msg = "Migration failed due to unable to find host " + ipaddr + " in XenServer pool " + _host.getPool(); - s_logger.warn(msg); - return new MigrateAnswer(cmd, false, msg, null); - } - for (final VM vm : vms) { - final Set vbds = vm.getVBDs(conn); - for (final VBD vbd : vbds) { - final VBD.Record vbdRec = vbd.getRecord(conn); - if (vbdRec.type.equals(Types.VbdType.CD) && !vbdRec.empty) { - vbd.eject(conn); - break; - } - } - migrateVM(conn, dsthost, vm, vmName); - vm.setAffinity(conn, dsthost); - } - return new MigrateAnswer(cmd, true, "migration succeeded", null); - } catch (final Exception e) { - s_logger.warn(e.getMessage(), e); - return new MigrateAnswer(cmd, false, e.getMessage(), null); - } - - } - - protected Pair getControlDomain(final Connection conn) throws XenAPIException, XmlRpcException { - final Host host = Host.getByUuid(conn, _host.getUuid()); - Set vms = null; - vms = host.getResidentVMs(conn); - for (final VM vm : vms) { - if (vm.getIsControlDomain(conn)) { - return new Pair(vm, vm.getRecord(conn)); - } - } - - throw new CloudRuntimeException("Com'on no control domain? What the crap?!#@!##$@"); - } - - public void umountSnapshotDir(final Connection conn, final Long dcId) { - try { - callHostPlugin(conn, "vmopsSnapshot", "unmountSnapshotsDir", "dcId", dcId.toString()); - } catch (final Exception e) { - s_logger.debug("Failed to umount snapshot dir",e); - } - } - - protected ReadyAnswer execute(final ReadyCommand cmd) { - final Connection conn = getConnection(); - final Long dcId = cmd.getDataCenterId(); - // Ignore the result of the callHostPlugin. Even if unmounting the - // snapshots dir fails, let Ready command - // succeed. - umountSnapshotDir(conn, dcId); - - setupLinkLocalNetwork(conn); - // try to destroy CD-ROM device for all system VMs on this host - try { - final Host host = Host.getByUuid(conn, _host.getUuid()); - final Set vms = host.getResidentVMs(conn); - for (final VM vm : vms) { - destroyPatchVbd(conn, vm.getNameLabel(conn)); - } - } catch (final Exception e) { - } - try { - final boolean result = cleanupHaltedVms(conn); - if (!result) { - return new ReadyAnswer(cmd, "Unable to cleanup halted vms"); - } - } catch (final XenAPIException e) { - s_logger.warn("Unable to cleanup halted vms", e); - return new ReadyAnswer(cmd, "Unable to cleanup halted vms"); - } catch (final XmlRpcException e) { - s_logger.warn("Unable to cleanup halted vms", e); - return new ReadyAnswer(cmd, "Unable to cleanup halted vms"); - } - - return new ReadyAnswer(cmd); - } - - public String getVncUrl(final Connection conn, final VM vm) { - VM.Record record; - Console c; - try { - record = vm.getRecord(conn); - final Set consoles = record.consoles; - - if (consoles.isEmpty()) { - s_logger.warn("There are no Consoles available to the vm : " + record.nameDescription); - return null; - } - final Iterator i = consoles.iterator(); - while (i.hasNext()) { - c = i.next(); - if (c.getProtocol(conn) == Types.ConsoleProtocol.RFB) { - return c.getLocation(conn); - } - } - } catch (final XenAPIException e) { - final String msg = "Unable to get console url due to " + e.toString(); - s_logger.warn(msg, e); - return null; - } catch (final XmlRpcException e) { - final String msg = "Unable to get console url due to " + e.getMessage(); - s_logger.warn(msg, e); - return null; - } - return null; - } - - @Override - public RebootAnswer execute(final RebootCommand cmd) { - final Connection conn = getConnection(); - s_logger.debug("7. The VM " + cmd.getVmName() + " is in Starting state"); - try { - Set vms = null; - try { - vms = VM.getByNameLabel(conn, cmd.getVmName()); - } catch (final XenAPIException e0) { - s_logger.debug("getByNameLabel failed " + e0.toString()); - return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString(), false); - } catch (final Exception e0) { - s_logger.debug("getByNameLabel failed " + e0.getMessage()); - return new RebootAnswer(cmd, "getByNameLabel failed", false); - } - for (final VM vm : vms) { - try { - rebootVM(conn, vm, vm.getNameLabel(conn)); - } catch (final Exception e) { - final String msg = e.toString(); - s_logger.warn(msg, e); - return new RebootAnswer(cmd, msg, false); - } - } - return new RebootAnswer(cmd, "reboot succeeded", true); - } finally { - s_logger.debug("8. The VM " + cmd.getVmName() + " is in Running state"); - } - } - - public Answer execute(final RebootRouterCommand cmd) { - final Connection conn = getConnection(); - final RebootAnswer answer = execute((RebootCommand)cmd); - if (answer.getResult()) { - final String cnct = connect(conn, cmd.getVmName(), cmd.getPrivateIpAddress()); - networkUsage(conn, cmd.getPrivateIpAddress(), "create", null); - if (cnct == null) { - return answer; - } else { - return new Answer(cmd, false, cnct); - } - } - return answer; - } - - protected void startvmfailhandle(final Connection conn, final VM vm, final List> mounts) { - if (vm != null) { - try { - - if (vm.getPowerState(conn) == VmPowerState.RUNNING) { - try { - vm.hardShutdown(conn); - } catch (final Exception e) { - final String msg = "VM hardshutdown failed due to " + e.toString(); - s_logger.warn(msg, e); - } - } - if (vm.getPowerState(conn) == VmPowerState.HALTED) { - try { - vm.destroy(conn); - } catch (final Exception e) { - final String msg = "VM destroy failed due to " + e.toString(); - s_logger.warn(msg, e); - } - } - } catch (final Exception e) { - final String msg = "VM getPowerState failed due to " + e.toString(); - s_logger.warn(msg, e); - } - } - if (mounts != null) { - for (final Ternary mount : mounts) { - final VDI vdi = mount.second(); - Set vbds = null; - try { - vbds = vdi.getVBDs(conn); - } catch (final Exception e) { - final String msg = "VDI getVBDS failed due to " + e.toString(); - s_logger.warn(msg, e); - continue; - } - for (final VBD vbd : vbds) { - try { - vbd.unplug(conn); - vbd.destroy(conn); - } catch (final Exception e) { - final String msg = "VBD destroy failed due to " + e.toString(); - s_logger.warn(msg, e); - } - } - } - } - } - - /** - * WARN: static-min <= dynamic-min <= dynamic-max <= static-max - * @see XcpServerResource#setMemory(com.xensource.xenapi.Connection, com.xensource.xenapi.VM, long, long) - * @param conn - * @param vm - * @param minMemsize - * @param maxMemsize - * @throws XmlRpcException - * @throws XenAPIException - */ - protected void setMemory(final Connection conn, final VM vm, final long minMemsize, final long maxMemsize) throws XmlRpcException, XenAPIException { - vm.setMemoryLimits(conn, mem_128m, maxMemsize, minMemsize, maxMemsize); - } - - /** - * When Dynamic Memory Control (DMC) is enabled - - * xenserver allows scaling the guest memory while the guest is running - * - * By default this is disallowed, override the specific xenserver resource - * if this is enabled - */ - public boolean isDmcEnabled(final Connection conn, final Host host) throws XenAPIException, XmlRpcException { - return false; - } - - public void waitForTask(final Connection c, final Task task, final long pollInterval, final long timeout) throws XenAPIException, XmlRpcException, TimeoutException { - final long beginTime = System.currentTimeMillis(); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") sent to " + c.getSessionReference() + " is pending completion with a " + timeout + - "ms timeout"); - } - while (task.getStatus(c) == Types.TaskStatusType.PENDING) { - try { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") is pending, sleeping for " + pollInterval + "ms"); - } - Thread.sleep(pollInterval); - } catch (final InterruptedException e) { - } - if (System.currentTimeMillis() - beginTime > timeout) { - final String msg = "Async " + timeout / 1000 + " seconds timeout for task " + task.toString(); - s_logger.warn(msg); - task.cancel(c); - task.destroy(c); - throw new TimeoutException(msg); - } - } - } - - public void checkForSuccess(final Connection c, final Task task) throws XenAPIException, XmlRpcException { - if (task.getStatus(c) == Types.TaskStatusType.SUCCESS) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") completed"); - } - return; - } else { - final String msg = "Task failed! Task record: " + task.getRecord(c); - s_logger.warn(msg); - task.cancel(c); - task.destroy(c); - throw new Types.BadAsyncResult(msg); - } - } - - public void rebootVM(final Connection conn, final VM vm, final String vmName) throws Exception { - Task task = null; - try { - task = vm.cleanRebootAsync(conn); - try { - //poll every 1 seconds , timeout after 10 minutes - waitForTask(conn, task, 1000, 10 * 60 * 1000); - checkForSuccess(conn, task); - } catch (final Types.HandleInvalid e) { - if (vm.getPowerState(conn) == VmPowerState.RUNNING) { - task = null; - return; - } - throw new CloudRuntimeException("Reboot VM catch HandleInvalid and VM is not in RUNNING state"); - } - } catch (final XenAPIException e) { - s_logger.debug("Unable to Clean Reboot VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString() + ", try hard reboot"); - try { - vm.hardReboot(conn); - } catch (final Exception e1) { - final String msg = "Unable to hard Reboot VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); - s_logger.warn(msg, e1); - throw new CloudRuntimeException(msg); - } - } finally { - if (task != null) { - try { - task.destroy(conn); - } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); - } - } - } - } - - void forceShutdownVM(final Connection conn, final VM vm) { - try { - final Long domId = vm.getDomid(conn); - callHostPlugin(conn, "vmopspremium", "forceShutdownVM", "domId", domId.toString()); - vm.powerStateReset(conn); - vm.destroy(conn); - } catch (final Exception e) { - final String msg = "forceShutdown failed due to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg); - } - } - - public void shutdownVM(final Connection conn, final VM vm, final String vmName) throws XmlRpcException { - Task task = null; - try { - task = vm.cleanShutdownAsync(conn); - try { - //poll every 1 seconds , timeout after 10 minutes - waitForTask(conn, task, 1000, 10 * 60 * 1000); - checkForSuccess(conn, task); - } catch (final TimeoutException e) { - if (vm.getPowerState(conn) == VmPowerState.HALTED) { - task = null; - return; - } - throw new CloudRuntimeException("Shutdown VM catch HandleInvalid and VM is not in HALTED state"); - } - } catch (final XenAPIException e) { - s_logger.debug("Unable to cleanShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString()); - try { - VmPowerState state = vm.getPowerState(conn); - if (state == VmPowerState.RUNNING) { - try { - vm.hardShutdown(conn); - } catch (final Exception e1) { - s_logger.debug("Unable to hardShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString()); - state = vm.getPowerState(conn); - if (state == VmPowerState.RUNNING) { - forceShutdownVM(conn, vm); - } - return; - } - } else if (state == VmPowerState.HALTED) { - return; - } else { - final String msg = "After cleanShutdown the VM status is " + state.toString() + ", that is not expected"; - s_logger.warn(msg); - throw new CloudRuntimeException(msg); - } - } catch (final Exception e1) { - final String msg = "Unable to hardShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); - s_logger.warn(msg, e1); - throw new CloudRuntimeException(msg); - } - } finally { - if (task != null) { - try { - task.destroy(conn); - } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); - } - } - } - } - - public void startVM(final Connection conn, final Host host, final VM vm, final String vmName) throws Exception { - Task task = null; - try { - task = vm.startOnAsync(conn, host, false, true); - try { - //poll every 1 seconds , timeout after 10 minutes - waitForTask(conn, task, 1000, 10 * 60 * 1000); - checkForSuccess(conn, task); - } catch (final Types.HandleInvalid e) { - if (vm.getPowerState(conn) == VmPowerState.RUNNING) { - s_logger.debug("VM " + vmName + " is in Running status"); - task = null; - return; - } - throw new CloudRuntimeException("Start VM " + vmName + " catch HandleInvalid and VM is not in RUNNING state"); - } catch (final TimeoutException e) { - if (vm.getPowerState(conn) == VmPowerState.RUNNING) { - s_logger.debug("VM " + vmName + " is in Running status"); - task = null; - return; - } - throw new CloudRuntimeException("Start VM " + vmName + " catch BadAsyncResult and VM is not in RUNNING state"); - } - } catch (final XenAPIException e) { - final String msg = "Unable to start VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg); - } finally { - if (task != null) { - try { - task.destroy(conn); - } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); - } - } - } - } - - public void migrateVM(final Connection conn, final Host destHost, final VM vm, final String vmName) throws Exception { - Task task = null; - try { - final Map other = new HashMap(); - other.put("live", "true"); - task = vm.poolMigrateAsync(conn, destHost, other); - try { - // poll every 1 seconds - final long timeout = _migratewait * 1000L; - waitForTask(conn, task, 1000, timeout); - checkForSuccess(conn, task); - } catch (final Types.HandleInvalid e) { - if (vm.getResidentOn(conn).equals(destHost)) { - task = null; - return; - } - throw new CloudRuntimeException("migrate VM catch HandleInvalid and VM is not running on dest host"); - } - } catch (final XenAPIException e) { - final String msg = "Unable to migrate VM(" + vmName + ") from host(" + _host.getUuid() + ")"; - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg); - } finally { - if (task != null) { - try { - task.destroy(conn); - } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); - } - } - } - } - - protected VDI cloudVDIcopy(final Connection conn, final VDI vdi, final SR sr, int wait) throws Exception { - Task task = null; - if (wait == 0) { - wait = 2 * 60 * 60; - } - try { - task = vdi.copyAsync(conn, sr); - // poll every 1 seconds , timeout after 2 hours - waitForTask(conn, task, 1000, (long)wait * 1000); - checkForSuccess(conn, task); - final VDI dvdi = Types.toVDI(task, conn); - return dvdi; - } finally { - if (task != null) { - try { - task.destroy(conn); - } catch (final Exception e) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e.toString()); - } - } - } - } - - protected String callHostPluginAsync(final Connection conn, final String plugin, final String cmd, final int wait, final String... params) { - final int timeout = wait * 1000; - final Map args = new HashMap(); - Task task = null; - try { - for (int i = 0; i < params.length; i += 2) { - args.put(params[i], params[i + 1]); - } - if (s_logger.isTraceEnabled()) { - s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); - } - final Host host = Host.getByUuid(conn, _host.getUuid()); - task = host.callPluginAsync(conn, plugin, cmd, args); - // poll every 1 seconds - waitForTask(conn, task, 1000, timeout); - checkForSuccess(conn, task); - final String result = task.getResult(conn); - if (s_logger.isTraceEnabled()) { - s_logger.trace("callHostPlugin Result: " + result); - } - return result.replace("", "").replace("", "").replace("\n", ""); - } catch (final Types.HandleInvalid e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + - e.handle); - } catch (final XenAPIException e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); - } catch (final Exception e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(), e); - } finally { - if (task != null) { - try { - task.destroy(conn); - } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); - } - } - } - return null; - } - @Override public StopAnswer execute(final StopCommand cmd) { final String vmName = cmd.getVmName(); @@ -3511,1870 +1949,44 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new StopAnswer(cmd, "Stop VM failed", platformstring, false); } - private List getVdis(final Connection conn, final VM vm) { - final List vdis = new ArrayList(); - try { - final Set vbds = vm.getVBDs(conn); - for (final VBD vbd : vbds) { - vdis.add(vbd.getVDI(conn)); - } - } catch (final XenAPIException e) { - final String msg = "getVdis can not get VPD due to " + e.toString(); - s_logger.warn(msg, e); - } catch (final XmlRpcException e) { - final String msg = "getVdis can not get VPD due to " + e.getMessage(); - s_logger.warn(msg, e); - } - return vdis; - } - - public String connect(final Connection conn, final String vmName, final String ipAddress, final int port) { - for (int i = 0; i <= _retry; i++) { - try { - final Set vms = VM.getByNameLabel(conn, vmName); - if (vms.size() < 1) { - final String msg = "VM " + vmName + " is not running"; - s_logger.warn(msg); - return msg; - } - } catch (final Exception e) { - final String msg = "VM.getByNameLabel " + vmName + " failed due to " + e.toString(); - s_logger.warn(msg, e); - return msg; - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Trying to connect to " + ipAddress + " attempt " + i + " of " + _retry); - } - if (pingdomr(conn, ipAddress, Integer.toString(port))) { - return null; - } - try { - Thread.sleep(_sleep); - } catch (final InterruptedException e) { - } - } - final String msg = "Timeout, Unable to logon to " + ipAddress; - s_logger.debug(msg); - - return msg; - } - - public String connect(final Connection conn, final String vmname, final String ipAddress) { - return connect(conn, vmname, ipAddress, 3922); - } - - public boolean isDeviceUsed(final Connection conn, final VM vm, final Long deviceId) { - // Figure out the disk number to attach the VM to - - String msg = null; - try { - final Set allowedVBDDevices = vm.getAllowedVBDDevices(conn); - if (allowedVBDDevices.contains(deviceId.toString())) { - return false; - } - return true; - } catch (final XmlRpcException e) { - msg = "Catch XmlRpcException due to: " + e.getMessage(); - s_logger.warn(msg, e); - } catch (final XenAPIException e) { - msg = "Catch XenAPIException due to: " + e.toString(); - s_logger.warn(msg, e); - } - throw new CloudRuntimeException("When check deviceId " + msg); - } - - public String getUnusedDeviceNum(final Connection conn, final VM vm) { - // Figure out the disk number to attach the VM to - try { - final Set allowedVBDDevices = vm.getAllowedVBDDevices(conn); - if (allowedVBDDevices.size() == 0) { - throw new CloudRuntimeException("Could not find an available slot in VM with name: " + vm.getNameLabel(conn) + " to attach a new disk."); - } - return allowedVBDDevices.iterator().next(); - } catch (final XmlRpcException e) { - final String msg = "Catch XmlRpcException due to: " + e.getMessage(); - s_logger.warn(msg, e); - } catch (final XenAPIException e) { - final String msg = "Catch XenAPIException due to: " + e.toString(); - s_logger.warn(msg, e); - } - throw new CloudRuntimeException("Could not find an available slot in VM with name to attach a new disk."); - } - - public String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) { - final Map args = new HashMap(); - String msg; - try { - for (int i = 0; i < params.length; i += 2) { - args.put(params[i], params[i + 1]); - } - - if (s_logger.isTraceEnabled()) { - s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); - } - final Host host = Host.getByUuid(conn, _host.getUuid()); - final String result = host.callPlugin(conn, plugin, cmd, args); - if (s_logger.isTraceEnabled()) { - s_logger.trace("callHostPlugin Result: " + result); - } - return result.replace("\n", ""); - } catch (final XenAPIException e) { - msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(); - s_logger.warn(msg); - } catch (final XmlRpcException e) { - msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(); - s_logger.debug(msg); - } - throw new CloudRuntimeException(msg); - } - - protected String getArgsString(final Map args) { - final StringBuilder argString = new StringBuilder(); - for (final Map.Entry arg : args.entrySet()) { - argString.append(arg.getKey() + ": " + arg.getValue() + ", "); - } - return argString.toString(); - } - - public boolean setIptables(final Connection conn) { - final String result = callHostPlugin(conn, "vmops", "setIptables"); - if (result == null || result.isEmpty()) { - return false; - } - return true; - } - - protected XsLocalNetwork getManagementNetwork(final Connection conn) throws XmlRpcException, XenAPIException { - PIF mgmtPif = null; - PIF.Record mgmtPifRec = null; - final Host host = Host.getByUuid(conn, _host.getUuid()); - final Set hostPifs = host.getPIFs(conn); - for (final PIF pif : hostPifs) { - final PIF.Record rec = pif.getRecord(conn); - if (rec.management) { - if (rec.VLAN != null && rec.VLAN != -1) { - final String msg = - new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.getUuid()) - .append("; pif=") - .append(rec.uuid) - .append("; vlan=") - .append(rec.VLAN) - .toString(); - s_logger.warn(msg); - throw new CloudRuntimeException(msg); - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Management network is on pif=" + rec.uuid); - } - mgmtPif = pif; - mgmtPifRec = rec; - break; - } - } - if (mgmtPif == null) { - final String msg = "Unable to find management network for " + _host.getUuid(); - s_logger.warn(msg); - throw new CloudRuntimeException(msg); - } - final Bond bond = mgmtPifRec.bondSlaveOf; - if (!isRefNull(bond)) { - final String msg = - "Management interface is on slave(" + mgmtPifRec.uuid + ") of bond(" + bond.getUuid(conn) + ") on host(" + _host.getUuid() + - "), please move management interface to bond!"; - s_logger.warn(msg); - throw new CloudRuntimeException(msg); - } - final Network nk = mgmtPifRec.network; - final Network.Record nkRec = nk.getRecord(conn); - return new XsLocalNetwork(this, nk, nkRec, mgmtPif, mgmtPifRec); - } - - protected VIF getCorrectVif(final Connection conn, final VM router, final Network network) throws XmlRpcException, XenAPIException { - final Set routerVIFs = router.getVIFs(conn); - for (final VIF vif : routerVIFs) { - final Network vifNetwork = vif.getNetwork(conn); - if (vifNetwork.getUuid(conn).equals(network.getUuid(conn))) { - return vif; - } - } - - return null; - } - - protected VIF getCorrectVif(final Connection conn, final VM router, final IpAddressTO ip) throws XmlRpcException, XenAPIException { - final NicTO nic = new NicTO(); - nic.setType(ip.getTrafficType()); - nic.setName(ip.getNetworkName()); - if (ip.getBroadcastUri() == null) { - nic.setBroadcastType(BroadcastDomainType.Native); - } else { - final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); - nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); - nic.setBroadcastUri(uri); - } - final Network network = getNetwork(conn, nic); - // Determine the correct VIF on DomR to associate/disassociate the - // IP address with - final Set routerVIFs = router.getVIFs(conn); - for (final VIF vif : routerVIFs) { - final Network vifNetwork = vif.getNetwork(conn); - if (vifNetwork.getUuid(conn).equals(network.getUuid(conn))) { - return vif; - } - } - return null; - } - - public VIF getVifByMac(final Connection conn, final VM router, String mac) throws XmlRpcException, XenAPIException { - final Set routerVIFs = router.getVIFs(conn); - mac = mac.trim(); - for (final VIF vif : routerVIFs) { - final String lmac = vif.getMAC(conn); - if (lmac.trim().equals(mac)) { - return vif; - } - } - return null; - } - - public String getLowestAvailableVIFDeviceNum(final Connection conn, final VM vm) { - String vmName = ""; - try { - vmName = vm.getNameLabel(conn); - final List usedDeviceNums = new ArrayList(); - final Set vifs = vm.getVIFs(conn); - final Iterator vifIter = vifs.iterator(); - while (vifIter.hasNext()) { - final VIF vif = vifIter.next(); - try { - final String deviceId = vif.getDevice(conn); - if(vm.getIsControlDomain(conn) || vif.getCurrentlyAttached(conn)) { - usedDeviceNums.add(Integer.valueOf(deviceId)); - } else { - s_logger.debug("Found unplugged VIF " + deviceId + " in VM " + vmName + " destroy it"); - vif.destroy(conn); - } - } catch (final NumberFormatException e) { - final String msg = "Obtained an invalid value for an allocated VIF device number for VM: " + vmName; - s_logger.debug(msg, e); - throw new CloudRuntimeException(msg); - } - } - - for (Integer i = 0; i < _maxNics; i++) { - if (!usedDeviceNums.contains(i)) { - s_logger.debug("Lowest available Vif device number: " + i + " for VM: " + vmName); - return i.toString(); - } - } - } catch (final XmlRpcException e) { - final String msg = "Caught XmlRpcException: " + e.getMessage(); - s_logger.warn(msg, e); - } catch (final XenAPIException e) { - final String msg = "Caught XenAPIException: " + e.toString(); - s_logger.warn(msg, e); - } - - throw new CloudRuntimeException("Could not find available VIF slot in VM with name: " + vmName); - } - - protected VDI mount(final Connection conn, final StoragePoolType poolType, final String volumeFolder, final String volumePath) { - return getVDIbyUuid(conn, volumePath); - } - - /** - * getNetworkByName() retrieves what the server thinks is the actual - * network used by the XenServer host. This method should always be - * used to talk to retrieve a network by the name. The reason is - * because of the problems in using the name label as the way to find - * the Network. - * - * To see how we are working around these problems, take a look at - * enableVlanNetwork(). The following description assumes you have looked - * at the description on that method. - * - * In order to understand this, we have to see what type of networks are - * within a XenServer that's under CloudStack control. - * - * - Native Networks: these are networks that are untagged on the - * XenServer and are used to crate VLAN networks on. These are - * created by the user and is assumed to be one per cluster. - * - VLAN Networks: these are dynamically created by CloudStack and can - * have problems with duplicated names. - * - LinkLocal Networks: these are dynamically created by CloudStack and - * can also have problems with duplicated names but these don't have - * actual PIFs. - * - * In order to speed to retrieval of a network, we do the following: - * - We retrieve by the name. If only one network is retrieved, we - * assume we retrieved the right network. - * - If more than one network is retrieved, we check to see which one - * has the pif for the local host and use that. - * - If a pif is not found, then we look at the tags and find the - * one with the lowest timestamp. (See enableVlanNetwork()) - * - * @param conn Xapi connection - * @param name name of the network - * @return XsNic an object that contains network, network record, pif, and pif record. - * @throws XenAPIException - * @throws XmlRpcException - * - * @see CitrixResourceBase#enableVlanNetwork - */ - public XsLocalNetwork getNetworkByName(final Connection conn, final String name) throws XenAPIException, XmlRpcException { - final Set networks = Network.getByNameLabel(conn, name); - if (networks.size() == 1) { - return new XsLocalNetwork(this, networks.iterator().next(), null, null, null); - } - - if (networks.size() == 0) { - return null; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found more than one network with the name " + name); - } - Network earliestNetwork = null; - Network.Record earliestNetworkRecord = null; - long earliestTimestamp = Long.MAX_VALUE; - int earliestRandom = Integer.MAX_VALUE; - for (final Network network : networks) { - final XsLocalNetwork nic = new XsLocalNetwork(this, network); - - if (nic.getPif(conn) != null) { - return nic; - } - - final Network.Record record = network.getRecord(conn); - if (record.tags != null) { - for (final String tag : record.tags) { - final Pair stamp = parseTimestamp(tag); - if (stamp == null) { - continue; - } - - if (stamp.first() < earliestTimestamp || stamp.first() == earliestTimestamp && stamp.second() < earliestRandom) { - earliestTimestamp = stamp.first(); - earliestRandom = stamp.second(); - earliestNetwork = network; - earliestNetworkRecord = record; - } - } - } - } - - return earliestNetwork != null ? new XsLocalNetwork(this, earliestNetwork, earliestNetworkRecord, null, null) : null; - } - - protected String generateTimeStamp() { - return new StringBuilder("CsCreateTime-").append(System.currentTimeMillis()).append("-").append(Rand.nextInt(Integer.MAX_VALUE)).toString(); - } - - protected Pair parseTimestamp(final String timeStampStr) { - final String[] tokens = timeStampStr.split("-"); - if (tokens.length != 3) { - s_logger.debug("timeStamp in network has wrong pattern: " + timeStampStr); - return null; - } - if (!tokens[0].equals("CsCreateTime")) { - s_logger.debug("timeStamp in network doesn't start with CsCreateTime: " + timeStampStr); - return null; - } - return new Pair(Long.parseLong(tokens[1]), Integer.parseInt(tokens[2])); - } - - /** - * enableVlanNetwork creates a Network object, Vlan object, and thereby - * a tagged PIF object in Xapi. - * - * In XenServer, VLAN is added by - * - Create a network, which is unique cluster wide. - * - Find the PIF that you want to create the VLAN on. - * - Create a VLAN using the network and the PIF. As a result of this - * operation, a tagged PIF object is also created. - * - * Here is a list of problems with clustered Xapi implementation that - * we are trying to circumvent. - * - There can be multiple Networks with the same name-label so searching - * using name-label is not unique. - * - There are no other ways to search for Networks other than listing - * all of them which is not efficient in our implementation because - * we can have over 4000 VLAN networks. - * - In a clustered situation, it's possible for both hosts to detect - * that the Network is missing and both creates it. This causes a - * lot of problems as one host may be using one Network and another - * may be using a different network for their VMs. This causes - * problems in migration because the VMs are logically attached - * to different networks in Xapi's database but in reality, they - * are attached to the same network. - * - * To work around these problems, we do the following. - * - * - When creating the VLAN network, we name it as VLAN-UUID of the - * Network it is created on-VLAN Tag. Because VLAN tags is unique with - * one particular network, this is a unique name-label to quickly - * retrieve the the VLAN network with when we need it again. - * - When we create the VLAN network, we add a timestamp and a random - * number as a tag into the network. Then instead of creating - * VLAN on that network, we actually retrieve the Network again - * and this time uses the VLAN network with lowest timestamp or - * lowest random number as the VLAN network. This allows VLAN creation - * to happen on multiple hosts concurrently but even if two VLAN - * networks were created with the same name, only one of them is used. - * - * One cavaet about this approach is that it relies on the timestamp to - * be relatively accurate among different hosts. - * - * @param conn Xapi Connection - * @param tag VLAN tag - * @param network network on this host to create the VLAN on. - * @return VLAN Network created. - * @throws XenAPIException - * @throws XmlRpcException - */ - protected Network enableVlanNetwork(final Connection conn, final long tag, final XsLocalNetwork network) throws XenAPIException, XmlRpcException { - Network vlanNetwork = null; - final String oldName = "VLAN" + Long.toString(tag); - final String newName = "VLAN-" + network.getNetworkRecord(conn).uuid + "-" + tag; - XsLocalNetwork vlanNic = getNetworkByName(conn, newName); - if (vlanNic == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Couldn't find vlan network with the new name so trying old name: " + oldName); - } - vlanNic = getNetworkByName(conn, oldName); - if (vlanNic != null) { - s_logger.info("Renaming VLAN with old name " + oldName + " to " + newName); - vlanNic.getNetwork().setNameLabel(conn, newName); - } - } - if (vlanNic == null) { // Can't find it, then create it. - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.getIp()); - } - final Network.Record nwr = new Network.Record(); - nwr.nameLabel = newName; - nwr.tags = new HashSet(); - nwr.tags.add(generateTimeStamp()); - vlanNetwork = Network.create(conn, nwr); - vlanNic = getNetworkByName(conn, newName); - if(vlanNic == null) { //Still vlanNic is null means we could not create it for some reason and no exception capture happened. - throw new CloudRuntimeException("Could not find/create vlan network with name: " + newName); - } - } - - final PIF nPif = network.getPif(conn); - final PIF.Record nPifr = network.getPifRecord(conn); - - vlanNetwork = vlanNic.getNetwork(); - if (vlanNic.getPif(conn) != null) { - return vlanNetwork; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating VLAN " + tag + " on host " + _host.getIp() + " on device " + nPifr.device); - } - final VLAN vlan = VLAN.create(conn, nPif, tag, vlanNetwork); - if (vlan != null) { - final VLAN.Record vlanr = vlan.getRecord(conn); - if (vlanr != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("VLAN is created for " + tag + ". The uuid is " + vlanr.uuid); - } - } - } - return vlanNetwork; - } - - public void disableVlanNetwork(final Connection conn, final Network network) { - } - - protected SR getLocalLVMSR(final Connection conn) { - try { - final Map map = SR.getAllRecords(conn); - if(map != null && !map.isEmpty()) { - for (final Map.Entry entry : map.entrySet()) { - final SR.Record srRec = entry.getValue(); - if (SRType.LVM.equals(srRec.type)) { - final Set pbds = srRec.PBDs; - if (pbds == null) { - continue; - } - for (final PBD pbd : pbds) { - final Host host = pbd.getHost(conn); - if (!isRefNull(host) && host.getUuid(conn).equals(_host.getUuid())) { - if (!pbd.getCurrentlyAttached(conn)) { - pbd.plug(conn); - } - final SR sr = entry.getKey(); - sr.scan(conn); - return sr; - } - } - } - } - } - } catch (final XenAPIException e) { - final String msg = "Unable to get local LVMSR in host:" + _host.getUuid() + e.toString(); - s_logger.warn(msg); - } catch (final XmlRpcException e) { - final String msg = "Unable to get local LVMSR in host:" + _host.getUuid() + e.getCause(); - s_logger.warn(msg); - } - return null; - } - - protected SR getLocalEXTSR(final Connection conn) { - try { - final Map map = SR.getAllRecords(conn); - if(map != null && !map.isEmpty()) { - for (final Map.Entry entry : map.entrySet()) { - final SR.Record srRec = entry.getValue(); - if (SRType.FILE.equals(srRec.type) || SRType.EXT.equals(srRec.type)) { - final Set pbds = srRec.PBDs; - if (pbds == null) { - continue; - } - for (final PBD pbd : pbds) { - final Host host = pbd.getHost(conn); - if (!isRefNull(host) && host.getUuid(conn).equals(_host.getUuid())) { - if (!pbd.getCurrentlyAttached(conn)) { - pbd.plug(conn); - } - final SR sr = entry.getKey(); - sr.scan(conn); - return sr; - } - } - } - } - } - } catch (final XenAPIException e) { - final String msg = "Unable to get local EXTSR in host:" + _host.getUuid() + e.toString(); - s_logger.warn(msg); - } catch (final XmlRpcException e) { - final String msg = "Unable to get local EXTSR in host:" + _host.getUuid() + e.getCause(); - s_logger.warn(msg); - } - return null; - } - - protected StartupStorageCommand initializeLocalSR(final Connection conn) { - final SR lvmsr = getLocalLVMSR(conn); - if (lvmsr != null) { - try { - _host.setLocalSRuuid(lvmsr.getUuid(conn)); - - final String lvmuuid = lvmsr.getUuid(conn); - final long cap = lvmsr.getPhysicalSize(conn); - if (cap > 0) { - final long avail = cap - lvmsr.getPhysicalUtilisation(conn); - lvmsr.setNameLabel(conn, lvmuuid); - final String name = "Cloud Stack Local LVM Storage Pool for " + _host.getUuid(); - lvmsr.setNameDescription(conn, name); - final Host host = Host.getByUuid(conn, _host.getUuid()); - final String address = host.getAddress(conn); - final StoragePoolInfo pInfo = new StoragePoolInfo(lvmuuid, address, SRType.LVM.toString(), SRType.LVM.toString(), StoragePoolType.LVM, cap, avail); - final StartupStorageCommand cmd = new StartupStorageCommand(); - cmd.setPoolInfo(pInfo); - cmd.setGuid(_host.getUuid()); - cmd.setDataCenter(Long.toString(_dcId)); - cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); - return cmd; - } - } catch (final XenAPIException e) { - final String msg = "build local LVM info err in host:" + _host.getUuid() + e.toString(); - s_logger.warn(msg); - } catch (final XmlRpcException e) { - final String msg = "build local LVM info err in host:" + _host.getUuid() + e.getMessage(); - s_logger.warn(msg); - } - } - - final SR extsr = getLocalEXTSR(conn); - if (extsr != null) { - try { - final String extuuid = extsr.getUuid(conn); - _host.setLocalSRuuid(extuuid); - final long cap = extsr.getPhysicalSize(conn); - if (cap > 0) { - final long avail = cap - extsr.getPhysicalUtilisation(conn); - extsr.setNameLabel(conn, extuuid); - final String name = "Cloud Stack Local EXT Storage Pool for " + _host.getUuid(); - extsr.setNameDescription(conn, name); - final Host host = Host.getByUuid(conn, _host.getUuid()); - final String address = host.getAddress(conn); - final StoragePoolInfo pInfo = new StoragePoolInfo(extuuid, address, SRType.EXT.toString(), SRType.EXT.toString(), StoragePoolType.EXT, cap, avail); - final StartupStorageCommand cmd = new StartupStorageCommand(); - cmd.setPoolInfo(pInfo); - cmd.setGuid(_host.getUuid()); - cmd.setDataCenter(Long.toString(_dcId)); - cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); - return cmd; - } - } catch (final XenAPIException e) { - final String msg = "build local EXT info err in host:" + _host.getUuid() + e.toString(); - s_logger.warn(msg); - } catch (final XmlRpcException e) { - final String msg = "build local EXT info err in host:" + _host.getUuid() + e.getMessage(); - s_logger.warn(msg); - } - } - return null; + @Override + public ExecutionResult executeInVR(final String routerIP, final String script, final String args) { + // Timeout is 120 seconds by default + return executeInVR(routerIP, script, args, 120); } @Override - public PingCommand getCurrentStatus(final long id) { + public ExecutionResult executeInVR(final String routerIP, final String script, final String args, final int timeout) { + Pair result; + String cmdline = "/opt/cloud/bin/router_proxy.sh " + script + " " + routerIP + " " + args; + // semicolon need to be escape for bash + cmdline = cmdline.replaceAll(";", "\\\\;"); try { - if (!pingXAPI()) { - Thread.sleep(1000); - if (!pingXAPI()) { - s_logger.warn("can not ping xenserver " + _host.getUuid()); - return null; - } - } - final Connection conn = getConnection(); - if (!_canBridgeFirewall && !_isOvs) { - return new PingRoutingCommand(getType(), id, getHostVmStateReport(conn)); - } else if (_isOvs) { - final List> ovsStates = ovsFullSyncStates(); - return new PingRoutingWithOvsCommand(getType(), id, getHostVmStateReport(conn), ovsStates); - } else { - final HashMap> nwGrpStates = syncNetworkGroups(conn, id); - return new PingRoutingWithNwGroupsCommand(getType(), id, getHostVmStateReport(conn), nwGrpStates); - } + s_logger.debug("Executing command in VR: " + cmdline); + result = SshHelper.sshExecute(_host.getIp(), 22, _username, null, _password.peek(), cmdline, + 60000, 60000, timeout * 1000); } catch (final Exception e) { - s_logger.warn("Unable to get current status", e); - return null; + return new ExecutionResult(false, e.getMessage()); } - } - - private HashMap> syncNetworkGroups(final Connection conn, final long id) { - final HashMap> states = new HashMap>(); - - final String result = callHostPlugin(conn, "vmops", "get_rule_logs_for_vms", "host_uuid", _host.getUuid()); - s_logger.trace("syncNetworkGroups: id=" + id + " got: " + result); - final String[] rulelogs = result != null ? result.split(";") : new String[0]; - for (final String rulesforvm : rulelogs) { - final String[] log = rulesforvm.split(","); - if (log.length != 6) { - continue; - } - //output = ','.join([vmName, vmID, vmIP, domID, signature, seqno]) - try { - states.put(log[0], new Pair(Long.parseLong(log[1]), Long.parseLong(log[5]))); - } catch (final NumberFormatException nfe) { - states.put(log[0], new Pair(-1L, -1L)); - } - } - return states; + return new ExecutionResult(result.first(), result.second()); } @Override - public Type getType() { - return com.cloud.host.Host.Type.Routing; - } + public Answer executeRequest(final Command cmd) { - protected boolean getHostInfo(final Connection conn) throws IllegalArgumentException { + // We need this one because the StorageSubSystemCommand is from another hierarchy. + if (cmd instanceof StorageSubSystemCommand) { + return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); + } + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); try { - final Host myself = Host.getByUuid(conn, _host.getUuid()); - Set hcs = null; - for (int i = 0; i < 10; i++) { - hcs = myself.getHostCPUs(conn); - if(hcs != null) { - _host.setCpus(hcs.size()); - if (_host.getCpus() > 0) { - break; - } - } - Thread.sleep(5000); - } - if (_host.getCpus() <= 0) { - throw new CloudRuntimeException("Cannot get the numbers of cpu from XenServer host " + _host.getIp()); - } - final Map cpuInfo = myself.getCpuInfo(conn); - if (cpuInfo.get("socket_count") != null) { - _host.setCpuSockets(Integer.parseInt(cpuInfo.get("socket_count"))); - } - // would hcs be null we would have thrown an exception on condition (_host.getCpus() <= 0) by now - for (final HostCpu hc : hcs) { - _host.setSpeed(hc.getSpeed(conn).intValue()); - break; - } - final Host.Record hr = myself.getRecord(conn); - _host.setProductVersion(CitrixHelper.getProductVersion(hr)); - - final XsLocalNetwork privateNic = getManagementNetwork(conn); - _privateNetworkName = privateNic.getNetworkRecord(conn).nameLabel; - _host.setPrivatePif(privateNic.getPifRecord(conn).uuid); - _host.setPrivateNetwork(privateNic.getNetworkRecord(conn).uuid); - _host.setSystemvmisouuid(null); - - XsLocalNetwork guestNic = null; - if (_guestNetworkName != null && !_guestNetworkName.equals(_privateNetworkName)) { - guestNic = getNetworkByName(conn, _guestNetworkName); - if (guestNic == null) { - s_logger.warn("Unable to find guest network " + _guestNetworkName); - throw new IllegalArgumentException("Unable to find guest network " + _guestNetworkName + " for host " + _host.getIp()); - } - } else { - guestNic = privateNic; - _guestNetworkName = _privateNetworkName; - } - _host.setGuestNetwork(guestNic.getNetworkRecord(conn).uuid); - _host.setGuestPif(guestNic.getPifRecord(conn).uuid); - - XsLocalNetwork publicNic = null; - if (_publicNetworkName != null && !_publicNetworkName.equals(_guestNetworkName)) { - publicNic = getNetworkByName(conn, _publicNetworkName); - if (publicNic == null) { - s_logger.warn("Unable to find public network " + _publicNetworkName + " for host " + _host.getIp()); - throw new IllegalArgumentException("Unable to find public network " + _publicNetworkName + " for host " + _host.getIp()); - } - } else { - publicNic = guestNic; - _publicNetworkName = _guestNetworkName; - } - _host.setPublicPif(publicNic.getPifRecord(conn).uuid); - _host.setPublicNetwork(publicNic.getNetworkRecord(conn).uuid); - if (_storageNetworkName1 == null) { - _storageNetworkName1 = _guestNetworkName; - } - XsLocalNetwork storageNic1 = null; - storageNic1 = getNetworkByName(conn, _storageNetworkName1); - if (storageNic1 == null) { - s_logger.warn("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.getIp()); - throw new IllegalArgumentException("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.getIp()); - } else { - _host.setStorageNetwork1(storageNic1.getNetworkRecord(conn).uuid); - _host.setStoragePif1(storageNic1.getPifRecord(conn).uuid); - } - - XsLocalNetwork storageNic2 = null; - if (_storageNetworkName2 != null) { - storageNic2 = getNetworkByName(conn, _storageNetworkName2); - if(storageNic2 != null) { - _host.setStoragePif2(storageNic2.getPifRecord(conn).uuid); - } - } - - s_logger.info("XenServer Version is " + _host.getProductVersion() + " for host " + _host.getIp()); - s_logger.info("Private Network is " + _privateNetworkName + " for host " + _host.getIp()); - s_logger.info("Guest Network is " + _guestNetworkName + " for host " + _host.getIp()); - s_logger.info("Public Network is " + _publicNetworkName + " for host " + _host.getIp()); - - return true; - } catch (final XenAPIException e) { - s_logger.warn("Unable to get host information for " + _host.getIp(), e); - return false; + return wrapper.execute(cmd, this); } catch (final Exception e) { - s_logger.warn("Unable to get host information for " + _host.getIp(), e); - return false; + return Answer.createUnsupportedCommandAnswer(cmd); } } - protected void plugDom0Vif(final Connection conn, final VIF dom0Vif) throws XmlRpcException, XenAPIException { - if (dom0Vif != null) { - dom0Vif.plug(conn); - } - } - - public void setupLinkLocalNetwork(final Connection conn) { - try { - final Network.Record rec = new Network.Record(); - final Set networks = Network.getByNameLabel(conn, _linkLocalPrivateNetworkName); - Network linkLocal = null; - - if (networks.size() == 0) { - rec.nameDescription = "link local network used by system vms"; - rec.nameLabel = _linkLocalPrivateNetworkName; - final Map configs = new HashMap(); - configs.put("ip_begin", NetUtils.getLinkLocalGateway()); - configs.put("ip_end", NetUtils.getLinkLocalIpEnd()); - configs.put("netmask", NetUtils.getLinkLocalNetMask()); - configs.put("vswitch-disable-in-band", "true"); - rec.otherConfig = configs; - linkLocal = Network.create(conn, rec); - } else { - linkLocal = networks.iterator().next(); - if (!linkLocal.getOtherConfig(conn).containsKey("vswitch-disable-in-band")) { - linkLocal.addToOtherConfig(conn, "vswitch-disable-in-band", "true"); - } - } - - /* Make sure there is a physical bridge on this network */ - VIF dom0vif = null; - final Pair vm = getControlDomain(conn); - final VM dom0 = vm.first(); - final Set vifs = dom0.getVIFs(conn); - if (vifs.size() != 0) { - for (final VIF vif : vifs) { - final Map otherConfig = vif.getOtherConfig(conn); - if (otherConfig != null) { - final String nameLabel = otherConfig.get("nameLabel"); - if (nameLabel != null && nameLabel.equalsIgnoreCase("link_local_network_vif")) { - dom0vif = vif; - } - } - } - } - - /* create temp VIF0 */ - if (dom0vif == null) { - s_logger.debug("Can't find a vif on dom0 for link local, creating a new one"); - final VIF.Record vifr = new VIF.Record(); - vifr.VM = dom0; - vifr.device = getLowestAvailableVIFDeviceNum(conn, dom0); - if (vifr.device == null) { - s_logger.debug("Failed to create link local network, no vif available"); - return; - } - final Map config = new HashMap(); - config.put("nameLabel", "link_local_network_vif"); - vifr.otherConfig = config; - vifr.MAC = "FE:FF:FF:FF:FF:FF"; - vifr.network = linkLocal; - vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT; - dom0vif = VIF.create(conn, vifr); - plugDom0Vif(conn, dom0vif); - } else { - s_logger.debug("already have a vif on dom0 for link local network"); - if (!dom0vif.getCurrentlyAttached(conn)) { - plugDom0Vif(conn, dom0vif); - } - } - - final String brName = linkLocal.getBridge(conn); - callHostPlugin(conn, "vmops", "setLinkLocalIP", "brName", brName); - _host.setLinkLocalNetwork(linkLocal.getUuid(conn)); - - } catch (final XenAPIException e) { - s_logger.warn("Unable to create local link network", e); - throw new CloudRuntimeException("Unable to create local link network due to " + e.toString(), e); - } catch (final XmlRpcException e) { - s_logger.warn("Unable to create local link network", e); - throw new CloudRuntimeException("Unable to create local link network due to " + e.toString(), e); - } - } - - 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); - Host.managementReconfigure(conn, dest); - String hostUuid = null; - final int count = 0; - while (count < 10) { - try { - Thread.sleep(10000); - hostUuid = host.getUuid(conn); - if (hostUuid != null) { - break; - } - } catch (final XmlRpcException e) { - s_logger.debug("Waiting for host to come back: " + e.getMessage()); - } catch (final XenAPIException e) { - s_logger.debug("Waiting for host to come back: " + e.getMessage()); - } catch (final InterruptedException e) { - s_logger.debug("Gotta run"); - return false; - } - } - if (hostUuid == null) { - s_logger.warn("Unable to transfer the management network from " + spr.uuid); - return false; - } - - src.reconfigureIp(conn, Types.IpConfigurationMode.NONE, null, null, null, null); - return true; - } - - @Override - public StartupCommand[] initialize() throws IllegalArgumentException { - final Connection conn = getConnection(); - if (!getHostInfo(conn)) { - s_logger.warn("Unable to get host information for " + _host.getIp()); - return null; - } - final StartupRoutingCommand cmd = new StartupRoutingCommand(); - fillHostInfo(conn, cmd); - cmd.setHypervisorType(HypervisorType.XenServer); - cmd.setCluster(_cluster); - cmd.setPoolSync(false); - - try { - final Pool pool = Pool.getByUuid(conn, _host.getPool()); - final Pool.Record poolr = pool.getRecord(conn); - poolr.master.getRecord(conn); - } catch (final Throwable e) { - s_logger.warn("Check for master failed, failing the FULL Cluster sync command"); - } - final StartupStorageCommand sscmd = initializeLocalSR(conn); - if (sscmd != null) { - return new StartupCommand[] {cmd, sscmd}; - } - return new StartupCommand[] {cmd}; - } - - public void cleanupTemplateSR(final Connection conn) { - Set pbds = null; - try { - final Host host = Host.getByUuid(conn, _host.getUuid()); - pbds = host.getPBDs(conn); - } catch (final XenAPIException e) { - s_logger.warn("Unable to get the SRs " + e.toString(), e); - throw new CloudRuntimeException("Unable to get SRs " + e.toString(), e); - } catch (final Exception e) { - throw new CloudRuntimeException("Unable to get SRs " + e.getMessage(), e); - } - for (final PBD pbd : pbds) { - SR sr = null; - SR.Record srRec = null; - try { - sr = pbd.getSR(conn); - srRec = sr.getRecord(conn); - } catch (final Exception e) { - s_logger.warn("pbd.getSR get Exception due to ", e); - continue; - } - final String type = srRec.type; - if (srRec.shared) { - continue; - } - if (SRType.NFS.equals(type) || SRType.ISO.equals(type) && srRec.nameDescription.contains("template")) { - try { - pbd.unplug(conn); - pbd.destroy(conn); - sr.forget(conn); - } catch (final Exception e) { - s_logger.warn("forget SR catch Exception due to ", e); - } - } - } - } - - public boolean launchHeartBeat(final Connection conn) { - final String result = callHostPluginPremium(conn, "heartbeat", - "host", _host.getUuid(), - "timeout", Integer.toString(_heartbeatTimeout), - "interval", Integer.toString(_heartbeatInterval)); - if (result == null || !result.contains("> DONE <")) { - s_logger.warn("Unable to launch the heartbeat process on " + _host.getIp()); - return false; - } - return true; - } - - protected SetupAnswer execute(final SetupCommand cmd) { - final Connection conn = getConnection(); - try { - final Map poolRecs = Pool.getAllRecords(conn); - if (poolRecs.size() != 1) { - throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.getUuid()); - } - final Host master = poolRecs.values().iterator().next().master; - setupServer(conn, master); - final Host host = Host.getByUuid(conn, _host.getUuid()); - setupServer(conn, host); - - if (!setIptables(conn)) { - s_logger.warn("set xenserver Iptable failed"); - return null; - } - - if (_securityGroupEnabled) { - _canBridgeFirewall = canBridgeFirewall(conn); - if (!_canBridgeFirewall) { - final String msg = "Failed to configure brige firewall"; - s_logger.warn(msg); - s_logger.warn("Check host " + _host.getIp() +" for CSP is installed or not and check network mode for bridge"); - return new SetupAnswer(cmd, msg); - } - - } - - - final boolean r = launchHeartBeat(conn); - if (!r) { - return null; - } - cleanupTemplateSR(conn); - try { - if (cmd.useMultipath()) { - // the config value is set to true - host.addToOtherConfig(conn, "multipathing", "true"); - host.addToOtherConfig(conn, "multipathhandle", "dmp"); - } - - } catch (final Types.MapDuplicateKey e) { - s_logger.debug("multipath is already set"); - } - - if (cmd.needSetup() ) { - final String result = callHostPlugin(conn, "vmops", "setup_iscsi", "uuid", _host.getUuid()); - - if (!result.contains("> DONE <")) { - s_logger.warn("Unable to setup iscsi: " + result); - return new SetupAnswer(cmd, result); - } - - Pair mgmtPif = null; - final Set hostPifs = host.getPIFs(conn); - for (final PIF pif : hostPifs) { - final PIF.Record rec = pif.getRecord(conn); - if (rec.management) { - if (rec.VLAN != null && rec.VLAN != -1) { - final String msg = - new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.getUuid()) - .append("; pif=") - .append(rec.uuid) - .append("; vlan=") - .append(rec.VLAN) - .toString(); - s_logger.warn(msg); - return new SetupAnswer(cmd, msg); - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Management network is on pif=" + rec.uuid); - } - mgmtPif = new Pair(pif, rec); - break; - } - } - - if (mgmtPif == null) { - final String msg = "Unable to find management network for " + _host.getUuid(); - s_logger.warn(msg); - return new SetupAnswer(cmd, msg); - } - - final Map networks = Network.getAllRecords(conn); - if(networks == null) { - final String msg = "Unable to setup as there are no networks in the host: " + _host.getUuid(); - s_logger.warn(msg); - return new SetupAnswer(cmd, msg); - } - for (final Network.Record network : networks.values()) { - if (network.nameLabel.equals("cloud-private")) { - for (final PIF pif : network.PIFs) { - final PIF.Record pr = pif.getRecord(conn); - if (_host.getUuid().equals(pr.host.getUuid(conn))) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found a network called cloud-private. host=" + _host.getUuid() + "; Network=" + network.uuid + "; pif=" + pr.uuid); - } - if (pr.VLAN != null && pr.VLAN != -1) { - final String msg = - new StringBuilder("Unsupported configuration. Network cloud-private is on a VLAN. Network=").append(network.uuid) - .append(" ; pif=") - .append(pr.uuid) - .toString(); - s_logger.warn(msg); - return new SetupAnswer(cmd, msg); - } - if (!pr.management && pr.bondMasterOf != null && pr.bondMasterOf.size() > 0) { - if (pr.bondMasterOf.size() > 1) { - final String msg = - new StringBuilder("Unsupported configuration. Network cloud-private has more than one bond. Network=").append(network.uuid) - .append("; pif=") - .append(pr.uuid) - .toString(); - s_logger.warn(msg); - return new SetupAnswer(cmd, msg); - } - final Bond bond = pr.bondMasterOf.iterator().next(); - final Set slaves = bond.getSlaves(conn); - for (final PIF slave : slaves) { - final PIF.Record spr = slave.getRecord(conn); - if (spr.management) { - if (!transferManagementNetwork(conn, host, slave, spr, pif)) { - final String msg = - new StringBuilder("Unable to transfer management network. slave=" + spr.uuid + "; master=" + pr.uuid + "; host=" + - _host.getUuid()).toString(); - s_logger.warn(msg); - return new SetupAnswer(cmd, msg); - } - break; - } - } - } - } - } - } - } - } - return new SetupAnswer(cmd, false); - - } catch (final XmlRpcException e) { - s_logger.warn("Unable to setup", e); - return new SetupAnswer(cmd, e.getMessage()); - } catch (final XenAPIException e) { - s_logger.warn("Unable to setup", e); - return new SetupAnswer(cmd, e.getMessage()); - } catch (final Exception e) { - s_logger.warn("Unable to setup", e); - return new SetupAnswer(cmd, e.getMessage()); - } - } - - /* return : if setup is needed */ - public boolean setupServer(final Connection conn, final Host host) { - final String packageVersion = CitrixResourceBase.class.getPackage().getImplementationVersion(); - final String version = this.getClass().getName() + "-" + (packageVersion == null ? Long.toString(System.currentTimeMillis()) : packageVersion); - - try { - /* push patches to XenServer */ - final Host.Record hr = host.getRecord(conn); - - final Iterator it = hr.tags.iterator(); - - while (it.hasNext()) { - final String tag = it.next(); - if (tag.startsWith("vmops-version-")) { - if (tag.contains(version)) { - s_logger.info(logX(host, "Host " + hr.address + " is already setup.")); - return false; - } else { - it.remove(); - } - } - } - - final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(hr.address, 22); - try { - sshConnection.connect(null, 60000, 60000); - if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { - throw new CloudRuntimeException("Unable to authenticate"); - } - - final com.trilead.ssh2.Session session = sshConnection.openSession(); - - final String cmd = "mkdir -p /opt/cloud/bin /var/log/cloud"; - if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { - throw new CloudRuntimeException("Cannot create directory /opt/cloud/bin on XenServer hosts"); - } - - final SCPClient scp = new SCPClient(sshConnection); - - final List files = getPatchFiles(); - if (files == null || files.isEmpty()) { - throw new CloudRuntimeException("Can not find patch file"); - } - for (final File file : files) { - final String path = file.getParentFile().getAbsolutePath() + "/"; - final Properties props = PropertiesUtil.loadFromFile(file); - - for (final Map.Entry entry : props.entrySet()) { - final String k = (String)entry.getKey(); - final String v = (String)entry.getValue(); - - assert k != null && k.length() > 0 && v != null && v.length() > 0 : "Problems with " + k + "=" + v; - - final String[] tokens = v.split(","); - String f = null; - if (tokens.length == 3 && tokens[0].length() > 0) { - if (tokens[0].startsWith("/")) { - f = tokens[0]; - } else if (tokens[0].startsWith("~")) { - final String homedir = System.getenv("HOME"); - f = homedir + tokens[0].substring(1) + k; - } else { - f = path + tokens[0] + '/' + k; - } - } else { - f = path + k; - } - final String directoryPath = tokens[tokens.length - 1]; - - f = f.replace('/', File.separatorChar); - - String permissions = "0755"; - if (tokens.length == 3) { - permissions = tokens[1]; - } else if (tokens.length == 2) { - permissions = tokens[0]; - } - - if (!new File(f).exists()) { - s_logger.warn("We cannot locate " + f); - continue; - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Copying " + f + " to " + directoryPath + " on " + hr.address + " with permission " + permissions); - } - try { - session.execCommand("mkdir -m 700 -p " + directoryPath); - } catch (final IOException e) { - s_logger.debug("Unable to create destination path: " + directoryPath + " on " + hr.address + " but trying anyway"); - } - try { - scp.put(f, directoryPath, permissions); - } catch (final IOException e) { - final String msg = "Unable to copy file " + f + " to path " + directoryPath + " with permissions " + permissions; - s_logger.debug(msg); - throw new CloudRuntimeException("Unable to setup the server: " + msg, e); - } - } - } - - } catch (final IOException e) { - throw new CloudRuntimeException("Unable to setup the server correctly", e); - } finally { - sshConnection.close(); - } - hr.tags.add("vmops-version-" + version); - host.setTags(conn, hr.tags); - return true; - } catch (final XenAPIException e) { - final String msg = "XenServer setup failed due to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException("Unable to get host information " + e.toString(), e); - } catch (final XmlRpcException e) { - final String msg = "XenServer setup failed due to " + e.getMessage(); - s_logger.warn(msg, e); - throw new CloudRuntimeException("Unable to get host information ", e); - } - } - - protected CheckNetworkAnswer execute(final CheckNetworkCommand cmd) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Checking if network name setup is done on the resource"); - } - - final List infoList = cmd.getPhysicalNetworkInfoList(); - - try { - boolean errorout = false; - String msg = ""; - for (final PhysicalNetworkSetupInfo info : infoList) { - if (!isNetworkSetupByName(info.getGuestNetworkName())) { - msg = - "For Physical Network id:" + info.getPhysicalNetworkId() + ", Guest Network is not configured on the backend by name " + - info.getGuestNetworkName(); - errorout = true; - break; - } - if (!isNetworkSetupByName(info.getPrivateNetworkName())) { - msg = - "For Physical Network id:" + info.getPhysicalNetworkId() + ", Private Network is not configured on the backend by name " + - info.getPrivateNetworkName(); - errorout = true; - break; - } - if (!isNetworkSetupByName(info.getPublicNetworkName())) { - msg = - "For Physical Network id:" + info.getPhysicalNetworkId() + ", Public Network is not configured on the backend by name " + - info.getPublicNetworkName(); - errorout = true; - break; - } - /*if(!isNetworkSetupByName(info.getStorageNetworkName())){ - msg = "For Physical Network id:"+ info.getPhysicalNetworkId() + ", Storage Network is not configured on the backend by name " + info.getStorageNetworkName(); - errorout = true; - break; - }*/ - } - if (errorout) { - s_logger.error(msg); - return new CheckNetworkAnswer(cmd, false, msg); - } else { - return new CheckNetworkAnswer(cmd, true, "Network Setup check by names is done"); - } - - } catch (final XenAPIException e) { - final String msg = "CheckNetworkCommand failed with XenAPIException:" + e.toString() + " host:" + _host.getUuid(); - s_logger.warn(msg, e); - return new CheckNetworkAnswer(cmd, false, msg); - } catch (final Exception e) { - final String msg = "CheckNetworkCommand failed with Exception:" + e.getMessage() + " host:" + _host.getUuid(); - s_logger.warn(msg, e); - return new CheckNetworkAnswer(cmd, false, msg); - } - } - - public boolean isNetworkSetupByName(final String nameTag) throws XenAPIException, XmlRpcException { - if (nameTag != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Looking for network setup by name " + nameTag); - } - final Connection conn = getConnection(); - final XsLocalNetwork network = getNetworkByName(conn, nameTag); - if (network == null) { - return false; - } - } - return true; - } - - protected List getPatchFiles() { - return null; - } - - protected SR getSRByNameLabelandHost(final Connection conn, final String name) throws BadServerResponse, XenAPIException, XmlRpcException { - final Set srs = SR.getByNameLabel(conn, name); - SR ressr = null; - for (final SR sr : srs) { - Set pbds; - pbds = sr.getPBDs(conn); - for (final PBD pbd : pbds) { - final PBD.Record pbdr = pbd.getRecord(conn); - if (pbdr.host != null && pbdr.host.getUuid(conn).equals(_host.getUuid())) { - if (!pbdr.currentlyAttached) { - pbd.plug(conn); - } - ressr = sr; - break; - } - } - } - return ressr; - } - - protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) { - final Connection conn = getConnection(); - try { - final Set srs = SR.getByNameLabel(conn, cmd.getStorageId()); - if (srs.size() != 1) { - final String msg = "There are " + srs.size() + " storageid: " + cmd.getStorageId(); - s_logger.warn(msg); - return new GetStorageStatsAnswer(cmd, msg); - } - final SR sr = srs.iterator().next(); - sr.scan(conn); - final long capacity = sr.getPhysicalSize(conn); - final long used = sr.getPhysicalUtilisation(conn); - return new GetStorageStatsAnswer(cmd, capacity, used); - } catch (final XenAPIException e) { - final String msg = "GetStorageStats Exception:" + e.toString() + "host:" + _host.getUuid() + "storageid: " + cmd.getStorageId(); - s_logger.warn(msg); - return new GetStorageStatsAnswer(cmd, msg); - } catch (final XmlRpcException e) { - final String msg = "GetStorageStats Exception:" + e.getMessage() + "host:" + _host.getUuid() + "storageid: " + cmd.getStorageId(); - s_logger.warn(msg); - return new GetStorageStatsAnswer(cmd, msg); - } - } - - private void pbdPlug(final Connection conn, final PBD pbd, final String uuid) { - try { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Plugging in PBD " + uuid + " for " + _host); - } - pbd.plug(conn); - } catch (final Exception e) { - final String msg = "PBD " + uuid + " is not attached! and PBD plug failed due to " + e.toString() + ". Please check this PBD in " + _host; - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg); - } - } - - protected boolean checkSR(final Connection conn, final SR sr) { - try { - final SR.Record srr = sr.getRecord(conn); - final Set pbds = sr.getPBDs(conn); - if (pbds.size() == 0) { - final String msg = "There is no PBDs for this SR: " + srr.nameLabel + " on host:" + _host.getUuid(); - s_logger.warn(msg); - return false; - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Checking " + srr.nameLabel + " or SR " + srr.uuid + " on " + _host); - } - if (srr.shared) { - if (SRType.NFS.equals(srr.type) ){ - final Map smConfig = srr.smConfig; - if( !smConfig.containsKey("nosubdir")) { - smConfig.put("nosubdir", "true"); - sr.setSmConfig(conn,smConfig); - } - } - - final Host host = Host.getByUuid(conn, _host.getUuid()); - boolean found = false; - for (final PBD pbd : pbds) { - final PBD.Record pbdr = pbd.getRecord(conn); - if (host.equals(pbdr.host)) { - if (!pbdr.currentlyAttached) { - pbdPlug(conn, pbd, pbdr.uuid); - } - found = true; - break; - } - } - if (!found) { - final PBD.Record pbdr = srr.PBDs.iterator().next().getRecord(conn); - pbdr.host = host; - pbdr.uuid = ""; - final PBD pbd = PBD.create(conn, pbdr); - pbdPlug(conn, pbd, pbd.getUuid(conn)); - } - } else { - for (final PBD pbd : pbds) { - final PBD.Record pbdr = pbd.getRecord(conn); - if (!pbdr.currentlyAttached) { - pbdPlug(conn, pbd, pbdr.uuid); - } - } - } - - } catch (final Exception e) { - final String msg = "checkSR failed host:" + _host + " due to " + e.toString(); - s_logger.warn(msg, e); - return false; - } - return true; - } - - protected Answer execute(final CreateStoragePoolCommand cmd) { - final Connection conn = getConnection(); - final StorageFilerTO pool = cmd.getPool(); - try { - if (pool.getType() == StoragePoolType.NetworkFilesystem) { - getNfsSR(conn, Long.toString(pool.getId()), pool.getUuid(), pool.getHost(), pool.getPath(), pool.toString()); - } else if (pool.getType() == StoragePoolType.IscsiLUN) { - getIscsiSR(conn, pool.getUuid(), pool.getHost(), pool.getPath(), null, null, false); - } else if (pool.getType() == StoragePoolType.PreSetup) { - } else { - return new Answer(cmd, false, "The pool type: " + pool.getType().name() + " is not supported."); - } - return new Answer(cmd, true, "success"); - } catch (final Exception e) { - final String msg = - "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.getUuid() + " pool: " + - pool.getHost() + pool.getPath(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } - - } - - protected String callHostPluginThroughMaster(final Connection conn, final String plugin, final String cmd, final String... params) { - final Map args = new HashMap(); - - try { - final Map poolRecs = Pool.getAllRecords(conn); - if (poolRecs.size() != 1) { - throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.getUuid()); - } - final Host master = poolRecs.values().iterator().next().master; - for (int i = 0; i < params.length; i += 2) { - args.put(params[i], params[i + 1]); - } - - if (s_logger.isTraceEnabled()) { - s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); - } - final String result = master.callPlugin(conn, plugin, cmd, args); - if (s_logger.isTraceEnabled()) { - s_logger.trace("callHostPlugin Result: " + result); - } - return result.replace("\n", ""); - } catch (final Types.HandleInvalid e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + - e.handle); - } catch (final XenAPIException e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); - } catch (final XmlRpcException e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(), e); - } - return null; - } - - public String callHostPluginPremium(final Connection conn, final String cmd, final String... params) { - return callHostPlugin(conn, "vmopspremium", cmd, params); - } - - public String setupHeartbeatSr(final Connection conn, final SR sr, final boolean force) throws XenAPIException, XmlRpcException { - final SR.Record srRec = sr.getRecord(conn); - final String srUuid = srRec.uuid; - if (!srRec.shared || !SRType.LVMOHBA.equals(srRec.type) && !SRType.LVMOISCSI.equals(srRec.type) && !SRType.NFS.equals(srRec.type)) { - return srUuid; - } - String result = null; - final Host host = Host.getByUuid(conn, _host.getUuid()); - final Set tags = host.getTags(conn); - if (force || !tags.contains("cloud-heartbeat-" + srUuid)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Setting up the heartbeat sr for host " + _host.getIp() + " and sr " + srUuid); - } - final Set pbds = sr.getPBDs(conn); - for (final PBD pbd : pbds) { - final PBD.Record pbdr = pbd.getRecord(conn); - if (!pbdr.currentlyAttached && pbdr.host.getUuid(conn).equals(_host.getUuid())) { - pbd.plug(conn); - break; - } - } - result = callHostPluginThroughMaster(conn, "vmopspremium", "setup_heartbeat_sr", "host", _host.getUuid(), "sr", srUuid); - if (result == null || !result.split("#")[1].equals("0")) { - throw new CloudRuntimeException("Unable to setup heartbeat sr on SR " + srUuid + " due to " + result); - } - - if (!tags.contains("cloud-heartbeat-" + srUuid)) { - tags.add("cloud-heartbeat-" + srUuid); - host.setTags(conn, tags); - } - } - result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.getUuid(), "sr", srUuid, "add", "true"); - if (result == null || !result.split("#")[1].equals("0")) { - throw new CloudRuntimeException("Unable to setup heartbeat file entry on SR " + srUuid + " due to " + result); - } - return srUuid; - } - - protected Answer execute(final ModifyStoragePoolCommand cmd) { - final Connection conn = getConnection(); - final StorageFilerTO pool = cmd.getPool(); - final boolean add = cmd.getAdd(); - if (add) { - try { - final SR sr = getStorageRepository(conn, pool.getUuid()); - setupHeartbeatSr(conn, sr, false); - final long capacity = sr.getPhysicalSize(conn); - final long available = capacity - sr.getPhysicalUtilisation(conn); - if (capacity == -1) { - final String msg = "Pool capacity is -1! pool: " + pool.getHost() + pool.getPath(); - s_logger.warn(msg); - return new Answer(cmd, false, msg); - } - final Map tInfo = new HashMap(); - final ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); - return answer; - } catch (final XenAPIException e) { - final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.toString() + " host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } catch (final Exception e) { - final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.getMessage() + " host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } - } else { - try { - final SR sr = getStorageRepository(conn, pool.getUuid()); - final String srUuid = sr.getUuid(conn); - final String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.getUuid(), "sr", srUuid, "add", "false"); - if (result == null || !result.split("#")[1].equals("0")) { - throw new CloudRuntimeException("Unable to remove heartbeat file entry for SR " + srUuid + " due to " + result); - } - return new Answer(cmd, true, "seccuss"); - } catch (final XenAPIException e) { - final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.toString() + " host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } catch (final Exception e) { - final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.getMessage() + " host:" + _host.getUuid() + " pool: " + pool.getHost() + pool.getPath(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } - } - - } - - private Answer execute(final OvsSetupBridgeCommand cmd) { - final Connection conn = getConnection(); - findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); - configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getHostId(), cmd.getBridgeName()); - s_logger.debug("OVS Bridge configured"); - return new Answer(cmd, true, null); - } - - private Answer execute(final OvsDestroyBridgeCommand cmd) { - try { - final Connection conn = getConnection(); - final Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); - cleanUpTmpDomVif(conn, nw); - destroyTunnelNetwork(conn, nw, cmd.getHostId()); - s_logger.debug("OVS Bridge destroyed"); - return new Answer(cmd, true, null); - } catch (final Exception e) { - s_logger.warn("caught execption when destroying ovs bridge", e); - return new Answer(cmd, false, e.getMessage()); - } - } - - private Answer execute(final OvsDestroyTunnelCommand cmd) { - final Connection conn = getConnection(); - try { - final Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); - if (nw == null) { - s_logger.warn("Unable to find tunnel network for GRE key:" + cmd.getBridgeName()); - return new Answer(cmd, false, "No network found"); - } - - final String bridge = nw.getBridge(conn); - final String result = callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", cmd.getInPortName()); - - if (result.equalsIgnoreCase("SUCCESS")) { - return new Answer(cmd, true, result); - } else { - return new Answer(cmd, false, result); - } - } catch (final Exception e) { - s_logger.warn("caught execption when destroy ovs tunnel", e); - return new Answer(cmd, false, e.getMessage()); - } - } - - public Answer execute(final OvsVpcPhysicalTopologyConfigCommand cmd) { - final Connection conn = getConnection(); - try { - final Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); - final String bridgeName = nw.getBridge(conn); - final long sequenceNo = cmd.getSequenceNumber(); - final String result = callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_network_topology", "bridge", - bridgeName, "config", cmd.getVpcConfigInJson(), "host-id", ((Long)cmd.getHostId()).toString(), - "seq-no", Long.toString(sequenceNo)); - if (result.startsWith("SUCCESS")) { - return new Answer(cmd, true, result); - } else { - return new Answer(cmd, false, result); - } - } catch (final Exception e) { - s_logger.warn("caught exception while updating host with latest VPC topology", e); - return new Answer(cmd, false, e.getMessage()); - } - } - - public Answer execute(final OvsVpcRoutingPolicyConfigCommand cmd) { - final Connection conn = getConnection(); - try { - final Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); - final String bridgeName = nw.getBridge(conn); - final long sequenceNo = cmd.getSequenceNumber(); - - final String result = callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_routing_policies", "bridge", - bridgeName, "host-id", ((Long)cmd.getHostId()).toString(), "config", - cmd.getVpcConfigInJson(), "seq-no", Long.toString(sequenceNo)); - if (result.startsWith("SUCCESS")) { - return new Answer(cmd, true, result); - } else { - return new Answer(cmd, false, result); - } - } catch (final Exception e) { - s_logger.warn("caught exception while updating host with latest routing policies", e); - return new Answer(cmd, false, e.getMessage()); - } - } - - private Answer execute(final UpdateHostPasswordCommand cmd) { - _password.add(cmd.getNewPassword()); - return new Answer(cmd, true, null); - } - - private OvsCreateTunnelAnswer execute(final OvsCreateTunnelCommand cmd) { - final Connection conn = getConnection(); - String bridge = "unknown"; - try { - final Network nw = findOrCreateTunnelNetwork(conn, cmd.getNetworkName()); - if (nw == null) { - s_logger.debug("Error during bridge setup"); - return new OvsCreateTunnelAnswer(cmd, false, "Cannot create network", bridge); - } - - configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom(), cmd.getNetworkName()); - bridge = nw.getBridge(conn); - final String result = - callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(), - "key", cmd.getKey().toString(), "from", - cmd.getFrom().toString(), "to", cmd.getTo().toString(), "cloudstack-network-id", - cmd.getNetworkUuid()); - final String[] res = result.split(":"); - if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) { - return new OvsCreateTunnelAnswer(cmd, true, result, res[1], bridge); - } else { - return new OvsCreateTunnelAnswer(cmd, false, result, bridge); - } - } catch (final Exception e) { - s_logger.debug("Error during tunnel setup"); - s_logger.warn("Caught execption when creating ovs tunnel", e); - return new OvsCreateTunnelAnswer(cmd, false, e.getMessage(), bridge); - } - } - - private Answer execute(final OvsDeleteFlowCommand cmd) { - _isOvs = true; - - final Connection conn = getConnection(); - try { - final Network nw = setupvSwitchNetwork(conn); - final String bridge = nw.getBridge(conn); - final String result = callHostPlugin(conn, "ovsgre", "ovs_delete_flow", "bridge", bridge, "vmName", cmd.getVmName()); - - if (result.equalsIgnoreCase("SUCCESS")) { - return new Answer(cmd, true, "success to delete flows for " + cmd.getVmName()); - } else { - return new Answer(cmd, 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(cmd, false, "failed to delete flow for " + cmd.getVmName()); - } - - private List> ovsFullSyncStates() { - final Connection conn = getConnection(); - final String result = callHostPlugin(conn, "ovsgre", "ovs_get_vm_log", "host_uuid", _host.getUuid()); - final String[] logs = result != null ? result.split(";") : new String[0]; - final List> states = new ArrayList>(); - for (final String log : logs) { - final String[] info = log.split(","); - if (info.length != 5) { - s_logger.warn("Wrong element number in ovs log(" + log + ")"); - continue; - } - - //','.join([bridge, vmName, vmId, seqno, tag]) - try { - states.add(new Pair(info[0], Long.parseLong(info[3]))); - } catch (final NumberFormatException nfe) { - states.add(new Pair(info[0], -1L)); - } - } - return states; - } - - private OvsSetTagAndFlowAnswer execute(final OvsSetTagAndFlowCommand cmd) { - _isOvs = true; - - final Connection conn = getConnection(); - try { - final Network nw = setupvSwitchNetwork(conn); - final String bridge = nw.getBridge(conn); - - /*If VM is domainRouter, this will try to set flow and tag on its - * none guest network nic. don't worry, it will fail silently at host - * plugin side - */ - final String result = - callHostPlugin(conn, "ovsgre", "ovs_set_tag_and_flow", "bridge", bridge, "vmName", cmd.getVmName(), "tag", cmd.getTag(), "vlans", cmd.getVlans(), - "seqno", cmd.getSeqNo()); - s_logger.debug("set flow for " + cmd.getVmName() + " " + result); - - if (result.equalsIgnoreCase("SUCCESS")) { - return new OvsSetTagAndFlowAnswer(cmd, true, result); - } else { - return new OvsSetTagAndFlowAnswer(cmd, false, result); - } - } catch (final BadServerResponse e) { - s_logger.error("Failed to set tag and flow", e); - } catch (final XenAPIException e) { - s_logger.error("Failed to set tag and flow", e); - } catch (final XmlRpcException e) { - s_logger.error("Failed to set tag and flow", e); - } - - return new OvsSetTagAndFlowAnswer(cmd, false, "EXCEPTION"); - } - - private OvsFetchInterfaceAnswer execute(final OvsFetchInterfaceCommand cmd) { - - String label = cmd.getLabel(); - //FIXME: this is a tricky to pass the network checking in XCP. I temporary get default label from Host. - if (isXcp()) { - label = getLabel(); - } - s_logger.debug("Will look for network with name-label:" + label + " on host " + _host.getIp()); - final Connection conn = getConnection(); - try { - final XsLocalNetwork nw = getNetworkByName(conn, label); - if(nw == null) { - throw new CloudRuntimeException("Unable to locate the network with name-label: " + label + " on host: " + _host.getIp()); - } - s_logger.debug("Network object:" + nw.getNetwork().getUuid(conn)); - final PIF pif = nw.getPif(conn); - final PIF.Record pifRec = pif.getRecord(conn); - s_logger.debug("PIF object:" + pifRec.uuid + "(" + pifRec.device + ")"); - return new OvsFetchInterfaceAnswer(cmd, true, "Interface " + pifRec.device + " retrieved successfully", pifRec.IP, pifRec.netmask, pifRec.MAC); - } catch (final BadServerResponse e) { - s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.getIp(), e); - return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); - } catch (final XenAPIException e) { - s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.getIp(), e); - return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); - } catch (final XmlRpcException e) { - s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.getIp(), e); - return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); - } - } - - private OvsCreateGreTunnelAnswer execute(final OvsCreateGreTunnelCommand cmd) { - _isOvs = true; - - final Connection conn = getConnection(); - String bridge = "unkonwn"; - try { - final Network nw = setupvSwitchNetwork(conn); - bridge = nw.getBridge(conn); - - final String result = - callHostPlugin(conn, "ovsgre", "ovs_create_gre", "bridge", bridge, "remoteIP", cmd.getRemoteIp(), "greKey", cmd.getKey(), "from", - Long.toString(cmd.getFrom()), "to", Long.toString(cmd.getTo())); - final String[] res = result.split(":"); - if (res.length != 2 || res.length == 2 && res[1].equalsIgnoreCase("[]")) { - return new OvsCreateGreTunnelAnswer(cmd, false, result, _host.getIp(), bridge); - } else { - return new OvsCreateGreTunnelAnswer(cmd, true, result, _host.getIp(), bridge, Integer.parseInt(res[1])); - } - } catch (final BadServerResponse e) { - s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.getIp(), e); - } catch (final XenAPIException e) { - s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.getIp(), e); - } catch (final XmlRpcException e) { - s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.getIp(), e); - } - - return new OvsCreateGreTunnelAnswer(cmd, false, "EXCEPTION", _host.getIp(), bridge); - } - - private Answer execute(final SecurityGroupRulesCmd cmd) { - final Connection conn = getConnection(); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Sending network rules command to " + _host.getIp()); - } - - if (!_canBridgeFirewall) { - s_logger.warn("Host " + _host.getIp() + " cannot do bridge firewalling"); - return new SecurityGroupRuleAnswer(cmd, false, "Host " + _host.getIp() + " cannot do bridge firewalling", - SecurityGroupRuleAnswer.FailureReason.CANNOT_BRIDGE_FIREWALL); - } - - final String result = - callHostPlugin(conn, "vmops", "network_rules", "vmName", cmd.getVmName(), "vmIP", cmd.getGuestIp(), "vmMAC", cmd.getGuestMac(), "vmID", - Long.toString(cmd.getVmId()), "signature", cmd.getSignature(), "seqno", Long.toString(cmd.getSeqNum()), "deflated", "true", "rules", - cmd.compressStringifiedRules(), "secIps", cmd.getSecIpsString()); - - if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { - s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); - return new SecurityGroupRuleAnswer(cmd, false, "programming network rules failed"); - } else { - s_logger.info("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", ingress numrules=" + cmd.getIngressRuleSet().length + - ", egress numrules=" + cmd.getEgressRuleSet().length); - return new SecurityGroupRuleAnswer(cmd); - } - } - - protected Answer execute(final DeleteStoragePoolCommand cmd) { - final Connection conn = getConnection(); - final StorageFilerTO poolTO = cmd.getPool(); - try { - final SR sr = getStorageRepository(conn, poolTO.getUuid()); - removeSR(conn, sr); - final Answer answer = new Answer(cmd, true, "success"); - return answer; - } catch (final Exception e) { - final String msg = "DeleteStoragePoolCommand XenAPIException:" + e.getMessage() + " host:" + _host.getUuid() + " pool: " + poolTO.getHost() + poolTO.getPath(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } - - } - - public Connection getConnection() { - return ConnPool.connect(_host.getUuid(), _host.getPool(), _host.getIp(), _username, _password, _wait); - } - - protected void fillHostInfo(final Connection conn, final StartupRoutingCommand cmd) { final StringBuilder caps = new StringBuilder(); try { @@ -5496,304 +2108,454 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - public CitrixResourceBase() { + protected void finalizeVmMetaData(final VM vm, final Connection conn, final VirtualMachineTO vmSpec) throws Exception { + + final Map details = vmSpec.getDetails(); + if (details != null) { + final String platformstring = details.get("platform"); + if (platformstring != null && !platformstring.isEmpty()) { + final Map platform = StringUtils.stringToMap(platformstring); + vm.setPlatform(conn, platform); + } else { + final String timeoffset = details.get("timeoffset"); + if (timeoffset != null) { + final Map platform = vm.getPlatform(conn); + platform.put("timeoffset", timeoffset); + vm.setPlatform(conn, platform); + } + final String coresPerSocket = details.get("cpu.corespersocket"); + if (coresPerSocket != null) { + final Map platform = vm.getPlatform(conn); + platform.put("cores-per-socket", coresPerSocket); + vm.setPlatform(conn, platform); + } + } + if ( !BootloaderType.CD.equals(vmSpec.getBootloader())) { + final String xenservertoolsversion = details.get("hypervisortoolsversion"); + if ((xenservertoolsversion == null || !xenservertoolsversion.equalsIgnoreCase("xenserver61")) && vmSpec.getGpuDevice() == null) { + final Map platform = vm.getPlatform(conn); + platform.remove("device_id"); + vm.setPlatform(conn, platform); + } + } + } + } + + /** + * This method just creates a XenServer network following the tunnel network naming convention + */ + public synchronized Network findOrCreateTunnelNetwork(final Connection conn, final String nwName) { + try { + Network nw = null; + final Network.Record rec = new Network.Record(); + final Set networks = Network.getByNameLabel(conn, nwName); + + if (networks.size() == 0) { + rec.nameDescription = "tunnel network id# " + nwName; + rec.nameLabel = nwName; + //Initialize the ovs-host-setup to avoid error when doing get-param in plugin + final Map otherConfig = new HashMap(); + otherConfig.put("ovs-host-setup", ""); + // Mark 'internal network' as shared so bridge gets automatically created on each host in the cluster + // when VM with vif connected to this internal network is started + otherConfig.put("assume_network_is_shared", "true"); + rec.otherConfig = otherConfig; + nw = Network.create(conn, rec); + s_logger.debug("### XenServer network for tunnels created:" + nwName); + } else { + nw = networks.iterator().next(); + s_logger.debug("XenServer network for tunnels found:" + nwName); + } + return nw; + } catch (final Exception e) { + s_logger.warn("createTunnelNetwork failed", e); + return null; + } + } + + void forceShutdownVM(final Connection conn, final VM vm) { + try { + final Long domId = vm.getDomid(conn); + callHostPlugin(conn, "vmopspremium", "forceShutdownVM", "domId", domId.toString()); + vm.powerStateReset(conn); + vm.destroy(conn); + } catch (final Exception e) { + final String msg = "forceShutdown failed due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } + } + + protected String generateTimeStamp() { + return new StringBuilder("CsCreateTime-").append(System.currentTimeMillis()).append("-").append(Rand.nextInt(Integer.MAX_VALUE)).toString(); } @Override - public boolean configure(final String name, final Map params) throws ConfigurationException { - _name = name; - - try { - _dcId = Long.parseLong((String)params.get("zone")); - } catch (final NumberFormatException e) { - throw new ConfigurationException("Unable to get the zone " + params.get("zone")); - } - - _host.setUuid((String)params.get("guid")); - - _name = _host.getUuid(); - _host.setIp((String)params.get("ipaddress")); - - _username = (String)params.get("username"); - _password.add((String)params.get("password")); - _pod = (String)params.get("pod"); - _cluster = (String)params.get("cluster"); - _privateNetworkName = (String)params.get("private.network.device"); - _publicNetworkName = (String)params.get("public.network.device"); - _guestNetworkName = (String)params.get("guest.network.device"); - _instance = (String)params.get("instance.name"); - _securityGroupEnabled = Boolean.parseBoolean((String)params.get("securitygroupenabled")); - - _linkLocalPrivateNetworkName = (String)params.get("private.linkLocal.device"); - if (_linkLocalPrivateNetworkName == null) { - _linkLocalPrivateNetworkName = "cloud_link_local_network"; - } - - _storageNetworkName1 = (String)params.get("storage.network.device1"); - _storageNetworkName2 = (String)params.get("storage.network.device2"); - - _heartbeatTimeout = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.timeout"), 120); - _heartbeatInterval = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.interval"), 60); - - String value = (String)params.get("wait"); - _wait = NumbersUtil.parseInt(value, 600); - - value = (String)params.get("migratewait"); - _migratewait = NumbersUtil.parseInt(value, 3600); - - _maxNics = NumbersUtil.parseInt((String)params.get("xenserver.nics.max"), 7); - - if (_pod == null) { - throw new ConfigurationException("Unable to get the pod"); - } - - if (_host.getIp() == null) { - throw new ConfigurationException("Unable to get the host address"); - } - - if (_username == null) { - throw new ConfigurationException("Unable to get the username"); - } - - if (_password.peek() == null) { - throw new ConfigurationException("Unable to get the password"); - } - - if (_host.getUuid() == null) { - throw new ConfigurationException("Unable to get the uuid"); - } - - CheckXenHostInfo(); - - storageHandler = buildStorageHandler(); - - _vrResource = new VirtualRoutingResource(this); - if (!_vrResource.configure(name, params)) { - throw new ConfigurationException("Unable to configure VirtualRoutingResource"); - } - return true; + public IAgentControl getAgentControl() { + return _agentControl; } - protected StorageSubsystemCommandHandler buildStorageHandler() { - final XenServerStorageProcessor processor = new XenServerStorageProcessor(this); - return new StorageSubsystemCommandHandlerBase(processor); - } - - private void CheckXenHostInfo() throws ConfigurationException { - final Connection conn = ConnPool.getConnect(_host.getIp(), _username, _password); - if( conn == null ) { - throw new ConfigurationException("Can not create connection to " + _host.getIp()); - } - try { - Host.Record hostRec = null; - try { - final Host host = Host.getByUuid(conn, _host.getUuid()); - hostRec = host.getRecord(conn); - final Pool.Record poolRec = Pool.getAllRecords(conn).values().iterator().next(); - _host.setPool(poolRec.uuid); - - } catch (final Exception e) { - throw new ConfigurationException("Can not get host information from " + _host.getIp()); - } - if (!hostRec.address.equals(_host.getIp())) { - final String msg = "Host " + _host.getIp() + " seems be reinstalled, please remove this host and readd"; - s_logger.error(msg); - throw new ConfigurationException(msg); - } - } finally { - try { - Session.logout(conn); - } catch (final Exception e) { - } + protected String getArgsString(final Map args) { + final StringBuilder argString = new StringBuilder(); + for (final Map.Entry arg : args.entrySet()) { + argString.append(arg.getKey() + ": " + arg.getValue() + ", "); } + return argString.toString(); } - public CreateAnswer execute(final CreateCommand cmd) { - final Connection conn = getConnection(); - final StorageFilerTO pool = cmd.getPool(); - final DiskProfile dskch = cmd.getDiskCharacteristics(); - VDI vdi = null; - try { - final SR poolSr = getStorageRepository(conn, pool.getUuid()); - if (cmd.getTemplateUrl() != null) { - VDI tmpltvdi = null; - tmpltvdi = getVDIbyUuid(conn, cmd.getTemplateUrl()); - vdi = tmpltvdi.createClone(conn, new HashMap()); - vdi.setNameLabel(conn, dskch.getName()); - } else { - final VDI.Record vdir = new VDI.Record(); - vdir.nameLabel = dskch.getName(); - vdir.SR = poolSr; - vdir.type = Types.VdiType.USER; - - vdir.virtualSize = dskch.getSize(); - vdi = VDI.create(conn, vdir); - } - - VDI.Record vdir; - vdir = vdi.getRecord(conn); - s_logger.debug("Succesfully created VDI for " + cmd + ". Uuid = " + vdir.uuid); - - final VolumeTO vol = - new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), vdir.nameLabel, pool.getPath(), vdir.uuid, vdir.virtualSize, null); - return new CreateAnswer(cmd, vol); - } catch (final Exception e) { - s_logger.warn("Unable to create volume; Pool=" + pool + "; Disk: " + dskch, e); - return new CreateAnswer(cmd, e); - } + @Override + public Map getConfigParams() { + return null; } - public Answer execute(final ResizeVolumeCommand cmd) { - final Connection conn = getConnection(); - final String volid = cmd.getPath(); - final long newSize = cmd.getNewSize(); - - try { - final VDI vdi = getVDIbyUuid(conn, volid); - vdi.resize(conn, newSize); - return new ResizeVolumeAnswer(cmd, true, "success", newSize); - } catch (final Exception e) { - s_logger.warn("Unable to resize volume", e); - final String error = "failed to resize volume:" + e; - return new ResizeVolumeAnswer(cmd, false, error); - } + public Connection getConnection() { + return ConnPool.connect(_host.getUuid(), _host.getPool(), _host.getIp(), _username, _password, _wait); } - public SR getISOSRbyVmName(final Connection conn, final String vmName) { - try { - final Set srs = SR.getByNameLabel(conn, vmName + "-ISO"); - if (srs.size() == 0) { - return null; - } else if (srs.size() == 1) { - return srs.iterator().next(); - } else { - final String msg = "getIsoSRbyVmName failed due to there are more than 1 SR having same Label"; - s_logger.warn(msg); + protected Pair getControlDomain(final Connection conn) throws XenAPIException, XmlRpcException { + final Host host = Host.getByUuid(conn, _host.getUuid()); + Set vms = null; + vms = host.getResidentVMs(conn); + for (final VM vm : vms) { + if (vm.getIsControlDomain(conn)) { + return new Pair(vm, vm.getRecord(conn)); + } + } + + throw new CloudRuntimeException("Com'on no control domain? What the crap?!#@!##$@"); + } + + protected VIF getCorrectVif(final Connection conn, final VM router, final IpAddressTO ip) throws XmlRpcException, XenAPIException { + final NicTO nic = new NicTO(); + nic.setType(ip.getTrafficType()); + nic.setName(ip.getNetworkName()); + if (ip.getBroadcastUri() == null) { + nic.setBroadcastType(BroadcastDomainType.Native); + } else { + final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); + nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); + nic.setBroadcastUri(uri); + } + final Network network = getNetwork(conn, nic); + // Determine the correct VIF on DomR to associate/disassociate the + // IP address with + final Set routerVIFs = router.getVIFs(conn); + for (final VIF vif : routerVIFs) { + final Network vifNetwork = vif.getNetwork(conn); + if (vifNetwork.getUuid(conn).equals(network.getUuid(conn))) { + return vif; } - } catch (final XenAPIException e) { - final String msg = "getIsoSRbyVmName failed due to " + e.toString(); - s_logger.warn(msg, e); - } catch (final Exception e) { - final String msg = "getIsoSRbyVmName failed due to " + e.getMessage(); - s_logger.warn(msg, e); } return null; } - protected SR createNfsSRbyURI(final Connection conn, final URI uri, final boolean shared) { - try { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating a " + (shared ? "shared SR for " : "not shared SR for ") + uri); + protected VIF getCorrectVif(final Connection conn, final VM router, final Network network) throws XmlRpcException, XenAPIException { + final Set routerVIFs = router.getVIFs(conn); + for (final VIF vif : routerVIFs) { + final Network vifNetwork = vif.getNetwork(conn); + if (vifNetwork.getUuid(conn).equals(network.getUuid(conn))) { + return vif; } + } - final Map deviceConfig = new HashMap(); - String path = uri.getPath(); - path = path.replace("//", "/"); - deviceConfig.put("server", uri.getHost()); - deviceConfig.put("serverpath", path); - final String name = UUID.nameUUIDFromBytes(new String(uri.getHost() + path).getBytes()).toString(); - if (!shared) { - final Set srs = SR.getByNameLabel(conn, name); - for (final SR sr : srs) { - final SR.Record record = sr.getRecord(conn); - if (SRType.NFS.equals(record.type) && record.contentType.equals("user") && !record.shared) { - removeSRSync(conn, sr); + return null; + } + + @Override + public PingCommand getCurrentStatus(final long id) { + try { + if (!pingXAPI()) { + Thread.sleep(1000); + if (!pingXAPI()) { + s_logger.warn("can not ping xenserver " + _host.getUuid()); + return null; + } + } + final Connection conn = getConnection(); + if (!_canBridgeFirewall && !_isOvs) { + return new PingRoutingCommand(getType(), id, getHostVmStateReport(conn)); + } else if (_isOvs) { + final List> ovsStates = ovsFullSyncStates(); + return new PingRoutingWithOvsCommand(getType(), id, getHostVmStateReport(conn), ovsStates); + } else { + final HashMap> nwGrpStates = syncNetworkGroups(conn, id); + return new PingRoutingWithNwGroupsCommand(getType(), id, getHostVmStateReport(conn), nwGrpStates); + } + } catch (final Exception e) { + s_logger.warn("Unable to get current status", e); + return null; + } + } + + protected double getDataAverage(final Node dataNode, final int col, final int numRows) { + double value = 0; + final double dummy = 0; + int numRowsUsed = 0; + for (int row = 0; row < numRows; row++) { + final Node data = dataNode.getChildNodes().item(numRows - 1 - row).getChildNodes().item(col + 1); + final Double currentDataAsDouble = Double.valueOf(getXMLNodeValue(data)); + if (!currentDataAsDouble.equals(Double.NaN)) { + numRowsUsed += 1; + value += currentDataAsDouble; + } + } + + if (numRowsUsed == 0) { + if (!Double.isInfinite(value) && !Double.isNaN(value)) { + return value; + } else { + s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows=0"); + return dummy; + } + } else { + if (!Double.isInfinite(value / numRowsUsed) && !Double.isNaN(value / numRowsUsed)) { + return value / numRowsUsed; + } else { + s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows>0"); + return dummy; + } + } + + } + + public HashMap> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException { + return null; + } + + protected String getGuestOsType(final String stdType, String platformEmulator, final boolean bootFromCD) { + if (platformEmulator == null) { + s_logger.debug("no guest OS type, start it as HVM guest"); + platformEmulator = "Other install media"; + } + return platformEmulator; + } + + public XsHost getHost() { + return _host; + } + + protected boolean getHostInfo(final Connection conn) throws IllegalArgumentException { + try { + final Host myself = Host.getByUuid(conn, _host.getUuid()); + Set hcs = null; + for (int i = 0; i < 10; i++) { + hcs = myself.getHostCPUs(conn); + if(hcs != null) { + _host.setCpus(hcs.size()); + if (_host.getCpus() > 0) { + break; } } + Thread.sleep(5000); + } + if (_host.getCpus() <= 0) { + throw new CloudRuntimeException("Cannot get the numbers of cpu from XenServer host " + _host.getIp()); + } + final Map cpuInfo = myself.getCpuInfo(conn); + if (cpuInfo.get("socket_count") != null) { + _host.setCpuSockets(Integer.parseInt(cpuInfo.get("socket_count"))); + } + // would hcs be null we would have thrown an exception on condition (_host.getCpus() <= 0) by now + for (final HostCpu hc : hcs) { + _host.setSpeed(hc.getSpeed(conn).intValue()); + break; + } + final Host.Record hr = myself.getRecord(conn); + _host.setProductVersion(CitrixHelper.getProductVersion(hr)); + + final XsLocalNetwork privateNic = getManagementNetwork(conn); + _privateNetworkName = privateNic.getNetworkRecord(conn).nameLabel; + _host.setPrivatePif(privateNic.getPifRecord(conn).uuid); + _host.setPrivateNetwork(privateNic.getNetworkRecord(conn).uuid); + _host.setSystemvmisouuid(null); + + XsLocalNetwork guestNic = null; + if (_guestNetworkName != null && !_guestNetworkName.equals(_privateNetworkName)) { + guestNic = getNetworkByName(conn, _guestNetworkName); + if (guestNic == null) { + s_logger.warn("Unable to find guest network " + _guestNetworkName); + throw new IllegalArgumentException("Unable to find guest network " + _guestNetworkName + " for host " + _host.getIp()); + } + } else { + guestNic = privateNic; + _guestNetworkName = _privateNetworkName; + } + _host.setGuestNetwork(guestNic.getNetworkRecord(conn).uuid); + _host.setGuestPif(guestNic.getPifRecord(conn).uuid); + + XsLocalNetwork publicNic = null; + if (_publicNetworkName != null && !_publicNetworkName.equals(_guestNetworkName)) { + publicNic = getNetworkByName(conn, _publicNetworkName); + if (publicNic == null) { + s_logger.warn("Unable to find public network " + _publicNetworkName + " for host " + _host.getIp()); + throw new IllegalArgumentException("Unable to find public network " + _publicNetworkName + " for host " + _host.getIp()); + } + } else { + publicNic = guestNic; + _publicNetworkName = _guestNetworkName; + } + _host.setPublicPif(publicNic.getPifRecord(conn).uuid); + _host.setPublicNetwork(publicNic.getNetworkRecord(conn).uuid); + if (_storageNetworkName1 == null) { + _storageNetworkName1 = _guestNetworkName; + } + XsLocalNetwork storageNic1 = null; + storageNic1 = getNetworkByName(conn, _storageNetworkName1); + if (storageNic1 == null) { + s_logger.warn("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.getIp()); + throw new IllegalArgumentException("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.getIp()); + } else { + _host.setStorageNetwork1(storageNic1.getNetworkRecord(conn).uuid); + _host.setStoragePif1(storageNic1.getPifRecord(conn).uuid); } - final Host host = Host.getByUuid(conn, _host.getUuid()); - final Map smConfig = new HashMap(); - smConfig.put("nosubdir", "true"); - final SR sr = SR.create(conn, host, deviceConfig, new Long(0), name, uri.getHost() + uri.getPath(), SRType.NFS.toString(), "user", shared, smConfig); - - if (!checkSR(conn, sr)) { - throw new Exception("no attached PBD"); - } - if (s_logger.isDebugEnabled()) { - s_logger.debug(logX(sr, "Created a SR; UUID is " + sr.getUuid(conn) + " device config is " + deviceConfig)); - } - sr.scan(conn); - return sr; - } catch (final XenAPIException e) { - final String msg = "Can not create second storage SR mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); - } catch (final Exception e) { - final String msg = "Can not create second storage SR mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.getMessage(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); - } - } - - protected SR createIsoSRbyURI(final Connection conn, final URI uri, final String vmName, final boolean shared) { - try { - final Map deviceConfig = new HashMap(); - String path = uri.getPath(); - path = path.replace("//", "/"); - deviceConfig.put("location", uri.getHost() + ":" + path); - final Host host = Host.getByUuid(conn, _host.getUuid()); - final SR sr = SR.create(conn, host, deviceConfig, new Long(0), uri.getHost() + path, "iso", "iso", "iso", shared, new HashMap()); - sr.setNameLabel(conn, vmName + "-ISO"); - sr.setNameDescription(conn, deviceConfig.get("location")); - - sr.scan(conn); - return sr; - } catch (final XenAPIException e) { - final String msg = "createIsoSRbyURI failed! mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); - } catch (final Exception e) { - final String msg = "createIsoSRbyURI failed! mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.getMessage(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); - } - } - - protected VDI getVDIbyLocationandSR(final Connection conn, final String loc, final SR sr) { - try { - final Set vdis = sr.getVDIs(conn); - for (final VDI vdi : vdis) { - if (vdi.getLocation(conn).startsWith(loc)) { - return vdi; + XsLocalNetwork storageNic2 = null; + if (_storageNetworkName2 != null) { + storageNic2 = getNetworkByName(conn, _storageNetworkName2); + if(storageNic2 != null) { + _host.setStoragePif2(storageNic2.getPifRecord(conn).uuid); } } - final String msg = "can not getVDIbyLocationandSR " + loc; - s_logger.warn(msg); - return null; + s_logger.info("XenServer Version is " + _host.getProductVersion() + " for host " + _host.getIp()); + s_logger.info("Private Network is " + _privateNetworkName + " for host " + _host.getIp()); + s_logger.info("Guest Network is " + _guestNetworkName + " for host " + _host.getIp()); + s_logger.info("Public Network is " + _publicNetworkName + " for host " + _host.getIp()); + + return true; } catch (final XenAPIException e) { - final String msg = "getVDIbyLocationandSR exception " + loc + " due to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); + s_logger.warn("Unable to get host information for " + _host.getIp(), e); + return false; } catch (final Exception e) { - final String msg = "getVDIbyLocationandSR exception " + loc + " due to " + e.getMessage(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); + s_logger.warn("Unable to get host information for " + _host.getIp(), e); + return false; + } + } + + public HostStatsEntry getHostStats(final Connection conn, final GetHostStatsCommand cmd, final String hostGuid, final long hostId) { + + final HostStatsEntry hostStats = new HostStatsEntry(hostId, 0, 0, 0, "host", 0, 0, 0, 0); + final Object[] rrdData = getRRDData(conn, 1); // call rrd method with 1 for host + + if (rrdData == null) { + return null; } - } + final Integer numRows = (Integer)rrdData[0]; + final Integer numColumns = (Integer)rrdData[1]; + final Node legend = (Node)rrdData[2]; + final Node dataNode = (Node)rrdData[3]; - public VDI getVDIbyUuid(final Connection conn, final String uuid) { - return getVDIbyUuid(conn, uuid, true); - } + final NodeList legendChildren = legend.getChildNodes(); + for (int col = 0; col < numColumns; col++) { - public VDI getVDIbyUuid(final Connection conn, final String uuid, final boolean throwExceptionIfNotFound) { - try { - return VDI.getByUuid(conn, uuid); - } catch (final Exception e) { - if (throwExceptionIfNotFound) { - final String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); - - s_logger.debug(msg); - - throw new CloudRuntimeException(msg, e); + if (legendChildren == null || legendChildren.item(col) == null) { + continue; } - return null; + final String columnMetadata = getXMLNodeValue(legendChildren.item(col)); + + if (columnMetadata == null) { + continue; + } + + final String[] columnMetadataList = columnMetadata.split(":"); + + if (columnMetadataList.length != 4) { + continue; + } + + final String type = columnMetadataList[1]; + final String param = columnMetadataList[3]; + + if (type.equalsIgnoreCase("host")) { + + if (param.matches("pif_eth0_rx")) { + hostStats.setNetworkReadKBs(getDataAverage(dataNode, col, numRows)/1000); + } else if (param.matches("pif_eth0_tx")) { + hostStats.setNetworkWriteKBs(getDataAverage(dataNode, col, numRows)/1000); + } else if (param.contains("memory_total_kib")) { + hostStats.setTotalMemoryKBs(getDataAverage(dataNode, col, numRows)); + } else if (param.contains("memory_free_kib")) { + hostStats.setFreeMemoryKBs(getDataAverage(dataNode, col, numRows)); + } else if (param.matches("cpu_avg")) { + // hostStats.setNumCpus(hostStats.getNumCpus() + 1); + hostStats.setCpuUtilization(hostStats.getCpuUtilization() + getDataAverage(dataNode, col, numRows)); + } + + /* + if (param.contains("loadavg")) { + hostStats.setAverageLoad((hostStats.getAverageLoad() + getDataAverage(dataNode, col, numRows))); + } + */ + } } + + // add the host cpu utilization + /* + if (hostStats.getNumCpus() != 0) { + hostStats.setCpuUtilization(hostStats.getCpuUtilization() / hostStats.getNumCpus()); + s_logger.debug("Host cpu utilization " + hostStats.getCpuUtilization()); + } + */ + + return hostStats; + } + + protected HashMap getHostVmStateReport(final Connection conn) { + + // TODO : new VM sync model does not require a cluster-scope report, we need to optimize + // the report accordingly + final HashMap vmStates = new HashMap(); + Map vm_map = null; + for (int i = 0; i < 2; i++) { + try { + vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER + break; + } catch (final Throwable e) { + s_logger.warn("Unable to get vms", e); + } + try { + Thread.sleep(1000); + } catch (final InterruptedException ex) { + + } + } + + if (vm_map == null) { + return vmStates; + } + for (final VM.Record record : vm_map.values()) { + if (record.isControlDomain || record.isASnapshot || record.isATemplate) { + continue; // Skip DOM0 + } + + final VmPowerState ps = record.powerState; + final Host host = record.residentOn; + String host_uuid = null; + if (!isRefNull(host)) { + try { + host_uuid = host.getUuid(conn); + } catch (final BadServerResponse e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } catch (final XenAPIException e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } catch (final XmlRpcException e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } + + if (host_uuid.equalsIgnoreCase(_host.getUuid())) { + vmStates.put( + record.nameLabel, + new HostVmStateReportEntry(convertToPowerState(ps), host_uuid) + ); + } + } + } + + return vmStates; } public SR getIscsiSR(final Connection conn, final String srNameLabel, final String target, String path, final String chapInitiatorUsername, final String chapInitiatorPassword, @@ -5940,6 +2702,406 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } + public SR getISOSRbyVmName(final Connection conn, final String vmName) { + try { + final Set srs = SR.getByNameLabel(conn, vmName + "-ISO"); + if (srs.size() == 0) { + return null; + } else if (srs.size() == 1) { + return srs.iterator().next(); + } else { + final String msg = "getIsoSRbyVmName failed due to there are more than 1 SR having same Label"; + s_logger.warn(msg); + } + } catch (final XenAPIException e) { + final String msg = "getIsoSRbyVmName failed due to " + e.toString(); + s_logger.warn(msg, e); + } catch (final Exception e) { + final String msg = "getIsoSRbyVmName failed due to " + e.getMessage(); + s_logger.warn(msg, e); + } + return null; + } + + public VDI getIsoVDIByURL(final Connection conn, final String vmName, final String isoURL) { + SR isoSR = null; + String mountpoint = null; + if (isoURL.startsWith("xs-tools")) { + try { + final Set vdis = VDI.getByNameLabel(conn, isoURL); + if (vdis.isEmpty()) { + throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL); + } + return vdis.iterator().next(); + + } catch (final XenAPIException e) { + throw new CloudRuntimeException("Unable to get pv iso: " + isoURL + " due to " + e.toString()); + } catch (final Exception e) { + throw new CloudRuntimeException("Unable to get pv iso: " + isoURL + " due to " + e.toString()); + } + } + + final int index = isoURL.lastIndexOf("/"); + mountpoint = isoURL.substring(0, index); + + URI uri; + try { + uri = new URI(mountpoint); + } catch (final URISyntaxException e) { + throw new CloudRuntimeException("isoURL is wrong: " + isoURL); + } + isoSR = getISOSRbyVmName(conn, vmName); + if (isoSR == null) { + isoSR = createIsoSRbyURI(conn, uri, vmName, false); + } + + final String isoName = isoURL.substring(index + 1); + + final VDI isoVDI = getVDIbyLocationandSR(conn, isoName, isoSR); + + if (isoVDI != null) { + return isoVDI; + } else { + throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL); + } + } + + public String getLabel() { + final Connection conn = getConnection(); + final String result = callHostPlugin(conn, "ovstunnel", "getLabel"); + return result; + } + + protected SR getLocalEXTSR(final Connection conn) { + try { + final Map map = SR.getAllRecords(conn); + if(map != null && !map.isEmpty()) { + for (final Map.Entry entry : map.entrySet()) { + final SR.Record srRec = entry.getValue(); + if (SRType.FILE.equals(srRec.type) || SRType.EXT.equals(srRec.type)) { + final Set pbds = srRec.PBDs; + if (pbds == null) { + continue; + } + for (final PBD pbd : pbds) { + final Host host = pbd.getHost(conn); + if (!isRefNull(host) && host.getUuid(conn).equals(_host.getUuid())) { + if (!pbd.getCurrentlyAttached(conn)) { + pbd.plug(conn); + } + final SR sr = entry.getKey(); + sr.scan(conn); + return sr; + } + } + } + } + } + } catch (final XenAPIException e) { + final String msg = "Unable to get local EXTSR in host:" + _host.getUuid() + e.toString(); + s_logger.warn(msg); + } catch (final XmlRpcException e) { + final String msg = "Unable to get local EXTSR in host:" + _host.getUuid() + e.getCause(); + s_logger.warn(msg); + } + return null; + } + + protected SR getLocalLVMSR(final Connection conn) { + try { + final Map map = SR.getAllRecords(conn); + if(map != null && !map.isEmpty()) { + for (final Map.Entry entry : map.entrySet()) { + final SR.Record srRec = entry.getValue(); + if (SRType.LVM.equals(srRec.type)) { + final Set pbds = srRec.PBDs; + if (pbds == null) { + continue; + } + for (final PBD pbd : pbds) { + final Host host = pbd.getHost(conn); + if (!isRefNull(host) && host.getUuid(conn).equals(_host.getUuid())) { + if (!pbd.getCurrentlyAttached(conn)) { + pbd.plug(conn); + } + final SR sr = entry.getKey(); + sr.scan(conn); + return sr; + } + } + } + } + } + } catch (final XenAPIException e) { + final String msg = "Unable to get local LVMSR in host:" + _host.getUuid() + e.toString(); + s_logger.warn(msg); + } catch (final XmlRpcException e) { + final String msg = "Unable to get local LVMSR in host:" + _host.getUuid() + e.getCause(); + s_logger.warn(msg); + } + return null; + } + + public String getLowestAvailableVIFDeviceNum(final Connection conn, final VM vm) { + String vmName = ""; + try { + vmName = vm.getNameLabel(conn); + final List usedDeviceNums = new ArrayList(); + final Set vifs = vm.getVIFs(conn); + final Iterator vifIter = vifs.iterator(); + while (vifIter.hasNext()) { + final VIF vif = vifIter.next(); + try { + final String deviceId = vif.getDevice(conn); + if(vm.getIsControlDomain(conn) || vif.getCurrentlyAttached(conn)) { + usedDeviceNums.add(Integer.valueOf(deviceId)); + } else { + s_logger.debug("Found unplugged VIF " + deviceId + " in VM " + vmName + " destroy it"); + vif.destroy(conn); + } + } catch (final NumberFormatException e) { + final String msg = "Obtained an invalid value for an allocated VIF device number for VM: " + vmName; + s_logger.debug(msg, e); + throw new CloudRuntimeException(msg); + } + } + + for (Integer i = 0; i < _maxNics; i++) { + if (!usedDeviceNums.contains(i)) { + s_logger.debug("Lowest available Vif device number: " + i + " for VM: " + vmName); + return i.toString(); + } + } + } catch (final XmlRpcException e) { + final String msg = "Caught XmlRpcException: " + e.getMessage(); + s_logger.warn(msg, e); + } catch (final XenAPIException e) { + final String msg = "Caught XenAPIException: " + e.toString(); + s_logger.warn(msg, e); + } + + throw new CloudRuntimeException("Could not find available VIF slot in VM with name: " + vmName); + } + + protected XsLocalNetwork getManagementNetwork(final Connection conn) throws XmlRpcException, XenAPIException { + PIF mgmtPif = null; + PIF.Record mgmtPifRec = null; + final Host host = Host.getByUuid(conn, _host.getUuid()); + final Set hostPifs = host.getPIFs(conn); + for (final PIF pif : hostPifs) { + final PIF.Record rec = pif.getRecord(conn); + if (rec.management) { + if (rec.VLAN != null && rec.VLAN != -1) { + final String msg = + new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.getUuid()) + .append("; pif=") + .append(rec.uuid) + .append("; vlan=") + .append(rec.VLAN) + .toString(); + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Management network is on pif=" + rec.uuid); + } + mgmtPif = pif; + mgmtPifRec = rec; + break; + } + } + if (mgmtPif == null) { + final String msg = "Unable to find management network for " + _host.getUuid(); + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + final Bond bond = mgmtPifRec.bondSlaveOf; + if (!isRefNull(bond)) { + final String msg = + "Management interface is on slave(" + mgmtPifRec.uuid + ") of bond(" + bond.getUuid(conn) + ") on host(" + _host.getUuid() + + "), please move management interface to bond!"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + final Network nk = mgmtPifRec.network; + final Network.Record nkRec = nk.getRecord(conn); + return new XsLocalNetwork(this, nk, nkRec, mgmtPif, mgmtPifRec); + } + + @Override + public String getName() { + return _name; + } + + 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); + } + return getNetworkByName(conn, name); + } + + if (type == TrafficType.Guest) { + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getGuestNetwork()), null, PIF.getByUuid(conn, _host.getGuestPif()), null); + } else if (type == TrafficType.Control) { + setupLinkLocalNetwork(conn); + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getLinkLocalNetwork())); + } else if (type == TrafficType.Management) { + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPrivateNetwork()), null, PIF.getByUuid(conn, _host.getPrivatePif()), null); + } else if (type == TrafficType.Public) { + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPublicNetwork()), null, PIF.getByUuid(conn, _host.getPublicPif()), null); + } else if (type == TrafficType.Storage) { + /* TrafficType.Storage is for secondary storage, while storageNetwork1 is for primary storage, we need better name here */ + return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getStorageNetwork1()), null, PIF.getByUuid(conn, _host.getStoragePif1()), null); + } + + throw new CloudRuntimeException("Unsupported network type: " + type); + } + + public Network getNetwork(final Connection conn, final NicTO nic) throws XenAPIException, XmlRpcException { + final String name = nic.getName(); + final XsLocalNetwork network = getNativeNetworkForTraffic(conn, nic.getType(), name); + if (network == null) { + s_logger.error("Network is not configured on the backend for nic " + nic.toString()); + throw new CloudRuntimeException("Network for the backend is not configured correctly for network broadcast domain: " + nic.getBroadcastUri()); + } + final URI uri = nic.getBroadcastUri(); + final BroadcastDomainType type = nic.getBroadcastType(); + if (uri != null && uri.toString().contains("untagged")) { + return network.getNetwork(); + } else if (uri != null && type == BroadcastDomainType.Vlan) { + assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Vlan; + final long vlan = Long.parseLong(BroadcastDomainType.getValue(uri)); + return enableVlanNetwork(conn, vlan, network); + } else if (type == BroadcastDomainType.Native || type == BroadcastDomainType.LinkLocal || + type == BroadcastDomainType.Vsp) { + return network.getNetwork(); + } else if (uri != null && type == BroadcastDomainType.Vswitch) { + final String header = uri.toString().substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length()); + if (header.startsWith("vlan")) { + _isOvs = true; + return setupvSwitchNetwork(conn); + } else { + return findOrCreateTunnelNetwork(conn, getOvsTunnelNetworkName(uri.getAuthority())); + } + } else if (type == BroadcastDomainType.Storage) { + if (uri == null) { + return network.getNetwork(); + } else { + final long vlan = Long.parseLong(BroadcastDomainType.getValue(uri)); + return enableVlanNetwork(conn, vlan, network); + } + } else if (type == BroadcastDomainType.Lswitch) { + // Nicira Logical Switch + return network.getNetwork(); + } else if (uri != null && type == BroadcastDomainType.Pvlan) { + assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Pvlan; + // should we consider moving this NetUtils method to BroadcastDomainType? + final long vlan = Long.parseLong(NetUtils.getPrimaryPvlanFromUri(uri)); + return enableVlanNetwork(conn, vlan, network); + } + + throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri()); + } + + /** + * getNetworkByName() retrieves what the server thinks is the actual + * network used by the XenServer host. This method should always be + * used to talk to retrieve a network by the name. The reason is + * because of the problems in using the name label as the way to find + * the Network. + * + * To see how we are working around these problems, take a look at + * enableVlanNetwork(). The following description assumes you have looked + * at the description on that method. + * + * In order to understand this, we have to see what type of networks are + * within a XenServer that's under CloudStack control. + * + * - Native Networks: these are networks that are untagged on the + * XenServer and are used to crate VLAN networks on. These are + * created by the user and is assumed to be one per cluster. + * - VLAN Networks: these are dynamically created by CloudStack and can + * have problems with duplicated names. + * - LinkLocal Networks: these are dynamically created by CloudStack and + * can also have problems with duplicated names but these don't have + * actual PIFs. + * + * In order to speed to retrieval of a network, we do the following: + * - We retrieve by the name. If only one network is retrieved, we + * assume we retrieved the right network. + * - If more than one network is retrieved, we check to see which one + * has the pif for the local host and use that. + * - If a pif is not found, then we look at the tags and find the + * one with the lowest timestamp. (See enableVlanNetwork()) + * + * @param conn Xapi connection + * @param name name of the network + * @return XsNic an object that contains network, network record, pif, and pif record. + * @throws XenAPIException + * @throws XmlRpcException + * + * @see CitrixResourceBase#enableVlanNetwork + */ + public XsLocalNetwork getNetworkByName(final Connection conn, final String name) throws XenAPIException, XmlRpcException { + final Set networks = Network.getByNameLabel(conn, name); + if (networks.size() == 1) { + return new XsLocalNetwork(this, networks.iterator().next(), null, null, null); + } + + if (networks.size() == 0) { + return null; + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found more than one network with the name " + name); + } + Network earliestNetwork = null; + Network.Record earliestNetworkRecord = null; + long earliestTimestamp = Long.MAX_VALUE; + int earliestRandom = Integer.MAX_VALUE; + for (final Network network : networks) { + final XsLocalNetwork nic = new XsLocalNetwork(this, network); + + if (nic.getPif(conn) != null) { + return nic; + } + + final Network.Record record = network.getRecord(conn); + if (record.tags != null) { + for (final String tag : record.tags) { + final Pair stamp = parseTimestamp(tag); + if (stamp == null) { + continue; + } + + if (stamp.first() < earliestTimestamp || stamp.first() == earliestTimestamp && stamp.second() < earliestRandom) { + earliestTimestamp = stamp.first(); + earliestRandom = stamp.second(); + earliestNetwork = network; + earliestNetworkRecord = record; + } + } + } + } + + return earliestNetwork != null ? new XsLocalNetwork(this, earliestNetwork, earliestNetworkRecord, null, null) : null; + } + + protected long[] getNetworkStats(final Connection conn, final String privateIP) { + final String result = networkUsage(conn, privateIP, "get", null); + final long[] stats = new long[2]; + if (result != null) { + final String[] splitResult = result.split(":"); + int i = 0; + while (i < splitResult.length - 1) { + stats[0] += new Long(splitResult[i++]).longValue(); + stats[1] += new Long(splitResult[i++]).longValue(); + } + } + return stats; + } + public SR getNfsSR(final Connection conn, final String poolid, final String uuid, final String server, String serverpath, final String pooldesc) { final Map deviceConfig = new HashMap(); try { @@ -5994,181 +3156,326 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - public Answer execute(final DestroyCommand cmd) { - final Connection conn = getConnection(); - final VolumeTO vol = cmd.getVolume(); - // Look up the VDI - final String volumeUUID = vol.getPath(); - VDI vdi = null; - try { - vdi = getVDIbyUuid(conn, volumeUUID); - } catch (final Exception e) { - return new Answer(cmd, true, "Success"); - } - Set vbds = null; - try { - vbds = vdi.getVBDs(conn); - } catch (final Exception e) { - final String msg = "VDI getVBDS for " + volumeUUID + " failed due to " + e.toString(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } - for (final VBD vbd : vbds) { - try { - vbd.unplug(conn); - vbd.destroy(conn); - } catch (final Exception e) { - final String msg = "VM destroy for " + volumeUUID + " failed due to " + e.toString(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } - } - try { - final Set snapshots = vdi.getSnapshots(conn); - for (final VDI snapshot : snapshots) { - snapshot.destroy(conn); - } - vdi.destroy(conn); - } catch (final Exception e) { - final String msg = "VDI destroy for " + volumeUUID + " failed due to " + e.toString(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } - - return new Answer(cmd, true, "Success"); - } - - public VDI createVdi(final SR sr, final String vdiNameLabel, final Long volumeSize) throws Types.XenAPIException, XmlRpcException { - final Connection conn = getConnection(); - - final VDI.Record vdir = new VDI.Record(); - - vdir.nameLabel = vdiNameLabel; - vdir.SR = sr; - vdir.type = Types.VdiType.USER; - - final long totalSrSpace = sr.getPhysicalSize(conn); - final long unavailableSrSpace = sr.getPhysicalUtilisation(conn); - final long availableSrSpace = totalSrSpace - unavailableSrSpace; - - if (availableSrSpace < volumeSize) { - throw new CloudRuntimeException("Available space for SR cannot be less than " + volumeSize + "."); - } - - vdir.virtualSize = volumeSize; - - return VDI.create(conn, vdir); - } - - public void handleSrAndVdiDetach(final String iqn, final Connection conn) throws Exception { - final SR sr = getStorageRepository(conn, iqn); - - removeSR(conn, sr); - } - - protected AttachVolumeAnswer execute(final AttachVolumeCommand cmd) { - final Connection conn = getConnection(); - final boolean attach = cmd.getAttach(); - final String vmName = cmd.getVmName(); - final String vdiNameLabel = vmName + "-DATA"; - final Long deviceId = cmd.getDeviceId(); - - String errorMsg; - if (attach) { - errorMsg = "Failed to attach volume"; + private String getOvsTunnelNetworkName(final String broadcastUri) { + if (broadcastUri.contains(".")) { + final String[] parts = broadcastUri.split("\\."); + return "OVS-DR-VPC-Bridge"+parts[0]; } else { - errorMsg = "Failed to detach volume"; + try { + return "OVSTunnel" + broadcastUri; + } catch (final Exception e) { + return null; + } } + } + + protected List getPatchFiles() { + return null; + } + + public String getPerfMon(final Connection conn, final Map params, + final int wait) { + String result = null; + try { + result = callHostPluginAsync(conn, "vmopspremium", "asmonitor", 60, + params); + if (result != null) { + return result; + } + } catch (final Exception e) { + s_logger.error("Can not get performance monitor for AS due to ", e); + } + return null; + } + + protected Object[] getRRDData(final Connection conn, final int flag) { + + /* + * Note: 1 => called from host, hence host stats 2 => called from vm, hence vm stats + */ + Document doc = null; try { - VDI vdi = null; + doc = getStatsRawXML(conn, flag == 1 ? true : false); + } catch (final Exception e1) { + s_logger.warn("Error whilst collecting raw stats from plugin: ", e1); + return null; + } - if (cmd.getAttach() && cmd.isManaged()) { - final SR sr = getIscsiSR(conn, cmd.get_iScsiName(), cmd.getStorageHost(), cmd.get_iScsiName(), cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), true); + if (doc == null) { //stats are null when the host plugin call fails (host down state) + return null; + } - vdi = getVDIbyUuid(conn, cmd.getVolumePath(), false); + final NodeList firstLevelChildren = doc.getChildNodes(); + final NodeList secondLevelChildren = firstLevelChildren.item(0).getChildNodes(); + final Node metaNode = secondLevelChildren.item(0); + final Node dataNode = secondLevelChildren.item(1); - if (vdi == null) { - vdi = createVdi(sr, vdiNameLabel, cmd.getVolumeSize()); - } - } else { - vdi = getVDIbyUuid(conn, cmd.getVolumePath()); + Integer numRows = 0; + Integer numColumns = 0; + Node legend = null; + final NodeList metaNodeChildren = metaNode.getChildNodes(); + for (int i = 0; i < metaNodeChildren.getLength(); i++) { + final Node n = metaNodeChildren.item(i); + if (n.getNodeName().equals("rows")) { + numRows = Integer.valueOf(getXMLNodeValue(n)); + } else if (n.getNodeName().equals("columns")) { + numColumns = Integer.valueOf(getXMLNodeValue(n)); + } else if (n.getNodeName().equals("legend")) { + legend = n; } + } - // Look up the VM - final VM vm = getVM(conn, vmName); - if (attach) { - // Figure out the disk number to attach the VM to - String diskNumber = null; - if (deviceId != null) { - if (deviceId.longValue() == 3) { - final String msg = "Device 3 is reserved for CD-ROM, choose other device"; - return new AttachVolumeAnswer(cmd, msg); + return new Object[] { numRows, numColumns, legend, dataNode }; + } + + @Override + public int getRunLevel() { + return 0; + } + + protected SR getSRByNameLabelandHost(final Connection conn, final String name) throws BadServerResponse, XenAPIException, XmlRpcException { + final Set srs = SR.getByNameLabel(conn, name); + SR ressr = null; + for (final SR sr : srs) { + Set pbds; + pbds = sr.getPBDs(conn); + for (final PBD pbd : pbds) { + final PBD.Record pbdr = pbd.getRecord(conn); + if (pbdr.host != null && pbdr.host.getUuid(conn).equals(_host.getUuid())) { + if (!pbdr.currentlyAttached) { + pbd.plug(conn); } - if (isDeviceUsed(conn, vm, deviceId)) { - final String msg = "Device " + deviceId + " is used in VM " + vmName; - return new AttachVolumeAnswer(cmd, msg); - } - diskNumber = deviceId.toString(); - } else { - diskNumber = getUnusedDeviceNum(conn, vm); + ressr = sr; + break; } - // Create a new VBD - final VBD.Record vbdr = new VBD.Record(); - vbdr.VM = vm; - vbdr.VDI = vdi; - vbdr.bootable = false; - vbdr.userdevice = diskNumber; - vbdr.mode = Types.VbdMode.RW; - vbdr.type = Types.VbdType.DISK; - vbdr.unpluggable = true; - final VBD vbd = VBD.create(conn, vbdr); - - // Attach the VBD to the VM - vbd.plug(conn); - - // Update the VDI's label to include the VM name - vdi.setNameLabel(conn, vdiNameLabel); - - return new AttachVolumeAnswer(cmd, Long.parseLong(diskNumber), vdi.getUuid(conn)); - } else { - // Look up all VBDs for this VDI - final Set vbds = vdi.getVBDs(conn); - - // Detach each VBD from its VM, and then destroy it - for (final VBD vbd : vbds) { - final VBD.Record vbdr = vbd.getRecord(conn); - - if (vbdr.currentlyAttached) { - vbd.unplug(conn); - } - - vbd.destroy(conn); - } - - // Update the VDI's label to be "detached" - vdi.setNameLabel(conn, "detached"); - - if (cmd.isManaged()) { - handleSrAndVdiDetach(cmd.get_iScsiName(), conn); - } - - return new AttachVolumeAnswer(cmd); } + } + return ressr; + } + + private long getStaticMax(final String os, final boolean b, final long dynamicMinRam, final long dynamicMaxRam){ + final long recommendedValue = CitrixHelper.getXenServerStaticMax(os, b); + if(recommendedValue == 0){ + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + final long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax){ // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + private long getStaticMin(final String os, final boolean b, final long dynamicMinRam, final long dynamicMaxRam) { + final long recommendedValue = CitrixHelper.getXenServerStaticMin(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + + if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); + } + return dynamicMinRam; + } + + protected Document getStatsRawXML(final Connection conn, final boolean host) { + final Date currentDate = new Date(); + String urlStr = "http://" + _host.getIp() + "/rrd_updates?"; + urlStr += "session_id=" + conn.getSessionReference(); + urlStr += "&host=" + (host ? "true" : "false"); + urlStr += "&cf=" + _consolidationFunction; + urlStr += "&interval=" + _pollingIntervalInSeconds; + urlStr += "&start=" + (currentDate.getTime() / 1000 - 1000 - 100); + + URL url; + BufferedReader in = null; + try { + url = new URL(urlStr); + url.openConnection(); + final URLConnection uc = url.openConnection(); + in = new BufferedReader(new InputStreamReader(uc.getInputStream())); + final InputSource statsSource = new InputSource(in); + return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(statsSource); + } catch (final MalformedURLException e) { + s_logger.warn("Malformed URL? come on...." + urlStr); + return null; + } catch (final IOException e) { + s_logger.warn("Problems getting stats using " + urlStr, e); + return null; + } catch (final SAXException e) { + s_logger.warn("Problems getting stats using " + urlStr, e); + return null; + } catch (final ParserConfigurationException e) { + s_logger.warn("Problems getting stats using " + urlStr, e); + return null; + } finally { + if (in != null) { + try { + in.close(); + } catch (final IOException e) { + s_logger.warn("Unable to close the buffer ", e); + } + } + } + } + + public SR getStorageRepository(final Connection conn, final String srNameLabel) { + Set srs; + try { + srs = SR.getByNameLabel(conn, srNameLabel); } catch (final XenAPIException e) { - final String msg = errorMsg + " for uuid: " + cmd.getVolumePath() + " due to " + e.toString(); - s_logger.warn(msg, e); - return new AttachVolumeAnswer(cmd, msg); + throw new CloudRuntimeException("Unable to get SR " + srNameLabel + " due to " + e.toString(), e); } catch (final Exception e) { - final String msg = errorMsg + " for uuid: " + cmd.getVolumePath() + " due to " + e.getMessage(); + throw new CloudRuntimeException("Unable to get SR " + srNameLabel + " due to " + e.getMessage(), e); + } + + if (srs.size() > 1) { + throw new CloudRuntimeException("More than one storage repository was found for pool with uuid: " + srNameLabel); + } else if (srs.size() == 1) { + final SR sr = srs.iterator().next(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("SR retrieved for " + srNameLabel); + } + + if (checkSR(conn, sr)) { + return sr; + } + throw new CloudRuntimeException("SR check failed for storage pool: " + srNameLabel + "on host:" + _host.getUuid()); + } else { + throw new CloudRuntimeException("Can not see storage pool: " + srNameLabel + " from on host:" + _host.getUuid()); + } + } + + protected Storage.StorageResourceType getStorageResourceType() { + return Storage.StorageResourceType.STORAGE_POOL; + } + + @Override + public Type getType() { + return com.cloud.host.Host.Type.Routing; + } + + public String getUnusedDeviceNum(final Connection conn, final VM vm) { + // Figure out the disk number to attach the VM to + try { + final Set allowedVBDDevices = vm.getAllowedVBDDevices(conn); + if (allowedVBDDevices.size() == 0) { + throw new CloudRuntimeException("Could not find an available slot in VM with name: " + vm.getNameLabel(conn) + " to attach a new disk."); + } + return allowedVBDDevices.iterator().next(); + } catch (final XmlRpcException e) { + final String msg = "Catch XmlRpcException due to: " + e.getMessage(); s_logger.warn(msg, e); - return new AttachVolumeAnswer(cmd, msg); + } catch (final XenAPIException e) { + final String msg = "Catch XenAPIException due to: " + e.toString(); + s_logger.warn(msg, e); + } + throw new CloudRuntimeException("Could not find an available slot in VM with name to attach a new disk."); + } + + protected VDI getVDIbyLocationandSR(final Connection conn, final String loc, final SR sr) { + try { + final Set vdis = sr.getVDIs(conn); + for (final VDI vdi : vdis) { + if (vdi.getLocation(conn).startsWith(loc)) { + return vdi; + } + } + + final String msg = "can not getVDIbyLocationandSR " + loc; + s_logger.warn(msg); + return null; + } catch (final XenAPIException e) { + final String msg = "getVDIbyLocationandSR exception " + loc + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (final Exception e) { + final String msg = "getVDIbyLocationandSR exception " + loc + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); } } - protected void umount(final Connection conn, final VDI vdi) { + public VDI getVDIbyUuid(final Connection conn, final String uuid) { + return getVDIbyUuid(conn, uuid, true); + } + public VDI getVDIbyUuid(final Connection conn, final String uuid, final boolean throwExceptionIfNotFound) { + try { + return VDI.getByUuid(conn, uuid); + } catch (final Exception e) { + if (throwExceptionIfNotFound) { + final String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); + + s_logger.debug(msg); + + throw new CloudRuntimeException(msg, e); + } + + return null; + } + } + + public String getVhdParent(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI) { + final String parentUuid = + callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", + isISCSI.toString()); + + if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { + s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid); + // errString is already logged. + return null; + } + return parentUuid; + } + + public VIF getVifByMac(final Connection conn, final VM router, String mac) throws XmlRpcException, XenAPIException { + final Set routerVIFs = router.getVIFs(conn); + mac = mac.trim(); + for (final VIF vif : routerVIFs) { + final String lmac = vif.getMAC(conn); + if (lmac.trim().equals(mac)) { + return vif; + } + } + return null; + } + + public VirtualRoutingResource getVirtualRoutingResource() { + return _vrResource; + } + + public VM getVM(final Connection conn, final String vmName) { + // Look up VMs with the specified name + Set vms; + try { + vms = VM.getByNameLabel(conn, vmName); + } catch (final XenAPIException e) { + throw new CloudRuntimeException("Unable to get " + vmName + ": " + e.toString(), e); + } catch (final Exception e) { + throw new CloudRuntimeException("Unable to get " + vmName + ": " + e.getMessage(), e); + } + + // If there are no VMs, throw an exception + if (vms.size() == 0) { + throw new CloudRuntimeException("VM with name: " + vmName + " does not exist."); + } + + // If there is more than one VM, print a warning + if (vms.size() > 1) { + s_logger.warn("Found " + vms.size() + " VMs with name: " + vmName); + } + + // Return the first VM in the set + return vms.iterator().next(); + } + + public String getVMInstanceName() { + return _instance; } public long getVMSnapshotChainSize(final Connection conn, final VolumeObjectTO volumeTo, final String vmName) throws BadServerResponse, XenAPIException, XmlRpcException { @@ -6218,540 +3525,624 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return size; } - protected Answer execute(final CreateVMSnapshotCommand cmd) { - final String vmName = cmd.getVmName(); - final String vmSnapshotName = cmd.getTarget().getSnapshotName(); - final List listVolumeTo = cmd.getVolumeTOs(); - VmPowerState vmState = VmPowerState.HALTED; - final String guestOSType = cmd.getGuestOSType(); - final String platformEmulator = cmd.getPlatformEmulator(); - - final boolean snapshotMemory = cmd.getTarget().getType() == VMSnapshot.Type.DiskAndMemory; - final long timeout = cmd.getWait(); - - final Connection conn = getConnection(); - VM vm = null; - VM vmSnapshot = null; - boolean success = false; - - try { - // check if VM snapshot already exists - final Set vmSnapshots = VM.getByNameLabel(conn, cmd.getTarget().getSnapshotName()); - if (vmSnapshots.size() > 0) { - return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), cmd.getVolumeTOs()); - } - - // check if there is already a task for this VM snapshot - Task task = null; - Set tasks = Task.getByNameLabel(conn, "Async.VM.snapshot"); - if(tasks == null) { - tasks = new LinkedHashSet<>(); - } - final Set tasksByName = Task.getByNameLabel(conn, "Async.VM.checkpoint"); - if(tasksByName != null) { - tasks.addAll(tasksByName); - } - for (final Task taskItem : tasks) { - if (taskItem.getOtherConfig(conn).containsKey("CS_VM_SNAPSHOT_KEY")) { - final String vmSnapshotTaskName = taskItem.getOtherConfig(conn).get("CS_VM_SNAPSHOT_KEY"); - if (vmSnapshotTaskName != null && vmSnapshotTaskName.equals(cmd.getTarget().getSnapshotName())) { - task = taskItem; - } + public PowerState getVmState(final Connection conn, final String vmName) { + int retry = 3; + while (retry-- > 0) { + try { + final Set vms = VM.getByNameLabel(conn, vmName); + for (final VM vm : vms) { + return convertToPowerState(vm.getPowerState(conn)); } - } - - // create a new task if there is no existing task for this VM snapshot - if (task == null) { + } catch (final BadServerResponse e) { + // There is a race condition within xenserver such that if a vm is + // deleted and we + // happen to ask for it, it throws this stupid response. So + // if this happens, + // we take a nap and try again which then avoids the race + // condition because + // the vm's information is now cleaned up by xenserver. The error + // is as follows + // com.xensource.xenapi.Types$BadServerResponse + // [HANDLE_INVALID, VM, + // 3dde93f9-c1df-55a7-2cde-55e1dce431ab] + s_logger.info("Unable to get a vm PowerState due to " + e.toString() + ". We are retrying. Count: " + retry); try { - vm = getVM(conn, vmName); - vmState = vm.getPowerState(conn); - } catch (final Exception e) { - if (!snapshotMemory) { - vm = createWorkingVM(conn, vmName, guestOSType, platformEmulator, listVolumeTo); - } - } + Thread.sleep(3000); + } catch (final InterruptedException ex) { - if (vm == null) { - return new CreateVMSnapshotAnswer(cmd, false, "Creating VM Snapshot Failed due to can not find vm: " + vmName); } - - // call Xenserver API - if (!snapshotMemory) { - task = vm.snapshotAsync(conn, vmSnapshotName); - } else { - final Set vbds = vm.getVBDs(conn); - final Pool pool = Pool.getByUuid(conn, _host.getPool()); - for (final VBD vbd : vbds) { - final VBD.Record vbdr = vbd.getRecord(conn); - if (vbdr.userdevice.equals("0")) { - final VDI vdi = vbdr.VDI; - final SR sr = vdi.getSR(conn); - // store memory image on the same SR with ROOT volume - pool.setSuspendImageSR(conn, sr); - } - } - task = vm.checkpointAsync(conn, vmSnapshotName); - } - task.addToOtherConfig(conn, "CS_VM_SNAPSHOT_KEY", vmSnapshotName); - } - - waitForTask(conn, task, 1000, timeout * 1000); - checkForSuccess(conn, task); - final String result = task.getResult(conn); - - // extract VM snapshot ref from result - final String ref = result.substring("".length(), result.length() - "".length()); - vmSnapshot = Types.toVM(ref); - try { - Thread.sleep(5000); - } catch (final InterruptedException ex) { - - } - // calculate used capacity for this VM snapshot - for (final VolumeObjectTO volumeTo : cmd.getVolumeTOs()) { - final long size = getVMSnapshotChainSize(conn, volumeTo, cmd.getVmName()); - volumeTo.setSize(size); - } - - success = true; - return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), cmd.getVolumeTOs()); - } catch (final Exception e) { - String msg = ""; - if (e instanceof Types.BadAsyncResult) { - final String licenseKeyWord = "LICENCE_RESTRICTION"; - final Types.BadAsyncResult errorResult = (Types.BadAsyncResult)e; - if (errorResult.shortDescription != null && errorResult.shortDescription.contains(licenseKeyWord)) { - msg = licenseKeyWord; - } - } else { - msg = e.toString(); - } - s_logger.warn("Creating VM Snapshot " + cmd.getTarget().getSnapshotName() + " failed due to: " + msg, e); - return new CreateVMSnapshotAnswer(cmd, false, msg); - } finally { - try { - if (!success) { - if (vmSnapshot != null) { - s_logger.debug("Delete exsisting VM Snapshot " + vmSnapshotName + " after making VolumeTO failed"); - final Set vbds = vmSnapshot.getVBDs(conn); - for (final VBD vbd : vbds) { - final VBD.Record vbdr = vbd.getRecord(conn); - if (vbdr.type == Types.VbdType.DISK) { - final VDI vdi = vbdr.VDI; - vdi.destroy(conn); - } - } - vmSnapshot.destroy(conn); - } - } - if (vmState == VmPowerState.HALTED) { - if (vm != null) { - vm.destroy(conn); - } - } - } catch (final Exception e2) { - s_logger.error("delete snapshot error due to " + e2.getMessage()); + } catch (final XenAPIException e) { + final String msg = "Unable to get a vm PowerState due to " + e.toString(); + s_logger.warn(msg, e); + break; + } catch (final XmlRpcException e) { + final String msg = "Unable to get a vm PowerState due to " + e.getMessage(); + s_logger.warn(msg, e); + break; } } + + return PowerState.PowerOff; } - public VM createWorkingVM(final Connection conn, final String vmName, final String guestOSType, final String platformEmulator, final List listVolumeTo) throws BadServerResponse, - Types.VmBadPowerState, Types.SrFull, - Types.OperationNotAllowed, XenAPIException, XmlRpcException { - //below is redundant but keeping for consistency and code readabilty - final String guestOsTypeName = platformEmulator; - if (guestOsTypeName == null) { - final String msg = - " Hypervisor " + this.getClass().getName() + " doesn't support guest OS type " + guestOSType + ". you can choose 'Other install media' to run it as HVM"; - s_logger.warn(msg); - throw new CloudRuntimeException(msg); + public HashMap getVmStats(final Connection conn, final GetVmStatsCommand cmd, final List vmUUIDs, final String hostGuid) { + final HashMap vmResponseMap = new HashMap(); + + for (final String vmUUID : vmUUIDs) { + vmResponseMap.put(vmUUID, new VmStatsEntry(0, 0, 0, 0, "vm")); } - final VM template = getVM(conn, guestOsTypeName); - final VM vm = template.createClone(conn, vmName); - vm.setIsATemplate(conn, false); - final Map vdiMap = new HashMap(); - for (final VolumeObjectTO volume : listVolumeTo) { - final String vdiUuid = volume.getPath(); - try { - final VDI vdi = VDI.getByUuid(conn, vdiUuid); - vdiMap.put(vdi, volume); - } catch (final Types.UuidInvalid e) { - s_logger.warn("Unable to find vdi by uuid: " + vdiUuid + ", skip it"); + + final Object[] rrdData = getRRDData(conn, 2); // call rrddata with 2 for vm + + if (rrdData == null) { + return null; + } + + final Integer numRows = (Integer)rrdData[0]; + final Integer numColumns = (Integer)rrdData[1]; + final Node legend = (Node)rrdData[2]; + final Node dataNode = (Node)rrdData[3]; + + final NodeList legendChildren = legend.getChildNodes(); + for (int col = 0; col < numColumns; col++) { + + if (legendChildren == null || legendChildren.item(col) == null) { + continue; + } + + final String columnMetadata = getXMLNodeValue(legendChildren.item(col)); + + if (columnMetadata == null) { + continue; + } + + final String[] columnMetadataList = columnMetadata.split(":"); + + if (columnMetadataList.length != 4) { + continue; + } + + final String type = columnMetadataList[1]; + final String uuid = columnMetadataList[2]; + final String param = columnMetadataList[3]; + + if (type.equals("vm") && vmResponseMap.keySet().contains(uuid)) { + final VmStatsEntry vmStatsAnswer = vmResponseMap.get(uuid); + + vmStatsAnswer.setEntityType("vm"); + + if (param.contains("cpu")) { + vmStatsAnswer.setNumCPUs(vmStatsAnswer.getNumCPUs() + 1); + vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() + getDataAverage(dataNode, col, numRows)); + } else if (param.matches("vif_\\d*_rx")) { + vmStatsAnswer.setNetworkReadKBs(vmStatsAnswer.getNetworkReadKBs() + getDataAverage(dataNode, col, numRows)/1000); + } else if (param.matches("vif_\\d*_tx")) { + vmStatsAnswer.setNetworkWriteKBs(vmStatsAnswer.getNetworkWriteKBs() + getDataAverage(dataNode, col, numRows)/1000); + } else if (param.matches("vbd_.*_read")) { + vmStatsAnswer.setDiskReadKBs(vmStatsAnswer.getDiskReadKBs() + getDataAverage(dataNode, col, numRows)/1000); + } else if (param.matches("vbd_.*_write")) { + vmStatsAnswer.setDiskWriteKBs(vmStatsAnswer.getDiskWriteKBs() + getDataAverage(dataNode, col, numRows)/1000); + } } } - for (final Map.Entryentry : vdiMap.entrySet()) { - final VDI vdi = entry.getKey(); - final VolumeObjectTO volumeTO = entry.getValue(); - final VBD.Record vbdr = new VBD.Record(); - vbdr.VM = vm; - vbdr.VDI = vdi; - if (volumeTO.getVolumeType() == Volume.Type.ROOT) { - vbdr.bootable = true; - vbdr.unpluggable = false; - } else { - vbdr.bootable = false; - vbdr.unpluggable = true; + + for (final Map.Entry entry: vmResponseMap.entrySet()) { + final VmStatsEntry vmStatsAnswer = entry.getValue(); + + if (vmStatsAnswer.getNumCPUs() != 0) { + vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() / vmStatsAnswer.getNumCPUs()); + } + + vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() * 100); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Vm cpu utilization " + vmStatsAnswer.getCPUUtilization()); } - vbdr.userdevice = Long.toString(volumeTO.getDeviceId()); - vbdr.mode = Types.VbdMode.RW; - vbdr.type = Types.VbdType.DISK; - VBD.create(conn, vbdr); } - return vm; + return vmResponseMap; } - protected Answer execute(final DeleteVMSnapshotCommand cmd) { - final String snapshotName = cmd.getTarget().getSnapshotName(); - final Connection conn = getConnection(); - + public String getVncUrl(final Connection conn, final VM vm) { + VM.Record record; + Console c; try { - final List vdiList = new ArrayList(); - final Set snapshots = VM.getByNameLabel(conn, snapshotName); - if (snapshots.size() == 0) { - s_logger.warn("VM snapshot with name " + snapshotName + " does not exist, assume it is already deleted"); - return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs()); + record = vm.getRecord(conn); + final Set consoles = record.consoles; + + if (consoles.isEmpty()) { + s_logger.warn("There are no Consoles available to the vm : " + record.nameDescription); + return null; } - final VM snapshot = snapshots.iterator().next(); - final Set vbds = snapshot.getVBDs(conn); - for (final VBD vbd : vbds) { - if (vbd.getType(conn) == Types.VbdType.DISK) { - final VDI vdi = vbd.getVDI(conn); - vdiList.add(vdi); + final Iterator i = consoles.iterator(); + while (i.hasNext()) { + c = i.next(); + if (c.getProtocol(conn) == Types.ConsoleProtocol.RFB) { + return c.getLocation(conn); } } - if (cmd.getTarget().getType() == VMSnapshot.Type.DiskAndMemory) { - vdiList.add(snapshot.getSuspendVDI(conn)); - } - snapshot.destroy(conn); - for (final VDI vdi : vdiList) { - vdi.destroy(conn); - } - - try { - Thread.sleep(5000); - } catch (final InterruptedException ex) { - - } - // re-calculate used capacify for this VM snapshot - for (final VolumeObjectTO volumeTo : cmd.getVolumeTOs()) { - final long size = getVMSnapshotChainSize(conn, volumeTo, cmd.getVmName()); - volumeTo.setSize(size); - } - - return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs()); - } catch (final Exception e) { - s_logger.warn("Catch Exception: " + e.getClass().toString() + " due to " + e.toString(), e); - return new DeleteVMSnapshotAnswer(cmd, false, e.getMessage()); - } - } - - protected Answer execute(final AttachIsoCommand cmd) { - final Connection conn = getConnection(); - final boolean attach = cmd.isAttach(); - final String vmName = cmd.getVmName(); - final String isoURL = cmd.getIsoPath(); - - String errorMsg; - if (attach) { - errorMsg = "Failed to attach ISO"; - } else { - errorMsg = "Failed to detach ISO"; - } - try { - if (attach) { - VBD isoVBD = null; - - // Find the VM - final VM vm = getVM(conn, vmName); - - // Find the ISO VDI - final VDI isoVDI = getIsoVDIByURL(conn, vmName, isoURL); - - // Find the VM's CD-ROM VBD - final Set vbds = vm.getVBDs(conn); - for (final VBD vbd : vbds) { - final String userDevice = vbd.getUserdevice(conn); - final Types.VbdType type = vbd.getType(conn); - - if (userDevice.equals("3") && type == Types.VbdType.CD) { - isoVBD = vbd; - break; - } - } - - if (isoVBD == null) { - throw new CloudRuntimeException("Unable to find CD-ROM VBD for VM: " + vmName); - } else { - // If an ISO is already inserted, eject it - if (isoVBD.getEmpty(conn) == false) { - isoVBD.eject(conn); - } - - // Insert the new ISO - isoVBD.insert(conn, isoVDI); - } - - return new Answer(cmd); - } else { - // Find the VM - final VM vm = getVM(conn, vmName); - final String vmUUID = vm.getUuid(conn); - - // Find the ISO VDI - final VDI isoVDI = getIsoVDIByURL(conn, vmName, isoURL); - - final SR sr = isoVDI.getSR(conn); - - // Look up all VBDs for this VDI - final Set vbds = isoVDI.getVBDs(conn); - - // Iterate through VBDs, and if the VBD belongs the VM, eject - // the ISO from it - for (final VBD vbd : vbds) { - final VM vbdVM = vbd.getVM(conn); - final String vbdVmUUID = vbdVM.getUuid(conn); - - if (vbdVmUUID.equals(vmUUID)) { - // If an ISO is already inserted, eject it - if (!vbd.getEmpty(conn)) { - vbd.eject(conn); - } - - break; - } - } - - if (!sr.getNameLabel(conn).startsWith("XenServer Tools")) { - removeSR(conn, sr); - } - - return new Answer(cmd); - } } catch (final XenAPIException e) { - s_logger.warn(errorMsg + ": " + e.toString(), e); - return new Answer(cmd, false, e.toString()); - } catch (final Exception e) { - s_logger.warn(errorMsg + ": " + e.toString(), e); - return new Answer(cmd, false, e.getMessage()); + final String msg = "Unable to get console url due to " + e.toString(); + s_logger.warn(msg, e); + return null; + } catch (final XmlRpcException e) { + final String msg = "Unable to get console url due to " + e.getMessage(); + s_logger.warn(msg, e); + return null; } + return null; + } + + protected String getXMLNodeValue(final Node n) { + return n.getChildNodes().item(0).getNodeValue(); + } + + public void handleSrAndVdiDetach(final String iqn, final Connection conn) throws Exception { + final SR sr = getStorageRepository(conn, iqn); + + removeSR(conn, sr); + } + + public String handleVmStartFailure(final Connection conn, final String vmName, final VM vm, final String message, final Throwable th) { + final String msg = "Unable to start " + vmName + " due to " + message; + s_logger.warn(msg, th); + + if (vm == null) { + return msg; + } + + try { + final VM.Record vmr = vm.getRecord(conn); + final List networks = new ArrayList(); + for (final VIF vif : vmr.VIFs) { + try { + final VIF.Record rec = vif.getRecord(conn); + if(rec != null) { + networks.add(rec.network); + } else { + s_logger.warn("Unable to cleanup VIF: " + vif.toWireString() + " As vif record is null"); + } + } catch (final Exception e) { + s_logger.warn("Unable to cleanup VIF", e); + } + } + if (vmr.powerState == VmPowerState.RUNNING) { + try { + vm.hardShutdown(conn); + } catch (final Exception e) { + s_logger.warn("VM hardshutdown failed due to ", e); + } + } + if (vm.getPowerState(conn) == VmPowerState.HALTED) { + try { + vm.destroy(conn); + } catch (final Exception e) { + s_logger.warn("VM destroy failed due to ", e); + } + } + for (final VBD vbd : vmr.VBDs) { + try { + vbd.unplug(conn); + vbd.destroy(conn); + } catch (final Exception e) { + s_logger.warn("Unable to clean up VBD due to ", e); + } + } + for (final VIF vif : vmr.VIFs) { + try { + vif.unplug(conn); + vif.destroy(conn); + } catch (final Exception e) { + s_logger.warn("Unable to cleanup VIF", e); + } + } + for (final Network network : networks) { + if (network.getNameLabel(conn).startsWith("VLAN")) { + disableVlanNetwork(conn, network); + } + } + } catch (final Exception e) { + s_logger.warn("VM getRecord failed due to ", e); + } + + return msg; + } + + @Override + public StartupCommand[] initialize() throws IllegalArgumentException { + final Connection conn = getConnection(); + if (!getHostInfo(conn)) { + s_logger.warn("Unable to get host information for " + _host.getIp()); + return null; + } + final StartupRoutingCommand cmd = new StartupRoutingCommand(); + fillHostInfo(conn, cmd); + cmd.setHypervisorType(HypervisorType.XenServer); + cmd.setCluster(_cluster); + cmd.setPoolSync(false); + + try { + final Pool pool = Pool.getByUuid(conn, _host.getPool()); + final Pool.Record poolr = pool.getRecord(conn); + poolr.master.getRecord(conn); + } catch (final Throwable e) { + s_logger.warn("Check for master failed, failing the FULL Cluster sync command"); + } + final StartupStorageCommand sscmd = initializeLocalSR(conn); + if (sscmd != null) { + return new StartupCommand[] {cmd, sscmd}; + } + return new StartupCommand[] {cmd}; + } + + protected StartupStorageCommand initializeLocalSR(final Connection conn) { + final SR lvmsr = getLocalLVMSR(conn); + if (lvmsr != null) { + try { + _host.setLocalSRuuid(lvmsr.getUuid(conn)); + + final String lvmuuid = lvmsr.getUuid(conn); + final long cap = lvmsr.getPhysicalSize(conn); + if (cap > 0) { + final long avail = cap - lvmsr.getPhysicalUtilisation(conn); + lvmsr.setNameLabel(conn, lvmuuid); + final String name = "Cloud Stack Local LVM Storage Pool for " + _host.getUuid(); + lvmsr.setNameDescription(conn, name); + final Host host = Host.getByUuid(conn, _host.getUuid()); + final String address = host.getAddress(conn); + final StoragePoolInfo pInfo = new StoragePoolInfo(lvmuuid, address, SRType.LVM.toString(), SRType.LVM.toString(), StoragePoolType.LVM, cap, avail); + final StartupStorageCommand cmd = new StartupStorageCommand(); + cmd.setPoolInfo(pInfo); + cmd.setGuid(_host.getUuid()); + cmd.setDataCenter(Long.toString(_dcId)); + cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); + return cmd; + } + } catch (final XenAPIException e) { + final String msg = "build local LVM info err in host:" + _host.getUuid() + e.toString(); + s_logger.warn(msg); + } catch (final XmlRpcException e) { + final String msg = "build local LVM info err in host:" + _host.getUuid() + e.getMessage(); + s_logger.warn(msg); + } + } + + final SR extsr = getLocalEXTSR(conn); + if (extsr != null) { + try { + final String extuuid = extsr.getUuid(conn); + _host.setLocalSRuuid(extuuid); + final long cap = extsr.getPhysicalSize(conn); + if (cap > 0) { + final long avail = cap - extsr.getPhysicalUtilisation(conn); + extsr.setNameLabel(conn, extuuid); + final String name = "Cloud Stack Local EXT Storage Pool for " + _host.getUuid(); + extsr.setNameDescription(conn, name); + final Host host = Host.getByUuid(conn, _host.getUuid()); + final String address = host.getAddress(conn); + final StoragePoolInfo pInfo = new StoragePoolInfo(extuuid, address, SRType.EXT.toString(), SRType.EXT.toString(), StoragePoolType.EXT, cap, avail); + final StartupStorageCommand cmd = new StartupStorageCommand(); + cmd.setPoolInfo(pInfo); + cmd.setGuid(_host.getUuid()); + cmd.setDataCenter(Long.toString(_dcId)); + cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); + return cmd; + } + } catch (final XenAPIException e) { + final String msg = "build local EXT info err in host:" + _host.getUuid() + e.toString(); + s_logger.warn(msg); + } catch (final XmlRpcException e) { + final String msg = "build local EXT info err in host:" + _host.getUuid() + e.getMessage(); + s_logger.warn(msg); + } + } + return null; + } + + public boolean isDeviceUsed(final Connection conn, final VM vm, final Long deviceId) { + // Figure out the disk number to attach the VM to + + String msg = null; + try { + final Set allowedVBDDevices = vm.getAllowedVBDDevices(conn); + if (allowedVBDDevices.contains(deviceId.toString())) { + return false; + } + return true; + } catch (final XmlRpcException e) { + msg = "Catch XmlRpcException due to: " + e.getMessage(); + s_logger.warn(msg, e); + } catch (final XenAPIException e) { + msg = "Catch XenAPIException due to: " + e.toString(); + s_logger.warn(msg, e); + } + throw new CloudRuntimeException("When check deviceId " + msg); + } + + /** + * When Dynamic Memory Control (DMC) is enabled - + * xenserver allows scaling the guest memory while the guest is running + * + * By default this is disallowed, override the specific xenserver resource + * if this is enabled + */ + public boolean isDmcEnabled(final Connection conn, final Host host) throws XenAPIException, XmlRpcException { + return false; } public boolean IsISCSI(final String type) { return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type); } - protected Answer execute(final UpgradeSnapshotCommand cmd) { - - final String secondaryStorageUrl = cmd.getSecondaryStorageUrl(); - final String backedUpSnapshotUuid = cmd.getSnapshotUuid(); - final Long volumeId = cmd.getVolumeId(); - final Long accountId = cmd.getAccountId(); - final Long templateId = cmd.getTemplateId(); - final Long tmpltAcountId = cmd.getTmpltAccountId(); - final String version = cmd.getVersion(); - - if (!version.equals("2.1")) { - return new Answer(cmd, true, "success"); - } - try { + public boolean isNetworkSetupByName(final String nameTag) throws XenAPIException, XmlRpcException { + if (nameTag != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Looking for network setup by name " + nameTag); + } final Connection conn = getConnection(); - final URI uri = new URI(secondaryStorageUrl); - final String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); - final String snapshotPath = secondaryStorageMountPath + "/snapshots/" + accountId + "/" + volumeId + "/" + backedUpSnapshotUuid + ".vhd"; - final String templatePath = secondaryStorageMountPath + "/template/tmpl/" + tmpltAcountId + "/" + templateId; - upgradeSnapshot(conn, templatePath, snapshotPath); - return new Answer(cmd, true, "success"); - } catch (final Exception e) { - final String details = "upgrading snapshot " + backedUpSnapshotUuid + " failed due to " + e.toString(); - s_logger.error(details, e); - + final XsLocalNetwork network = getNetworkByName(conn, nameTag); + if (network == null) { + return false; + } } - return new Answer(cmd, false, "failure"); + return true; } - private boolean destroySnapshotOnPrimaryStorageExceptThis(final Connection conn, final String volumeUuid, final String avoidSnapshotUuid) { - try { - final VDI volume = getVDIbyUuid(conn, volumeUuid); - if (volume == null) { - throw new InternalErrorException("Could not destroy snapshot on volume " + volumeUuid + " due to can not find it"); - } - final Set snapshots = volume.getSnapshots(conn); - for (final VDI snapshot : snapshots) { - try { - if (!snapshot.getUuid(conn).equals(avoidSnapshotUuid)) { - snapshot.destroy(conn); - } - } catch (final Exception e) { - final String msg = "Destroying snapshot: " + snapshot + " on primary storage failed due to " + e.toString(); - s_logger.warn(msg, e); - } - } - s_logger.debug("Successfully destroyed snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid); - return true; - } catch (final XenAPIException e) { - final String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); - s_logger.error(msg, e); - } catch (final Exception e) { - final String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); - s_logger.warn(msg, e); - } + public boolean isOvs() { + return _isOvs; + } + public boolean isRefNull(final XenAPIObject object) { + return object == null || object.toWireString().equals("OpaqueRef:NULL") || object.toWireString().equals(""); + } + + public boolean isSecurityGroupEnabled() { + return _securityGroupEnabled; + } + + public boolean isXcp() { + final Connection conn = getConnection(); + final String result = callHostPlugin(conn, "ovstunnel", "is_xcp"); + if (result.equals("XCP")) { + return true; + } return false; } - public VM getVM(final Connection conn, final String vmName) { - // Look up VMs with the specified name - Set vms; - try { - vms = VM.getByNameLabel(conn, vmName); - } catch (final XenAPIException e) { - throw new CloudRuntimeException("Unable to get " + vmName + ": " + e.toString(), e); - } catch (final Exception e) { - throw new CloudRuntimeException("Unable to get " + vmName + ": " + e.getMessage(), e); - } - - // If there are no VMs, throw an exception - if (vms.size() == 0) { - throw new CloudRuntimeException("VM with name: " + vmName + " does not exist."); - } - - // If there is more than one VM, print a warning - if (vms.size() > 1) { - s_logger.warn("Found " + vms.size() + " VMs with name: " + vmName); - } - - // Return the first VM in the set - return vms.iterator().next(); - } - - public VDI getIsoVDIByURL(final Connection conn, final String vmName, final String isoURL) { - SR isoSR = null; - String mountpoint = null; - if (isoURL.startsWith("xs-tools")) { - try { - final Set vdis = VDI.getByNameLabel(conn, isoURL); - if (vdis.isEmpty()) { - throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL); - } - return vdis.iterator().next(); - - } catch (final XenAPIException e) { - throw new CloudRuntimeException("Unable to get pv iso: " + isoURL + " due to " + e.toString()); - } catch (final Exception e) { - throw new CloudRuntimeException("Unable to get pv iso: " + isoURL + " due to " + e.toString()); - } - } - - final int index = isoURL.lastIndexOf("/"); - mountpoint = isoURL.substring(0, index); - - URI uri; - try { - uri = new URI(mountpoint); - } catch (final URISyntaxException e) { - throw new CloudRuntimeException("isoURL is wrong: " + isoURL); - } - isoSR = getISOSRbyVmName(conn, vmName); - if (isoSR == null) { - isoSR = createIsoSRbyURI(conn, uri, vmName, false); - } - - final String isoName = isoURL.substring(index + 1); - - final VDI isoVDI = getVDIbyLocationandSR(conn, isoName, isoSR); - - if (isoVDI != null) { - return isoVDI; + boolean killCopyProcess(final Connection conn, final String nameLabel) { + final String results = callHostPluginAsync(conn, "vmops", "kill_copy_process", 60, "namelabel", nameLabel); + String errMsg = null; + if (results == null || results.equals("false")) { + errMsg = "kill_copy_process failed"; + s_logger.warn(errMsg); + return false; } else { - throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL); + return true; } } - public SR getStorageRepository(final Connection conn, final String srNameLabel) { - Set srs; + public boolean launchHeartBeat(final Connection conn) { + final String result = callHostPluginPremium(conn, "heartbeat", + "host", _host.getUuid(), + "timeout", Integer.toString(_heartbeatTimeout), + "interval", Integer.toString(_heartbeatInterval)); + if (result == null || !result.contains("> DONE <")) { + s_logger.warn("Unable to launch the heartbeat process on " + _host.getIp()); + return false; + } + return true; + } + + protected String logX(final XenAPIObject obj, final String msg) { + return new StringBuilder("Host ").append(_host.getIp()).append(" ").append(obj.toWireString()).append(": ").append(msg).toString(); + } + + public void migrateVM(final Connection conn, final Host destHost, final VM vm, final String vmName) throws Exception { + Task task = null; try { - srs = SR.getByNameLabel(conn, srNameLabel); - } catch (final XenAPIException e) { - throw new CloudRuntimeException("Unable to get SR " + srNameLabel + " due to " + e.toString(), e); - } catch (final Exception e) { - throw new CloudRuntimeException("Unable to get SR " + srNameLabel + " due to " + e.getMessage(), e); - } - - if (srs.size() > 1) { - throw new CloudRuntimeException("More than one storage repository was found for pool with uuid: " + srNameLabel); - } else if (srs.size() == 1) { - final SR sr = srs.iterator().next(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("SR retrieved for " + srNameLabel); - } - - if (checkSR(conn, sr)) { - return sr; - } - throw new CloudRuntimeException("SR check failed for storage pool: " + srNameLabel + "on host:" + _host.getUuid()); - } else { - throw new CloudRuntimeException("Can not see storage pool: " + srNameLabel + " from on host:" + _host.getUuid()); - } - } - - protected Answer execute(final CheckConsoleProxyLoadCommand cmd) { - return executeProxyLoadScan(cmd, cmd.getProxyVmId(), cmd.getProxyVmName(), cmd.getProxyManagementIp(), cmd.getProxyCmdPort()); - } - - protected Answer execute(final WatchConsoleProxyLoadCommand cmd) { - return executeProxyLoadScan(cmd, cmd.getProxyVmId(), cmd.getProxyVmName(), cmd.getProxyManagementIp(), cmd.getProxyCmdPort()); - } - - protected Answer executeProxyLoadScan(final Command cmd, final long proxyVmId, final String proxyVmName, final String proxyManagementIp, final int cmdPort) { - String result = null; - - final StringBuffer sb = new StringBuffer(); - sb.append("http://").append(proxyManagementIp).append(":" + cmdPort).append("/cmd/getstatus"); - - boolean success = true; - try { - final URL url = new URL(sb.toString()); - final URLConnection conn = url.openConnection(); - - // setting TIMEOUTs to avoid possible waiting until death situations - conn.setConnectTimeout(5000); - conn.setReadTimeout(5000); - - final InputStream is = conn.getInputStream(); - final BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - final StringBuilder sb2 = new StringBuilder(); - String line = null; + final Map other = new HashMap(); + other.put("live", "true"); + task = vm.poolMigrateAsync(conn, destHost, other); try { - while ((line = reader.readLine()) != null) { - sb2.append(line + "\n"); + // poll every 1 seconds + final long timeout = _migratewait * 1000L; + waitForTask(conn, task, 1000, timeout); + checkForSuccess(conn, task); + } catch (final Types.HandleInvalid e) { + if (vm.getResidentOn(conn).equals(destHost)) { + task = null; + return; } - result = sb2.toString(); - } catch (final IOException e) { - success = false; - } finally { + throw new CloudRuntimeException("migrate VM catch HandleInvalid and VM is not running on dest host"); + } + } catch (final XenAPIException e) { + final String msg = "Unable to migrate VM(" + vmName + ") from host(" + _host.getUuid() + ")"; + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } finally { + if (task != null) { try { - is.close(); - } catch (final IOException e) { - s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp); - success = false; + task.destroy(conn); + } catch (final Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } - } catch (final IOException e) { - s_logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp); - success = false; + } + } + + protected VDI mount(final Connection conn, final StoragePoolType poolType, final String volumeFolder, final String volumePath) { + return getVDIbyUuid(conn, volumePath); + } + + protected VDI mount(final Connection conn, final String vmName, final DiskTO volume) throws XmlRpcException, XenAPIException { + final DataTO data = volume.getData(); + final Volume.Type type = volume.getType(); + if (type == Volume.Type.ISO) { + final TemplateObjectTO iso = (TemplateObjectTO)data; + final DataStoreTO store = iso.getDataStore(); + + if (store == null) { + //It's a fake iso + return null; + } + + //corer case, xenserver pv driver iso + final String templateName = iso.getName(); + if (templateName.startsWith("xs-tools")) { + try { + final Set vdis = VDI.getByNameLabel(conn, templateName); + if (vdis.isEmpty()) { + throw new CloudRuntimeException("Could not find ISO with URL: " + templateName); + } + return vdis.iterator().next(); + } catch (final XenAPIException e) { + throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString()); + } catch (final Exception e) { + throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString()); + } + } + + if (!(store instanceof NfsTO)) { + throw new CloudRuntimeException("only support mount iso on nfs"); + } + final NfsTO nfsStore = (NfsTO)store; + final String isoPath = nfsStore.getUrl() + File.separator + iso.getPath(); + final int index = isoPath.lastIndexOf("/"); + + final String mountpoint = isoPath.substring(0, index); + URI uri; + try { + uri = new URI(mountpoint); + } catch (final URISyntaxException e) { + throw new CloudRuntimeException("Incorrect uri " + mountpoint, e); + } + final SR isoSr = createIsoSRbyURI(conn, uri, vmName, false); + + final String isoname = isoPath.substring(index + 1); + + final VDI isoVdi = getVDIbyLocationandSR(conn, isoname, isoSr); + + if (isoVdi == null) { + throw new CloudRuntimeException("Unable to find ISO " + isoPath); + } + return isoVdi; + } else { + final VolumeObjectTO vol = (VolumeObjectTO)data; + return VDI.getByUuid(conn, vol.getPath()); + } + } + + public String networkUsage(final Connection conn, final String privateIpAddress, final String option, final String vif) { + if (option.equals("get")) { + return "0:0"; + } + return null; + } + + private List> ovsFullSyncStates() { + final Connection conn = getConnection(); + final String result = callHostPlugin(conn, "ovsgre", "ovs_get_vm_log", "host_uuid", _host.getUuid()); + final String[] logs = result != null ? result.split(";") : new String[0]; + final List> states = new ArrayList>(); + for (final String log : logs) { + final String[] info = log.split(","); + if (info.length != 5) { + s_logger.warn("Wrong element number in ovs log(" + log + ")"); + continue; + } + + //','.join([bridge, vmName, vmId, seqno, tag]) + try { + states.add(new Pair(info[0], Long.parseLong(info[3]))); + } catch (final NumberFormatException nfe) { + states.add(new Pair(info[0], -1L)); + } + } + return states; + } + + + public HashMap parseDefaultOvsRuleComamnd(final String str) { + final HashMap cmd = new HashMap(); + final String[] sarr = str.split("/"); + for (int i = 0; i < sarr.length; i++) { + String c = sarr[i]; + c = c.startsWith("/") ? c.substring(1) : c; + c = c.endsWith("/") ? c.substring(0, c.length() - 1) : c; + final String[] p = c.split(";"); + if (p.length != 2) { + continue; + } + if (p[0].equalsIgnoreCase("vlans")) { + p[1] = p[1].replace("@", "["); + p[1] = p[1].replace("#", "]"); + } + cmd.put(p[0], p[1]); + } + return cmd; + } + + protected Pair parseTimestamp(final String timeStampStr) { + final String[] tokens = timeStampStr.split("-"); + if (tokens.length != 3) { + s_logger.debug("timeStamp in network has wrong pattern: " + timeStampStr); + return null; + } + if (!tokens[0].equals("CsCreateTime")) { + s_logger.debug("timeStamp in network doesn't start with CsCreateTime: " + timeStampStr); + return null; + } + return new Pair(Long.parseLong(tokens[1]), Integer.parseInt(tokens[2])); + } + + private void pbdPlug(final Connection conn, final PBD pbd, final String uuid) { + try { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Plugging in PBD " + uuid + " for " + _host); + } + pbd.plug(conn); + } catch (final Exception e) { + final String msg = "PBD " + uuid + " is not attached! and PBD plug failed due to " + e.toString() + ". Please check this PBD in " + _host; + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } + } + + protected boolean pingdomr(final Connection conn, final String host, final String port) { + String status; + status = callHostPlugin(conn, "vmops", "pingdomr", "host", host, "port", port); + + if (status == null || status.isEmpty()) { + return false; } - return new ConsoleProxyLoadAnswer(cmd, proxyVmId, proxyVmName, success, result); + return true; + } - protected boolean createSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String newFolder) { - final String result = callHostPlugin(conn, "vmopsSnapshot", "create_secondary_storage_folder", "remoteMountPath", remoteMountPath, "newFolder", newFolder); - return result != null; + public boolean pingXAPI() { + final Connection conn = getConnection(); + try { + final Host host = Host.getByUuid(conn, _host.getUuid()); + if( !host.getEnabled(conn) ) { + s_logger.debug("Host " + _host.getIp() + " is not enabled!"); + return false; + } + } catch (final Exception e) { + s_logger.debug("cannot get host enabled status, host " + _host.getIp() + " due to " + e.toString(), e); + return false; + } + try { + callHostPlugin(conn, "echo", "main"); + } catch (final Exception e) { + s_logger.debug("cannot ping host " + _host.getIp() + " due to " + e.toString(), e); + return false; + } + return true; } - protected boolean deleteSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String folder) { - final String details = callHostPlugin(conn, "vmopsSnapshot", "delete_secondary_storage_folder", "remoteMountPath", remoteMountPath, "folder", folder); - return details != null && details.equals("1"); + protected void plugDom0Vif(final Connection conn, final VIF dom0Vif) throws XmlRpcException, XenAPIException { + if (dom0Vif != null) { + dom0Vif.plug(conn); + } } protected boolean postCreatePrivateTemplate(final Connection conn, final String templatePath, final String tmpltFilename, final String templateName, String templateDescription, @@ -6785,234 +4176,278 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return success; } - public String getVhdParent(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI) { - final String parentUuid = - callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", - isISCSI.toString()); + @Override + public ExecutionResult prepareCommand(final NetworkElementCommand cmd) { + //Update IP used to access router + cmd.setRouterAccessIp(cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP)); + assert cmd.getRouterAccessIp() != null; - if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { - s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid); - // errString is already logged. + if (cmd instanceof IpAssocVpcCommand) { + return prepareNetworkElementCommand((IpAssocVpcCommand)cmd); + } else if (cmd instanceof IpAssocCommand) { + return prepareNetworkElementCommand((IpAssocCommand)cmd); + } else if (cmd instanceof SetupGuestNetworkCommand) { + return prepareNetworkElementCommand((SetupGuestNetworkCommand)cmd); + } else if (cmd instanceof SetSourceNatCommand) { + return prepareNetworkElementCommand((SetSourceNatCommand)cmd); + } else if (cmd instanceof SetNetworkACLCommand) { + return prepareNetworkElementCommand((SetNetworkACLCommand)cmd); + } + return new ExecutionResult(true, null); + } + + public void prepareISO(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException { + + final Set vms = VM.getByNameLabel(conn, vmName); + if (vms == null || vms.size() != 1) { + throw new CloudRuntimeException("There are " + (vms == null ? "0" : vms.size()) + " VMs named " + vmName); + } + final VM vm = vms.iterator().next(); + final Set vbds = vm.getVBDs(conn); + for (final VBD vbd : vbds) { + final VBD.Record vbdr = vbd.getRecord(conn); + if (vbdr.type == Types.VbdType.CD && vbdr.empty == false) { + final VDI vdi = vbdr.VDI; + final SR sr = vdi.getSR(conn); + final Set pbds = sr.getPBDs(conn); + if (pbds == null) { + throw new CloudRuntimeException("There is no pbd for sr " + sr); + } + for (final PBD pbd : pbds) { + final PBD.Record pbdr = pbd.getRecord(conn); + if (pbdr.host.getUuid(conn).equals(_host.getUuid())) { + return; + } + } + sr.setShared(conn, true); + final Host host = Host.getByUuid(conn, _host.getUuid()); + final PBD.Record pbdr = pbds.iterator().next().getRecord(conn); + pbdr.host = host; + pbdr.uuid = ""; + final PBD pbd = PBD.create(conn, pbdr); + pbdPlug(conn, pbd, pbd.getUuid(conn)); + break; + } + } + } + + // the idea here is to see if the DiskTO in question is from managed storage and + // does not yet have an SR + // if no SR, create it and create a VDI in it + public VDI prepareManagedDisk(final Connection conn, final DiskTO disk, final String vmName) throws Exception { + final Map details = disk.getDetails(); + + if (details == null) { return null; } - return parentUuid; - } - protected String deleteSnapshotBackup(final Connection conn, final Long dcId, final Long accountId, final Long volumeId, final String secondaryStorageMountPath, final String backupUUID) { + final boolean isManaged = new Boolean(details.get(DiskTO.MANAGED)).booleanValue(); - // If anybody modifies the formatting below again, I'll skin them - final String result = - callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "dcId", dcId.toString(), "accountId", accountId.toString(), - "volumeId", volumeId.toString(), "secondaryStorageMountPath", secondaryStorageMountPath); - - return result; - } - - @Override - public boolean start() { - return true; - } - - @Override - public boolean stop() { - disconnected(); - return true; - } - - @Override - public String getName() { - return _name; - } - - @Override - public IAgentControl getAgentControl() { - return _agentControl; - } - - @Override - public void setAgentControl(final IAgentControl agentControl) { - _agentControl = agentControl; - } - - private Answer execute(final CleanupNetworkRulesCmd cmd) { - if (!_canBridgeFirewall) { - return new Answer(cmd, true, null); - } - final Connection conn = getConnection(); - final String result = callHostPlugin(conn, "vmops", "cleanup_rules", "instance", _instance); - final int numCleaned = Integer.parseInt(result); - if (result == null || result.isEmpty() || numCleaned < 0) { - s_logger.warn("Failed to cleanup rules for host " + _host.getIp()); - return new Answer(cmd, false, result); - } - if (numCleaned > 0) { - s_logger.info("Cleaned up rules for " + result + " vms on host " + _host.getIp()); - } - return new Answer(cmd, true, result); - } - - protected String getGuestOsType(final String stdType, String platformEmulator, final boolean bootFromCD) { - if (platformEmulator == null) { - s_logger.debug("no guest OS type, start it as HVM guest"); - platformEmulator = "Other install media"; - } - return platformEmulator; - } - - private Answer execute(final NetworkRulesSystemVmCommand cmd) { - boolean success = true; - final Connection conn = getConnection(); - if (cmd.getType() != VirtualMachine.Type.User) { - final String result = callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", cmd.getVmName()); - if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { - success = false; - } + if (!isManaged) { + return null; } - return new Answer(cmd, success, ""); - } + final String iqn = details.get(DiskTO.IQN); - private Answer execute(final NetworkRulesVmSecondaryIpCommand cmd) { - boolean success = true; - final Connection conn = getConnection(); + final Set srNameLabels = SR.getByNameLabel(conn, iqn); - final String result = - callHostPlugin(conn, "vmops", "network_rules_vmSecondaryIp", "vmName", cmd.getVmName(), "vmMac", cmd.getVmMac(), "vmSecIp", cmd.getVmSecIp(), "action", - cmd.getAction()); - if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { - success = false; + if (srNameLabels.size() != 0) { + return null; } - return new Answer(cmd, success, ""); + final String vdiNameLabel = vmName + "-DATA"; + + return prepareManagedStorage(conn, details, null, vdiNameLabel); } - protected ClusterVMMetaDataSyncAnswer execute(final ClusterVMMetaDataSyncCommand cmd) { - final Connection conn = getConnection(); - //check if this is master - Pool pool; - try { - pool = Pool.getByUuid(conn, _host.getPool()); - final Pool.Record poolr = pool.getRecord(conn); - final Host.Record hostr = poolr.master.getRecord(conn); - if (!_host.getUuid().equals(hostr.uuid)) { - return new ClusterVMMetaDataSyncAnswer(cmd.getClusterId(), null); - } - } catch (final Throwable e) { - s_logger.warn("Check for master failed, failing the Cluster sync VMMetaData command"); - return new ClusterVMMetaDataSyncAnswer(cmd.getClusterId(), null); + protected SR prepareManagedSr(final Connection conn, final Map details) { + final String iScsiName = details.get(DiskTO.IQN); + final String storageHost = details.get(DiskTO.STORAGE_HOST); + final String chapInitiatorUsername = details.get(DiskTO.CHAP_INITIATOR_USERNAME); + final String chapInitiatorSecret = details.get(DiskTO.CHAP_INITIATOR_SECRET); + final String mountpoint = details.get(DiskTO.MOUNT_POINT); + final String protocoltype = details.get(DiskTO.PROTOCOL_TYPE); + + if (StoragePoolType.NetworkFilesystem.toString().equalsIgnoreCase(protocoltype)) { + final String poolid = storageHost + ":" + mountpoint; + final String namelable = mountpoint; + final String volumedesc = storageHost + ":" + mountpoint; + + return getNfsSR(conn, poolid, namelable, storageHost, mountpoint, volumedesc); + } else { + return getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true); } - final HashMap vmMetadatum = clusterVMMetaDataSync(conn); - return new ClusterVMMetaDataSyncAnswer(cmd.getClusterId(), vmMetadatum); } - public HashMap clusterVMMetaDataSync(final Connection conn) { - final HashMap vmMetaDatum = new HashMap(); - try { - final Map vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER - if(vm_map != null) { - for (final VM.Record record : vm_map.values()) { - if (record.isControlDomain || record.isASnapshot || record.isATemplate) { - continue; // Skip DOM0 - } - vmMetaDatum.put(record.nameLabel, StringUtils.mapToString(record.platform)); - } - } - } catch (final Throwable e) { - final String msg = "Unable to get vms through host " + _host.getUuid() + " due to to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg); - } - return vmMetaDatum; - } + protected VDI prepareManagedStorage(final Connection conn, final Map details, final String path, final String vdiNameLabel) throws Exception { + final SR sr = prepareManagedSr(conn, details); + + VDI vdi = getVDIbyUuid(conn, path, false); + final Long volumeSize = Long.parseLong(details.get(DiskTO.VOLUME_SIZE)); + + if (vdi == null) { + vdi = createVdi(sr, vdiNameLabel, volumeSize); + } else { + // if VDI is not null, it must have already been created, so check whether a resize of the volume was performed + // if true, resize the VDI to the volume size + + s_logger.info("checking for the resize of the datadisk"); + + final long vdiVirtualSize = vdi.getVirtualSize(conn); + + if (vdiVirtualSize != volumeSize) { + s_logger.info("resizing the data disk (vdi) from vdiVirtualsize: "+ vdiVirtualSize + " to volumeSize: " + volumeSize); - /** - * @param cmd - * @return - */ - private UnPlugNicAnswer execute(final UnPlugNicCommand cmd) { - final Connection conn = getConnection(); - final String vmName = cmd.getVmName(); - try { - final Set vms = VM.getByNameLabel(conn, vmName); - if (vms == null || vms.isEmpty()) { - return new UnPlugNicAnswer(cmd, false, "Can not find VM " + vmName); - } - final VM vm = vms.iterator().next(); - final NicTO nic = cmd.getNic(); - final String mac = nic.getMac(); - final VIF vif = getVifByMac(conn, vm, mac); - if (vif != null) { - vif.unplug(conn); - final Network network = vif.getNetwork(conn); - vif.destroy(conn); try { - if (network.getNameLabel(conn).startsWith("VLAN")) { - disableVlanNetwork(conn, network); - } + vdi.resize(conn, volumeSize); } catch (final Exception e) { + s_logger.warn("Unable to resize volume", e); } } - return new UnPlugNicAnswer(cmd, true, "success"); - } catch (final Exception e) { - final String msg = " UnPlug Nic failed due to " + e.toString(); - s_logger.warn(msg, e); - return new UnPlugNicAnswer(cmd, false, msg); } + + return vdi; } - /** - * @param cmd - * @return - */ - private PlugNicAnswer execute(final PlugNicCommand cmd) { + protected ExecutionResult prepareNetworkElementCommand(final IpAssocCommand cmd) { final Connection conn = getConnection(); - final String vmName = cmd.getVmName(); + final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + final String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + try { - final Set vms = VM.getByNameLabel(conn, vmName); - if (vms == null || vms.isEmpty()) { - return new PlugNicAnswer(cmd, false, "Can not find VM " + vmName); - } - final VM vm = vms.iterator().next(); - final NicTO nic = cmd.getNic(); + final IpAddressTO[] ips = cmd.getIpAddresses(); + for (final IpAddressTO ip : ips) { - String mac = nic.getMac(); - final Set routerVIFs = vm.getVIFs(conn); - mac = mac.trim(); + final VM router = getVM(conn, routerName); - int counter = 0; - for (final VIF vif : routerVIFs) { - final String lmac = vif.getMAC(conn); - if (lmac.trim().equals(mac)) { - counter++; + final NicTO nic = new NicTO(); + nic.setMac(ip.getVifMacAddress()); + nic.setType(ip.getTrafficType()); + if (ip.getBroadcastUri()== null) { + nic.setBroadcastType(BroadcastDomainType.Native); + } else { + final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); + nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); + nic.setBroadcastUri(uri); + } + nic.setDeviceId(0); + nic.setNetworkRateMbps(ip.getNetworkRate()); + nic.setName(ip.getNetworkName()); + + final Network network = getNetwork(conn, nic); + + // Determine the correct VIF on DomR to associate/disassociate the + // IP address with + VIF correctVif = getCorrectVif(conn, router, network); + + // If we are associating an IP address and DomR doesn't have a VIF + // for the specified vlan ID, we need to add a VIF + // If we are disassociating the last IP address in the VLAN, we need + // to remove a VIF + boolean addVif = false; + if (ip.isAdd() && correctVif == null) { + addVif = true; + } + + if (addVif) { + // Add a new VIF to DomR + final String vifDeviceNum = getLowestAvailableVIFDeviceNum(conn, router); + + if (vifDeviceNum == null) { + throw new InternalErrorException("There were no more available slots for a new VIF on router: " + router.getNameLabel(conn)); + } + + nic.setDeviceId(Integer.valueOf(vifDeviceNum)); + + correctVif = createVif(conn, routerName, router, null, nic); + correctVif.plug(conn); + // Add iptables rule for network usage + networkUsage(conn, routerIp, "addVif", "eth" + correctVif.getDevice(conn)); + } + + if (ip.isAdd() && correctVif == null) { + throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with."); + } + if (correctVif != null ) { + ip.setNicDevId(Integer.valueOf(correctVif.getDevice(conn))); + ip.setNewNic(addVif); } } - // We allow 2 routers with the same mac. It's needed for the redundant vpc routers. - // [FIXME] Find a way to identify the type of the router or if it's redundant. - if (counter > 2) { - final String msg = " Plug Nic failed due to a VIF with the same mac " + nic.getMac() + " exists in more than 2 routers."; - s_logger.error(msg); - return new PlugNicAnswer(cmd, false, msg); - } - - // Wilder Rodrigues - replaced this code with the code above. - // VIF vif = getVifByMac(conn, vm, nic.getMac()); - // if (vif != null) { - // final String msg = " Plug Nic failed due to a VIF with the same mac " + nic.getMac() + " exists"; - // s_logger.warn(msg); - // return new PlugNicAnswer(cmd, false, msg); - // } - - final String deviceId = getLowestAvailableVIFDeviceNum(conn, vm); - nic.setDeviceId(Integer.parseInt(deviceId)); - final VIF vif = createVif(conn, vmName, vm, null, nic); - // vif = createVif(conn, vmName, vm, null, nic); - vif.plug(conn); - return new PlugNicAnswer(cmd, true, "success"); + } catch (final InternalErrorException e) { + s_logger.error("Ip Assoc failure on applying one ip due to exception: ", e); + return new ExecutionResult(false, e.getMessage()); } catch (final Exception e) { - final String msg = " Plug Nic failed due to " + e.toString(); - s_logger.error(msg, e); - return new PlugNicAnswer(cmd, false, msg); + return new ExecutionResult(false, e.getMessage()); } + return new ExecutionResult(true, null); + } + + protected ExecutionResult prepareNetworkElementCommand(final IpAssocVpcCommand cmd) { + final Connection conn = getConnection(); + final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + try { + final IpAddressTO[] ips = cmd.getIpAddresses(); + for (final IpAddressTO ip : ips) { + + final VM router = getVM(conn, routerName); + + final VIF correctVif = getVifByMac(conn, router, ip.getVifMacAddress()); + setNicDevIdIfCorrectVifIsNotNull(conn, ip, correctVif); + } + } catch (final Exception e) { + s_logger.error("Ip Assoc failure on applying one ip due to exception: ", e); + return new ExecutionResult(false, e.getMessage()); + } + + return new ExecutionResult(true, null); + } + + protected ExecutionResult prepareNetworkElementCommand(final SetNetworkACLCommand cmd) { + final Connection conn = getConnection(); + final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + + try { + final VM router = getVM(conn, routerName); + + final NicTO nic = cmd.getNic(); + if(nic != null) { + final VIF vif = getVifByMac(conn, router, nic.getMac()); + if(vif == null) { + final String msg = "Prepare SetNetworkACL failed due to VIF is null for : " + nic.getMac() +" with routername: " + routerName; + s_logger.error(msg); + return new ExecutionResult(false, msg); + } + nic.setDeviceId(Integer.valueOf(vif.getDevice(conn))); + } else { + final String msg = "Prepare SetNetworkACL failed due to nic is null for : " + routerName; + s_logger.error(msg); + return new ExecutionResult(false, msg); + } + } catch (final Exception e) { + final String msg = "Prepare SetNetworkACL failed due to " + e.toString(); + s_logger.error(msg, e); + return new ExecutionResult(false, msg); + } + return new ExecutionResult(true, null); + } + + protected ExecutionResult prepareNetworkElementCommand(final SetSourceNatCommand cmd) { + final Connection conn = getConnection(); + final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + final IpAddressTO pubIp = cmd.getIpAddress(); + try { + final VM router = getVM(conn, routerName); + + final VIF correctVif = getCorrectVif(conn, router, pubIp); + + pubIp.setNicDevId(Integer.valueOf(correctVif.getDevice(conn))); + + } catch (final Exception e) { + final String msg = "Ip SNAT failure due to " + e.toString(); + s_logger.error(msg, e); + return new ExecutionResult(false, msg); + } + return new ExecutionResult(true, null); } /** @@ -7052,24 +4487,238 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new ExecutionResult(true, null); } - protected ExecutionResult prepareNetworkElementCommand(final IpAssocVpcCommand cmd) { - final Connection conn = getConnection(); - final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + public void rebootVM(final Connection conn, final VM vm, final String vmName) throws Exception { + Task task = null; try { - final IpAddressTO[] ips = cmd.getIpAddresses(); - for (final IpAddressTO ip : ips) { - - final VM router = getVM(conn, routerName); - - final VIF correctVif = getVifByMac(conn, router, ip.getVifMacAddress()); - setNicDevIdIfCorrectVifIsNotNull(conn, ip, correctVif); + task = vm.cleanRebootAsync(conn); + try { + //poll every 1 seconds , timeout after 10 minutes + waitForTask(conn, task, 1000, 10 * 60 * 1000); + checkForSuccess(conn, task); + } catch (final Types.HandleInvalid e) { + if (vm.getPowerState(conn) == VmPowerState.RUNNING) { + task = null; + return; + } + throw new CloudRuntimeException("Reboot VM catch HandleInvalid and VM is not in RUNNING state"); } - } catch (final Exception e) { - s_logger.error("Ip Assoc failure on applying one ip due to exception: ", e); - return new ExecutionResult(false, e.getMessage()); + } catch (final XenAPIException e) { + s_logger.debug("Unable to Clean Reboot VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString() + ", try hard reboot"); + try { + vm.hardReboot(conn); + } catch (final Exception e1) { + final String msg = "Unable to hard Reboot VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); + s_logger.warn(msg, e1); + throw new CloudRuntimeException(msg); + } + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (final Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); + } + } + } + } + + public void removeSR(final Connection conn, final SR sr) { + if (sr == null) { + return; } - return new ExecutionResult(true, null); + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "Removing SR")); + } + + for (int i = 0; i < 2; i++) { + try { + final Set vdis = sr.getVDIs(conn); + for (final VDI vdi : vdis) { + vdi.forget(conn); + } + + Set pbds = sr.getPBDs(conn); + for (final PBD pbd : pbds) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(pbd, "Unplugging pbd")); + } + + // if (pbd.getCurrentlyAttached(conn)) { + pbd.unplug(conn); + //} + + pbd.destroy(conn); + } + + pbds = sr.getPBDs(conn); + + if (pbds.size() == 0) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "Forgetting")); + } + + sr.forget(conn); + + return; + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "There is still one or more PBDs attached.")); + + if (s_logger.isTraceEnabled()) { + for (final PBD pbd : pbds) { + s_logger.trace(logX(pbd, " Still attached")); + } + } + } + } catch (final XenAPIException e) { + s_logger.debug(logX(sr, "Catch XenAPIException: " + e.toString())); + } catch (final XmlRpcException e) { + s_logger.debug(logX(sr, "Catch Exception: " + e.getMessage())); + } + } + + s_logger.warn(logX(sr, "Unable to remove SR")); + } + + protected String removeSRSync(final Connection conn, final SR sr) { + if (sr == null) { + return null; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "Removing SR")); + } + long waittime = 0; + try { + final Set vdis = sr.getVDIs(conn); + for (final VDI vdi : vdis) { + final Map currentOperation = vdi.getCurrentOperations(conn); + if (currentOperation == null || currentOperation.size() == 0) { + continue; + } + if (waittime >= 1800000) { + final String msg = "This template is being used, try late time"; + s_logger.warn(msg); + return msg; + } + waittime += 30000; + try { + Thread.sleep(30000); + } catch (final InterruptedException ex) { + } + } + removeSR(conn, sr); + return null; + } catch (final XenAPIException e) { + s_logger.warn(logX(sr, "Unable to get current opertions " + e.toString()), e); + } catch (final XmlRpcException e) { + s_logger.warn(logX(sr, "Unable to get current opertions " + e.getMessage()), e); + } + final String msg = "Remove SR failed"; + s_logger.warn(msg); + return msg; + + } + + public String revertToSnapshot(final Connection conn, final VM vmSnapshot, final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) throws XenAPIException, + XmlRpcException { + + final String results = + callHostPluginAsync(conn, "vmopsSnapshot", "revert_memory_snapshot", 10 * 60 * 1000, "snapshotUUID", vmSnapshot.getUuid(conn), "vmName", vmName, "oldVmUuid", + oldVmUuid, "snapshotMemory", snapshotMemory.toString(), "hostUUID", hostUUID); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "revert_memory_snapshot return null"; + } else { + if (results.equals("0")) { + return results; + } else { + errMsg = "revert_memory_snapshot exception"; + } + } + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + + 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); + final Long newDynamicMemoryMin = vmSpec.getMinRam(); + final Long newDynamicMemoryMax = vmSpec.getMaxRam(); + if (staticMemoryMin > newDynamicMemoryMin || newDynamicMemoryMax > staticMemoryMax) { + throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: " + "0 <= memory-static-min(" + staticMemoryMin + + ") <= memory-dynamic-min(" + newDynamicMemoryMin + ") <= memory-dynamic-max(" + newDynamicMemoryMax + ") <= memory-static-max(" + staticMemoryMax + ")"); + } + + vm.setMemoryDynamicRange(conn, newDynamicMemoryMin, newDynamicMemoryMax); + vm.setVCPUsNumberLive(conn, (long)vmSpec.getCpus()); + + final Integer speed = vmSpec.getMinSpeed(); + if (speed != null) { + + int cpuWeight = _maxWeight; //cpu_weight + + // weight based allocation + + cpuWeight = (int)(speed * 0.99 / _host.getSpeed() * _maxWeight); + if (cpuWeight > _maxWeight) { + cpuWeight = _maxWeight; + } + + if (vmSpec.getLimitCpuUse()) { + long utilization = 0; // max CPU cap, default is unlimited + utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100); + //vm.addToVCPUsParamsLive(conn, "cap", Long.toString(utilization)); currently xenserver doesnot support Xapi to add VCPUs params live. + callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", Long.toString(utilization), "vmname", vmSpec.getName()); + } + //vm.addToVCPUsParamsLive(conn, "weight", Integer.toString(cpuWeight)); + callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", Integer.toString(cpuWeight), "vmname", vmSpec.getName()); + } + } + + @Override + public void setAgentControl(final IAgentControl agentControl) { + _agentControl = agentControl; + } + + public void setCanBridgeFirewall(final boolean canBridgeFirewall) { + _canBridgeFirewall = canBridgeFirewall; + } + + @Override + public void setConfigParams(final Map params) { + } + + public boolean setIptables(final Connection conn) { + final String result = callHostPlugin(conn, "vmops", "setIptables"); + if (result == null || result.isEmpty()) { + return false; + } + return true; + } + + public void setIsOvs(final boolean isOvs) { + _isOvs = isOvs; + } + + /** + * WARN: static-min <= dynamic-min <= dynamic-max <= static-max + * @see XcpServerResource#setMemory(com.xensource.xenapi.Connection, com.xensource.xenapi.VM, long, long) + * @param conn + * @param vm + * @param minMemsize + * @param maxMemsize + * @throws XmlRpcException + * @throws XenAPIException + */ + protected void setMemory(final Connection conn, final VM vm, final long minMemsize, final long maxMemsize) throws XmlRpcException, XenAPIException { + vm.setMemoryLimits(conn, mem_128m, maxMemsize, minMemsize, maxMemsize); + } + + @Override + public void setName(final String name) { } protected void setNicDevIdIfCorrectVifIsNotNull(final Connection conn, final IpAddressTO ip, final VIF correctVif) throws InternalErrorException, BadServerResponse, XenAPIException, @@ -7085,88 +4734,527 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected ExecutionResult prepareNetworkElementCommand(final SetSourceNatCommand cmd) { - final Connection conn = getConnection(); - final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); - final IpAddressTO pubIp = cmd.getIpAddress(); - try { - final VM router = getVM(conn, routerName); - - final VIF correctVif = getCorrectVif(conn, router, pubIp); - - pubIp.setNicDevId(Integer.valueOf(correctVif.getDevice(conn))); - - } catch (final Exception e) { - final String msg = "Ip SNAT failure due to " + e.toString(); - s_logger.error(msg, e); - return new ExecutionResult(false, msg); - } - return new ExecutionResult(true, null); - } - - protected ExecutionResult prepareNetworkElementCommand(final SetNetworkACLCommand cmd) { - final Connection conn = getConnection(); - final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); - - try { - final VM router = getVM(conn, routerName); - - final NicTO nic = cmd.getNic(); - if(nic != null) { - final VIF vif = getVifByMac(conn, router, nic.getMac()); - if(vif == null) { - final String msg = "Prepare SetNetworkACL failed due to VIF is null for : " + nic.getMac() +" with routername: " + routerName; - s_logger.error(msg); - return new ExecutionResult(false, msg); - } - nic.setDeviceId(Integer.valueOf(vif.getDevice(conn))); - } else { - final String msg = "Prepare SetNetworkACL failed due to nic is null for : " + routerName; - s_logger.error(msg); - return new ExecutionResult(false, msg); - } - } catch (final Exception e) { - final String msg = "Prepare SetNetworkACL failed due to " + e.toString(); - s_logger.error(msg, e); - return new ExecutionResult(false, msg); - } - return new ExecutionResult(true, null); - } - - @Override - public void setName(final String name) { - } - - @Override - public void setConfigParams(final Map params) { - } - - @Override - public Map getConfigParams() { - return null; - } - - @Override - public int getRunLevel() { - return 0; - } - @Override public void setRunLevel(final int level) { } - public boolean isXcp() { - final Connection conn = getConnection(); - final String result = callHostPlugin(conn, "ovstunnel", "is_xcp"); - if (result.equals("XCP")) { - return true; + public String setupHeartbeatSr(final Connection conn, final SR sr, final boolean force) throws XenAPIException, XmlRpcException { + final SR.Record srRec = sr.getRecord(conn); + final String srUuid = srRec.uuid; + if (!srRec.shared || !SRType.LVMOHBA.equals(srRec.type) && !SRType.LVMOISCSI.equals(srRec.type) && !SRType.NFS.equals(srRec.type)) { + return srUuid; } - return false; + String result = null; + final Host host = Host.getByUuid(conn, _host.getUuid()); + final Set tags = host.getTags(conn); + if (force || !tags.contains("cloud-heartbeat-" + srUuid)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Setting up the heartbeat sr for host " + _host.getIp() + " and sr " + srUuid); + } + final Set pbds = sr.getPBDs(conn); + for (final PBD pbd : pbds) { + final PBD.Record pbdr = pbd.getRecord(conn); + if (!pbdr.currentlyAttached && pbdr.host.getUuid(conn).equals(_host.getUuid())) { + pbd.plug(conn); + break; + } + } + result = callHostPluginThroughMaster(conn, "vmopspremium", "setup_heartbeat_sr", "host", _host.getUuid(), "sr", srUuid); + if (result == null || !result.split("#")[1].equals("0")) { + throw new CloudRuntimeException("Unable to setup heartbeat sr on SR " + srUuid + " due to " + result); + } + + if (!tags.contains("cloud-heartbeat-" + srUuid)) { + tags.add("cloud-heartbeat-" + srUuid); + host.setTags(conn, tags); + } + } + result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.getUuid(), "sr", srUuid, "add", "true"); + if (result == null || !result.split("#")[1].equals("0")) { + throw new CloudRuntimeException("Unable to setup heartbeat file entry on SR " + srUuid + " due to " + result); + } + return srUuid; } - public String getLabel() { - final Connection conn = getConnection(); - final String result = callHostPlugin(conn, "ovstunnel", "getLabel"); - return result; + public void setupLinkLocalNetwork(final Connection conn) { + try { + final Network.Record rec = new Network.Record(); + final Set networks = Network.getByNameLabel(conn, _linkLocalPrivateNetworkName); + Network linkLocal = null; + + if (networks.size() == 0) { + rec.nameDescription = "link local network used by system vms"; + rec.nameLabel = _linkLocalPrivateNetworkName; + final Map configs = new HashMap(); + configs.put("ip_begin", NetUtils.getLinkLocalGateway()); + configs.put("ip_end", NetUtils.getLinkLocalIpEnd()); + configs.put("netmask", NetUtils.getLinkLocalNetMask()); + configs.put("vswitch-disable-in-band", "true"); + rec.otherConfig = configs; + linkLocal = Network.create(conn, rec); + } else { + linkLocal = networks.iterator().next(); + if (!linkLocal.getOtherConfig(conn).containsKey("vswitch-disable-in-band")) { + linkLocal.addToOtherConfig(conn, "vswitch-disable-in-band", "true"); + } + } + + /* Make sure there is a physical bridge on this network */ + VIF dom0vif = null; + final Pair vm = getControlDomain(conn); + final VM dom0 = vm.first(); + final Set vifs = dom0.getVIFs(conn); + if (vifs.size() != 0) { + for (final VIF vif : vifs) { + final Map otherConfig = vif.getOtherConfig(conn); + if (otherConfig != null) { + final String nameLabel = otherConfig.get("nameLabel"); + if (nameLabel != null && nameLabel.equalsIgnoreCase("link_local_network_vif")) { + dom0vif = vif; + } + } + } + } + + /* create temp VIF0 */ + if (dom0vif == null) { + s_logger.debug("Can't find a vif on dom0 for link local, creating a new one"); + final VIF.Record vifr = new VIF.Record(); + vifr.VM = dom0; + vifr.device = getLowestAvailableVIFDeviceNum(conn, dom0); + if (vifr.device == null) { + s_logger.debug("Failed to create link local network, no vif available"); + return; + } + final Map config = new HashMap(); + config.put("nameLabel", "link_local_network_vif"); + vifr.otherConfig = config; + vifr.MAC = "FE:FF:FF:FF:FF:FF"; + vifr.network = linkLocal; + vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT; + dom0vif = VIF.create(conn, vifr); + plugDom0Vif(conn, dom0vif); + } else { + s_logger.debug("already have a vif on dom0 for link local network"); + if (!dom0vif.getCurrentlyAttached(conn)) { + plugDom0Vif(conn, dom0vif); + } + } + + final String brName = linkLocal.getBridge(conn); + callHostPlugin(conn, "vmops", "setLinkLocalIP", "brName", brName); + _host.setLinkLocalNetwork(linkLocal.getUuid(conn)); + + } catch (final XenAPIException e) { + s_logger.warn("Unable to create local link network", e); + throw new CloudRuntimeException("Unable to create local link network due to " + e.toString(), e); + } catch (final XmlRpcException e) { + s_logger.warn("Unable to create local link network", e); + throw new CloudRuntimeException("Unable to create local link network due to " + e.toString(), e); + } + } + + /* return : if setup is needed */ + public boolean setupServer(final Connection conn, final Host host) { + final String packageVersion = CitrixResourceBase.class.getPackage().getImplementationVersion(); + final String version = this.getClass().getName() + "-" + (packageVersion == null ? Long.toString(System.currentTimeMillis()) : packageVersion); + + try { + /* push patches to XenServer */ + final Host.Record hr = host.getRecord(conn); + + final Iterator it = hr.tags.iterator(); + + while (it.hasNext()) { + final String tag = it.next(); + if (tag.startsWith("vmops-version-")) { + if (tag.contains(version)) { + s_logger.info(logX(host, "Host " + hr.address + " is already setup.")); + return false; + } else { + it.remove(); + } + } + } + + final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(hr.address, 22); + try { + sshConnection.connect(null, 60000, 60000); + if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { + throw new CloudRuntimeException("Unable to authenticate"); + } + + final com.trilead.ssh2.Session session = sshConnection.openSession(); + + final String cmd = "mkdir -p /opt/cloud/bin /var/log/cloud"; + if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { + throw new CloudRuntimeException("Cannot create directory /opt/cloud/bin on XenServer hosts"); + } + + final SCPClient scp = new SCPClient(sshConnection); + + final List files = getPatchFiles(); + if (files == null || files.isEmpty()) { + throw new CloudRuntimeException("Can not find patch file"); + } + for (final File file : files) { + final String path = file.getParentFile().getAbsolutePath() + "/"; + final Properties props = PropertiesUtil.loadFromFile(file); + + for (final Map.Entry entry : props.entrySet()) { + final String k = (String)entry.getKey(); + final String v = (String)entry.getValue(); + + assert k != null && k.length() > 0 && v != null && v.length() > 0 : "Problems with " + k + "=" + v; + + final String[] tokens = v.split(","); + String f = null; + if (tokens.length == 3 && tokens[0].length() > 0) { + if (tokens[0].startsWith("/")) { + f = tokens[0]; + } else if (tokens[0].startsWith("~")) { + final String homedir = System.getenv("HOME"); + f = homedir + tokens[0].substring(1) + k; + } else { + f = path + tokens[0] + '/' + k; + } + } else { + f = path + k; + } + final String directoryPath = tokens[tokens.length - 1]; + + f = f.replace('/', File.separatorChar); + + String permissions = "0755"; + if (tokens.length == 3) { + permissions = tokens[1]; + } else if (tokens.length == 2) { + permissions = tokens[0]; + } + + if (!new File(f).exists()) { + s_logger.warn("We cannot locate " + f); + continue; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Copying " + f + " to " + directoryPath + " on " + hr.address + " with permission " + permissions); + } + try { + session.execCommand("mkdir -m 700 -p " + directoryPath); + } catch (final IOException e) { + s_logger.debug("Unable to create destination path: " + directoryPath + " on " + hr.address + " but trying anyway"); + } + try { + scp.put(f, directoryPath, permissions); + } catch (final IOException e) { + final String msg = "Unable to copy file " + f + " to path " + directoryPath + " with permissions " + permissions; + s_logger.debug(msg); + throw new CloudRuntimeException("Unable to setup the server: " + msg, e); + } + } + } + + } catch (final IOException e) { + throw new CloudRuntimeException("Unable to setup the server correctly", e); + } finally { + sshConnection.close(); + } + hr.tags.add("vmops-version-" + version); + host.setTags(conn, hr.tags); + return true; + } catch (final XenAPIException e) { + final String msg = "XenServer setup failed due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException("Unable to get host information " + e.toString(), e); + } catch (final XmlRpcException e) { + final String msg = "XenServer setup failed due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException("Unable to get host information ", e); + } + } + + public synchronized Network setupvSwitchNetwork(final Connection conn) { + try { + if (_host.getVswitchNetwork() == null) { + Network vswitchNw = null; + final Network.Record rec = new Network.Record(); + final String nwName = Networks.BroadcastScheme.VSwitch.toString(); + final Set networks = Network.getByNameLabel(conn, nwName); + + if (networks.size() == 0) { + rec.nameDescription = "vswitch network for " + nwName; + rec.nameLabel = nwName; + vswitchNw = Network.create(conn, rec); + } else { + vswitchNw = networks.iterator().next(); + } + _host.setVswitchNetwork(vswitchNw); + } + return _host.getVswitchNetwork(); + } catch (final BadServerResponse e) { + s_logger.error("Failed to setup vswitch network", e); + } catch (final XenAPIException e) { + s_logger.error("Failed to setup vswitch network", e); + } catch (final XmlRpcException e) { + s_logger.error("Failed to setup vswitch network", e); + } + + return null; + } + + public void shutdownVM(final Connection conn, final VM vm, final String vmName) throws XmlRpcException { + Task task = null; + try { + task = vm.cleanShutdownAsync(conn); + try { + //poll every 1 seconds , timeout after 10 minutes + waitForTask(conn, task, 1000, 10 * 60 * 1000); + checkForSuccess(conn, task); + } catch (final TimeoutException e) { + if (vm.getPowerState(conn) == VmPowerState.HALTED) { + task = null; + return; + } + throw new CloudRuntimeException("Shutdown VM catch HandleInvalid and VM is not in HALTED state"); + } + } catch (final XenAPIException e) { + s_logger.debug("Unable to cleanShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString()); + try { + VmPowerState state = vm.getPowerState(conn); + if (state == VmPowerState.RUNNING) { + try { + vm.hardShutdown(conn); + } catch (final Exception e1) { + s_logger.debug("Unable to hardShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString()); + state = vm.getPowerState(conn); + if (state == VmPowerState.RUNNING) { + forceShutdownVM(conn, vm); + } + return; + } + } else if (state == VmPowerState.HALTED) { + return; + } else { + final String msg = "After cleanShutdown the VM status is " + state.toString() + ", that is not expected"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + } catch (final Exception e1) { + final String msg = "Unable to hardShutdown VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); + s_logger.warn(msg, e1); + throw new CloudRuntimeException(msg); + } + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (final Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); + } + } + } + } + + @Override + public boolean start() { + return true; + } + + public void startVM(final Connection conn, final Host host, final VM vm, final String vmName) throws Exception { + Task task = null; + try { + task = vm.startOnAsync(conn, host, false, true); + try { + //poll every 1 seconds , timeout after 10 minutes + waitForTask(conn, task, 1000, 10 * 60 * 1000); + checkForSuccess(conn, task); + } catch (final Types.HandleInvalid e) { + if (vm.getPowerState(conn) == VmPowerState.RUNNING) { + s_logger.debug("VM " + vmName + " is in Running status"); + task = null; + return; + } + throw new CloudRuntimeException("Start VM " + vmName + " catch HandleInvalid and VM is not in RUNNING state"); + } catch (final TimeoutException e) { + if (vm.getPowerState(conn) == VmPowerState.RUNNING) { + s_logger.debug("VM " + vmName + " is in Running status"); + task = null; + return; + } + throw new CloudRuntimeException("Start VM " + vmName + " catch BadAsyncResult and VM is not in RUNNING state"); + } + } catch (final XenAPIException e) { + final String msg = "Unable to start VM(" + vmName + ") on host(" + _host.getUuid() + ") due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (final Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); + } + } + } + } + + protected void startvmfailhandle(final Connection conn, final VM vm, final List> mounts) { + if (vm != null) { + try { + + if (vm.getPowerState(conn) == VmPowerState.RUNNING) { + try { + vm.hardShutdown(conn); + } catch (final Exception e) { + final String msg = "VM hardshutdown failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + if (vm.getPowerState(conn) == VmPowerState.HALTED) { + try { + vm.destroy(conn); + } catch (final Exception e) { + final String msg = "VM destroy failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + } catch (final Exception e) { + final String msg = "VM getPowerState failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + if (mounts != null) { + for (final Ternary mount : mounts) { + final VDI vdi = mount.second(); + Set vbds = null; + try { + vbds = vdi.getVBDs(conn); + } catch (final Exception e) { + final String msg = "VDI getVBDS failed due to " + e.toString(); + s_logger.warn(msg, e); + continue; + } + for (final VBD vbd : vbds) { + try { + vbd.unplug(conn); + vbd.destroy(conn); + } catch (final Exception e) { + final String msg = "VBD destroy failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + } + } + } + + @Override + public boolean stop() { + disconnected(); + return true; + } + + private HashMap> syncNetworkGroups(final Connection conn, final long id) { + final HashMap> states = new HashMap>(); + + final String result = callHostPlugin(conn, "vmops", "get_rule_logs_for_vms", "host_uuid", _host.getUuid()); + s_logger.trace("syncNetworkGroups: id=" + id + " got: " + result); + final String[] rulelogs = result != null ? result.split(";") : new String[0]; + for (final String rulesforvm : rulelogs) { + final String[] log = rulesforvm.split(","); + if (log.length != 6) { + continue; + } + //output = ','.join([vmName, vmID, vmIP, domID, signature, seqno]) + try { + states.put(log[0], new Pair(Long.parseLong(log[1]), Long.parseLong(log[5]))); + } catch (final NumberFormatException nfe) { + states.put(log[0], new Pair(-1L, -1L)); + } + } + return states; + } + + 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); + Host.managementReconfigure(conn, dest); + String hostUuid = null; + final int count = 0; + while (count < 10) { + try { + Thread.sleep(10000); + hostUuid = host.getUuid(conn); + if (hostUuid != null) { + break; + } + } catch (final XmlRpcException e) { + s_logger.debug("Waiting for host to come back: " + e.getMessage()); + } catch (final XenAPIException e) { + s_logger.debug("Waiting for host to come back: " + e.getMessage()); + } catch (final InterruptedException e) { + s_logger.debug("Gotta run"); + return false; + } + } + if (hostUuid == null) { + s_logger.warn("Unable to transfer the management network from " + spr.uuid); + return false; + } + + src.reconfigureIp(conn, Types.IpConfigurationMode.NONE, null, null, null, null); + return true; + } + + protected void umount(final Connection conn, final VDI vdi) { + + } + + public void umountSnapshotDir(final Connection conn, final Long dcId) { + try { + callHostPlugin(conn, "vmopsSnapshot", "unmountSnapshotsDir", "dcId", dcId.toString()); + } catch (final Exception e) { + s_logger.debug("Failed to umount snapshot dir",e); + } + } + + public String upgradeSnapshot(final Connection conn, final String templatePath, final String snapshotPath) { + final String results = callHostPluginAsync(conn, "vmopspremium", "upgrade_snapshot", 2 * 60 * 60, "templatePath", templatePath, "snapshotPath", snapshotPath); + + if (results == null || results.isEmpty()) { + final String msg = "upgrade_snapshot return null"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + final String[] tmp = results.split("#"); + final String status = tmp[0]; + if (status.equals("0")) { + return results; + } else { + s_logger.warn(results); + throw new CloudRuntimeException(results); + } + } + + public void waitForTask(final Connection c, final Task task, final long pollInterval, final long timeout) throws XenAPIException, XmlRpcException, TimeoutException { + final long beginTime = System.currentTimeMillis(); + if (s_logger.isTraceEnabled()) { + s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") sent to " + c.getSessionReference() + " is pending completion with a " + timeout + + "ms timeout"); + } + while (task.getStatus(c) == Types.TaskStatusType.PENDING) { + try { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") is pending, sleeping for " + pollInterval + "ms"); + } + Thread.sleep(pollInterval); + } catch (final InterruptedException e) { + } + if (System.currentTimeMillis() - beginTime > timeout) { + final String msg = "Async " + timeout / 1000 + " seconds timeout for task " + task.toString(); + s_logger.warn(msg); + task.cancel(c); + task.destroy(c); + throw new TimeoutException(msg); + } + } } } \ No newline at end of file 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 f695582f525..26f148e57c4 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 @@ -66,7 +66,7 @@ public class XenServer56FP1Resource extends XenServer56Resource { protected FenceAnswer execute(final FenceCommand cmd) { final Connection conn = getConnection(); try { - final Boolean alive = check_heartbeat(cmd.getHostGuid()); + 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"); 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 6b3efb5d930..85cdf04ac3b 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 @@ -27,14 +27,13 @@ import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.CheckOnHostAnswer; -import com.cloud.agent.api.CheckOnHostCommand; 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; +import com.cloud.hypervisor.xenserver.resource.wrapper.CitrixRequestWrapper; import com.cloud.resource.ServerResource; import com.cloud.utils.ExecutionResult; import com.cloud.utils.exception.CloudRuntimeException; @@ -55,16 +54,24 @@ public class XenServer56Resource extends CitrixResourceBase { @Override public Answer executeRequest(final Command cmd) { + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + try { + return wrapper.execute(cmd, this); + } catch (final Exception e) { + // return Answer.createUnsupportedCommandAnswer(cmd); + // Ignore this for now. Still working on converting the other commands. + } + if (cmd instanceof FenceCommand) { - return execute((FenceCommand)cmd); + return execute((FenceCommand) cmd); } else if (cmd instanceof NetworkUsageCommand) { - return execute((NetworkUsageCommand)cmd); + return execute((NetworkUsageCommand) cmd); } else { return super.executeRequest(cmd); } } - @Override protected List getPatchFiles() { final List files = new ArrayList(); @@ -144,7 +151,6 @@ public class XenServer56Resource extends CitrixResourceBase { protected NetworkUsageAnswer VPCNetworkUsage(final NetworkUsageCommand cmd) { try { - final Connection conn = getConnection(); final String option = cmd.getOption(); final String publicIp = cmd.getGatewayIP(); @@ -209,7 +215,7 @@ public class XenServer56Resource extends CitrixResourceBase { } } - protected Boolean check_heartbeat(final String hostuuid) { + public Boolean checkHeartbeat(final String hostuuid) { final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); try { sshConnection.connect(null, 60000, 60000); @@ -217,15 +223,14 @@ public class XenServer56Resource extends CitrixResourceBase { throw new CloudRuntimeException("Unable to authenticate"); } - final String shcmd = "/opt/cloud/bin/check_heartbeat.sh " + hostuuid + " " - + Integer.toString(_heartbeatInterval * 2); + final String shcmd = "/opt/cloud/bin/check_heartbeat.sh " + hostuuid + " " + Integer.toString(_heartbeatInterval * 2); if (!SSHCmdHelper.sshExecuteCmd(sshConnection, shcmd)) { s_logger.debug("Heart beat is gone so dead."); return false; } s_logger.debug("Heart beat is still going"); return true; - } catch (final Exception e) { + } catch (final Exception e) { s_logger.debug("health check failed due to catch exception " + e.toString()); return null; } finally { @@ -236,12 +241,12 @@ public class XenServer56Resource extends CitrixResourceBase { protected FenceAnswer execute(final FenceCommand cmd) { final Connection conn = getConnection(); try { - final Boolean alive = check_heartbeat(cmd.getHostGuid()); - if ( alive == null ) { + 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 ) { + 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"); } @@ -261,7 +266,6 @@ public class XenServer56Resource extends CitrixResourceBase { } } - @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); @@ -300,26 +304,7 @@ public class XenServer56Resource extends CitrixResourceBase { return cmds; } - - @Override - protected CheckOnHostAnswer execute(final CheckOnHostCommand cmd) { - final Boolean alive = check_heartbeat(cmd.getHost().getGuid()); - String msg = ""; - if (alive == null) { - msg = " cannot determine "; - } else if ( alive == true) { - msg = "Heart beat is still going"; - } else { - msg = "Heart beat is gone so dead."; - } - s_logger.debug(msg); - return new CheckOnHostAnswer(cmd, alive, msg); - - } - - public XenServer56Resource() { super(); } - -} +} \ 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 15532397f37..05caabd1d4a 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,8 +21,6 @@ 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; @@ -83,6 +81,8 @@ 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.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; import com.cloud.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; import com.cloud.resource.ServerResource; @@ -95,91 +95,113 @@ public class CitrixRequestWrapper extends RequestWrapper { instance = new CitrixRequestWrapper(); } + private boolean initialised; + @SuppressWarnings("rawtypes") - private final Hashtable, CommandWrapper> map; + private final Hashtable, Hashtable, CommandWrapper>> resources; @SuppressWarnings("rawtypes") private CitrixRequestWrapper() { - map = new Hashtable, CommandWrapper>(); + resources = new Hashtable, Hashtable, CommandWrapper>>(); init(); } + @SuppressWarnings("rawtypes") private void init() { - map.put(RebootRouterCommand.class, new CitrixRebootRouterCommandWrapper()); - map.put(CreateCommand.class, new CitrixCreateCommandWrapper()); - map.put(CheckConsoleProxyLoadCommand.class, new CitrixCheckConsoleProxyLoadCommandWrapper()); - map.put(WatchConsoleProxyLoadCommand.class, new CitrixWatchConsoleProxyLoadCommandWrapper()); - map.put(ReadyCommand.class, new CitrixReadyCommandWrapper()); - map.put(GetHostStatsCommand.class, new CitrixGetHostStatsCommandWrapper()); - map.put(GetVmStatsCommand.class, new CitrixGetVmStatsCommandWrapper()); - map.put(GetVmDiskStatsCommand.class, new CitrixGetVmDiskStatsCommandWrapper()); - map.put(CheckHealthCommand.class, new CitrixCheckHealthCommandWrapper()); - map.put(StopCommand.class, new CitrixStopCommandWrapper()); - map.put(RebootCommand.class, new CitrixRebootCommandWrapper()); - map.put(CheckVirtualMachineCommand.class, new CitrixCheckVirtualMachineCommandWrapper()); - map.put(PrepareForMigrationCommand.class, new CitrixPrepareForMigrationCommandWrapper()); - map.put(MigrateCommand.class, new CitrixMigrateCommandWrapper()); - map.put(DestroyCommand.class, new CitrixDestroyCommandWrapper()); - map.put(CreateStoragePoolCommand.class, new CitrixCreateStoragePoolCommandWrapper()); - map.put(ModifyStoragePoolCommand.class, new CitrixModifyStoragePoolCommandWrapper()); - map.put(DeleteStoragePoolCommand.class, new CitrixDeleteStoragePoolCommandWrapper()); - map.put(ResizeVolumeCommand.class, new CitrixResizeVolumeCommandWrapper()); - map.put(AttachVolumeCommand.class, new CitrixAttachVolumeCommandWrapper()); - map.put(AttachIsoCommand.class, new CitrixAttachIsoCommandWrapper()); - map.put(UpgradeSnapshotCommand.class, new CitrixUpgradeSnapshotCommandWrapper()); - map.put(GetStorageStatsCommand.class, new CitrixGetStorageStatsCommandWrapper()); - map.put(PrimaryStorageDownloadCommand.class, new CitrixPrimaryStorageDownloadCommandWrapper()); - map.put(GetVncPortCommand.class, new CitrixGetVncPortCommandWrapper()); - map.put(SetupCommand.class, new CitrixSetupCommandWrapper()); - map.put(MaintainCommand.class, new CitrixMaintainCommandWrapper()); - map.put(PingTestCommand.class, new CitrixPingTestCommandWrapper()); - map.put(CheckOnHostCommand.class, new CitrixCheckOnHostCommandWrapper()); - map.put(ModifySshKeysCommand.class, new CitrixModifySshKeysCommandWrapper()); - map.put(StartCommand.class, new CitrixStartCommandWrapper()); - map.put(OvsSetTagAndFlowCommand.class, new CitrixOvsSetTagAndFlowCommandWrapper()); - 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()); - map.put(NetworkRulesSystemVmCommand.class, new CitrixNetworkRulesSystemVmCommandWrapper()); - map.put(OvsCreateTunnelCommand.class, new CitrixOvsCreateTunnelCommandWrapper()); - map.put(OvsSetupBridgeCommand.class, new CitrixOvsSetupBridgeCommandWrapper()); - map.put(OvsDestroyBridgeCommand.class, new CitrixOvsDestroyBridgeCommandWrapper()); - map.put(OvsDestroyTunnelCommand.class, new CitrixOvsDestroyTunnelCommandWrapper()); - map.put(UpdateHostPasswordCommand.class, new CitrixUpdateHostPasswordCommandWrapper()); - map.put(ClusterVMMetaDataSyncCommand.class, new CitrixClusterVMMetaDataSyncCommandWrapper()); - map.put(CheckNetworkCommand.class, new CitrixCheckNetworkCommandWrapper()); - map.put(PlugNicCommand.class, new CitrixPlugNicCommandWrapper()); - map.put(UnPlugNicCommand.class, new CitrixUnPlugNicCommandWrapper()); - 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()); + // CitrixResourceBase commands + final Hashtable, CommandWrapper> citrixCommands = new Hashtable, CommandWrapper>(); + citrixCommands.put(RebootRouterCommand.class, new CitrixRebootRouterCommandWrapper()); + citrixCommands.put(CreateCommand.class, new CitrixCreateCommandWrapper()); + citrixCommands.put(CheckConsoleProxyLoadCommand.class, new CitrixCheckConsoleProxyLoadCommandWrapper()); + citrixCommands.put(WatchConsoleProxyLoadCommand.class, new CitrixWatchConsoleProxyLoadCommandWrapper()); + citrixCommands.put(ReadyCommand.class, new CitrixReadyCommandWrapper()); + citrixCommands.put(GetHostStatsCommand.class, new CitrixGetHostStatsCommandWrapper()); + citrixCommands.put(GetVmStatsCommand.class, new CitrixGetVmStatsCommandWrapper()); + citrixCommands.put(GetVmDiskStatsCommand.class, new CitrixGetVmDiskStatsCommandWrapper()); + citrixCommands.put(CheckHealthCommand.class, new CitrixCheckHealthCommandWrapper()); + citrixCommands.put(StopCommand.class, new CitrixStopCommandWrapper()); + citrixCommands.put(RebootCommand.class, new CitrixRebootCommandWrapper()); + citrixCommands.put(CheckVirtualMachineCommand.class, new CitrixCheckVirtualMachineCommandWrapper()); + citrixCommands.put(PrepareForMigrationCommand.class, new CitrixPrepareForMigrationCommandWrapper()); + citrixCommands.put(MigrateCommand.class, new CitrixMigrateCommandWrapper()); + citrixCommands.put(DestroyCommand.class, new CitrixDestroyCommandWrapper()); + citrixCommands.put(CreateStoragePoolCommand.class, new CitrixCreateStoragePoolCommandWrapper()); + citrixCommands.put(ModifyStoragePoolCommand.class, new CitrixModifyStoragePoolCommandWrapper()); + citrixCommands.put(DeleteStoragePoolCommand.class, new CitrixDeleteStoragePoolCommandWrapper()); + citrixCommands.put(ResizeVolumeCommand.class, new CitrixResizeVolumeCommandWrapper()); + citrixCommands.put(AttachVolumeCommand.class, new CitrixAttachVolumeCommandWrapper()); + citrixCommands.put(AttachIsoCommand.class, new CitrixAttachIsoCommandWrapper()); + citrixCommands.put(UpgradeSnapshotCommand.class, new CitrixUpgradeSnapshotCommandWrapper()); + citrixCommands.put(GetStorageStatsCommand.class, new CitrixGetStorageStatsCommandWrapper()); + citrixCommands.put(PrimaryStorageDownloadCommand.class, new CitrixPrimaryStorageDownloadCommandWrapper()); + citrixCommands.put(GetVncPortCommand.class, new CitrixGetVncPortCommandWrapper()); + citrixCommands.put(SetupCommand.class, new CitrixSetupCommandWrapper()); + citrixCommands.put(MaintainCommand.class, new CitrixMaintainCommandWrapper()); + citrixCommands.put(PingTestCommand.class, new CitrixPingTestCommandWrapper()); + citrixCommands.put(CheckOnHostCommand.class, new CitrixCheckOnHostCommandWrapper()); + citrixCommands.put(ModifySshKeysCommand.class, new CitrixModifySshKeysCommandWrapper()); + citrixCommands.put(StartCommand.class, new CitrixStartCommandWrapper()); + citrixCommands.put(OvsSetTagAndFlowCommand.class, new CitrixOvsSetTagAndFlowCommandWrapper()); + citrixCommands.put(CheckSshCommand.class, new CitrixCheckSshCommandWrapper()); + citrixCommands.put(SecurityGroupRulesCmd.class, new CitrixSecurityGroupRulesCommandWrapper()); + citrixCommands.put(OvsFetchInterfaceCommand.class, new CitrixOvsFetchInterfaceCommandWrapper()); + citrixCommands.put(OvsCreateGreTunnelCommand.class, new CitrixOvsCreateGreTunnelCommandWrapper()); + citrixCommands.put(OvsDeleteFlowCommand.class, new CitrixOvsDeleteFlowCommandWrapper()); + citrixCommands.put(OvsVpcPhysicalTopologyConfigCommand.class, new CitrixOvsVpcPhysicalTopologyConfigCommandWrapper()); + citrixCommands.put(OvsVpcRoutingPolicyConfigCommand.class, new CitrixOvsVpcRoutingPolicyConfigCommandWrapper()); + citrixCommands.put(CleanupNetworkRulesCmd.class, new CitrixCleanupNetworkRulesCmdWrapper()); + citrixCommands.put(NetworkRulesSystemVmCommand.class, new CitrixNetworkRulesSystemVmCommandWrapper()); + citrixCommands.put(OvsCreateTunnelCommand.class, new CitrixOvsCreateTunnelCommandWrapper()); + citrixCommands.put(OvsSetupBridgeCommand.class, new CitrixOvsSetupBridgeCommandWrapper()); + citrixCommands.put(OvsDestroyBridgeCommand.class, new CitrixOvsDestroyBridgeCommandWrapper()); + citrixCommands.put(OvsDestroyTunnelCommand.class, new CitrixOvsDestroyTunnelCommandWrapper()); + citrixCommands.put(UpdateHostPasswordCommand.class, new CitrixUpdateHostPasswordCommandWrapper()); + citrixCommands.put(ClusterVMMetaDataSyncCommand.class, new CitrixClusterVMMetaDataSyncCommandWrapper()); + citrixCommands.put(CheckNetworkCommand.class, new CitrixCheckNetworkCommandWrapper()); + citrixCommands.put(PlugNicCommand.class, new CitrixPlugNicCommandWrapper()); + citrixCommands.put(UnPlugNicCommand.class, new CitrixUnPlugNicCommandWrapper()); + citrixCommands.put(CreateVMSnapshotCommand.class, new CitrixCreateVMSnapshotCommandWrapper()); + citrixCommands.put(DeleteVMSnapshotCommand.class, new CitrixDeleteVMSnapshotCommandWrapper()); + citrixCommands.put(RevertToVMSnapshotCommand.class, new CitrixRevertToVMSnapshotCommandWrapper()); + citrixCommands.put(NetworkRulesVmSecondaryIpCommand.class, new CitrixNetworkRulesVmSecondaryIpCommandWrapper()); + citrixCommands.put(ScaleVmCommand.class, new CitrixScaleVmCommandWrapper()); + citrixCommands.put(PvlanSetupCommand.class, new CitrixPvlanSetupCommandWrapper()); + citrixCommands.put(PerformanceMonitorCommand.class, new CitrixPerformanceMonitorCommandWrapper()); + citrixCommands.put(NetworkElementCommand.class, new CitrixNetworkElementCommandWrapper()); + resources.put(CitrixResourceBase.class, citrixCommands); + + // XenServer56Resource commands + final Hashtable, CommandWrapper> xenServer56Commands = new Hashtable, CommandWrapper>(); + xenServer56Commands.put(CheckOnHostCommand.class, new XenServer56CheckOnHostCommandWrapper()); + resources.put(XenServer56Resource.class, xenServer56Commands); + + initialised = true; } public static CitrixRequestWrapper getInstance() { return instance; } - @SuppressWarnings("unchecked") + boolean isInitialised() { + return initialised; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Answer execute(final Command command, final ServerResource serverResource) { - CommandWrapper commandWrapper = map.get(command.getClass()); + Hashtable, CommandWrapper> commands = resources.get(serverResource.getClass()); + + // Can't instantiate the CitrixResourceBase because it's abstract. In order to reuse the command with subclasses + // I need to do this check here. + if (commands == null) { + commands = resources.get(serverResource.getClass().getSuperclass()); + } + + CommandWrapper commandWrapper = commands.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); + commandWrapper = commands.get(NetworkElementCommand.class); } if (commandWrapper == null) { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56CheckOnHostCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56CheckOnHostCommandWrapper.java new file mode 100644 index 00000000000..972936ec8d3 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56CheckOnHostCommandWrapper.java @@ -0,0 +1,48 @@ +// +// 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.CheckOnHostAnswer; +import com.cloud.agent.api.CheckOnHostCommand; +import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; +import com.cloud.resource.CommandWrapper; + +public final class XenServer56CheckOnHostCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(XenServer56CheckOnHostCommandWrapper.class); + + @Override + public Answer execute(final CheckOnHostCommand command, final XenServer56Resource xenServer56) { + final Boolean alive = xenServer56.checkHeartbeat(command.getHost().getGuid()); + String msg = ""; + if (alive == null) { + msg = " cannot determine "; + } else if ( alive == true) { + msg = "Heart beat is still going"; + } else { + msg = "Heart beat is gone so dead."; + } + s_logger.debug(msg); + return new CheckOnHostAnswer(command, alive, 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 deleted file mode 100644 index 4d492aaac12..00000000000 --- a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java +++ /dev/null @@ -1,188 +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.hypervisor.xenserver.resource; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import org.apache.xmlrpc.XmlRpcException; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import com.cloud.agent.api.ScaleVmAnswer; -import com.cloud.agent.api.ScaleVmCommand; -import com.cloud.agent.api.to.IpAddressTO; -import com.cloud.agent.api.to.VirtualMachineTO; -import com.xensource.xenapi.Connection; -import com.xensource.xenapi.Host; -import com.xensource.xenapi.Types; -import com.xensource.xenapi.VIF; -import com.xensource.xenapi.VM; -import com.xensource.xenapi.XenAPIObject; - -public class CitrixResourceBaseTest { - - @Spy - CitrixResourceBase _resource = new CitrixResourceBase() { - - @Override - public ScaleVmAnswer execute(final ScaleVmCommand cmd) { - return super.execute(cmd); - } - - @Override - public String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) { - return "Success"; - } - - @Override - 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 - public boolean isDmcEnabled(final Connection conn, final Host host) throws Types.XenAPIException, XmlRpcException { - return true; - } - }; - @Mock - XsHost _host; - @Mock - Host host; - @Mock - ScaleVmCommand cmd; - @Mock - VirtualMachineTO vmSpec; - @Mock - Connection conn; - @Mock - VM vm; - - @Before - public void setup() { - - MockitoAnnotations.initMocks(this); - - doReturn(vmSpec).when(cmd).getVirtualMachine(); - doReturn("i-2-3-VM").when(vmSpec).getName(); - - } - - // Expecting XmlRpcException while trying to get the record of vm using connection - @Test(expected = XmlRpcException.class) - public void testScaleVMF1() throws Types.BadServerResponse, Types.XenAPIException, XmlRpcException { - doReturn(conn).when(_resource).getConnection(); - final Set vms = mock(Set.class); - - final Iterator iter = mock(Iterator.class); - doReturn(iter).when(vms).iterator(); - when(iter.hasNext()).thenReturn(true).thenReturn(false); - doReturn(vm).when(iter).next(); - final VM.Record vmr = mock(VM.Record.class); - when(vm.getRecord(conn)).thenThrow(new XmlRpcException("XmlRpcException")); - when(vm.getRecord(conn)).thenReturn(vmr); - vmr.powerState = Types.VmPowerState.RUNNING; - vmr.residentOn = mock(Host.class); - final XenAPIObject object = mock(XenAPIObject.class); - doReturn(new String("OpaqueRef:NULL")).when(object).toWireString(); - doNothing().when(_resource).scaleVM(conn, vm, vmSpec, host); - - _resource.execute(cmd); - verify(iter, times(2)).hasNext(); - verify(iter, times(2)).next(); - - } - - // Test to scale vm "i-2-3-VM" cpu-cap disabled - @Test - public void testScaleVMF2() throws Types.XenAPIException, XmlRpcException { - - when(vm.getMemoryStaticMax(conn)).thenReturn(1073741824L); - when(vm.getMemoryStaticMin(conn)).thenReturn(268435456L); - doReturn(536870912L).when(vmSpec).getMinRam(); - doReturn(536870912L).when(vmSpec).getMaxRam(); - doNothing().when(vm).setMemoryDynamicRange(conn, 536870912L, 536870912L); - doReturn(1).when(vmSpec).getCpus(); - doNothing().when(vm).setVCPUsNumberLive(conn, 1L); - doReturn(500).when(vmSpec).getMinSpeed(); - doReturn(false).when(vmSpec).getLimitCpuUse(); - final Map args = mock(HashMap.class); - when(host.callPlugin(conn, "vmops", "add_to_VCPUs_params_live", args)).thenReturn("Success"); - doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); - - _resource.scaleVM(conn, vm, vmSpec, host); - - verify(vmSpec, times(1)).getLimitCpuUse(); - verify(_resource, times(1)).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); - } - - // Test to scale vm "i-2-3-VM" cpu-cap enabled - @Test - public void testScaleVMF3() throws Types.XenAPIException, XmlRpcException { - - when(vm.getMemoryStaticMax(conn)).thenReturn(1073741824L); - when(vm.getMemoryStaticMin(conn)).thenReturn(268435456L); - doReturn(536870912L).when(vmSpec).getMinRam(); - doReturn(536870912L).when(vmSpec).getMaxRam(); - doNothing().when(vm).setMemoryDynamicRange(conn, 536870912L, 536870912L); - doReturn(1).when(vmSpec).getCpus(); - doNothing().when(vm).setVCPUsNumberLive(conn, 1L); - doReturn(500).when(vmSpec).getMinSpeed(); - doReturn(500).when(vmSpec).getMaxSpeed(); - doReturn(true).when(vmSpec).getLimitCpuUse(); - doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", "99", "vmname", "i-2-3-VM"); - final Map args = mock(HashMap.class); - when(host.callPlugin(conn, "vmops", "add_to_VCPUs_params_live", args)).thenReturn("Success"); - doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); - - _resource.scaleVM(conn, vm, vmSpec, host); - - verify(vmSpec, times(1)).getLimitCpuUse(); - verify(_resource, times(1)).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); - verify(_resource, times(1)).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", "99", "vmname", "i-2-3-VM"); - } - - - @Test - public void testSetNicDevIdIfCorrectVifIsNotNull() throws Exception { - final IpAddressTO ip = mock(IpAddressTO.class); - when(ip.isAdd()).thenReturn(false); - final VIF correctVif = null; - try { - _resource.setNicDevIdIfCorrectVifIsNotNull(conn, ip, correctVif); - } catch (final NullPointerException e) { - fail("this test is meant to show that null pointer is not thrown"); - } - } -} 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 new file mode 100644 index 00000000000..b8f43df7268 --- /dev/null +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56WrapperTest.java @@ -0,0 +1,38 @@ +package com.cloud.hypervisor.xenserver.resource.wrapper; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +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.hypervisor.xenserver.resource.XenServer56Resource; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ Connection.class, Host.Record.class }) +public class XenServer56WrapperTest { + + @Mock + private XenServer56Resource xenServer56Resource; + + @Test + public void testCheckOnHostCommand() { + final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class); + final CheckOnHostCommand onHostCommand = new CheckOnHostCommand(host); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(onHostCommand, xenServer56Resource); + + assertTrue(answer.getResult()); + } +} From f3842c81f8ae35b21131abe8d88c8cbc3b201b1c Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 31 Mar 2015 07:44:39 +0200 Subject: [PATCH 27/30] Refactoring XenServer56 and 56FP1 Resources in order to cope with new FenceCommandWrapper - Unit tests added Also removed an unit test that was doing nothing. --- .../resource/XenServer56FP1Resource.java | 56 ----------- .../resource/XenServer56Resource.java | 36 +------- .../wrapper/CitrixRequestWrapper.java | 8 ++ .../XenServer56FP1FenceCommandWrapper.java | 92 +++++++++++++++++++ .../XenServer56FenceCommandWrapper.java | 71 ++++++++++++++ .../com/cloud/ha/XenServerFencerTest.java | 39 -------- .../wrapper/XenServer56FP1WrapperTest.java | 49 ++++++++++ .../wrapper/XenServer56WrapperTest.java | 34 ++++++- 8 files changed, 251 insertions(+), 134 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FP1FenceCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FenceCommandWrapper.java delete mode 100644 plugins/hypervisors/xenserver/test/com/cloud/ha/XenServerFencerTest.java create mode 100644 plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FP1WrapperTest.java 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 From 3ad30a01a85c69cc0a983468b6c12d036fe9d725 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 31 Mar 2015 09:10:40 +0200 Subject: [PATCH 28/30] Refactoring XenServer56NetworkUsageCommandWrapper in order to cope with the new design - Unit tests added CitrixResourceBase, XenServer56Resource and XenServer56FP1Resource are now done. i --- .../resource/CitrixResourceBase.java | 2 +- .../resource/XenServer56Resource.java | 76 ------------- .../wrapper/CitrixRequestWrapper.java | 2 + ...XenServer56NetworkUsageCommandWrapper.java | 102 ++++++++++++++++++ .../wrapper/XenServer56WrapperTest.java | 76 +++++++++++++ 5 files changed, 181 insertions(+), 77 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56NetworkUsageCommandWrapper.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 ee9fd2b6f8a..dddff46384e 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 @@ -3088,7 +3088,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return earliestNetwork != null ? new XsLocalNetwork(this, earliestNetwork, earliestNetworkRecord, null, null) : null; } - protected long[] getNetworkStats(final Connection conn, final String privateIP) { + public long[] getNetworkStats(final Connection conn, final String privateIP) { final String result = networkUsage(conn, privateIP, "get", null); final long[] stats = new long[2]; if (result != null) { 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 3a9baf115e3..3a30dae8347 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 @@ -27,12 +27,9 @@ import org.apache.xmlrpc.XmlRpcException; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; -import com.cloud.agent.api.NetworkUsageAnswer; -import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.hypervisor.xenserver.resource.wrapper.CitrixRequestWrapper; import com.cloud.resource.ServerResource; -import com.cloud.utils.ExecutionResult; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SSHCmdHelper; @@ -55,13 +52,6 @@ public class XenServer56Resource extends CitrixResourceBase { try { return wrapper.execute(cmd, this); } catch (final Exception e) { - // return Answer.createUnsupportedCommandAnswer(cmd); - // Ignore this for now. Still working on converting the other commands. - } - - if (cmd instanceof NetworkUsageCommand) { - return execute((NetworkUsageCommand) cmd); - } else { return super.executeRequest(cmd); } } @@ -143,72 +133,6 @@ public class XenServer56Resource extends CitrixResourceBase { return executeInVR(privateIpAddress, "netusage.sh", args).getDetails(); } - protected NetworkUsageAnswer VPCNetworkUsage(final NetworkUsageCommand cmd) { - try { - final String option = cmd.getOption(); - final String publicIp = cmd.getGatewayIP(); - - String args = " -l " + publicIp + " "; - if (option.equals("get")) { - args += "-g"; - } else if (option.equals("create")) { - args += "-c"; - final String vpcCIDR = cmd.getVpcCIDR(); - args += " -v " + vpcCIDR; - } else if (option.equals("reset")) { - args += "-r"; - } else if (option.equals("vpn")) { - args += "-n"; - } else if (option.equals("remove")) { - args += "-d"; - } else { - return new NetworkUsageAnswer(cmd, "success", 0L, 0L); - } - - final ExecutionResult result = executeInVR(cmd.getPrivateIP(), "vpc_netusage.sh", args); - final String detail = result.getDetails(); - if (!result.isSuccess()) { - throw new Exception(" vpc network usage plugin call failed "); - } - if (option.equals("get") || option.equals("vpn")) { - final long[] stats = new long[2]; - if (detail != null) { - final String[] splitResult = detail.split(":"); - int i = 0; - while (i < splitResult.length - 1) { - stats[0] += new Long(splitResult[i++]).longValue(); - stats[1] += new Long(splitResult[i++]).longValue(); - } - return new NetworkUsageAnswer(cmd, "success", stats[0], stats[1]); - } - } - return new NetworkUsageAnswer(cmd, "success", 0L, 0L); - } catch (final Exception ex) { - s_logger.warn("Failed to get network usage stats due to ", ex); - return new NetworkUsageAnswer(cmd, ex); - } - } - - protected NetworkUsageAnswer execute(final NetworkUsageCommand cmd) { - if (cmd.isForVpc()) { - return VPCNetworkUsage(cmd); - } - try { - final Connection conn = getConnection(); - if (cmd.getOption() != null && cmd.getOption().equals("create")) { - final String result = networkUsage(conn, cmd.getPrivateIP(), "create", null); - final NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, result, 0L, 0L); - return answer; - } - final long[] stats = getNetworkStats(conn, cmd.getPrivateIP()); - final NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]); - return answer; - } catch (final Exception ex) { - s_logger.warn("Failed to get network usage stats due to ", ex); - return new NetworkUsageAnswer(cmd, ex); - } - } - public Boolean checkHeartbeat(final String hostuuid) { final com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.getIp(), 22); try { 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 a5ca115cd8c..8b0043f6437 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 @@ -47,6 +47,7 @@ import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.NetworkRulesSystemVmCommand; import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; +import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.OvsCreateGreTunnelCommand; import com.cloud.agent.api.OvsCreateTunnelCommand; import com.cloud.agent.api.OvsDeleteFlowCommand; @@ -176,6 +177,7 @@ public class CitrixRequestWrapper extends RequestWrapper { final Hashtable, CommandWrapper> xenServer56Commands = new Hashtable, CommandWrapper>(); xenServer56Commands.put(CheckOnHostCommand.class, new XenServer56CheckOnHostCommandWrapper()); xenServer56Commands.put(FenceCommand.class, new XenServer56FenceCommandWrapper()); + xenServer56Commands.put(NetworkUsageCommand.class, new XenServer56NetworkUsageCommandWrapper()); resources.put(XenServer56Resource.class, xenServer56Commands); // XenServer56FP1Resource commands diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56NetworkUsageCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56NetworkUsageCommandWrapper.java new file mode 100644 index 00000000000..0e3f922f630 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56NetworkUsageCommandWrapper.java @@ -0,0 +1,102 @@ +// +// 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.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.ExecutionResult; +import com.xensource.xenapi.Connection; + +public final class XenServer56NetworkUsageCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(XenServer56NetworkUsageCommandWrapper.class); + + @Override + public Answer execute(final NetworkUsageCommand command, final XenServer56Resource xenServer56) { + if (command.isForVpc()) { + return executeNetworkUsage(command, xenServer56); + } + try { + final Connection conn = xenServer56.getConnection(); + if (command.getOption() != null && command.getOption().equals("create")) { + final String result = xenServer56.networkUsage(conn, command.getPrivateIP(), "create", null); + final NetworkUsageAnswer answer = new NetworkUsageAnswer(command, result, 0L, 0L); + return answer; + } + final long[] stats = xenServer56.getNetworkStats(conn, command.getPrivateIP()); + final NetworkUsageAnswer answer = new NetworkUsageAnswer(command, "", stats[0], stats[1]); + return answer; + } catch (final Exception ex) { + s_logger.warn("Failed to get network usage stats due to ", ex); + return new NetworkUsageAnswer(command, ex); + } + } + + protected NetworkUsageAnswer executeNetworkUsage(final NetworkUsageCommand command, final XenServer56Resource xenServer56) { + try { + final String option = command.getOption(); + final String publicIp = command.getGatewayIP(); + + String args = " -l " + publicIp + " "; + if (option.equals("get")) { + args += "-g"; + } else if (option.equals("create")) { + args += "-c"; + final String vpcCIDR = command.getVpcCIDR(); + args += " -v " + vpcCIDR; + } else if (option.equals("reset")) { + args += "-r"; + } else if (option.equals("vpn")) { + args += "-n"; + } else if (option.equals("remove")) { + args += "-d"; + } else { + return new NetworkUsageAnswer(command, "success", 0L, 0L); + } + + final ExecutionResult result = xenServer56.executeInVR(command.getPrivateIP(), "vpc_netusage.sh", args); + final String detail = result.getDetails(); + if (!result.isSuccess()) { + throw new Exception(" vpc network usage plugin call failed "); + } + if (option.equals("get") || option.equals("vpn")) { + final long[] stats = new long[2]; + if (detail != null) { + final String[] splitResult = detail.split(":"); + int i = 0; + while (i < splitResult.length - 1) { + stats[0] += new Long(splitResult[i++]).longValue(); + stats[1] += new Long(splitResult[i++]).longValue(); + } + return new NetworkUsageAnswer(command, "success", stats[0], stats[1]); + } + } + return new NetworkUsageAnswer(command, "success", 0L, 0L); + } catch (final Exception ex) { + s_logger.warn("Failed to get network usage stats due to ", ex); + return new NetworkUsageAnswer(command, ex); + } + } +} \ 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 f93a83635e4..2035c521b71 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 @@ -16,8 +16,10 @@ 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.agent.api.NetworkUsageCommand; import com.cloud.host.Host; import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; +import com.cloud.utils.ExecutionResult; import com.cloud.vm.VMInstanceVO; import com.xensource.xenapi.Connection; @@ -61,4 +63,78 @@ public class XenServer56WrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testNetworkUsageCommandSuccess() { + final Connection conn = Mockito.mock(Connection.class); + + final NetworkUsageCommand networkCommand = new NetworkUsageCommand("192.168.10.10", "domRName", false, "192.168.10.1"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer56Resource.getConnection()).thenReturn(conn); + when(xenServer56Resource.getNetworkStats(conn, networkCommand.getPrivateIP())).thenReturn(new long[]{1, 1}); + + final Answer answer = wrapper.execute(networkCommand, xenServer56Resource); + + verify(xenServer56Resource, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testNetworkUsageCommandFailure() { + final Connection conn = Mockito.mock(Connection.class); + + final NetworkUsageCommand networkCommand = new NetworkUsageCommand("192.168.10.10", "domRName", false, "192.168.10.1"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer56Resource.getConnection()).thenReturn(conn); + when(xenServer56Resource.getNetworkStats(conn, networkCommand.getPrivateIP())).thenReturn(new long[0]); + + final Answer answer = wrapper.execute(networkCommand, xenServer56Resource); + + verify(xenServer56Resource, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testNetworkUsageCommandCreateVpc() { + final ExecutionResult executionResult = Mockito.mock(ExecutionResult.class); + + final NetworkUsageCommand networkCommand = new NetworkUsageCommand("192.168.10.10", "domRName", true, "192.168.10.1", "10.1.1.1/24"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final String args = " -l 192.168.10.1 -c -v 10.1.1.1/24"; + when(xenServer56Resource.executeInVR(networkCommand.getPrivateIP(), "vpc_netusage.sh", args)).thenReturn(executionResult); + when(executionResult.isSuccess()).thenReturn(true); + + final Answer answer = wrapper.execute(networkCommand, xenServer56Resource); + + assertTrue(answer.getResult()); + } + + @Test + public void testNetworkUsageCommandCreateVpcFailure() { + final ExecutionResult executionResult = Mockito.mock(ExecutionResult.class); + + final NetworkUsageCommand networkCommand = new NetworkUsageCommand("192.168.10.10", "domRName", true, "192.168.10.1", "10.1.1.1/24"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final String args = " -l 192.168.10.1 -c -v 10.1.1.1/24"; + when(xenServer56Resource.executeInVR(networkCommand.getPrivateIP(), "vpc_netusage.sh", args)).thenReturn(executionResult); + when(executionResult.isSuccess()).thenReturn(false); + + final Answer answer = wrapper.execute(networkCommand, xenServer56Resource); + + assertFalse(answer.getResult()); + } } \ No newline at end of file From d93935caacb46dae183d21a260a112d43cf88caf Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 31 Mar 2015 09:26:58 +0200 Subject: [PATCH 29/30] We don't need the Start, Stop, Reboot command in the CitrixRebaseClaas anymore. --- .../resource/CitrixResourceBase.java | 1036 ++++++----------- 1 file changed, 358 insertions(+), 678 deletions(-) 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 dddff46384e..77296365810 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 @@ -64,8 +64,6 @@ import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.HostStatsEntry; import com.cloud.agent.api.HostVmStateReportEntry; -import com.cloud.agent.api.OvsSetTagAndFlowAnswer; -import com.cloud.agent.api.OvsSetTagAndFlowCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; @@ -104,7 +102,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.xenserver.resource.wrapper.CitrixRequestWrapper; import com.cloud.network.Networks; import com.cloud.network.Networks.BroadcastDomainType; -import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.TrafficType; import com.cloud.resource.ServerResource; import com.cloud.resource.hypervisor.HypervisorResource; @@ -125,7 +122,6 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.utils.ssh.SSHCmdHelper; import com.cloud.utils.ssh.SshHelper; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.PowerState; import com.trilead.ssh2.SCPClient; import com.xensource.xenapi.Bond; @@ -147,22 +143,20 @@ import com.xensource.xenapi.Types.VmPowerState; import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VBD; import com.xensource.xenapi.VDI; -import com.xensource.xenapi.VGPU; import com.xensource.xenapi.VIF; import com.xensource.xenapi.VLAN; import com.xensource.xenapi.VM; import com.xensource.xenapi.XenAPIObject; /** - * CitrixResourceBase encapsulates the calls to the XenServer Xapi process - * to perform the required functionalities for CloudStack. + * CitrixResourceBase encapsulates the calls to the XenServer Xapi process to + * perform the required functionalities for CloudStack. * - * ==============> READ THIS <============== - * Because the XenServer objects can expire when the session expires, we cannot - * keep any of the actual XenServer objects in this class. The only - * thing that is constant is the UUID of the XenServer objects but not the - * objects themselves! This is very important before you do any changes in - * this code here. + * ==============> READ THIS <============== Because the XenServer objects can + * expire when the session expires, we cannot keep any of the actual XenServer + * objects in this class. The only thing that is constant is the UUID of the + * XenServer objects but not the objects themselves! This is very important + * before you do any changes in this code here. * */ @Local(value = ServerResource.class) @@ -188,7 +182,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } protected static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance(); - //static min values for guests on xenserver + // static min values for guests on xenserver private static final long mem_128m = 134217728L; static final Random Rand = new Random(System.currentTimeMillis()); @@ -206,11 +200,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private static PowerState convertToPowerState(final VmPowerState ps) { final PowerState powerState = s_powerStatesTable.get(ps); - return powerState == null ? PowerState.PowerUnknown : powerState; + return powerState == null ? PowerState.PowerUnknown : powerState; } private static boolean isAlienVm(final VM vm, final Connection conn) throws XenAPIException, XmlRpcException { - // TODO : we need a better way to tell whether or not the VM belongs to CloudStack + // TODO : we need a better way to tell whether or not the VM belongs to + // CloudStack final String vmName = vm.getNameLabel(conn); if (vmName.matches("^[ivs]-\\d+-.+")) { return false; @@ -229,7 +224,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected int _heartbeatInterval = 60; protected int _heartbeatTimeout = 120; protected final XsHost _host = new XsHost(); - protected String _instance; //instance name (default is usually "VM") + protected String _instance; // instance name (default is usually "VM") protected boolean _isOvs = false; protected String _linkLocalPrivateNetworkName; protected int _maxNics = 7; @@ -258,10 +253,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected VirtualRoutingResource _vrResource; protected int _wait; - //Hypervisor specific params with generic value, may need to be overridden for specific versions + // Hypervisor specific params with generic value, may need to be overridden + // for specific versions long _xsMemoryUsed = 128 * 1024 * 1024L; // xenserver hypervisor used 128 M - double _xsVirtualizationFactor = 63.0 / 64.0; // 1 - virtualization overhead + double _xsVirtualizationFactor = 63.0 / 64.0; // 1 - virtualization overhead protected StorageSubsystemCommandHandler storageHandler; @@ -304,18 +300,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException(msg); } - protected String callHostPluginAsync(final Connection conn, final String plugin, - final String cmd, final int wait, final Map params) { + protected String callHostPluginAsync(final Connection conn, final String plugin, final String cmd, final int wait, final Map params) { final int timeout = wait * 1000; final Map args = new HashMap(); Task task = null; try { - for (final Map.Entry< String, String > entry : params.entrySet()) { + for (final Map.Entry entry : params.entrySet()) { args.put(entry.getKey(), entry.getValue()); } if (s_logger.isTraceEnabled()) { - s_logger.trace("callHostPlugin executing for command " + cmd - + " with " + getArgsString(args)); + s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); } final Host host = Host.getByUuid(conn, _host.getUuid()); task = host.callPluginAsync(conn, plugin, cmd, args); @@ -326,24 +320,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (s_logger.isTraceEnabled()) { s_logger.trace("callHostPlugin Result: " + result); } - return result.replace("", "").replace("", "") - .replace("\n", ""); + return result.replace("", "").replace("", "").replace("\n", ""); } catch (final Types.HandleInvalid e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd - + " with args " + getArgsString(args) - + " due to HandleInvalid clazz:" + e.clazz + ", handle:" - + e.handle); + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + e.handle); } catch (final Exception e) { - s_logger.warn( - "callHostPlugin failed for cmd: " + cmd + " with args " - + getArgsString(args) + " due to " + e.toString(), - e); + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); } finally { if (task != null) { try { task.destroy(conn); } catch (final Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString()); } } } @@ -372,8 +359,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } return result.replace("", "").replace("", "").replace("\n", ""); } catch (final Types.HandleInvalid e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + - e.handle); + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + e.handle); } catch (final XenAPIException e) { s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); } catch (final Exception e) { @@ -416,8 +402,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } return result.replace("\n", ""); } catch (final Types.HandleInvalid e) { - s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + - e.handle); + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + e.handle); } catch (final XenAPIException e) { s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); } catch (final XmlRpcException e) { @@ -462,11 +447,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.debug("Checking " + srr.nameLabel + " or SR " + srr.uuid + " on " + _host); } if (srr.shared) { - if (SRType.NFS.equals(srr.type) ){ + if (SRType.NFS.equals(srr.type)) { final Map smConfig = srr.smConfig; - if( !smConfig.containsKey("nosubdir")) { + if (!smConfig.containsKey("nosubdir")) { smConfig.put("nosubdir", "true"); - sr.setSmConfig(conn,smConfig); + sr.setSmConfig(conn, smConfig); } } @@ -508,7 +493,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private void CheckXenHostInfo() throws ConfigurationException { final Connection conn = ConnPool.getConnect(_host.getIp(), _username, _password); - if( conn == null ) { + if (conn == null) { throw new ConfigurationException("Can not create connection to " + _host.getIp()); } try { @@ -538,17 +523,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe @Override public ExecutionResult cleanupCommand(final NetworkElementCommand cmd) { if (cmd instanceof IpAssocCommand && !(cmd instanceof IpAssocVpcCommand)) { - return cleanupNetworkElementCommand((IpAssocCommand)cmd); + return cleanupNetworkElementCommand((IpAssocCommand) cmd); } return new ExecutionResult(true, null); } - public boolean cleanupHaltedVms(final Connection conn) throws XenAPIException, XmlRpcException { final Host host = Host.getByUuid(conn, _host.getUuid()); final Map vms = VM.getAllRecords(conn); boolean success = true; - if(vms != null && !vms.isEmpty()) { + if (vms != null && !vms.isEmpty()) { for (final Map.Entry entry : vms.entrySet()) { final VM vm = entry.getKey(); final VM.Record vmRec = entry.getValue(); @@ -583,7 +567,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final NicTO nic = new NicTO(); nic.setMac(ip.getVifMacAddress()); nic.setType(ip.getTrafficType()); - if (ip.getBroadcastUri()== null) { + if (ip.getBroadcastUri() == null) { nic.setBroadcastType(BroadcastDomainType.Native); } else { final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); @@ -596,19 +580,21 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe Network network = getNetwork(conn, nic); - - // If we are disassociating the last IP address in the VLAN, we need + // If we are disassociating the last IP address in the VLAN, we + // need // to remove a VIF boolean removeVif = false; - //there is only one ip in this public vlan and removing it, so remove the nic + // there is only one ip in this public vlan and removing it, so + // remove the nic if (ipsCount == 1 && !ip.isAdd()) { removeVif = true; } if (removeVif) { - // Determine the correct VIF on DomR to associate/disassociate the + // Determine the correct VIF on DomR to + // associate/disassociate the // IP address with final VIF correctVif = getCorrectVif(conn, router, network); if (correctVif != null) { @@ -680,7 +666,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { final VIF.Record vifr = v.getRecord(conn); if (v.getNetwork(conn).getUuid(conn).equals(nw.getUuid(conn))) { - if(vifr != null) { + if (vifr != null) { final Map config = vifr.otherConfig; vifName = config.get("nameLabel"); } @@ -702,7 +688,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task = vdi.copyAsync(conn, sr); // poll every 1 seconds , timeout after 2 hours - waitForTask(conn, task, 1000, (long)wait * 1000); + waitForTask(conn, task, 1000, (long) wait * 1000); checkForSuccess(conn, task); final VDI dvdi = Types.toVDI(task, conn); return dvdi; @@ -720,8 +706,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public HashMap clusterVMMetaDataSync(final Connection conn) { final HashMap vmMetaDatum = new HashMap(); try { - final Map vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER - if(vm_map != null) { + final Map vm_map = VM.getAllRecords(conn); // USE + // THIS TO + // GET ALL + // VMS + // FROM A + // CLUSTER + if (vm_map != null) { for (final VM.Record record : vm_map.values()) { if (record.isControlDomain || record.isASnapshot || record.isATemplate) { continue; // Skip DOM0 @@ -742,44 +733,44 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe _name = name; try { - _dcId = Long.parseLong((String)params.get("zone")); + _dcId = Long.parseLong((String) params.get("zone")); } catch (final NumberFormatException e) { throw new ConfigurationException("Unable to get the zone " + params.get("zone")); } - _host.setUuid((String)params.get("guid")); + _host.setUuid((String) params.get("guid")); _name = _host.getUuid(); - _host.setIp((String)params.get("ipaddress")); + _host.setIp((String) params.get("ipaddress")); - _username = (String)params.get("username"); - _password.add((String)params.get("password")); - _pod = (String)params.get("pod"); - _cluster = (String)params.get("cluster"); - _privateNetworkName = (String)params.get("private.network.device"); - _publicNetworkName = (String)params.get("public.network.device"); - _guestNetworkName = (String)params.get("guest.network.device"); - _instance = (String)params.get("instance.name"); - _securityGroupEnabled = Boolean.parseBoolean((String)params.get("securitygroupenabled")); + _username = (String) params.get("username"); + _password.add((String) params.get("password")); + _pod = (String) params.get("pod"); + _cluster = (String) params.get("cluster"); + _privateNetworkName = (String) params.get("private.network.device"); + _publicNetworkName = (String) params.get("public.network.device"); + _guestNetworkName = (String) params.get("guest.network.device"); + _instance = (String) params.get("instance.name"); + _securityGroupEnabled = Boolean.parseBoolean((String) params.get("securitygroupenabled")); - _linkLocalPrivateNetworkName = (String)params.get("private.linkLocal.device"); + _linkLocalPrivateNetworkName = (String) params.get("private.linkLocal.device"); if (_linkLocalPrivateNetworkName == null) { _linkLocalPrivateNetworkName = "cloud_link_local_network"; } - _storageNetworkName1 = (String)params.get("storage.network.device1"); - _storageNetworkName2 = (String)params.get("storage.network.device2"); + _storageNetworkName1 = (String) params.get("storage.network.device1"); + _storageNetworkName2 = (String) params.get("storage.network.device2"); - _heartbeatTimeout = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.timeout"), 120); - _heartbeatInterval = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.interval"), 60); + _heartbeatTimeout = NumbersUtil.parseInt((String) params.get("xenserver.heartbeat.timeout"), 120); + _heartbeatInterval = NumbersUtil.parseInt((String) params.get("xenserver.heartbeat.interval"), 60); - String value = (String)params.get("wait"); + String value = (String) params.get("wait"); _wait = NumbersUtil.parseInt(value, 600); - value = (String)params.get("migratewait"); + value = (String) params.get("migratewait"); _migratewait = NumbersUtil.parseInt(value, 3600); - _maxNics = NumbersUtil.parseInt((String)params.get("xenserver.nics.max"), 7); + _maxNics = NumbersUtil.parseInt((String) params.get("xenserver.nics.max"), 7); if (_pod == null) { throw new ConfigurationException("Unable to get the pod"); @@ -813,12 +804,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } /** - * This method creates a XenServer network and configures it for being used as a L2-in-L3 tunneled network + * This method creates a XenServer network and configures it for being used + * as a L2-in-L3 tunneled network */ public synchronized Network configureTunnelNetwork(final Connection conn, final Long networkId, final long hostId, final String bridgeName) { try { final Network nw = findOrCreateTunnelNetwork(conn, bridgeName); - //Invoke plugin to setup the bridge which will be used by this network + // Invoke plugin to setup the bridge which will be used by this + // network final String bridge = nw.getBridge(conn); final Map nwOtherConfig = nw.getOtherConfig(conn); final String configuredHosts = nwOtherConfig.get("ovs-host-setup"); @@ -826,7 +819,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (configuredHosts != null) { final String hostIdsStr[] = configuredHosts.split(","); for (final String hostIdStr : hostIdsStr) { - if (hostIdStr.equals(((Long)hostId).toString())) { + if (hostIdStr.equals(((Long) hostId).toString())) { configured = true; break; } @@ -836,22 +829,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (!configured) { String result; if (bridgeName.startsWith("OVS-DR-VPC-Bridge")) { - result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge, - "key", bridgeName, - "xs_nw_uuid", nw.getUuid(conn), - "cs_host_id", ((Long)hostId).toString()); + result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge, "key", bridgeName, "xs_nw_uuid", nw.getUuid(conn), + "cs_host_id", ((Long) hostId).toString()); } else { - result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge, - "key", bridgeName, - "xs_nw_uuid", nw.getUuid(conn), - "cs_host_id", ((Long)hostId).toString()); + result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge, "key", bridgeName, "xs_nw_uuid", nw.getUuid(conn), "cs_host_id", + ((Long) hostId).toString()); } - //Note down the fact that the ovs bridge has been setup + // Note down the fact that the ovs bridge has been setup final String[] res = result.split(":"); if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) { - //TODO: Should make this error not fatal? - throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge ); + // TODO: Should make this error not fatal? + throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge); } } return nw; @@ -898,8 +887,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public String copyVhdFromSecondaryStorage(final Connection conn, final String mountpoint, final String sruuid, final int wait) { final String nameLabel = "cloud-" + UUID.randomUUID().toString(); - final String results = - callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel); + final String results = callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", + nameLabel); String errMsg = null; if (results == null || results.isEmpty()) { errMsg = "copy_vhd_from_secondarystorage return null"; @@ -925,7 +914,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Connection conn = getConnection(); final String hostPath = "/tmp/"; - s_logger.debug("Copying VR with ip " + routerIp +" config file into host "+ _host.getIp() ); + s_logger.debug("Copying VR with ip " + routerIp + " config file into host " + _host.getIp()); try { SshHelper.scpTo(_host.getIp(), 22, _username, null, _password.peek(), hostPath, content.getBytes(Charset.defaultCharset()), filename, null); } catch (final Exception e) { @@ -933,7 +922,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path); - s_logger.debug ("VR Config file " + filename + " got created in VR, ip " + routerIp + " with content \n" + content); + s_logger.debug("VR Config file " + filename + " got created in VR, ip " + routerIp + " with content \n" + content); return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); } @@ -1054,9 +1043,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String createTemplateFromSnapshot(final Connection conn, final String templatePath, final String snapshotPath, final int wait) { final String tmpltLocalDir = UUID.randomUUID().toString(); - final String results = - callHostPluginAsync(conn, "vmopspremium", "create_privatetemplate_from_snapshot", wait, "templatePath", templatePath, "snapshotPath", snapshotPath, - "tmpltLocalDir", tmpltLocalDir); + final String results = callHostPluginAsync(conn, "vmopspremium", "create_privatetemplate_from_snapshot", wait, "templatePath", templatePath, "snapshotPath", snapshotPath, + "tmpltLocalDir", tmpltLocalDir); String errMsg = null; if (results == null || results.isEmpty()) { errMsg = "create_privatetemplate_from_snapshot return null"; @@ -1075,7 +1063,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException(errMsg); } - public VBD createVbd(final Connection conn, final DiskTO volume, final String vmName, final VM vm, final BootloaderType bootLoaderType, VDI vdi) throws XmlRpcException, XenAPIException { + public VBD createVbd(final Connection conn, final DiskTO volume, final String vmName, final VM vm, final BootloaderType bootLoaderType, VDI vdi) throws XmlRpcException, + XenAPIException { final Volume.Type type = volume.getType(); if (vdi == null) { @@ -1176,7 +1165,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vifr.otherConfig.put("cloudstack-vm-id", vmSpec.getUuid()); } - // OVS plugin looks at network UUID in the vif 'otherconfig' details to group VIF's & tunnel ports as part of tier + // OVS plugin looks at network UUID in the vif 'otherconfig' details to + // group VIF's & tunnel ports as part of tier // when bridge is setup for distributed routing vifr.otherConfig.put("cloudstack-network-id", nic.getNetworkUuid()); @@ -1200,7 +1190,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final VIF vif = VIF.create(conn, vifr); if (s_logger.isDebugEnabled()) { vifr = vif.getRecord(conn); - if(vifr != null) { + if (vifr != null) { s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId()); } } @@ -1211,7 +1201,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmSpec, final Host host) throws XenAPIException, XmlRpcException { final String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getPlatformEmulator(), vmSpec.getBootloader() == BootloaderType.CD); final Set templates = VM.getByNameLabel(conn, guestOsTypeName); - if ( templates == null || templates.isEmpty()) { + if (templates == null || templates.isEmpty()) { throw new CloudRuntimeException("Cannot find template " + guestOsTypeName + " on XenServer host"); } assert templates.size() == 1 : "Should only have 1 template but found " + templates.size(); @@ -1227,11 +1217,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY; vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY; vmr.otherConfig.put("vm_uuid", vmSpec.getUuid()); - vmr.VCPUsMax = (long) vmSpec.getCpus(); // FIX ME: In case of dynamic scaling this VCPU max should be the minumum of + vmr.VCPUsMax = (long) vmSpec.getCpus(); // FIX ME: In case of dynamic + // scaling this VCPU max should + // be the minumum of // recommended value for that template and capacity remaining on host if (isDmcEnabled(conn, host) && vmSpec.isEnableDynamicallyScaleVm()) { - //scaling is allowed + // scaling is allowed vmr.memoryStaticMin = getStaticMin(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD, vmSpec.getMinRam(), vmSpec.getMaxRam()); vmr.memoryStaticMax = getStaticMax(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD, vmSpec.getMinRam(), vmSpec.getMaxRam()); vmr.memoryDynamicMin = vmSpec.getMinRam(); @@ -1244,13 +1236,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } } else { - //scaling disallowed, set static memory target + // scaling disallowed, set static memory target if (vmSpec.isEnableDynamicallyScaleVm() && !isDmcEnabled(conn, host)) { s_logger.warn("Host " + host.getHostname(conn) + " does not support dynamic scaling, so the vm " + vmSpec.getName() + " is not dynamically scalable"); } vmr.memoryStaticMin = vmSpec.getMinRam(); vmr.memoryStaticMax = vmSpec.getMaxRam(); - vmr.memoryDynamicMin = vmSpec.getMinRam();; + vmr.memoryDynamicMin = vmSpec.getMinRam(); + ; vmr.memoryDynamicMax = vmSpec.getMaxRam(); vmr.VCPUsMax = (long) vmSpec.getCpus(); @@ -1273,14 +1266,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe int utilization = 0; // max CPU cap, default is unlimited // weight based allocation, CPU weight is calculated per VCPU - cpuWeight = (int)(speed * 0.99 / _host.getSpeed() * _maxWeight); + cpuWeight = (int) (speed * 0.99 / _host.getSpeed() * _maxWeight); if (cpuWeight > _maxWeight) { cpuWeight = _maxWeight; } if (vmSpec.getLimitCpuUse()) { - // CPU cap is per VM, so need to assign cap based on the number of vcpus - utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100); + // CPU cap is per VM, so need to assign cap based on the number + // of vcpus + utilization = (int) (vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100); } vcpuParams.put("weight", Integer.toString(cpuWeight)); @@ -1307,7 +1301,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final DiskTO[] disks = vmSpec.getDisks(); for (final DiskTO disk : disks) { if (disk.getType() == Volume.Type.ISO) { - final TemplateObjectTO iso = (TemplateObjectTO)disk.getData(); + final TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); final String osType = iso.getGuestOsType(); if (osType != null) { final String isoGuestOsName = getGuestOsType(osType, vmSpec.getPlatformEmulator(), vmSpec.getBootloader() == BootloaderType.CD); @@ -1338,14 +1332,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vm; } - public VM createWorkingVM(final Connection conn, final String vmName, final String guestOSType, final String platformEmulator, final List listVolumeTo) throws BadServerResponse, - Types.VmBadPowerState, Types.SrFull, - Types.OperationNotAllowed, XenAPIException, XmlRpcException { - //below is redundant but keeping for consistency and code readabilty + public VM createWorkingVM(final Connection conn, final String vmName, final String guestOSType, final String platformEmulator, final List listVolumeTo) + throws BadServerResponse, Types.VmBadPowerState, Types.SrFull, Types.OperationNotAllowed, XenAPIException, XmlRpcException { + // below is redundant but keeping for consistency and code readabilty final String guestOsTypeName = platformEmulator; if (guestOsTypeName == null) { - final String msg = - " Hypervisor " + this.getClass().getName() + " doesn't support guest OS type " + guestOSType + ". you can choose 'Other install media' to run it as HVM"; + final String msg = " Hypervisor " + this.getClass().getName() + " doesn't support guest OS type " + guestOSType + + ". you can choose 'Other install media' to run it as HVM"; s_logger.warn(msg); throw new CloudRuntimeException(msg); } @@ -1362,7 +1355,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.warn("Unable to find vdi by uuid: " + vdiUuid + ", skip it"); } } - for (final Map.Entryentry : vdiMap.entrySet()) { + for (final Map.Entry entry : vdiMap.entrySet()) { final VDI vdi = entry.getKey(); final VolumeObjectTO volumeTO = entry.getValue(); final VBD.Record vbdr = new VBD.Record(); @@ -1383,19 +1376,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vm; } - protected boolean deleteSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String folder) { final String details = callHostPlugin(conn, "vmopsSnapshot", "delete_secondary_storage_folder", "remoteMountPath", remoteMountPath, "folder", folder); return details != null && details.equals("1"); } - - protected String deleteSnapshotBackup(final Connection conn, final Long dcId, final Long accountId, final Long volumeId, final String secondaryStorageMountPath, final String backupUUID) { + protected String deleteSnapshotBackup(final Connection conn, final Long dcId, final Long accountId, final Long volumeId, final String secondaryStorageMountPath, + final String backupUUID) { // If anybody modifies the formatting below again, I'll skin them - final String result = - callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "dcId", dcId.toString(), "accountId", accountId.toString(), - "volumeId", volumeId.toString(), "secondaryStorageMountPath", secondaryStorageMountPath); + final String result = callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "dcId", dcId.toString(), "accountId", accountId.toString(), + "volumeId", volumeId.toString(), "secondaryStorageMountPath", secondaryStorageMountPath); return result; } @@ -1424,13 +1415,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public synchronized void destroyTunnelNetwork(final Connection conn, final Network nw, final long hostId) { try { final String bridge = nw.getBridge(conn); - final String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge, - "cs_host_id", ((Long)hostId).toString()); + final String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge, "cs_host_id", ((Long) hostId).toString()); final String[] res = result.split(":"); if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) { - //TODO: Should make this error not fatal? - //Can Concurrent VM shutdown/migration/reboot events can cause this method - //to be executed on a bridge which has already been removed? + // TODO: Should make this error not fatal? + // Can Concurrent VM shutdown/migration/reboot events can cause + // this method + // to be executed on a bridge which has already been removed? throw new CloudRuntimeException("Unable to remove OVS bridge " + bridge + ":" + result); } return; @@ -1440,7 +1431,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - void destroyVDIbyNameLabel(final Connection conn, final String nameLabel) { try { final Set vdis = VDI.getByNameLabel(conn, nameLabel); @@ -1506,50 +1496,48 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } /** - * enableVlanNetwork creates a Network object, Vlan object, and thereby - * a tagged PIF object in Xapi. + * enableVlanNetwork creates a Network object, Vlan object, and thereby a + * tagged PIF object in Xapi. * - * In XenServer, VLAN is added by - * - Create a network, which is unique cluster wide. - * - Find the PIF that you want to create the VLAN on. - * - Create a VLAN using the network and the PIF. As a result of this - * operation, a tagged PIF object is also created. + * In XenServer, VLAN is added by - Create a network, which is unique + * cluster wide. - Find the PIF that you want to create the VLAN on. - + * Create a VLAN using the network and the PIF. As a result of this + * operation, a tagged PIF object is also created. * - * Here is a list of problems with clustered Xapi implementation that - * we are trying to circumvent. - * - There can be multiple Networks with the same name-label so searching - * using name-label is not unique. - * - There are no other ways to search for Networks other than listing - * all of them which is not efficient in our implementation because - * we can have over 4000 VLAN networks. - * - In a clustered situation, it's possible for both hosts to detect - * that the Network is missing and both creates it. This causes a - * lot of problems as one host may be using one Network and another - * may be using a different network for their VMs. This causes - * problems in migration because the VMs are logically attached - * to different networks in Xapi's database but in reality, they - * are attached to the same network. + * Here is a list of problems with clustered Xapi implementation that we are + * trying to circumvent. - There can be multiple Networks with the same + * name-label so searching using name-label is not unique. - There are no + * other ways to search for Networks other than listing all of them which is + * not efficient in our implementation because we can have over 4000 VLAN + * networks. - In a clustered situation, it's possible for both hosts to + * detect that the Network is missing and both creates it. This causes a lot + * of problems as one host may be using one Network and another may be using + * a different network for their VMs. This causes problems in migration + * because the VMs are logically attached to different networks in Xapi's + * database but in reality, they are attached to the same network. * * To work around these problems, we do the following. * - * - When creating the VLAN network, we name it as VLAN-UUID of the - * Network it is created on-VLAN Tag. Because VLAN tags is unique with - * one particular network, this is a unique name-label to quickly - * retrieve the the VLAN network with when we need it again. - * - When we create the VLAN network, we add a timestamp and a random - * number as a tag into the network. Then instead of creating - * VLAN on that network, we actually retrieve the Network again - * and this time uses the VLAN network with lowest timestamp or - * lowest random number as the VLAN network. This allows VLAN creation - * to happen on multiple hosts concurrently but even if two VLAN - * networks were created with the same name, only one of them is used. + * - When creating the VLAN network, we name it as VLAN-UUID of the Network + * it is created on-VLAN Tag. Because VLAN tags is unique with one + * particular network, this is a unique name-label to quickly retrieve the + * the VLAN network with when we need it again. - When we create the VLAN + * network, we add a timestamp and a random number as a tag into the + * network. Then instead of creating VLAN on that network, we actually + * retrieve the Network again and this time uses the VLAN network with + * lowest timestamp or lowest random number as the VLAN network. This allows + * VLAN creation to happen on multiple hosts concurrently but even if two + * VLAN networks were created with the same name, only one of them is used. * - * One cavaet about this approach is that it relies on the timestamp to - * be relatively accurate among different hosts. + * One cavaet about this approach is that it relies on the timestamp to be + * relatively accurate among different hosts. * - * @param conn Xapi Connection - * @param tag VLAN tag - * @param network network on this host to create the VLAN on. + * @param conn + * Xapi Connection + * @param tag + * VLAN tag + * @param network + * network on this host to create the VLAN on. * @return VLAN Network created. * @throws XenAPIException * @throws XmlRpcException @@ -1579,7 +1567,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe nwr.tags.add(generateTimeStamp()); vlanNetwork = Network.create(conn, nwr); vlanNic = getNetworkByName(conn, newName); - if(vlanNic == null) { //Still vlanNic is null means we could not create it for some reason and no exception capture happened. + if (vlanNic == null) { // Still vlanNic is null means we could not + // create it for some reason and no exception + // capture happened. throw new CloudRuntimeException("Could not find/create vlan network with name: " + newName); } } @@ -1607,346 +1597,22 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vlanNetwork; } - private OvsSetTagAndFlowAnswer execute(final OvsSetTagAndFlowCommand cmd) { - _isOvs = true; - - final Connection conn = getConnection(); - try { - final Network nw = setupvSwitchNetwork(conn); - final String bridge = nw.getBridge(conn); - - /* - * If VM is domainRouter, this will try to set flow and tag on its - * none guest network nic. don't worry, it will fail silently at - * host plugin side - */ - final String result = callHostPlugin(conn, "ovsgre", "ovs_set_tag_and_flow", "bridge", bridge, "vmName", cmd.getVmName(), "tag", cmd.getTag(), "vlans", - cmd.getVlans(), "seqno", cmd.getSeqNo()); - s_logger.debug("set flow for " + cmd.getVmName() + " " + result); - - if (result.equalsIgnoreCase("SUCCESS")) { - return new OvsSetTagAndFlowAnswer(cmd, true, result); - } else { - return new OvsSetTagAndFlowAnswer(cmd, false, result); - } - } catch (final BadServerResponse e) { - s_logger.error("Failed to set tag and flow", e); - } catch (final XenAPIException e) { - s_logger.error("Failed to set tag and flow", e); - } catch (final XmlRpcException e) { - s_logger.error("Failed to set tag and flow", e); - } - - return new OvsSetTagAndFlowAnswer(cmd, false, "EXCEPTION"); - } - @Override public RebootAnswer execute(final RebootCommand cmd) { - final Connection conn = getConnection(); - s_logger.debug("7. The VM " + cmd.getVmName() + " is in Starting state"); - try { - Set vms = null; - try { - vms = VM.getByNameLabel(conn, cmd.getVmName()); - } catch (final XenAPIException e0) { - s_logger.debug("getByNameLabel failed " + e0.toString()); - return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString(), false); - } catch (final Exception e0) { - s_logger.debug("getByNameLabel failed " + e0.getMessage()); - return new RebootAnswer(cmd, "getByNameLabel failed", false); - } - for (final VM vm : vms) { - try { - rebootVM(conn, vm, vm.getNameLabel(conn)); - } catch (final Exception e) { - final String msg = e.toString(); - s_logger.warn(msg, e); - return new RebootAnswer(cmd, msg, false); - } - } - return new RebootAnswer(cmd, "reboot succeeded", true); - } finally { - s_logger.debug("8. The VM " + cmd.getVmName() + " is in Running state"); - } + throw new CloudRuntimeException("The method has been replaced but the implementation CitrixRebootCommandWrapper. " + + "Please use the new design in order to keep compatibility. Once all ServerResource implementation are refactored those methods will dissapper."); } @Override public StartAnswer execute(final StartCommand cmd) { - final Connection conn = getConnection(); - final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - final String vmName = vmSpec.getName(); - VmPowerState state = VmPowerState.HALTED; - VM vm = null; - // if a VDI is created, record its UUID to send back to the CS MS - final Map iqnToPath = new HashMap(); - try { - final Set vms = VM.getByNameLabel(conn, vmName); - if (vms != null) { - for (final VM v : vms) { - final VM.Record vRec = v.getRecord(conn); - if (vRec.powerState == VmPowerState.HALTED) { - v.destroy(conn); - } else if (vRec.powerState == VmPowerState.RUNNING) { - final String host = vRec.residentOn.getUuid(conn); - final String msg = "VM " + vmName + " is runing on host " + host; - s_logger.debug(msg); - return new StartAnswer(cmd, msg, host); - } else { - final String msg = "There is already a VM having the same name " + vmName + " vm record " + vRec.toString(); - s_logger.warn(msg); - return new StartAnswer(cmd, msg); - } - } - } - s_logger.debug("1. The VM " + vmName + " is in Starting state."); - - final Host host = Host.getByUuid(conn, _host.getUuid()); - vm = createVmFromTemplate(conn, vmSpec, host); - - final GPUDeviceTO gpuDevice = vmSpec.getGpuDevice(); - if (gpuDevice != null) { - s_logger.debug("Creating VGPU for of VGPU type: " + gpuDevice.getVgpuType() + " in GPU group " - + gpuDevice.getGpuGroup() + " for VM " + vmName ); - createVGPU(conn, cmd, vm, gpuDevice); - } - - for (final DiskTO disk : vmSpec.getDisks()) { - final VDI newVdi = prepareManagedDisk(conn, disk, vmName); - - if (newVdi != null) { - final String path = newVdi.getUuid(conn); - - iqnToPath.put(disk.getDetails().get(DiskTO.IQN), path); - } - - createVbd(conn, disk, vmName, vm, vmSpec.getBootloader(), newVdi); - } - - if (vmSpec.getType() != VirtualMachine.Type.User) { - createPatchVbd(conn, vmName, vm); - } - - for (final NicTO nic : vmSpec.getNics()) { - createVif(conn, vmName, vm, vmSpec, nic); - } - - startVM(conn, host, vm, vmName); - - if (_isOvs) { - // TODO(Salvatore-orlando): This code should go - for (final NicTO nic : vmSpec.getNics()) { - if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vswitch) { - final HashMap args = parseDefaultOvsRuleComamnd(BroadcastDomainType.getValue(nic.getBroadcastUri())); - final OvsSetTagAndFlowCommand flowCmd = - new OvsSetTagAndFlowCommand(args.get("vmName"), args.get("tag"), args.get("vlans"), args.get("seqno"), Long.parseLong(args.get("vmId"))); - final OvsSetTagAndFlowAnswer r = execute(flowCmd); - if (!r.getResult()) { - s_logger.warn("Failed to set flow for VM " + r.getVmId()); - } else { - s_logger.info("Success to set flow for VM " + r.getVmId()); - } - } - } - } - - if (_canBridgeFirewall) { - String result = null; - if (vmSpec.getType() != VirtualMachine.Type.User) { - final NicTO[] nics = vmSpec.getNics(); - boolean secGrpEnabled = false; - for (final NicTO nic : nics) { - if (nic.isSecurityGroupEnabled() || - nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { - secGrpEnabled = true; - break; - } - } - if (secGrpEnabled) { - result = callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", vmName); - if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { - s_logger.warn("Failed to program default network rules for " + vmName); - } else { - s_logger.info("Programmed default network rules for " + vmName); - } - } - - } else { - //For user vm, program the rules for each nic if the isolation uri scheme is ec2 - final NicTO[] nics = vmSpec.getNics(); - for (final NicTO nic : nics) { - if (nic.isSecurityGroupEnabled() || nic.getIsolationUri() != null && - nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { - final List nicSecIps = nic.getNicSecIps(); - String secIpsStr; - final StringBuilder sb = new StringBuilder(); - if (nicSecIps != null) { - for (final String ip : nicSecIps) { - sb.append(ip).append(":"); - } - secIpsStr = sb.toString(); - } else { - secIpsStr = "0:"; - } - result = - callHostPlugin(conn, "vmops", "default_network_rules", "vmName", vmName, "vmIP", nic.getIp(), "vmMAC", nic.getMac(), "vmID", - Long.toString(vmSpec.getId()), "secIps", secIpsStr); - - if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { - s_logger.warn("Failed to program default network rules for " + vmName + " on nic with ip:" + nic.getIp() + " mac:" + nic.getMac()); - } else { - s_logger.info("Programmed default network rules for " + vmName + " on nic with ip:" + nic.getIp() + " mac:" + nic.getMac()); - } - } - } - } - } - - state = VmPowerState.RUNNING; - - final StartAnswer startAnswer = new StartAnswer(cmd); - - startAnswer.setIqnToPath(iqnToPath); - - return startAnswer; - } catch (final Exception e) { - s_logger.warn("Catch Exception: " + e.getClass().toString() + " due to " + e.toString(), e); - final String msg = handleVmStartFailure(conn, vmName, vm, "", e); - - final StartAnswer startAnswer = new StartAnswer(cmd, msg); - - startAnswer.setIqnToPath(iqnToPath); - - return startAnswer; - } finally { - if (state != VmPowerState.HALTED) { - s_logger.debug("2. The VM " + vmName + " is in " + state + " state."); - } else { - s_logger.debug("The VM is in stopped state, detected problem during startup : " + vmName); - } - } + throw new CloudRuntimeException("The method has been replaced but the implementation CitrixStartCommandWrapper. " + + "Please use the new design in order to keep compatibility. Once all ServerResource implementation are refactored those methods will dissapper."); } @Override public StopAnswer execute(final StopCommand cmd) { - final String vmName = cmd.getVmName(); - String platformstring = null; - try { - final Connection conn = getConnection(); - final Set vms = VM.getByNameLabel(conn, vmName); - // 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.RUNNING) { - continue; - } - if (isRefNull(vmr.residentOn)) { - continue; - } - if (vmr.residentOn.getUuid(conn).equals(_host.getUuid())) { - continue; - } - iter.remove(); - } - - if (vms.size() == 0) { - return new StopAnswer(cmd, "VM does not exist", true); - } - for (final VM vm : vms) { - final VM.Record vmr = vm.getRecord(conn); - platformstring = StringUtils.mapToString(vmr.platform); - if (vmr.isControlDomain) { - final String msg = "Tring to Shutdown control domain"; - s_logger.warn(msg); - return new StopAnswer(cmd, msg, false); - } - - if (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.getUuid())) { - final String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + _host.getUuid() + " but host:" + vmr.residentOn.getUuid(conn); - s_logger.warn(msg); - return new StopAnswer(cmd, msg, platformstring, false); - } - - if (cmd.checkBeforeCleanup() && vmr.powerState == VmPowerState.RUNNING) { - final String msg = "Vm " + vmName + " is running on host and checkBeforeCleanup flag is set, so bailing out"; - s_logger.debug(msg); - return new StopAnswer(cmd, msg, false); - } - - s_logger.debug("9. The VM " + vmName + " is in Stopping state"); - - try { - if (vmr.powerState == VmPowerState.RUNNING) { - /* when stop a vm, set affinity to current xenserver */ - vm.setAffinity(conn, vm.getResidentOn(conn)); - - if (_canBridgeFirewall) { - final String result = callHostPlugin(conn, "vmops", "destroy_network_rules_for_vm", "vmName", cmd.getVmName()); - if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { - s_logger.warn("Failed to remove network rules for vm " + cmd.getVmName()); - } else { - s_logger.info("Removed network rules for vm " + cmd.getVmName()); - } - } - shutdownVM(conn, vm, vmName); - } - } catch (final Exception e) { - final String msg = "Catch exception " + e.getClass().getName() + " when stop VM:" + cmd.getVmName() + " due to " + e.toString(); - s_logger.debug(msg); - return new StopAnswer(cmd, msg, platformstring, false); - } finally { - - try { - if (vm.getPowerState(conn) == VmPowerState.HALTED) { - Set vGPUs = null; - // Get updated GPU details - try { - vGPUs = vm.getVGPUs(conn); - } catch (final XenAPIException e2) { - s_logger.debug("VM " + vmName + " does not have GPU support."); - } - if (vGPUs != null && !vGPUs.isEmpty()) { - final HashMap> groupDetails = getGPUGroupDetails(conn); - cmd.setGpuDevice(new GPUDeviceTO(null, null, groupDetails)); - } - - final Set vifs = vm.getVIFs(conn); - final List networks = new ArrayList(); - for (final VIF vif : vifs) { - networks.add(vif.getNetwork(conn)); - } - vm.destroy(conn); - final SR sr = getISOSRbyVmName(conn, cmd.getVmName()); - removeSR(conn, sr); - // Disable any VLAN networks that aren't used - // anymore - for (final Network network : networks) { - try { - if (network.getNameLabel(conn).startsWith("VLAN")) { - disableVlanNetwork(conn, network); - } - } catch (final Exception e) { - // network might be destroyed by other host - } - } - return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", platformstring, true); - } - } catch (final Exception e) { - final String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.getMessage(); - s_logger.warn(msg, e); - } finally { - s_logger.debug("10. The VM " + vmName + " is in Stopped state"); - } - } - } - - } catch (final Exception e) { - final String msg = "Stop Vm " + vmName + " fail due to " + e.toString(); - s_logger.warn(msg, e); - return new StopAnswer(cmd, msg, platformstring, false); - } - return new StopAnswer(cmd, "Stop VM failed", platformstring, false); + throw new CloudRuntimeException("The method has been replaced but the implementation CitrixStopCommandWrapper. " + + "Please use the new design in order to keep compatibility. Once all ServerResource implementation are refactored those methods will dissapper."); } @Override @@ -1963,8 +1629,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe cmdline = cmdline.replaceAll(";", "\\\\;"); try { s_logger.debug("Executing command in VR: " + cmdline); - result = SshHelper.sshExecute(_host.getIp(), 22, _username, null, _password.peek(), cmdline, - 60000, 60000, timeout * 1000); + result = SshHelper.sshExecute(_host.getIp(), 22, _username, null, _password.peek(), cmdline, 60000, 60000, timeout * 1000); } catch (final Exception e) { return new ExecutionResult(false, e.getMessage()); } @@ -1974,7 +1639,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe @Override public Answer executeRequest(final Command cmd) { - // We need this one because the StorageSubSystemCommand is from another hierarchy. + // We need this one because the StorageSubSystemCommand is from another + // hierarchy. if (cmd instanceof StorageSubSystemCommand) { return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); } @@ -2047,7 +1713,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - ram = (long)((ram - dom0Ram - _xsMemoryUsed) * _xsVirtualizationFactor); + ram = (long) ((ram - dom0Ram - _xsMemoryUsed) * _xsVirtualizationFactor); cmd.setMemory(ram); cmd.setDom0MinMemory(dom0Ram); @@ -2130,7 +1796,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vm.setPlatform(conn, platform); } } - if ( !BootloaderType.CD.equals(vmSpec.getBootloader())) { + if (!BootloaderType.CD.equals(vmSpec.getBootloader())) { final String xenservertoolsversion = details.get("hypervisortoolsversion"); if ((xenservertoolsversion == null || !xenservertoolsversion.equalsIgnoreCase("xenserver61")) && vmSpec.getGpuDevice() == null) { final Map platform = vm.getPlatform(conn); @@ -2142,7 +1808,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } /** - * This method just creates a XenServer network following the tunnel network naming convention + * This method just creates a XenServer network following the tunnel network + * naming convention */ public synchronized Network findOrCreateTunnelNetwork(final Connection conn, final String nwName) { try { @@ -2153,11 +1820,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (networks.size() == 0) { rec.nameDescription = "tunnel network id# " + nwName; rec.nameLabel = nwName; - //Initialize the ovs-host-setup to avoid error when doing get-param in plugin + // Initialize the ovs-host-setup to avoid error when doing + // get-param in plugin final Map otherConfig = new HashMap(); otherConfig.put("ovs-host-setup", ""); - // Mark 'internal network' as shared so bridge gets automatically created on each host in the cluster - // when VM with vif connected to this internal network is started + // Mark 'internal network' as shared so bridge gets + // automatically created on each host in the cluster + // when VM with vif connected to this internal network is + // started otherConfig.put("assume_network_is_shared", "true"); rec.otherConfig = otherConfig; nw = Network.create(conn, rec); @@ -2203,8 +1873,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return argString.toString(); } - - @Override public Map getConfigParams() { return null; @@ -2342,7 +2010,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe Set hcs = null; for (int i = 0; i < 10; i++) { hcs = myself.getHostCPUs(conn); - if(hcs != null) { + if (hcs != null) { _host.setCpus(hcs.size()); if (_host.getCpus() > 0) { break; @@ -2357,7 +2025,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cpuInfo.get("socket_count") != null) { _host.setCpuSockets(Integer.parseInt(cpuInfo.get("socket_count"))); } - // would hcs be null we would have thrown an exception on condition (_host.getCpus() <= 0) by now + // would hcs be null we would have thrown an exception on condition + // (_host.getCpus() <= 0) by now for (final HostCpu hc : hcs) { _host.setSpeed(hc.getSpeed(conn).intValue()); break; @@ -2414,7 +2083,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe XsLocalNetwork storageNic2 = null; if (_storageNetworkName2 != null) { storageNic2 = getNetworkByName(conn, _storageNetworkName2); - if(storageNic2 != null) { + if (storageNic2 != null) { _host.setStoragePif2(storageNic2.getPifRecord(conn).uuid); } } @@ -2437,16 +2106,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public HostStatsEntry getHostStats(final Connection conn, final GetHostStatsCommand cmd, final String hostGuid, final long hostId) { final HostStatsEntry hostStats = new HostStatsEntry(hostId, 0, 0, 0, "host", 0, 0, 0, 0); - final Object[] rrdData = getRRDData(conn, 1); // call rrd method with 1 for host + final Object[] rrdData = getRRDData(conn, 1); // call rrd method with 1 + // for host if (rrdData == null) { return null; } - final Integer numRows = (Integer)rrdData[0]; - final Integer numColumns = (Integer)rrdData[1]; - final Node legend = (Node)rrdData[2]; - final Node dataNode = (Node)rrdData[3]; + final Integer numRows = (Integer) rrdData[0]; + final Integer numColumns = (Integer) rrdData[1]; + final Node legend = (Node) rrdData[2]; + final Node dataNode = (Node) rrdData[3]; final NodeList legendChildren = legend.getChildNodes(); for (int col = 0; col < numColumns; col++) { @@ -2473,9 +2143,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (type.equalsIgnoreCase("host")) { if (param.matches("pif_eth0_rx")) { - hostStats.setNetworkReadKBs(getDataAverage(dataNode, col, numRows)/1000); + hostStats.setNetworkReadKBs(getDataAverage(dataNode, col, numRows) / 1000); } else if (param.matches("pif_eth0_tx")) { - hostStats.setNetworkWriteKBs(getDataAverage(dataNode, col, numRows)/1000); + hostStats.setNetworkWriteKBs(getDataAverage(dataNode, col, numRows) / 1000); } else if (param.contains("memory_total_kib")) { hostStats.setTotalMemoryKBs(getDataAverage(dataNode, col, numRows)); } else if (param.contains("memory_free_kib")) { @@ -2486,19 +2156,19 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } /* - if (param.contains("loadavg")) { - hostStats.setAverageLoad((hostStats.getAverageLoad() + getDataAverage(dataNode, col, numRows))); - } + * if (param.contains("loadavg")) { + * hostStats.setAverageLoad((hostStats.getAverageLoad() + + * getDataAverage(dataNode, col, numRows))); } */ } } // add the host cpu utilization /* - if (hostStats.getNumCpus() != 0) { - hostStats.setCpuUtilization(hostStats.getCpuUtilization() / hostStats.getNumCpus()); - s_logger.debug("Host cpu utilization " + hostStats.getCpuUtilization()); - } + * if (hostStats.getNumCpus() != 0) { + * hostStats.setCpuUtilization(hostStats.getCpuUtilization() / + * hostStats.getNumCpus()); s_logger.debug("Host cpu utilization " + + * hostStats.getCpuUtilization()); } */ return hostStats; @@ -2506,13 +2176,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected HashMap getHostVmStateReport(final Connection conn) { - // TODO : new VM sync model does not require a cluster-scope report, we need to optimize + // TODO : new VM sync model does not require a cluster-scope report, we + // need to optimize // the report accordingly final HashMap vmStates = new HashMap(); Map vm_map = null; for (int i = 0; i < 2; i++) { try { - vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER + vm_map = VM.getAllRecords(conn); // USE THIS TO GET ALL VMS FROM + // A CLUSTER break; } catch (final Throwable e) { s_logger.warn("Unable to get vms", e); @@ -2547,10 +2219,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (host_uuid.equalsIgnoreCase(_host.getUuid())) { - vmStates.put( - record.nameLabel, - new HostVmStateReportEntry(convertToPowerState(ps), host_uuid) - ); + vmStates.put(record.nameLabel, new HostVmStateReportEntry(convertToPowerState(ps), host_uuid)); } } } @@ -2558,8 +2227,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vmStates; } - public SR getIscsiSR(final Connection conn, final String srNameLabel, final String target, String path, final String chapInitiatorUsername, final String chapInitiatorPassword, - final boolean ignoreIntroduceException) { + public SR getIscsiSR(final Connection conn, final String srNameLabel, final String target, String path, final String chapInitiatorUsername, + final String chapInitiatorPassword, final boolean ignoreIntroduceException) { synchronized (srNameLabel.intern()) { final Map deviceConfig = new HashMap(); try { @@ -2601,8 +2270,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe continue; } if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) { - throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" + dc.get("targetIQN") + - ", lunid:" + dc.get("lunid") + " for pool " + srNameLabel + "on host:" + _host.getUuid()); + throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" + dc.get("targetIQN") + + ", lunid:" + dc.get("lunid") + " for pool " + srNameLabel + "on host:" + _host.getUuid()); } } deviceConfig.put("target", target); @@ -2671,7 +2340,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } final Set setHosts = Host.getAll(conn); - if(setHosts == null) { + if (setHosts == null) { final String msg = "Unable to create Iscsi SR " + deviceConfig + " due to hosts not available."; s_logger.warn(msg); throw new CloudRuntimeException(msg); @@ -2775,7 +2444,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected SR getLocalEXTSR(final Connection conn) { try { final Map map = SR.getAllRecords(conn); - if(map != null && !map.isEmpty()) { + if (map != null && !map.isEmpty()) { for (final Map.Entry entry : map.entrySet()) { final SR.Record srRec = entry.getValue(); if (SRType.FILE.equals(srRec.type) || SRType.EXT.equals(srRec.type)) { @@ -2810,7 +2479,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected SR getLocalLVMSR(final Connection conn) { try { final Map map = SR.getAllRecords(conn); - if(map != null && !map.isEmpty()) { + if (map != null && !map.isEmpty()) { for (final Map.Entry entry : map.entrySet()) { final SR.Record srRec = entry.getValue(); if (SRType.LVM.equals(srRec.type)) { @@ -2853,7 +2522,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final VIF vif = vifIter.next(); try { final String deviceId = vif.getDevice(conn); - if(vm.getIsControlDomain(conn) || vif.getCurrentlyAttached(conn)) { + if (vm.getIsControlDomain(conn) || vif.getCurrentlyAttached(conn)) { usedDeviceNums.add(Integer.valueOf(deviceId)); } else { s_logger.debug("Found unplugged VIF " + deviceId + " in VM " + vmName + " destroy it"); @@ -2892,13 +2561,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final PIF.Record rec = pif.getRecord(conn); if (rec.management) { if (rec.VLAN != null && rec.VLAN != -1) { - final String msg = - new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.getUuid()) - .append("; pif=") - .append(rec.uuid) - .append("; vlan=") - .append(rec.VLAN) - .toString(); + final String msg = new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.getUuid()).append("; pif=") + .append(rec.uuid).append("; vlan=").append(rec.VLAN).toString(); s_logger.warn(msg); throw new CloudRuntimeException(msg); } @@ -2917,9 +2581,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } final Bond bond = mgmtPifRec.bondSlaveOf; if (!isRefNull(bond)) { - final String msg = - "Management interface is on slave(" + mgmtPifRec.uuid + ") of bond(" + bond.getUuid(conn) + ") on host(" + _host.getUuid() + - "), please move management interface to bond!"; + final String msg = "Management interface is on slave(" + mgmtPifRec.uuid + ") of bond(" + bond.getUuid(conn) + ") on host(" + _host.getUuid() + + "), please move management interface to bond!"; s_logger.warn(msg); throw new CloudRuntimeException(msg); } @@ -2951,7 +2614,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } else if (type == TrafficType.Public) { return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPublicNetwork()), null, PIF.getByUuid(conn, _host.getPublicPif()), null); } else if (type == TrafficType.Storage) { - /* TrafficType.Storage is for secondary storage, while storageNetwork1 is for primary storage, we need better name here */ + /* + * TrafficType.Storage is for secondary storage, while + * storageNetwork1 is for primary storage, we need better name here + */ return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getStorageNetwork1()), null, PIF.getByUuid(conn, _host.getStoragePif1()), null); } @@ -2973,8 +2639,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Vlan; final long vlan = Long.parseLong(BroadcastDomainType.getValue(uri)); return enableVlanNetwork(conn, vlan, network); - } else if (type == BroadcastDomainType.Native || type == BroadcastDomainType.LinkLocal || - type == BroadcastDomainType.Vsp) { + } else if (type == BroadcastDomainType.Native || type == BroadcastDomainType.LinkLocal || type == BroadcastDomainType.Vsp) { return network.getNetwork(); } else if (uri != null && type == BroadcastDomainType.Vswitch) { final String header = uri.toString().substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length()); @@ -2996,7 +2661,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return network.getNetwork(); } else if (uri != null && type == BroadcastDomainType.Pvlan) { assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Pvlan; - // should we consider moving this NetUtils method to BroadcastDomainType? + // should we consider moving this NetUtils method to + // BroadcastDomainType? final long vlan = Long.parseLong(NetUtils.getPrimaryPvlanFromUri(uri)); return enableVlanNetwork(conn, vlan, network); } @@ -3005,39 +2671,39 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } /** - * getNetworkByName() retrieves what the server thinks is the actual - * network used by the XenServer host. This method should always be - * used to talk to retrieve a network by the name. The reason is - * because of the problems in using the name label as the way to find - * the Network. + * getNetworkByName() retrieves what the server thinks is the actual network + * used by the XenServer host. This method should always be used to talk to + * retrieve a network by the name. The reason is because of the problems in + * using the name label as the way to find the Network. * * To see how we are working around these problems, take a look at - * enableVlanNetwork(). The following description assumes you have looked - * at the description on that method. + * enableVlanNetwork(). The following description assumes you have looked at + * the description on that method. * * In order to understand this, we have to see what type of networks are * within a XenServer that's under CloudStack control. * - * - Native Networks: these are networks that are untagged on the - * XenServer and are used to crate VLAN networks on. These are - * created by the user and is assumed to be one per cluster. - * - VLAN Networks: these are dynamically created by CloudStack and can - * have problems with duplicated names. - * - LinkLocal Networks: these are dynamically created by CloudStack and - * can also have problems with duplicated names but these don't have - * actual PIFs. + * - Native Networks: these are networks that are untagged on the XenServer + * and are used to crate VLAN networks on. These are created by the user and + * is assumed to be one per cluster. - VLAN Networks: these are dynamically + * created by CloudStack and can have problems with duplicated names. - + * LinkLocal Networks: these are dynamically created by CloudStack and can + * also have problems with duplicated names but these don't have actual + * PIFs. * - * In order to speed to retrieval of a network, we do the following: - * - We retrieve by the name. If only one network is retrieved, we - * assume we retrieved the right network. - * - If more than one network is retrieved, we check to see which one - * has the pif for the local host and use that. - * - If a pif is not found, then we look at the tags and find the - * one with the lowest timestamp. (See enableVlanNetwork()) + * In order to speed to retrieval of a network, we do the following: - We + * retrieve by the name. If only one network is retrieved, we assume we + * retrieved the right network. - If more than one network is retrieved, we + * check to see which one has the pif for the local host and use that. - If + * a pif is not found, then we look at the tags and find the one with the + * lowest timestamp. (See enableVlanNetwork()) * - * @param conn Xapi connection - * @param name name of the network - * @return XsNic an object that contains network, network record, pif, and pif record. + * @param conn + * Xapi connection + * @param name + * name of the network + * @return XsNic an object that contains network, network record, pif, and + * pif record. * @throws XenAPIException * @throws XmlRpcException * @@ -3107,7 +2773,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { serverpath = serverpath.replace("//", "/"); final Set srs = SR.getAll(conn); - if(srs != null && !srs.isEmpty()) { + if (srs != null && !srs.isEmpty()) { for (final SR sr : srs) { if (!SRType.NFS.equals(sr.getType(conn))) { continue; @@ -3135,8 +2801,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) { - throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + dc.get("serverpath") + - " for pool " + uuid + " on host:" + _host.getUuid()); + throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + dc.get("serverpath") + + " for pool " + uuid + " on host:" + _host.getUuid()); } } @@ -3159,7 +2825,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private String getOvsTunnelNetworkName(final String broadcastUri) { if (broadcastUri.contains(".")) { final String[] parts = broadcastUri.split("\\."); - return "OVS-DR-VPC-Bridge"+parts[0]; + return "OVS-DR-VPC-Bridge" + parts[0]; } else { try { return "OVSTunnel" + broadcastUri; @@ -3173,12 +2839,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } - public String getPerfMon(final Connection conn, final Map params, - final int wait) { + public String getPerfMon(final Connection conn, final Map params, final int wait) { String result = null; try { - result = callHostPluginAsync(conn, "vmopspremium", "asmonitor", 60, - params); + result = callHostPluginAsync(conn, "vmopspremium", "asmonitor", 60, params); if (result != null) { return result; } @@ -3191,7 +2855,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected Object[] getRRDData(final Connection conn, final int flag) { /* - * Note: 1 => called from host, hence host stats 2 => called from vm, hence vm stats + * Note: 1 => called from host, hence host stats 2 => called from vm, + * hence vm stats */ Document doc = null; @@ -3202,7 +2867,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } - if (doc == null) { //stats are null when the host plugin call fails (host down state) + if (doc == null) { // stats are null when the host plugin call fails + // (host down state) return null; } @@ -3254,15 +2920,20 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return ressr; } - private long getStaticMax(final String os, final boolean b, final long dynamicMinRam, final long dynamicMaxRam){ + private long getStaticMax(final String os, final boolean b, final long dynamicMinRam, final long dynamicMaxRam) { final long recommendedValue = CitrixHelper.getXenServerStaticMax(os, b); - if(recommendedValue == 0){ + if (recommendedValue == 0) { s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); return dynamicMaxRam; } - final long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability - if (dynamicMaxRam > staticMax){ // XS contraint that dynamic max <= static max - s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + ", can lead to stability issues. Setting static max as much as dynamic max "); + final long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS + // constraint + // for + // stability + if (dynamicMaxRam > staticMax) { // XS contraint that dynamic max <= + // static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + + ", can lead to stability issues. Setting static max as much as dynamic max "); return dynamicMaxRam; } return staticMax; @@ -3275,7 +2946,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return dynamicMinRam; } - if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min + if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min + // > static min s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); } return dynamicMinRam; @@ -3421,9 +3093,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } public String getVhdParent(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI) { - final String parentUuid = - callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", - isISCSI.toString()); + final String parentUuid = callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", + isISCSI.toString()); if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid); @@ -3486,7 +3157,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (vdi.getIsASnapshot(conn) && vdi.getSmConfig(conn).get("vhd-parent") != null) { final String parentUuid = vdi.getSmConfig(conn).get("vhd-parent"); final VDI parentVDI = VDI.getByUuid(conn, parentUuid); - // add size of snapshot vdi node, usually this only contains meta data + // add size of snapshot vdi node, usually this only contains + // meta data size = size + vdi.getPhysicalUtilisation(conn); // add size of snapshot vdi parent, this contains data if (!isRefNull(parentVDI)) { @@ -3534,13 +3206,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return convertToPowerState(vm.getPowerState(conn)); } } catch (final BadServerResponse e) { - // There is a race condition within xenserver such that if a vm is + // There is a race condition within xenserver such that if a vm + // is // deleted and we // happen to ask for it, it throws this stupid response. So // if this happens, // we take a nap and try again which then avoids the race // condition because - // the vm's information is now cleaned up by xenserver. The error + // the vm's information is now cleaned up by xenserver. The + // error // is as follows // com.xensource.xenapi.Types$BadServerResponse // [HANDLE_INVALID, VM, @@ -3572,16 +3246,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vmResponseMap.put(vmUUID, new VmStatsEntry(0, 0, 0, 0, "vm")); } - final Object[] rrdData = getRRDData(conn, 2); // call rrddata with 2 for vm + final Object[] rrdData = getRRDData(conn, 2); // call rrddata with 2 for + // vm if (rrdData == null) { return null; } - final Integer numRows = (Integer)rrdData[0]; - final Integer numColumns = (Integer)rrdData[1]; - final Node legend = (Node)rrdData[2]; - final Node dataNode = (Node)rrdData[3]; + final Integer numRows = (Integer) rrdData[0]; + final Integer numColumns = (Integer) rrdData[1]; + final Node legend = (Node) rrdData[2]; + final Node dataNode = (Node) rrdData[3]; final NodeList legendChildren = legend.getChildNodes(); for (int col = 0; col < numColumns; col++) { @@ -3615,18 +3290,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vmStatsAnswer.setNumCPUs(vmStatsAnswer.getNumCPUs() + 1); vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() + getDataAverage(dataNode, col, numRows)); } else if (param.matches("vif_\\d*_rx")) { - vmStatsAnswer.setNetworkReadKBs(vmStatsAnswer.getNetworkReadKBs() + getDataAverage(dataNode, col, numRows)/1000); + vmStatsAnswer.setNetworkReadKBs(vmStatsAnswer.getNetworkReadKBs() + getDataAverage(dataNode, col, numRows) / 1000); } else if (param.matches("vif_\\d*_tx")) { - vmStatsAnswer.setNetworkWriteKBs(vmStatsAnswer.getNetworkWriteKBs() + getDataAverage(dataNode, col, numRows)/1000); + vmStatsAnswer.setNetworkWriteKBs(vmStatsAnswer.getNetworkWriteKBs() + getDataAverage(dataNode, col, numRows) / 1000); } else if (param.matches("vbd_.*_read")) { - vmStatsAnswer.setDiskReadKBs(vmStatsAnswer.getDiskReadKBs() + getDataAverage(dataNode, col, numRows)/1000); + vmStatsAnswer.setDiskReadKBs(vmStatsAnswer.getDiskReadKBs() + getDataAverage(dataNode, col, numRows) / 1000); } else if (param.matches("vbd_.*_write")) { - vmStatsAnswer.setDiskWriteKBs(vmStatsAnswer.getDiskWriteKBs() + getDataAverage(dataNode, col, numRows)/1000); + vmStatsAnswer.setDiskWriteKBs(vmStatsAnswer.getDiskWriteKBs() + getDataAverage(dataNode, col, numRows) / 1000); } } } - for (final Map.Entry entry: vmResponseMap.entrySet()) { + for (final Map.Entry entry : vmResponseMap.entrySet()) { final VmStatsEntry vmStatsAnswer = entry.getValue(); if (vmStatsAnswer.getNumCPUs() != 0) { @@ -3695,7 +3370,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe for (final VIF vif : vmr.VIFs) { try { final VIF.Record rec = vif.getRecord(conn); - if(rec != null) { + if (rec != null) { networks.add(rec.network); } else { s_logger.warn("Unable to cleanup VIF: " + vif.toWireString() + " As vif record is null"); @@ -3768,9 +3443,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } final StartupStorageCommand sscmd = initializeLocalSR(conn); if (sscmd != null) { - return new StartupCommand[] {cmd, sscmd}; + return new StartupCommand[] { cmd, sscmd }; } - return new StartupCommand[] {cmd}; + return new StartupCommand[] { cmd }; } protected StartupStorageCommand initializeLocalSR(final Connection conn) { @@ -3858,8 +3533,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } /** - * When Dynamic Memory Control (DMC) is enabled - - * xenserver allows scaling the guest memory while the guest is running + * When Dynamic Memory Control (DMC) is enabled - xenserver allows scaling + * the guest memory while the guest is running * * By default this is disallowed, override the specific xenserver resource * if this is enabled @@ -3920,10 +3595,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } public boolean launchHeartBeat(final Connection conn) { - final String result = callHostPluginPremium(conn, "heartbeat", - "host", _host.getUuid(), - "timeout", Integer.toString(_heartbeatTimeout), - "interval", Integer.toString(_heartbeatInterval)); + final String result = callHostPluginPremium(conn, "heartbeat", "host", _host.getUuid(), "timeout", Integer.toString(_heartbeatTimeout), "interval", + Integer.toString(_heartbeatInterval)); if (result == null || !result.contains("> DONE <")) { s_logger.warn("Unable to launch the heartbeat process on " + _host.getIp()); return false; @@ -3976,15 +3649,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final DataTO data = volume.getData(); final Volume.Type type = volume.getType(); if (type == Volume.Type.ISO) { - final TemplateObjectTO iso = (TemplateObjectTO)data; + final TemplateObjectTO iso = (TemplateObjectTO) data; final DataStoreTO store = iso.getDataStore(); if (store == null) { - //It's a fake iso + // It's a fake iso return null; } - //corer case, xenserver pv driver iso + // corer case, xenserver pv driver iso final String templateName = iso.getName(); if (templateName.startsWith("xs-tools")) { try { @@ -4003,7 +3676,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (!(store instanceof NfsTO)) { throw new CloudRuntimeException("only support mount iso on nfs"); } - final NfsTO nfsStore = (NfsTO)store; + final NfsTO nfsStore = (NfsTO) store; final String isoPath = nfsStore.getUrl() + File.separator + iso.getPath(); final int index = isoPath.lastIndexOf("/"); @@ -4025,7 +3698,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } return isoVdi; } else { - final VolumeObjectTO vol = (VolumeObjectTO)data; + final VolumeObjectTO vol = (VolumeObjectTO) data; return VDI.getByUuid(conn, vol.getPath()); } } @@ -4049,7 +3722,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe continue; } - //','.join([bridge, vmName, vmId, seqno, tag]) + // ','.join([bridge, vmName, vmId, seqno, tag]) try { states.add(new Pair(info[0], Long.parseLong(info[3]))); } catch (final NumberFormatException nfe) { @@ -4059,7 +3732,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return states; } - public HashMap parseDefaultOvsRuleComamnd(final String str) { final HashMap cmd = new HashMap(); final String[] sarr = str.split("/"); @@ -4122,18 +3794,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Connection conn = getConnection(); try { final Host host = Host.getByUuid(conn, _host.getUuid()); - if( !host.getEnabled(conn) ) { + if (!host.getEnabled(conn)) { s_logger.debug("Host " + _host.getIp() + " is not enabled!"); return false; } } catch (final Exception e) { - s_logger.debug("cannot get host enabled status, host " + _host.getIp() + " due to " + e.toString(), e); + s_logger.debug("cannot get host enabled status, host " + _host.getIp() + " due to " + e.toString(), e); return false; } try { callHostPlugin(conn, "echo", "main"); } catch (final Exception e) { - s_logger.debug("cannot ping host " + _host.getIp() + " due to " + e.toString(), e); + s_logger.debug("cannot ping host " + _host.getIp() + " due to " + e.toString(), e); return false; } return true; @@ -4145,8 +3817,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected boolean postCreatePrivateTemplate(final Connection conn, final String templatePath, final String tmpltFilename, final String templateName, String templateDescription, - String checksum, final long size, final long virtualSize, final long templateId) { + protected boolean postCreatePrivateTemplate(final Connection conn, final String templatePath, final String tmpltFilename, final String templateName, + String templateDescription, String checksum, final long size, final long virtualSize, final long templateId) { if (templateDescription == null) { templateDescription = ""; @@ -4156,10 +3828,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe checksum = ""; } - final String result = - callHostPlugin(conn, "vmopsSnapshot", "post_create_private_template", "templatePath", templatePath, "templateFilename", tmpltFilename, "templateName", - templateName, "templateDescription", templateDescription, "checksum", checksum, "size", String.valueOf(size), "virtualSize", String.valueOf(virtualSize), - "templateId", String.valueOf(templateId)); + final String result = callHostPlugin(conn, "vmopsSnapshot", "post_create_private_template", "templatePath", templatePath, "templateFilename", tmpltFilename, + "templateName", templateName, "templateDescription", templateDescription, "checksum", checksum, "size", String.valueOf(size), "virtualSize", + String.valueOf(virtualSize), "templateId", String.valueOf(templateId)); boolean success = false; if (result != null && !result.isEmpty()) { @@ -4178,20 +3849,20 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe @Override public ExecutionResult prepareCommand(final NetworkElementCommand cmd) { - //Update IP used to access router + // Update IP used to access router cmd.setRouterAccessIp(cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP)); assert cmd.getRouterAccessIp() != null; if (cmd instanceof IpAssocVpcCommand) { - return prepareNetworkElementCommand((IpAssocVpcCommand)cmd); + return prepareNetworkElementCommand((IpAssocVpcCommand) cmd); } else if (cmd instanceof IpAssocCommand) { - return prepareNetworkElementCommand((IpAssocCommand)cmd); + return prepareNetworkElementCommand((IpAssocCommand) cmd); } else if (cmd instanceof SetupGuestNetworkCommand) { - return prepareNetworkElementCommand((SetupGuestNetworkCommand)cmd); + return prepareNetworkElementCommand((SetupGuestNetworkCommand) cmd); } else if (cmd instanceof SetSourceNatCommand) { - return prepareNetworkElementCommand((SetSourceNatCommand)cmd); + return prepareNetworkElementCommand((SetSourceNatCommand) cmd); } else if (cmd instanceof SetNetworkACLCommand) { - return prepareNetworkElementCommand((SetNetworkACLCommand)cmd); + return prepareNetworkElementCommand((SetNetworkACLCommand) cmd); } return new ExecutionResult(true, null); } @@ -4231,7 +3902,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - // the idea here is to see if the DiskTO in question is from managed storage and + // the idea here is to see if the DiskTO in question is from managed storage + // and // does not yet have an SR // if no SR, create it and create a VDI in it public VDI prepareManagedDisk(final Connection conn, final DiskTO disk, final String vmName) throws Exception { @@ -4288,7 +3960,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (vdi == null) { vdi = createVdi(sr, vdiNameLabel, volumeSize); } else { - // if VDI is not null, it must have already been created, so check whether a resize of the volume was performed + // if VDI is not null, it must have already been created, so check + // whether a resize of the volume was performed // if true, resize the VDI to the volume size s_logger.info("checking for the resize of the datadisk"); @@ -4296,7 +3969,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final long vdiVirtualSize = vdi.getVirtualSize(conn); if (vdiVirtualSize != volumeSize) { - s_logger.info("resizing the data disk (vdi) from vdiVirtualsize: "+ vdiVirtualSize + " to volumeSize: " + volumeSize); + s_logger.info("resizing the data disk (vdi) from vdiVirtualsize: " + vdiVirtualSize + " to volumeSize: " + volumeSize); try { vdi.resize(conn, volumeSize); @@ -4323,7 +3996,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final NicTO nic = new NicTO(); nic.setMac(ip.getVifMacAddress()); nic.setType(ip.getTrafficType()); - if (ip.getBroadcastUri()== null) { + if (ip.getBroadcastUri() == null) { nic.setBroadcastType(BroadcastDomainType.Native); } else { final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); @@ -4336,13 +4009,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Network network = getNetwork(conn, nic); - // Determine the correct VIF on DomR to associate/disassociate the + // Determine the correct VIF on DomR to associate/disassociate + // the // IP address with VIF correctVif = getCorrectVif(conn, router, network); - // If we are associating an IP address and DomR doesn't have a VIF + // If we are associating an IP address and DomR doesn't have a + // VIF // for the specified vlan ID, we need to add a VIF - // If we are disassociating the last IP address in the VLAN, we need + // If we are disassociating the last IP address in the VLAN, we + // need // to remove a VIF boolean addVif = false; if (ip.isAdd() && correctVif == null) { @@ -4368,7 +4044,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (ip.isAdd() && correctVif == null) { throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with."); } - if (correctVif != null ) { + if (correctVif != null) { ip.setNicDevId(Integer.valueOf(correctVif.getDevice(conn))); ip.setNewNic(addVif); } @@ -4410,10 +4086,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final VM router = getVM(conn, routerName); final NicTO nic = cmd.getNic(); - if(nic != null) { + if (nic != null) { final VIF vif = getVifByMac(conn, router, nic.getMac()); - if(vif == null) { - final String msg = "Prepare SetNetworkACL failed due to VIF is null for : " + nic.getMac() +" with routername: " + routerName; + if (vif == null) { + final String msg = "Prepare SetNetworkACL failed due to VIF is null for : " + nic.getMac() + " with routername: " + routerName; s_logger.error(msg); return new ExecutionResult(false, msg); } @@ -4470,8 +4146,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final String lmac = vif.getMAC(conn); if (lmac.equals(mac)) { domrVif = vif; - //Do not break it! We have 2 routers. - //break; + // Do not break it! We have 2 routers. + // break; } } if (domrVif == null) { @@ -4492,7 +4168,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task = vm.cleanRebootAsync(conn); try { - //poll every 1 seconds , timeout after 10 minutes + // poll every 1 seconds , timeout after 10 minutes waitForTask(conn, task, 1000, 10 * 60 * 1000); checkForSuccess(conn, task); } catch (final Types.HandleInvalid e) { @@ -4546,7 +4222,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe // if (pbd.getCurrentlyAttached(conn)) { pbd.unplug(conn); - //} + // } pbd.destroy(conn); } @@ -4621,12 +4297,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - public String revertToSnapshot(final Connection conn, final VM vmSnapshot, final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) throws XenAPIException, - XmlRpcException { + public String revertToSnapshot(final Connection conn, final VM vmSnapshot, final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) + throws XenAPIException, XmlRpcException { - final String results = - callHostPluginAsync(conn, "vmopsSnapshot", "revert_memory_snapshot", 10 * 60 * 1000, "snapshotUUID", vmSnapshot.getUuid(conn), "vmName", vmName, "oldVmUuid", - oldVmUuid, "snapshotMemory", snapshotMemory.toString(), "hostUUID", hostUUID); + final String results = callHostPluginAsync(conn, "vmopsSnapshot", "revert_memory_snapshot", 10 * 60 * 1000, "snapshotUUID", vmSnapshot.getUuid(conn), "vmName", vmName, + "oldVmUuid", oldVmUuid, "snapshotMemory", snapshotMemory.toString(), "hostUUID", hostUUID); String errMsg = null; if (results == null || results.isEmpty()) { errMsg = "revert_memory_snapshot return null"; @@ -4648,32 +4323,35 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Long newDynamicMemoryMin = vmSpec.getMinRam(); final Long newDynamicMemoryMax = vmSpec.getMaxRam(); if (staticMemoryMin > newDynamicMemoryMin || newDynamicMemoryMax > staticMemoryMax) { - throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: " + "0 <= memory-static-min(" + staticMemoryMin + - ") <= memory-dynamic-min(" + newDynamicMemoryMin + ") <= memory-dynamic-max(" + newDynamicMemoryMax + ") <= memory-static-max(" + staticMemoryMax + ")"); + throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: " + "0 <= memory-static-min(" + staticMemoryMin + + ") <= memory-dynamic-min(" + newDynamicMemoryMin + ") <= memory-dynamic-max(" + newDynamicMemoryMax + ") <= memory-static-max(" + staticMemoryMax + ")"); } vm.setMemoryDynamicRange(conn, newDynamicMemoryMin, newDynamicMemoryMax); - vm.setVCPUsNumberLive(conn, (long)vmSpec.getCpus()); + vm.setVCPUsNumberLive(conn, (long) vmSpec.getCpus()); final Integer speed = vmSpec.getMinSpeed(); if (speed != null) { - int cpuWeight = _maxWeight; //cpu_weight + int cpuWeight = _maxWeight; // cpu_weight // weight based allocation - cpuWeight = (int)(speed * 0.99 / _host.getSpeed() * _maxWeight); + cpuWeight = (int) (speed * 0.99 / _host.getSpeed() * _maxWeight); if (cpuWeight > _maxWeight) { cpuWeight = _maxWeight; } if (vmSpec.getLimitCpuUse()) { long utilization = 0; // max CPU cap, default is unlimited - utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100); - //vm.addToVCPUsParamsLive(conn, "cap", Long.toString(utilization)); currently xenserver doesnot support Xapi to add VCPUs params live. + utilization = (int) (vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100); + // vm.addToVCPUsParamsLive(conn, "cap", + // Long.toString(utilization)); currently xenserver doesnot + // support Xapi to add VCPUs params live. callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", Long.toString(utilization), "vmname", vmSpec.getName()); } - //vm.addToVCPUsParamsLive(conn, "weight", Integer.toString(cpuWeight)); + // vm.addToVCPUsParamsLive(conn, "weight", + // Integer.toString(cpuWeight)); callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", Integer.toString(cpuWeight), "vmname", vmSpec.getName()); } } @@ -4705,7 +4383,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe /** * WARN: static-min <= dynamic-min <= dynamic-max <= static-max - * @see XcpServerResource#setMemory(com.xensource.xenapi.Connection, com.xensource.xenapi.VM, long, long) + * + * @see XcpServerResource#setMemory(com.xensource.xenapi.Connection, + * com.xensource.xenapi.VM, long, long) * @param conn * @param vm * @param minMemsize @@ -4721,8 +4401,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public void setName(final String name) { } - protected void setNicDevIdIfCorrectVifIsNotNull(final Connection conn, final IpAddressTO ip, final VIF correctVif) throws InternalErrorException, BadServerResponse, XenAPIException, - XmlRpcException { + protected void setNicDevIdIfCorrectVifIsNotNull(final Connection conn, final IpAddressTO ip, final VIF correctVif) throws InternalErrorException, BadServerResponse, + XenAPIException, XmlRpcException { if (correctVif == null) { if (ip.isAdd()) { throw new InternalErrorException("Failed to find DomR VIF to associate IP with."); @@ -4902,8 +4582,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final Properties props = PropertiesUtil.loadFromFile(file); for (final Map.Entry entry : props.entrySet()) { - final String k = (String)entry.getKey(); - final String v = (String)entry.getValue(); + final String k = (String) entry.getKey(); + final String v = (String) entry.getValue(); assert k != null && k.length() > 0 && v != null && v.length() > 0 : "Problems with " + k + "=" + v; @@ -5007,7 +4687,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task = vm.cleanShutdownAsync(conn); try { - //poll every 1 seconds , timeout after 10 minutes + // poll every 1 seconds , timeout after 10 minutes waitForTask(conn, task, 1000, 10 * 60 * 1000); checkForSuccess(conn, task); } catch (final TimeoutException e) { @@ -5065,7 +4745,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task = vm.startOnAsync(conn, host, false, true); try { - //poll every 1 seconds , timeout after 10 minutes + // poll every 1 seconds , timeout after 10 minutes waitForTask(conn, task, 1000, 10 * 60 * 1000); checkForSuccess(conn, task); } catch (final Types.HandleInvalid e) { @@ -5164,7 +4844,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (log.length != 6) { continue; } - //output = ','.join([vmName, vmID, vmIP, domID, signature, seqno]) + // output = ','.join([vmName, vmID, vmIP, domID, signature, seqno]) try { states.put(log[0], new Pair(Long.parseLong(log[1]), Long.parseLong(log[5]))); } catch (final NumberFormatException nfe) { @@ -5212,7 +4892,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { callHostPlugin(conn, "vmopsSnapshot", "unmountSnapshotsDir", "dcId", dcId.toString()); } catch (final Exception e) { - s_logger.debug("Failed to umount snapshot dir",e); + s_logger.debug("Failed to umount snapshot dir", e); } } @@ -5237,8 +4917,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public void waitForTask(final Connection c, final Task task, final long pollInterval, final long timeout) throws XenAPIException, XmlRpcException, TimeoutException { final long beginTime = System.currentTimeMillis(); if (s_logger.isTraceEnabled()) { - s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") sent to " + c.getSessionReference() + " is pending completion with a " + timeout + - "ms timeout"); + s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") sent to " + c.getSessionReference() + " is pending completion with a " + timeout + + "ms timeout"); } while (task.getStatus(c) == Types.TaskStatusType.PENDING) { try { From 57d0931b4950d202994d1b6609329502a60a9edf Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Tue, 31 Mar 2015 16:49:48 +0200 Subject: [PATCH 30/30] Adding more tests to cover other possibilities concerning different versions of the XenServer Adding a better algorithm in order to corver deeper inheritance form the command classes Removing some unsued variables. --- api/src/com/cloud/agent/api/Answer.java | 14 +-- .../cloudstack/api/agent/test/AnswerTest.java | 8 +- .../xenserver/resource/XcpServerResource.java | 1 - .../resource/XenServer56SP2Resource.java | 11 +- .../resource/XenServer600Resource.java | 15 +-- .../resource/XenServer610Resource.java | 2 - .../resource/XenServer650Resource.java | 26 ++--- .../wrapper/CitrixRequestWrapper.java | 103 ++++++++++++++---- .../wrapper/CitrixRequestWrapperTest.java | 23 +++- .../wrapper/XenServer56WrapperTest.java | 21 ++++ .../wrapper/XenServer610WrapperTest.java | 56 ++++++++++ .../wrapper/XenServer620WrapperTest.java | 35 ++++++ 12 files changed, 244 insertions(+), 71 deletions(-) create mode 100644 plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java create mode 100644 plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer620WrapperTest.java diff --git a/api/src/com/cloud/agent/api/Answer.java b/api/src/com/cloud/agent/api/Answer.java index 9d106115d91..fd6a0d1b46a 100644 --- a/api/src/com/cloud/agent/api/Answer.java +++ b/api/src/com/cloud/agent/api/Answer.java @@ -26,16 +26,16 @@ public class Answer extends Command { this(null); } - public Answer(Command command) { + public Answer(final Command command) { this(command, true, null); } - public Answer(Command command, boolean success, String details) { + public Answer(final Command command, final boolean success, final String details) { result = success; this.details = details; } - public Answer(Command command, Exception e) { + public Answer(final Command command, final Exception e) { this(command, false, ExceptionUtil.toString(e)); } @@ -52,11 +52,11 @@ public class Answer extends Command { return false; } - public static UnsupportedAnswer createUnsupportedCommandAnswer(Command cmd) { - return new UnsupportedAnswer(cmd, "Unsupported command issued:" + cmd.toString() + ". Are you sure you got the right type of server?"); + public static UnsupportedAnswer createUnsupportedCommandAnswer(final Command cmd) { + return new UnsupportedAnswer(cmd, "Unsupported command issued: " + cmd.toString() + ". Are you sure you got the right type of server?"); } - public static UnsupportedAnswer createUnsupportedVersionAnswer(Command cmd) { + public static UnsupportedAnswer createUnsupportedVersionAnswer(final Command cmd) { return new UnsupportedAnswer(cmd, "Unsuppored Version."); } -} +} \ No newline at end of file diff --git a/core/test/org/apache/cloudstack/api/agent/test/AnswerTest.java b/core/test/org/apache/cloudstack/api/agent/test/AnswerTest.java index c685d682975..608791736ac 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/AnswerTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/AnswerTest.java @@ -34,19 +34,19 @@ public class AnswerTest { @Test public void testExecuteInSequence() { - boolean b = a.executeInSequence(); + final boolean b = a.executeInSequence(); assertFalse(b); } @Test public void testGetResult() { - boolean b = a.getResult(); + final boolean b = a.getResult(); assertTrue(b); } @Test public void testGetDetails() { - String d = a.getDetails(); + final String d = a.getDetails(); assertTrue(d.equals("details")); } @@ -60,7 +60,7 @@ public class AnswerTest { assertFalse(b); String d = usa.getDetails(); - assertTrue(d.equals("Unsupported command issued:" + acc.toString() + ". Are you sure you got the right type of server?")); + assertTrue(d.contains("Unsupported command issued: " + acc.toString() + ". Are you sure you got the right type of server?")); usa = Answer.createUnsupportedVersionAnswer(acc); b = usa.executeInSequence(); 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 63cdf114bf2..4b2936eb720 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 @@ -41,7 +41,6 @@ import com.xensource.xenapi.VM; public class XcpServerResource extends CitrixResourceBase { private final static Logger s_logger = Logger.getLogger(XcpServerResource.class); private static final long mem_32m = 33554432L; - private String version; public XcpServerResource() { super(); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56SP2Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56SP2Resource.java index c0d6f004e3b..37748178fbb 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56SP2Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56SP2Resource.java @@ -22,15 +22,12 @@ import java.util.List; import javax.ejb.Local; -import org.apache.log4j.Logger; - import com.cloud.resource.ServerResource; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; @Local(value = ServerResource.class) public class XenServer56SP2Resource extends XenServer56FP1Resource { - private static final Logger s_logger = Logger.getLogger(XenServer56SP2Resource.class); public XenServer56SP2Resource() { super(); @@ -40,13 +37,13 @@ public class XenServer56SP2Resource extends XenServer56FP1Resource { @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; } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer600Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer600Resource.java index 037ded32321..c6e5d82af06 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer600Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer600Resource.java @@ -22,29 +22,22 @@ import java.util.List; import javax.ejb.Local; -import org.apache.log4j.Logger; - import com.cloud.resource.ServerResource; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; @Local(value = ServerResource.class) public class XenServer600Resource extends XenServer56SP2Resource { - private static final Logger s_logger = Logger.getLogger(XenServer600Resource.class); - - public XenServer600Resource() { - super(); - } @Override protected List getPatchFiles() { - List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xenserver60/patch"; - String patchfilePath = Script.findScript("", patch); + final List files = new ArrayList(); + final String patch = "scripts/vm/hypervisor/xenserver/xenserver60/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; } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java index 3c5caf03ce3..e71a97db2b6 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java @@ -239,7 +239,6 @@ public class XenServer610Resource extends XenServer600Resource { final Map token = cmd.getToken(); final String vmName = vmSpec.getName(); final Set volumeToSet = null; - boolean migrated = false; Task task = null; try { final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); @@ -295,7 +294,6 @@ public class XenServer610Resource extends XenServer600Resource { throw new CloudRuntimeException("Error while migrating vm " + vmName, e); } - migrated = true; return new MigrateWithStorageSendAnswer(cmd, volumeToSet); } catch (final CloudRuntimeException e) { s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer650Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer650Resource.java index 4fa82a80680..98796eb0435 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer650Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer650Resource.java @@ -18,32 +18,28 @@ */ package com.cloud.hypervisor.xenserver.resource; -import com.cloud.resource.ServerResource; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; -import org.apache.log4j.Logger; - -import javax.ejb.Local; import java.io.File; import java.util.ArrayList; import java.util.List; +import javax.ejb.Local; + +import com.cloud.resource.ServerResource; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + @Local(value=ServerResource.class) public class XenServer650Resource extends Xenserver625Resource { - private static final Logger s_logger = Logger.getLogger(XenServer650Resource.class); - - public XenServer650Resource() { - super(); - } + @Override protected List getPatchFiles() { - List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xenserver65/patch"; - String patchfilePath = Script.findScript("", patch); + final List files = new ArrayList(); + final String patch = "scripts/vm/hypervisor/xenserver/xenserver65/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; } 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 8b0043f6437..b68ef38ddc4 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.log4j.Logger; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeCommand; @@ -92,14 +94,14 @@ import com.cloud.resource.ServerResource; public class CitrixRequestWrapper extends RequestWrapper { + private static final Logger s_logger = Logger.getLogger(CitrixRequestWrapper.class); + private static CitrixRequestWrapper instance; static { instance = new CitrixRequestWrapper(); } - private boolean initialised; - @SuppressWarnings("rawtypes") private final Hashtable, Hashtable, CommandWrapper>> resources; @@ -184,40 +186,95 @@ public class CitrixRequestWrapper extends RequestWrapper { final Hashtable, CommandWrapper> xenServer56P1Commands = new Hashtable, CommandWrapper>(); xenServer56P1Commands.put(FenceCommand.class, new XenServer56FP1FenceCommandWrapper()); resources.put(XenServer56FP1Resource.class, xenServer56P1Commands); - - initialised = true; } public static CitrixRequestWrapper getInstance() { return instance; } - boolean isInitialised() { - return initialised; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"rawtypes" }) @Override public Answer execute(final Command command, final ServerResource serverResource) { - Hashtable, CommandWrapper> commands = resources.get(serverResource.getClass()); + final Class resourceClass = serverResource.getClass(); - // Can't instantiate the CitrixResourceBase because it's abstract. In order to reuse the command with subclasses - // I need to do this check here. - if (commands == null) { - commands = resources.get(serverResource.getClass().getSuperclass()); - } + final Hashtable, CommandWrapper> resourceCommands = retrieveResource(command, resourceClass); - CommandWrapper commandWrapper = commands.get(command.getClass()); + CommandWrapper commandWrapper = retrieveCommands(command.getClass(), resourceCommands); - // This is temporary. We have to map the classes with several sub-classes better. - if (commandWrapper == null && command instanceof NetworkElementCommand) { - commandWrapper = commands.get(NetworkElementCommand.class); - } - - if (commandWrapper == null) { - throw new NullPointerException("No key found for '" + command.getClass() + "' in the Map!"); + while (commandWrapper == null) { + //Could not find the command in the given resource, will traverse the family tree. + commandWrapper = retryWhenAllFails(command, resourceClass, resourceCommands); } return commandWrapper.execute(command, serverResource); } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected Hashtable, CommandWrapper> retrieveResource(final Command command, final Class resourceClass) { + Class keepResourceClass = resourceClass; + Hashtable, CommandWrapper> resource = resources.get(keepResourceClass); + while (resource == null) { + try { + final Class keepResourceClass2 = (Class) keepResourceClass.getSuperclass(); + resource = resources.get(keepResourceClass2); + + keepResourceClass = keepResourceClass2; + } catch (final ClassCastException e) { + throw new NullPointerException("No key found for '" + command.getClass() + "' in the Map!"); + } + } + return resource; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected CommandWrapper retrieveCommands(final Class commandClass, + final Hashtable, CommandWrapper> resourceCommands) { + + Class keepCommandClass = commandClass; + CommandWrapper commandWrapper = resourceCommands.get(keepCommandClass); + while (commandWrapper == null) { + try { + final Class commandClass2 = (Class) keepCommandClass.getSuperclass(); + + if (commandClass2 == null) { + throw new NullPointerException("All the COMMAND hierarchy tree has been visited but no compliant key has been found for '" + commandClass +"'."); + } + + commandWrapper = resourceCommands.get(commandClass2); + + keepCommandClass = commandClass2; + } catch (final NullPointerException e) { + // Will now traverse all the resource hierarchy. Returning null is not a problem. + // It is all being nicely checked and in case we do not have a resource, an Unsupported answer will be thrown by the base class. + return null; + } + } + return commandWrapper; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected CommandWrapper retryWhenAllFails(final Command command, final Class resourceClass, + final Hashtable, CommandWrapper> resourceCommands) { + + Class keepResourceClass = resourceClass; + CommandWrapper commandWrapper = resourceCommands.get(command.getClass()); + while (commandWrapper == null) { + //Could not find the command in the given resource, will traverse the family tree. + try { + final Class resourceClass2 = (Class) keepResourceClass.getSuperclass(); + + if (resourceClass2 == null) { + throw new NullPointerException("All the SERVER-RESOURCE hierarchy tree has been visited but no compliant key has been found for '" + command.getClass() +"'."); + } + + final Hashtable, CommandWrapper> resourceCommands2 = retrieveResource(command, (Class) keepResourceClass.getSuperclass()); + keepResourceClass = resourceClass2; + + commandWrapper = retrieveCommands(command.getClass(), resourceCommands2); + } catch (final NullPointerException e) { + throw e; + } + } + return commandWrapper; + } } \ No newline at end of file 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 286708a6e8f..1a02af4b57c 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 @@ -86,6 +86,7 @@ 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.IpAssocCommand; import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; @@ -1753,7 +1754,7 @@ public class CitrixRequestWrapperTest { } @Test - public void testNetworkElementCommand() { + public void testIpAssocVpcCommand() { final VirtualRoutingResource routingResource = Mockito.mock(VirtualRoutingResource.class); final IpAddressTO [] ips = new IpAddressTO[0]; @@ -1771,6 +1772,26 @@ public class CitrixRequestWrapperTest { // Requires more testing, but the VirtualResourceRouting is quite big. assertNull(answer); } + + @Test + public void testIpAssocCommand() { + final VirtualRoutingResource routingResource = Mockito.mock(VirtualRoutingResource.class); + final IpAddressTO [] ips = new IpAddressTO[0]; + + final IpAssocCommand ipAssociation = new IpAssocCommand(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 { 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 2035c521b71..a004344cfa8 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 @@ -17,8 +17,11 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.FenceCommand; import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.SetupCommand; import com.cloud.host.Host; +import com.cloud.host.HostEnvironment; import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; +import com.cloud.hypervisor.xenserver.resource.XsHost; import com.cloud.utils.ExecutionResult; import com.cloud.vm.VMInstanceVO; import com.xensource.xenapi.Connection; @@ -137,4 +140,22 @@ public class XenServer56WrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testSetupCommand() { + final XsHost xsHost = Mockito.mock(XsHost.class); + final HostEnvironment env = Mockito.mock(HostEnvironment.class); + + final SetupCommand setupCommand = new SetupCommand(env); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer56Resource.getHost()).thenReturn(xsHost); + + final Answer answer = wrapper.execute(setupCommand, xenServer56Resource); + verify(xenServer56Resource, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } } \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java new file mode 100644 index 00000000000..edc4b6d93d0 --- /dev/null +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java @@ -0,0 +1,56 @@ +package com.cloud.hypervisor.xenserver.resource.wrapper; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +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.CheckNetworkCommand; +import com.cloud.agent.api.SetupCommand; +import com.cloud.host.HostEnvironment; +import com.cloud.hypervisor.xenserver.resource.XenServer610Resource; +import com.cloud.network.PhysicalNetworkSetupInfo; + +@RunWith(PowerMockRunner.class) +public class XenServer610WrapperTest { + + @Mock + protected XenServer610Resource xenServer610Resource; + + @Test + public void testCheckNetworkCommandFailure() { + final XenServer610Resource xenServer610Resource = new XenServer610Resource(); + + final PhysicalNetworkSetupInfo info = new PhysicalNetworkSetupInfo(); + + final List setupInfos = new ArrayList(); + setupInfos.add(info); + + final CheckNetworkCommand checkNet = new CheckNetworkCommand(setupInfos); + + final Answer answer = xenServer610Resource.executeRequest(checkNet); + + assertTrue(answer.getResult()); + } + + @Test + public void testSetupCommand() { + final XenServer610Resource xenServer610Resource = new XenServer610Resource(); + + final HostEnvironment env = Mockito.mock(HostEnvironment.class); + + final SetupCommand setupCommand = new SetupCommand(env); + + final Answer answer = xenServer610Resource.executeRequest(setupCommand); + + assertFalse(answer.getResult()); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer620WrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer620WrapperTest.java new file mode 100644 index 00000000000..74fc9cd04c7 --- /dev/null +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer620WrapperTest.java @@ -0,0 +1,35 @@ +package com.cloud.hypervisor.xenserver.resource.wrapper; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckNetworkCommand; +import com.cloud.hypervisor.xenserver.resource.XenServer620Resource; +import com.cloud.network.PhysicalNetworkSetupInfo; + +@RunWith(PowerMockRunner.class) +public class XenServer620WrapperTest { + + @Test + public void testCheckNetworkCommandFailure() { + final XenServer620Resource xenServer620Resource = new XenServer620Resource(); + + final PhysicalNetworkSetupInfo info = new PhysicalNetworkSetupInfo(); + + final List setupInfos = new ArrayList(); + setupInfos.add(info); + + final CheckNetworkCommand checkNet = new CheckNetworkCommand(setupInfos); + + final Answer answer = xenServer620Resource.executeRequest(checkNet); + + assertTrue(answer.getResult()); + } +} \ No newline at end of file