From 24bbfbc1e6608aff56b66a6678a8a876842945eb Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Mon, 30 Mar 2015 17:31:09 +0200 Subject: [PATCH] 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 {