cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bhais...@apache.org
Subject [29/39] git commit: updated refs/heads/master to 3e28747
Date Thu, 02 Apr 2015 18:23:10 GMT
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


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/24bbfbc1
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/24bbfbc1
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/24bbfbc1

Branch: refs/heads/master
Commit: 24bbfbc1e6608aff56b66a6678a8a876842945eb
Parents: fbcae54
Author: wilderrodrigues <wrodrigues@schubergphilis.com>
Authored: Mon Mar 30 17:31:09 2015 +0200
Committer: wilderrodrigues <wrodrigues@schubergphilis.com>
Committed: Tue Mar 31 10:38:32 2015 +0200

----------------------------------------------------------------------
 .../xenserver/resource/CitrixResourceBase.java  |  38 ++--
 .../CitrixCheckNetworkCommandWrapper.java       |  94 +++++++++
 ...trixClusterVMMetaDataSyncCommandWrapper.java |  57 ++++++
 .../CitrixCreateVMSnapshotCommandWrapper.java   | 188 +++++++++++++++++
 .../CitrixDeleteVMSnapshotCommandWrapper.java   |  90 +++++++++
 .../wrapper/CitrixPlugNicCommandWrapper.java    |  92 +++++++++
 .../resource/wrapper/CitrixRequestWrapper.java  |  16 ++
 .../CitrixRevertToVMSnapshotCommandWrapper.java | 110 ++++++++++
 .../wrapper/CitrixUnPlugNicCommandWrapper.java  |  72 +++++++
 .../CitrixUpdateHostPasswordCommandWrapper.java |  34 ++++
 .../wrapper/CitrixRequestWrapperTest.java       | 202 +++++++++++++++++++
 11 files changed, 968 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.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 c495b75..aa92681 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<VIF> 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<VDI> 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<VolumeObjectTO> listVolumeTo) throws BadServerResponse,
+    public VM createWorkingVM(final Connection conn, final String vmName, final String guestOSType, final String platformEmulator, final List<VolumeObjectTO> 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<String, String> clusterVMMetaDataSync(final Connection conn) {
+    public HashMap<String, String> clusterVMMetaDataSync(final Connection conn) {
         final HashMap<String, String> vmMetaDatum = new HashMap<String, String>();
         try {
             final Map<VM, VM.Record>  vm_map = VM.getAllRecords(conn);  //USE THIS TO GET ALL VMS FROM  A CLUSTER

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCheckNetworkCommandWrapper.java
----------------------------------------------------------------------
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 0000000..fb62fce
--- /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<CheckNetworkCommand, Answer, CitrixResourceBase> {
+
+    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<PhysicalNetworkSetupInfo> 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixClusterVMMetaDataSyncCommandWrapper.java
----------------------------------------------------------------------
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 0000000..fb7384b
--- /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<ClusterVMMetaDataSyncCommand, Answer, CitrixResourceBase> {
+
+    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<String, String> vmMetadatum = citrixResourceBase.clusterVMMetaDataSync(conn);
+        return new ClusterVMMetaDataSyncAnswer(command.getClusterId(), vmMetadatum);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCreateVMSnapshotCommandWrapper.java
----------------------------------------------------------------------
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 0000000..7ccf927
--- /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<CreateVMSnapshotCommand, Answer, CitrixResourceBase> {
+
+    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<VolumeObjectTO> 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<VM> 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<Task> tasks = Task.getByNameLabel(conn, "Async.VM.snapshot");
+            if(tasks == null) {
+                tasks = new LinkedHashSet<>();
+            }
+            final Set<Task> 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<VBD> 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("<value>".length(), result.length() - "</value>".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<VBD> 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixDeleteVMSnapshotCommandWrapper.java
----------------------------------------------------------------------
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 0000000..10f4091
--- /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<DeleteVMSnapshotCommand, Answer, CitrixResourceBase> {
+
+    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<VDI> vdiList = new ArrayList<VDI>();
+            final Set<VM> 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<VBD> 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPlugNicCommandWrapper.java
----------------------------------------------------------------------
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 0000000..a3edfbe
--- /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<PlugNicCommand, Answer, CitrixResourceBase> {
+
+    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<VM> 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<VIF> 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java
----------------------------------------------------------------------
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 eff580a..289fff9 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() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRevertToVMSnapshotCommandWrapper.java
----------------------------------------------------------------------
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 0000000..a929132
--- /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<RevertToVMSnapshotCommand, Answer, CitrixResourceBase> {
+
+    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<VolumeObjectTO> 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<VM> 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<VBD> vbds = vm.getVBDs(conn);
+            final Map<String, VDI> vdiMap = new HashMap<String, VDI>();
+            // 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUnPlugNicCommandWrapper.java
----------------------------------------------------------------------
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 0000000..6250835
--- /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<UnPlugNicCommand, Answer, CitrixResourceBase> {
+
+    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<VM> 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixUpdateHostPasswordCommandWrapper.java
----------------------------------------------------------------------
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 0000000..f2f1fb5
--- /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<UpdateHostPasswordCommand, Answer, CitrixResourceBase> {
+
+    @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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/24bbfbc1/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapperTest.java
----------------------------------------------------------------------
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 8b8c9ce..72d5c1a 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<PhysicalNetworkSetupInfo> setupInfos = new ArrayList<PhysicalNetworkSetupInfo>();
+
+        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<PhysicalNetworkSetupInfo> setupInfos = new ArrayList<PhysicalNetworkSetupInfo>();
+        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<VolumeObjectTO> volumeTOs = new ArrayList<VolumeObjectTO>();
+
+        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<VolumeObjectTO> volumeTOs = new ArrayList<VolumeObjectTO>();
+
+        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<VolumeObjectTO> volumeTOs = new ArrayList<VolumeObjectTO>();
+
+        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 {


Mime
View raw message