You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2015/04/02 20:23:13 UTC

[32/39] git commit: updated refs/heads/master to 3e28747

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4600eef8/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 6ef756c..ee9fd2b 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
@@ -19,7 +19,6 @@ package com.cloud.hypervisor.xenserver.resource;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.MalformedURLException;
 import java.net.URI;
@@ -32,7 +31,6 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -61,87 +59,19 @@ import org.xml.sax.SAXException;
 
 import com.cloud.agent.IAgentControl;
 import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.AttachIsoCommand;
-import com.cloud.agent.api.AttachVolumeAnswer;
-import com.cloud.agent.api.AttachVolumeCommand;
-import com.cloud.agent.api.CheckHealthAnswer;
-import com.cloud.agent.api.CheckHealthCommand;
-import com.cloud.agent.api.CheckNetworkAnswer;
-import com.cloud.agent.api.CheckNetworkCommand;
-import com.cloud.agent.api.CheckOnHostAnswer;
-import com.cloud.agent.api.CheckOnHostCommand;
-import com.cloud.agent.api.CheckVirtualMachineAnswer;
-import com.cloud.agent.api.CheckVirtualMachineCommand;
-import com.cloud.agent.api.CleanupNetworkRulesCmd;
-import com.cloud.agent.api.ClusterVMMetaDataSyncAnswer;
-import com.cloud.agent.api.ClusterVMMetaDataSyncCommand;
 import com.cloud.agent.api.Command;
-import com.cloud.agent.api.CreateStoragePoolCommand;
-import com.cloud.agent.api.CreateVMSnapshotAnswer;
-import com.cloud.agent.api.CreateVMSnapshotCommand;
-import com.cloud.agent.api.DeleteStoragePoolCommand;
-import com.cloud.agent.api.DeleteVMSnapshotAnswer;
-import com.cloud.agent.api.DeleteVMSnapshotCommand;
-import com.cloud.agent.api.GetHostStatsAnswer;
 import com.cloud.agent.api.GetHostStatsCommand;
-import com.cloud.agent.api.GetStorageStatsAnswer;
-import com.cloud.agent.api.GetStorageStatsCommand;
-import com.cloud.agent.api.GetVmDiskStatsAnswer;
-import com.cloud.agent.api.GetVmDiskStatsCommand;
-import com.cloud.agent.api.GetVmStatsAnswer;
 import com.cloud.agent.api.GetVmStatsCommand;
-import com.cloud.agent.api.GetVncPortAnswer;
-import com.cloud.agent.api.GetVncPortCommand;
 import com.cloud.agent.api.HostStatsEntry;
 import com.cloud.agent.api.HostVmStateReportEntry;
-import com.cloud.agent.api.MaintainAnswer;
-import com.cloud.agent.api.MaintainCommand;
-import com.cloud.agent.api.MigrateAnswer;
-import com.cloud.agent.api.MigrateCommand;
-import com.cloud.agent.api.ModifySshKeysCommand;
-import com.cloud.agent.api.ModifyStoragePoolAnswer;
-import com.cloud.agent.api.ModifyStoragePoolCommand;
-import com.cloud.agent.api.NetworkRulesSystemVmCommand;
-import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand;
-import com.cloud.agent.api.OvsCreateGreTunnelAnswer;
-import com.cloud.agent.api.OvsCreateGreTunnelCommand;
-import com.cloud.agent.api.OvsCreateTunnelAnswer;
-import com.cloud.agent.api.OvsCreateTunnelCommand;
-import com.cloud.agent.api.OvsDeleteFlowCommand;
-import com.cloud.agent.api.OvsDestroyBridgeCommand;
-import com.cloud.agent.api.OvsDestroyTunnelCommand;
-import com.cloud.agent.api.OvsFetchInterfaceAnswer;
-import com.cloud.agent.api.OvsFetchInterfaceCommand;
 import com.cloud.agent.api.OvsSetTagAndFlowAnswer;
 import com.cloud.agent.api.OvsSetTagAndFlowCommand;
-import com.cloud.agent.api.OvsSetupBridgeCommand;
-import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
-import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
-import com.cloud.agent.api.PerformanceMonitorAnswer;
-import com.cloud.agent.api.PerformanceMonitorCommand;
 import com.cloud.agent.api.PingCommand;
 import com.cloud.agent.api.PingRoutingCommand;
 import com.cloud.agent.api.PingRoutingWithNwGroupsCommand;
 import com.cloud.agent.api.PingRoutingWithOvsCommand;
-import com.cloud.agent.api.PingTestCommand;
-import com.cloud.agent.api.PlugNicAnswer;
-import com.cloud.agent.api.PlugNicCommand;
-import com.cloud.agent.api.PrepareForMigrationAnswer;
-import com.cloud.agent.api.PrepareForMigrationCommand;
-import com.cloud.agent.api.PvlanSetupCommand;
-import com.cloud.agent.api.ReadyAnswer;
-import com.cloud.agent.api.ReadyCommand;
 import com.cloud.agent.api.RebootAnswer;
 import com.cloud.agent.api.RebootCommand;
-import com.cloud.agent.api.RebootRouterCommand;
-import com.cloud.agent.api.RevertToVMSnapshotAnswer;
-import com.cloud.agent.api.RevertToVMSnapshotCommand;
-import com.cloud.agent.api.ScaleVmAnswer;
-import com.cloud.agent.api.ScaleVmCommand;
-import com.cloud.agent.api.SecurityGroupRuleAnswer;
-import com.cloud.agent.api.SecurityGroupRulesCmd;
-import com.cloud.agent.api.SetupAnswer;
-import com.cloud.agent.api.SetupCommand;
 import com.cloud.agent.api.SetupGuestNetworkCommand;
 import com.cloud.agent.api.StartAnswer;
 import com.cloud.agent.api.StartCommand;
@@ -151,29 +81,13 @@ import com.cloud.agent.api.StartupStorageCommand;
 import com.cloud.agent.api.StopAnswer;
 import com.cloud.agent.api.StopCommand;
 import com.cloud.agent.api.StoragePoolInfo;
-import com.cloud.agent.api.UnPlugNicAnswer;
-import com.cloud.agent.api.UnPlugNicCommand;
-import com.cloud.agent.api.UpdateHostPasswordCommand;
-import com.cloud.agent.api.UpgradeSnapshotCommand;
 import com.cloud.agent.api.VgpuTypesInfo;
 import com.cloud.agent.api.VmStatsEntry;
-import com.cloud.agent.api.check.CheckSshAnswer;
-import com.cloud.agent.api.check.CheckSshCommand;
-import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
-import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
-import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
 import com.cloud.agent.api.routing.IpAssocCommand;
 import com.cloud.agent.api.routing.IpAssocVpcCommand;
 import com.cloud.agent.api.routing.NetworkElementCommand;
 import com.cloud.agent.api.routing.SetNetworkACLCommand;
 import com.cloud.agent.api.routing.SetSourceNatCommand;
-import com.cloud.agent.api.storage.CreateAnswer;
-import com.cloud.agent.api.storage.CreateCommand;
-import com.cloud.agent.api.storage.DestroyCommand;
-import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
-import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
-import com.cloud.agent.api.storage.ResizeVolumeAnswer;
-import com.cloud.agent.api.storage.ResizeVolumeCommand;
 import com.cloud.agent.api.to.DataStoreTO;
 import com.cloud.agent.api.to.DataTO;
 import com.cloud.agent.api.to.DiskTO;
@@ -181,9 +95,7 @@ import com.cloud.agent.api.to.GPUDeviceTO;
 import com.cloud.agent.api.to.IpAddressTO;
 import com.cloud.agent.api.to.NfsTO;
 import com.cloud.agent.api.to.NicTO;
-import com.cloud.agent.api.to.StorageFilerTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
-import com.cloud.agent.api.to.VolumeTO;
 import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer;
 import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource;
 import com.cloud.exception.InternalErrorException;
@@ -194,7 +106,6 @@ import com.cloud.network.Networks;
 import com.cloud.network.Networks.BroadcastDomainType;
 import com.cloud.network.Networks.IsolationType;
 import com.cloud.network.Networks.TrafficType;
-import com.cloud.network.PhysicalNetworkSetupInfo;
 import com.cloud.resource.ServerResource;
 import com.cloud.resource.hypervisor.HypervisorResource;
 import com.cloud.storage.Storage;
@@ -203,7 +114,6 @@ import com.cloud.storage.Volume;
 import com.cloud.storage.VolumeVO;
 import com.cloud.storage.resource.StorageSubsystemCommandHandler;
 import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
-import com.cloud.storage.template.TemplateProp;
 import com.cloud.template.VirtualMachineTemplate.BootloaderType;
 import com.cloud.utils.ExecutionResult;
 import com.cloud.utils.NumbersUtil;
@@ -215,10 +125,8 @@ import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.utils.ssh.SSHCmdHelper;
 import com.cloud.utils.ssh.SshHelper;
-import com.cloud.vm.DiskProfile;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.PowerState;
-import com.cloud.vm.snapshot.VMSnapshot;
 import com.trilead.ssh2.SCPClient;
 import com.xensource.xenapi.Bond;
 import com.xensource.xenapi.Connection;
@@ -260,57 +168,8 @@ import com.xensource.xenapi.XenAPIObject;
 @Local(value = ServerResource.class)
 public abstract class CitrixResourceBase implements ServerResource, HypervisorResource, VirtualRouterDeployer {
 
-    private static final Logger s_logger = Logger.getLogger(CitrixResourceBase.class);
-
-    static final Random Rand = new Random(System.currentTimeMillis());
-    protected static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance();
-
-    protected String _name;
-    protected String _username;
-    protected Queue<String> _password = new LinkedList<String>();
-    protected final int _retry = 100;
-    protected final int _sleep = 10000;
-    protected long _dcId;
-    protected String _pod;
-    protected String _cluster;
-    protected String _privateNetworkName;
-    protected String _linkLocalPrivateNetworkName;
-    protected String _publicNetworkName;
-    protected String _storageNetworkName1;
-    protected String _storageNetworkName2;
-    protected String _guestNetworkName;
-    protected int _wait;
-    protected int _migratewait;
-    protected String _instance; //instance name (default is usually "VM")
-    protected boolean _securityGroupEnabled;
-    protected IAgentControl _agentControl;
-
-    final int _maxWeight = 256;
-    protected int _heartbeatTimeout = 120;
-    protected int _heartbeatInterval = 60;
-    protected final XsHost _host = new XsHost();
-
-    // Guest and Host Performance Statistics
-    protected String _consolidationFunction = "AVERAGE";
-    protected int _pollingIntervalInSeconds = 60;
-
-    //Hypervisor specific params with generic value, may need to be overridden for specific versions
-    long _xsMemoryUsed = 128 * 1024 * 1024L; // xenserver hypervisor used 128 M
-    double _xsVirtualizationFactor = 63.0 / 64.0;  // 1 - virtualization overhead
-
-    //static min values for guests on xenserver
-    private static final long mem_128m = 134217728L;
-
-    protected boolean _canBridgeFirewall = false;
-    protected boolean _isOvs = false;
-    protected List<VIF> _tmpDom0Vif = new ArrayList<VIF>();
-    protected StorageSubsystemCommandHandler storageHandler;
-    protected int _maxNics = 7;
-
-    protected VirtualRoutingResource _vrResource;
-
     public enum SRType {
-        NFS, LVM, ISCSI, ISO, LVMOISCSI, LVMOHBA, EXT, FILE;
+        EXT, FILE, ISCSI, ISO, LVM, LVMOHBA, LVMOISCSI, NFS;
 
         String _str;
 
@@ -318,17 +177,24 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             _str = super.toString().toLowerCase();
         }
 
+        public boolean equals(final String type) {
+            return _str.equalsIgnoreCase(type);
+        }
+
         @Override
         public String toString() {
             return _str;
         }
-
-        public boolean equals(final String type) {
-            return _str.equalsIgnoreCase(type);
-        }
     }
 
+    protected static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance();
+    //static min values for guests on xenserver
+    private static final long mem_128m = 134217728L;
+
+    static final Random Rand = new Random(System.currentTimeMillis());
+    private static final Logger s_logger = Logger.getLogger(CitrixResourceBase.class);
     protected static final HashMap<VmPowerState, PowerState> s_powerStatesTable;
+
     static {
         s_powerStatesTable = new HashMap<VmPowerState, PowerState>();
         s_powerStatesTable.put(VmPowerState.HALTED, PowerState.PowerOff);
@@ -338,44 +204,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         s_powerStatesTable.put(VmPowerState.UNRECOGNIZED, PowerState.PowerUnknown);
     }
 
-    public XsHost getHost() {
-        return _host;
-    }
-
-    public String getVMInstanceName() {
-        return _instance;
-    }
-
-    public void addToPwdQueue(final String password) {
-        _password.add(password);
-    }
-
-    public VirtualRoutingResource getVirtualRoutingResource() {
-        return _vrResource;
-    }
-
-    public boolean isOvs() {
-        return _isOvs;
-    }
-
-    public void setIsOvs(final boolean isOvs) {
-        _isOvs = isOvs;
-    }
-
-    public boolean isSecurityGroupEnabled() {
-        return _securityGroupEnabled;
-    }
-
-    public void setCanBridgeFirewall(final boolean canBridgeFirewall) {
-        _canBridgeFirewall = canBridgeFirewall;
-    }
-
-    public boolean canBridgeFirewall() {
-        return _canBridgeFirewall;
-    }
-
-    public boolean canBridgeFirewall(final Connection conn) {
-        return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.getUuid(), "instance", _instance));
+    private static PowerState convertToPowerState(final VmPowerState ps) {
+        final PowerState powerState = s_powerStatesTable.get(ps);
+        return powerState == null ?  PowerState.PowerUnknown : powerState;
     }
 
     private static boolean isAlienVm(final VM vm, final Connection conn) throws XenAPIException, XmlRpcException {
@@ -388,184 +219,89 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return true;
     }
 
-    public boolean cleanupHaltedVms(final Connection conn) throws XenAPIException, XmlRpcException {
-        final Host host = Host.getByUuid(conn, _host.getUuid());
-        final Map<VM, VM.Record> vms = VM.getAllRecords(conn);
-        boolean success = true;
-        if(vms != null && !vms.isEmpty()) {
-            for (final Map.Entry<VM, VM.Record> entry : vms.entrySet()) {
-                final VM vm = entry.getKey();
-                final VM.Record vmRec = entry.getValue();
-                if (vmRec.isATemplate || vmRec.isControlDomain) {
-                    continue;
-                }
-
-                if (VmPowerState.HALTED.equals(vmRec.powerState) && vmRec.affinity.equals(host) && !isAlienVm(vm, conn)) {
-                    try {
-                        vm.destroy(conn);
-                    } catch (final Exception e) {
-                        s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to ", e);
-                        success = false;
-                    }
-                }
-            }
-        }
-        return success;
-    }
-
-    public boolean isRefNull(final XenAPIObject object) {
-        return object == null || object.toWireString().equals("OpaqueRef:NULL") || object.toWireString().equals("<not in database>");
-    }
+    protected IAgentControl _agentControl;
+    protected boolean _canBridgeFirewall = false;
+    protected String _cluster;
+    // Guest and Host Performance Statistics
+    protected String _consolidationFunction = "AVERAGE";
+    protected long _dcId;
+    protected String _guestNetworkName;
+    protected int _heartbeatInterval = 60;
+    protected int _heartbeatTimeout = 120;
+    protected final XsHost _host = new XsHost();
+    protected String _instance; //instance name (default is usually "VM")
+    protected boolean _isOvs = false;
+    protected String _linkLocalPrivateNetworkName;
+    protected int _maxNics = 7;
 
-    @Override
-    public void disconnected() {
-    }
+    final int _maxWeight = 256;
+    protected int _migratewait;
+    protected String _name;
+    protected Queue<String> _password = new LinkedList<String>();
 
-    protected boolean pingdomr(final Connection conn, final String host, final String port) {
-        String status;
-        status = callHostPlugin(conn, "vmops", "pingdomr", "host", host, "port", port);
+    protected String _pod;
+    protected int _pollingIntervalInSeconds = 60;
 
-        if (status == null || status.isEmpty()) {
-            return false;
-        }
+    protected String _privateNetworkName;
+    protected String _publicNetworkName;
 
-        return true;
+    protected final int _retry = 100;
 
-    }
+    protected boolean _securityGroupEnabled;
+    protected final int _sleep = 10000;
+    protected String _storageNetworkName1;
+    protected String _storageNetworkName2;
+    protected List<VIF> _tmpDom0Vif = new ArrayList<VIF>();
 
-    public boolean pingXAPI() {
-        final Connection conn = getConnection();
-        try {
-            final Host host = Host.getByUuid(conn, _host.getUuid());
-            if( !host.getEnabled(conn) ) {
-                s_logger.debug("Host " + _host.getIp() + " is not enabled!");
-                return false;
-            }
-        } catch (final Exception e) {
-            s_logger.debug("cannot get host enabled status, host " + _host.getIp() + " due to " + e.toString(),  e);
-            return false;
-        }
-        try {
-            callHostPlugin(conn, "echo", "main");
-        } catch (final Exception e) {
-            s_logger.debug("cannot ping host " + _host.getIp() + " due to " + e.toString(),  e);
-            return false;
-        }
-        return true;
-    }
+    protected String _username;
 
+    protected VirtualRoutingResource _vrResource;
 
-    protected String logX(final XenAPIObject obj, final String msg) {
-        return new StringBuilder("Host ").append(_host.getIp()).append(" ").append(obj.toWireString()).append(": ").append(msg).toString();
-    }
+    protected int _wait;
+    //Hypervisor specific params with generic value, may need to be overridden for specific versions
+    long _xsMemoryUsed = 128 * 1024 * 1024L; // xenserver hypervisor used 128 M
 
-    @Override
-    public Answer executeRequest(final Command cmd) {
+    double _xsVirtualizationFactor = 63.0 / 64.0;  // 1 - virtualization overhead
 
-        // We need this one because the StorageSubSystemCommand is from another hierarchy.
-        if (cmd instanceof StorageSubSystemCommand) {
-            return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd);
-        }
+    protected StorageSubsystemCommandHandler storageHandler;
 
-        final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance();
-        try {
-            return wrapper.execute(cmd, this);
-        } catch (final Exception e) {
-            return Answer.createUnsupportedCommandAnswer(cmd);
-        }
+    public CitrixResourceBase() {
     }
 
-    @Override
-    public ExecutionResult executeInVR(final String routerIP, final String script, final String args, final int timeout) {
-        Pair<Boolean, String> result;
-        String cmdline = "/opt/cloud/bin/router_proxy.sh " + script + " " + routerIP + " " + args;
-        // semicolon need to be escape for bash
-        cmdline = cmdline.replaceAll(";", "\\\\;");
-        try {
-            s_logger.debug("Executing command in VR: " + cmdline);
-            result = SshHelper.sshExecute(_host.getIp(), 22, _username, null, _password.peek(), cmdline,
-                    60000, 60000, timeout * 1000);
-        } catch (final Exception e) {
-            return new ExecutionResult(false, e.getMessage());
-        }
-        return new ExecutionResult(result.first(), result.second());
+    public void addToPwdQueue(final String password) {
+        _password.add(password);
     }
 
-    @Override
-    public ExecutionResult executeInVR(final String routerIP, final String script, final String args) {
-        // Timeout is 120 seconds by default
-        return executeInVR(routerIP, script, args, 120);
+    protected StorageSubsystemCommandHandler buildStorageHandler() {
+        final XenServerStorageProcessor processor = new XenServerStorageProcessor(this);
+        return new StorageSubsystemCommandHandlerBase(processor);
     }
 
-    @Override
-    public ExecutionResult createFileInVR(final String routerIp, final String path, final String filename, final String content) {
-        final Connection conn = getConnection();
-        final String hostPath = "/tmp/";
-
-        s_logger.debug("Copying VR with ip " + routerIp +" config file into host "+ _host.getIp() );
+    public String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) {
+        final Map<String, String> args = new HashMap<String, String>();
+        String msg;
         try {
-            SshHelper.scpTo(_host.getIp(), 22, _username, null, _password.peek(), hostPath, content.getBytes(Charset.defaultCharset()), filename, null);
-        } catch (final Exception e) {
-            s_logger.warn("scp VR config file into host " + _host.getIp() + " failed with exception " + e.getMessage().toString());
-        }
+            for (int i = 0; i < params.length; i += 2) {
+                args.put(params[i], params[i + 1]);
+            }
 
-        final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path);
-        s_logger.debug ("VR Config file " + filename + " got created in VR, ip " + routerIp + " with content \n" + content);
-
-        return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5));
-    }
-
-    @Override
-    public ExecutionResult prepareCommand(final NetworkElementCommand cmd) {
-        //Update IP used to access router
-        cmd.setRouterAccessIp(cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP));
-        assert cmd.getRouterAccessIp() != null;
-
-        if (cmd instanceof IpAssocVpcCommand) {
-            return prepareNetworkElementCommand((IpAssocVpcCommand)cmd);
-        } else if (cmd instanceof IpAssocCommand) {
-            return prepareNetworkElementCommand((IpAssocCommand)cmd);
-        } else if (cmd instanceof SetupGuestNetworkCommand) {
-            return prepareNetworkElementCommand((SetupGuestNetworkCommand)cmd);
-        } else if (cmd instanceof SetSourceNatCommand) {
-            return prepareNetworkElementCommand((SetSourceNatCommand)cmd);
-        } else if (cmd instanceof SetNetworkACLCommand) {
-            return prepareNetworkElementCommand((SetNetworkACLCommand)cmd);
-        }
-        return new ExecutionResult(true, null);
-    }
-
-    @Override
-    public ExecutionResult cleanupCommand(final NetworkElementCommand cmd) {
-        if (cmd instanceof IpAssocCommand && !(cmd instanceof IpAssocVpcCommand)) {
-            return cleanupNetworkElementCommand((IpAssocCommand)cmd);
-        }
-        return new ExecutionResult(true, null);
-    }
-
-    private Answer execute(final PerformanceMonitorCommand cmd) {
-        final Connection conn = getConnection();
-        final String perfMon = getPerfMon(conn, cmd.getParams(), cmd.getWait());
-        if (perfMon == null) {
-            return new PerformanceMonitorAnswer(cmd, false, perfMon);
-        } else {
-            return new PerformanceMonitorAnswer(cmd, true, perfMon);
-        }
-    }
-
-    public String getPerfMon(final Connection conn, final Map<String, String> params,
-            final int wait) {
-        String result = null;
-        try {
-            result = callHostPluginAsync(conn, "vmopspremium", "asmonitor", 60,
-                    params);
-            if (result != null) {
-                return result;
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args));
             }
-        } catch (final Exception e) {
-            s_logger.error("Can not get performance monitor for AS due to ", e);
+            final Host host = Host.getByUuid(conn, _host.getUuid());
+            final String result = host.callPlugin(conn, plugin, cmd, args);
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("callHostPlugin Result: " + result);
+            }
+            return result.replace("\n", "");
+        } catch (final XenAPIException e) {
+            msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString();
+            s_logger.warn(msg);
+        } catch (final XmlRpcException e) {
+            msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage();
+            s_logger.debug(msg);
         }
-        return null;
+        throw new CloudRuntimeException(msg);
     }
 
     protected String callHostPluginAsync(final Connection conn, final String plugin,
@@ -614,866 +350,662 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return null;
     }
 
-    public void scaleVM(final Connection conn, final VM vm, final VirtualMachineTO vmSpec, final Host host) throws XenAPIException, XmlRpcException {
-
-        final Long staticMemoryMax = vm.getMemoryStaticMax(conn);
-        final Long staticMemoryMin = vm.getMemoryStaticMin(conn);
-        final Long newDynamicMemoryMin = vmSpec.getMinRam();
-        final Long newDynamicMemoryMax = vmSpec.getMaxRam();
-        if (staticMemoryMin > newDynamicMemoryMin || newDynamicMemoryMax > staticMemoryMax) {
-            throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: " + "0 <= memory-static-min(" + staticMemoryMin +
-                    ") <= memory-dynamic-min(" + newDynamicMemoryMin + ") <= memory-dynamic-max(" + newDynamicMemoryMax + ") <= memory-static-max(" + staticMemoryMax + ")");
-        }
-
-        vm.setMemoryDynamicRange(conn, newDynamicMemoryMin, newDynamicMemoryMax);
-        vm.setVCPUsNumberLive(conn, (long)vmSpec.getCpus());
-
-        final Integer speed = vmSpec.getMinSpeed();
-        if (speed != null) {
-
-            int cpuWeight = _maxWeight; //cpu_weight
-
-            // weight based allocation
-
-            cpuWeight = (int)(speed * 0.99 / _host.getSpeed() * _maxWeight);
-            if (cpuWeight > _maxWeight) {
-                cpuWeight = _maxWeight;
-            }
-
-            if (vmSpec.getLimitCpuUse()) {
-                long utilization = 0; // max CPU cap, default is unlimited
-                utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100);
-                //vm.addToVCPUsParamsLive(conn, "cap", Long.toString(utilization)); currently xenserver doesnot support Xapi to add VCPUs params live.
-                callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", Long.toString(utilization), "vmname", vmSpec.getName());
-            }
-            //vm.addToVCPUsParamsLive(conn, "weight", Integer.toString(cpuWeight));
-            callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", Integer.toString(cpuWeight), "vmname", vmSpec.getName());
-        }
-    }
-
-    public ScaleVmAnswer execute(final ScaleVmCommand cmd) {
-        final VirtualMachineTO vmSpec = cmd.getVirtualMachine();
-        final String vmName = vmSpec.getName();
+    protected String callHostPluginAsync(final Connection conn, final String plugin, final String cmd, final int wait, final String... params) {
+        final int timeout = wait * 1000;
+        final Map<String, String> args = new HashMap<String, String>();
+        Task task = null;
         try {
-            final Connection conn = getConnection();
-            final Set<VM> vms = VM.getByNameLabel(conn, vmName);
-            final Host host = Host.getByUuid(conn, _host.getUuid());
-
-            // If DMC is not enable then don't execute this command.
-            if (!isDmcEnabled(conn, host)) {
-                throw new CloudRuntimeException("Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.getUuid() +
-                        " ,check your license and hypervisor version.");
+            for (int i = 0; i < params.length; i += 2) {
+                args.put(params[i], params[i + 1]);
             }
-
-            // stop vm which is running on this host or is in halted state
-            final Iterator<VM> iter = vms.iterator();
-            while (iter.hasNext()) {
-                final VM vm = iter.next();
-                final VM.Record vmr = vm.getRecord(conn);
-
-                if (vmr.powerState == VmPowerState.HALTED ||
-                        vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.getUuid())) {
-                    iter.remove();
-                }
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args));
             }
-
-            if (vms.size() == 0) {
-                s_logger.info("No running VM " + vmName + " exists on XenServer" + _host.getUuid());
-                return new ScaleVmAnswer(cmd, false, "VM does not exist");
+            final Host host = Host.getByUuid(conn, _host.getUuid());
+            task = host.callPluginAsync(conn, plugin, cmd, args);
+            // poll every 1 seconds
+            waitForTask(conn, task, 1000, timeout);
+            checkForSuccess(conn, task);
+            final String result = task.getResult(conn);
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("callHostPlugin Result: " + result);
             }
-
-            for (final VM vm : vms) {
-                vm.getRecord(conn);
+            return result.replace("<value>", "").replace("</value>", "").replace("\n", "");
+        } catch (final Types.HandleInvalid e) {
+            s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" +
+                    e.handle);
+        } catch (final XenAPIException e) {
+            s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e);
+        } catch (final Exception e) {
+            s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(), e);
+        } finally {
+            if (task != null) {
                 try {
-                    scaleVM(conn, vm, vmSpec, host);
-                } catch (final Exception e) {
-                    final String msg = "Catch exception " + e.getClass().getName() + " when scaling VM:" + vmName + " due to " + e.toString();
-                    s_logger.debug(msg);
-                    return new ScaleVmAnswer(cmd, false, msg);
+                    task.destroy(conn);
+                } catch (final Exception e1) {
+                    s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e1.toString());
                 }
-
             }
-            final String msg = "scaling VM " + vmName + " is successful on host " + host;
-            s_logger.debug(msg);
-            return new ScaleVmAnswer(cmd, true, msg);
-
-        } catch (final XenAPIException e) {
-            final String msg = "Upgrade Vm " + vmName + " fail due to " + e.toString();
-            s_logger.warn(msg, e);
-            return new ScaleVmAnswer(cmd, false, msg);
-        } catch (final XmlRpcException e) {
-            final String msg = "Upgrade Vm " + vmName + " fail due to " + e.getMessage();
-            s_logger.warn(msg, e);
-            return new ScaleVmAnswer(cmd, false, msg);
-        } catch (final Exception e) {
-            final String msg = "Unable to upgrade " + vmName + " due to " + e.getMessage();
-            s_logger.warn(msg, e);
-            return new ScaleVmAnswer(cmd, false, msg);
         }
+        return null;
     }
 
-    private Answer execute(final RevertToVMSnapshotCommand cmd) {
-        final String vmName = cmd.getVmName();
-        final List<VolumeObjectTO> listVolumeTo = cmd.getVolumeTOs();
-        final VMSnapshot.Type vmSnapshotType = cmd.getTarget().getType();
-        final Boolean snapshotMemory = vmSnapshotType == VMSnapshot.Type.DiskAndMemory;
-        final Connection conn = getConnection();
-        PowerState vmState = null;
-        VM vm = null;
-        try {
-
-            final Set<VM> vmSnapshots = VM.getByNameLabel(conn, cmd.getTarget().getSnapshotName());
-            if (vmSnapshots.size() == 0) {
-                return new RevertToVMSnapshotAnswer(cmd, false, "Cannot find vmSnapshot with name: " + cmd.getTarget().getSnapshotName());
-            }
-
-            final VM vmSnapshot = vmSnapshots.iterator().next();
+    public String callHostPluginPremium(final Connection conn, final String cmd, final String... params) {
+        return callHostPlugin(conn, "vmopspremium", cmd, params);
+    }
 
-            // find target VM or creating a work VM
-            try {
-                vm = getVM(conn, vmName);
-            } catch (final Exception e) {
-                vm = createWorkingVM(conn, vmName, cmd.getGuestOSType(), cmd.getPlatformEmulator(), listVolumeTo);
-            }
+    protected String callHostPluginThroughMaster(final Connection conn, final String plugin, final String cmd, final String... params) {
+        final Map<String, String> args = new HashMap<String, String>();
 
-            if (vm == null) {
-                return new RevertToVMSnapshotAnswer(cmd, false, "Revert to VM Snapshot Failed due to can not find vm: " + vmName);
+        try {
+            final Map<Pool, Pool.Record> poolRecs = Pool.getAllRecords(conn);
+            if (poolRecs.size() != 1) {
+                throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.getUuid());
             }
-
-            // call plugin to execute revert
-            revertToSnapshot(conn, vmSnapshot, vmName, vm.getUuid(conn), snapshotMemory, _host.getUuid());
-            vm = 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);
-                }
+            final Host master = poolRecs.values().iterator().next().master;
+            for (int i = 0; i < params.length; i += 2) {
+                args.put(params[i], params[i + 1]);
             }
 
-            if (!snapshotMemory) {
-                vm.destroy(conn);
-                vmState = PowerState.PowerOff;
-            } else {
-                vmState = PowerState.PowerOn;
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args));
             }
-
-            // 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));
+            final String result = master.callPlugin(conn, plugin, cmd, args);
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("callHostPlugin Result: " + result);
             }
-
-            return new RevertToVMSnapshotAnswer(cmd, listVolumeTo, vmState);
-        } catch (final Exception e) {
-            s_logger.error("revert vm " + vmName + " to snapshot " + cmd.getTarget().getSnapshotName() + " failed due to " + e.getMessage());
-            return new RevertToVMSnapshotAnswer(cmd, false, e.getMessage());
+            return result.replace("\n", "");
+        } catch (final Types.HandleInvalid e) {
+            s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" +
+                    e.handle);
+        } catch (final XenAPIException e) {
+            s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e);
+        } catch (final XmlRpcException e) {
+            s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(), e);
         }
+        return null;
     }
 
-    public String revertToSnapshot(final Connection conn, final VM vmSnapshot, final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) throws XenAPIException,
-    XmlRpcException {
+    public boolean canBridgeFirewall() {
+        return _canBridgeFirewall;
+    }
 
-        final String results =
-                callHostPluginAsync(conn, "vmopsSnapshot", "revert_memory_snapshot", 10 * 60 * 1000, "snapshotUUID", vmSnapshot.getUuid(conn), "vmName", vmName, "oldVmUuid",
-                        oldVmUuid, "snapshotMemory", snapshotMemory.toString(), "hostUUID", hostUUID);
-        String errMsg = null;
-        if (results == null || results.isEmpty()) {
-            errMsg = "revert_memory_snapshot return null";
-        } else {
-            if (results.equals("0")) {
-                return results;
-            } else {
-                errMsg = "revert_memory_snapshot exception";
-            }
-        }
-        s_logger.warn(errMsg);
-        throw new CloudRuntimeException(errMsg);
+    public boolean canBridgeFirewall(final Connection conn) {
+        return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.getUuid(), "instance", _instance));
     }
 
-    public XsLocalNetwork getNativeNetworkForTraffic(final Connection conn, final TrafficType type, final String name) throws XenAPIException, XmlRpcException {
-        if (name != null) {
-            if (s_logger.isDebugEnabled()) {
-                s_logger.debug("Looking for network named " + name);
+    public void checkForSuccess(final Connection c, final Task task) throws XenAPIException, XmlRpcException {
+        if (task.getStatus(c) == Types.TaskStatusType.SUCCESS) {
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") completed");
             }
-            return getNetworkByName(conn, name);
-        }
-
-        if (type == TrafficType.Guest) {
-            return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getGuestNetwork()), null, PIF.getByUuid(conn, _host.getGuestPif()), null);
-        } else if (type == TrafficType.Control) {
-            setupLinkLocalNetwork(conn);
-            return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getLinkLocalNetwork()));
-        } else if (type == TrafficType.Management) {
-            return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPrivateNetwork()), null, PIF.getByUuid(conn, _host.getPrivatePif()), null);
-        } else if (type == TrafficType.Public) {
-            return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getPublicNetwork()), null, PIF.getByUuid(conn, _host.getPublicPif()), null);
-        } else if (type == TrafficType.Storage) {
-            /*   TrafficType.Storage is for secondary storage, while storageNetwork1 is for primary storage, we need better name here */
-            return new XsLocalNetwork(this, Network.getByUuid(conn, _host.getStorageNetwork1()), null, PIF.getByUuid(conn, _host.getStoragePif1()), null);
+            return;
+        } else {
+            final String msg = "Task failed! Task record: " + task.getRecord(c);
+            s_logger.warn(msg);
+            task.cancel(c);
+            task.destroy(c);
+            throw new Types.BadAsyncResult(msg);
         }
-
-        throw new CloudRuntimeException("Unsupported network type: " + type);
     }
 
-    public synchronized Network setupvSwitchNetwork(final Connection conn) {
+    protected boolean checkSR(final Connection conn, final SR sr) {
         try {
-            if (_host.getVswitchNetwork() == null) {
-                Network vswitchNw = null;
-                final Network.Record rec = new Network.Record();
-                final String nwName = Networks.BroadcastScheme.VSwitch.toString();
-                final Set<Network> networks = Network.getByNameLabel(conn, nwName);
-
-                if (networks.size() == 0) {
-                    rec.nameDescription = "vswitch network for " + nwName;
-                    rec.nameLabel = nwName;
-                    vswitchNw = Network.create(conn, rec);
-                } else {
-                    vswitchNw = networks.iterator().next();
-                }
-                _host.setVswitchNetwork(vswitchNw);
+            final SR.Record srr = sr.getRecord(conn);
+            final Set<PBD> pbds = sr.getPBDs(conn);
+            if (pbds.size() == 0) {
+                final String msg = "There is no PBDs for this SR: " + srr.nameLabel + " on host:" + _host.getUuid();
+                s_logger.warn(msg);
+                return false;
             }
-            return _host.getVswitchNetwork();
-        } catch (final BadServerResponse e) {
-            s_logger.error("Failed to setup vswitch network", e);
-        } catch (final XenAPIException e) {
-            s_logger.error("Failed to setup vswitch network", e);
-        } catch (final XmlRpcException e) {
-            s_logger.error("Failed to setup vswitch network", e);
-        }
-
-        return null;
-    }
-
-    /**
-     * This method just creates a XenServer network following the tunnel network naming convention
-     */
-    public synchronized Network findOrCreateTunnelNetwork(final Connection conn, final String nwName) {
-        try {
-            Network nw = null;
-            final Network.Record rec = new Network.Record();
-            final Set<Network> networks = Network.getByNameLabel(conn, nwName);
-
-            if (networks.size() == 0) {
-                rec.nameDescription = "tunnel network id# " + nwName;
-                rec.nameLabel = nwName;
-                //Initialize the ovs-host-setup to avoid error when doing get-param in plugin
-                final Map<String, String> otherConfig = new HashMap<String, String>();
-                otherConfig.put("ovs-host-setup", "");
-                // Mark 'internal network' as shared so bridge gets automatically created on each host in the cluster
-                // when VM with vif connected to this internal network is started
-                otherConfig.put("assume_network_is_shared", "true");
-                rec.otherConfig = otherConfig;
-                nw = Network.create(conn, rec);
-                s_logger.debug("### XenServer network for tunnels created:" + nwName);
-            } else {
-                nw = networks.iterator().next();
-                s_logger.debug("XenServer network for tunnels found:" + nwName);
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("Checking " + srr.nameLabel + " or SR " + srr.uuid + " on " + _host);
             }
-            return nw;
-        } catch (final Exception e) {
-            s_logger.warn("createTunnelNetwork failed", e);
-            return null;
-        }
-    }
+            if (srr.shared) {
+                if (SRType.NFS.equals(srr.type) ){
+                    final Map<String, String> smConfig = srr.smConfig;
+                    if( !smConfig.containsKey("nosubdir")) {
+                        smConfig.put("nosubdir", "true");
+                        sr.setSmConfig(conn,smConfig);
+                    }
+                }
 
-    /**
-     * This method creates a XenServer network and configures it for being used as a L2-in-L3 tunneled network
-     */
-    public synchronized Network configureTunnelNetwork(final Connection conn, final Long networkId, final long hostId, final String bridgeName) {
-        try {
-            final Network nw = findOrCreateTunnelNetwork(conn, bridgeName);
-            final String nwName = bridgeName;
-            //Invoke plugin to setup the bridge which will be used by this network
-            final String bridge = nw.getBridge(conn);
-            final Map<String, String> nwOtherConfig = nw.getOtherConfig(conn);
-            final String configuredHosts = nwOtherConfig.get("ovs-host-setup");
-            boolean configured = false;
-            if (configuredHosts != null) {
-                final String hostIdsStr[] = configuredHosts.split(",");
-                for (final String hostIdStr : hostIdsStr) {
-                    if (hostIdStr.equals(((Long)hostId).toString())) {
-                        configured = true;
+                final Host host = Host.getByUuid(conn, _host.getUuid());
+                boolean found = false;
+                for (final PBD pbd : pbds) {
+                    final PBD.Record pbdr = pbd.getRecord(conn);
+                    if (host.equals(pbdr.host)) {
+                        if (!pbdr.currentlyAttached) {
+                            pbdPlug(conn, pbd, pbdr.uuid);
+                        }
+                        found = true;
                         break;
                     }
                 }
-            }
-
-            if (!configured) {
-                String result;
-                if (bridgeName.startsWith("OVS-DR-VPC-Bridge")) {
-                    result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge,
-                            "key", bridgeName,
-                            "xs_nw_uuid", nw.getUuid(conn),
-                            "cs_host_id", ((Long)hostId).toString());
-                } else {
-                    result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge,
-                            "key", bridgeName,
-                            "xs_nw_uuid", nw.getUuid(conn),
-                            "cs_host_id", ((Long)hostId).toString());
+                if (!found) {
+                    final PBD.Record pbdr = srr.PBDs.iterator().next().getRecord(conn);
+                    pbdr.host = host;
+                    pbdr.uuid = "";
+                    final PBD pbd = PBD.create(conn, pbdr);
+                    pbdPlug(conn, pbd, pbd.getUuid(conn));
                 }
-
-                //Note down the fact that the ovs bridge has been setup
-                final String[] res = result.split(":");
-                if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
-                    //TODO: Should make this error not fatal?
-                    throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge );
+            } else {
+                for (final PBD pbd : pbds) {
+                    final PBD.Record pbdr = pbd.getRecord(conn);
+                    if (!pbdr.currentlyAttached) {
+                        pbdPlug(conn, pbd, pbdr.uuid);
+                    }
                 }
             }
-            return nw;
-        } catch (final Exception e) {
-            s_logger.warn("createandConfigureTunnelNetwork failed", e);
-            return null;
-        }
-    }
 
-    public synchronized void destroyTunnelNetwork(final Connection conn, final Network nw, final long hostId) {
-        try {
-            final String bridge = nw.getBridge(conn);
-            final String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge,
-                    "cs_host_id", ((Long)hostId).toString());
-            final String[] res = result.split(":");
-            if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
-                //TODO: Should make this error not fatal?
-                //Can Concurrent VM shutdown/migration/reboot events can cause this method
-                //to be executed on a bridge which has already been removed?
-                throw new CloudRuntimeException("Unable to remove OVS bridge " + bridge + ":" + result);
-            }
-            return;
         } catch (final Exception e) {
-            s_logger.warn("destroyTunnelNetwork failed:", e);
-            return;
+            final String msg = "checkSR failed host:" + _host + " due to " + e.toString();
+            s_logger.warn(msg, e);
+            return false;
         }
+        return true;
     }
 
-    public Network getNetwork(final Connection conn, final NicTO nic) throws XenAPIException, XmlRpcException {
-        final String name = nic.getName();
-        final XsLocalNetwork network = getNativeNetworkForTraffic(conn, nic.getType(), name);
-        if (network == null) {
-            s_logger.error("Network is not configured on the backend for nic " + nic.toString());
-            throw new CloudRuntimeException("Network for the backend is not configured correctly for network broadcast domain: " + nic.getBroadcastUri());
+    private void CheckXenHostInfo() throws ConfigurationException {
+        final Connection conn = ConnPool.getConnect(_host.getIp(), _username, _password);
+        if( conn == null ) {
+            throw new ConfigurationException("Can not create connection to " + _host.getIp());
         }
-        final URI uri = nic.getBroadcastUri();
-        final BroadcastDomainType type = nic.getBroadcastType();
-        if (uri != null && uri.toString().contains("untagged")) {
-            return network.getNetwork();
-        } else if (uri != null && type == BroadcastDomainType.Vlan) {
-            assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Vlan;
-            final long vlan = Long.parseLong(BroadcastDomainType.getValue(uri));
-            return enableVlanNetwork(conn, vlan, network);
-        } else if (type == BroadcastDomainType.Native || type == BroadcastDomainType.LinkLocal ||
-                type == BroadcastDomainType.Vsp) {
-            return network.getNetwork();
-        } else if (uri != null && type == BroadcastDomainType.Vswitch) {
-            final String header = uri.toString().substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length());
-            if (header.startsWith("vlan")) {
-                _isOvs = true;
-                return setupvSwitchNetwork(conn);
-            } else {
-                return findOrCreateTunnelNetwork(conn, getOvsTunnelNetworkName(uri.getAuthority()));
+        try {
+            Host.Record hostRec = null;
+            try {
+                final Host host = Host.getByUuid(conn, _host.getUuid());
+                hostRec = host.getRecord(conn);
+                final Pool.Record poolRec = Pool.getAllRecords(conn).values().iterator().next();
+                _host.setPool(poolRec.uuid);
+
+            } catch (final Exception e) {
+                throw new ConfigurationException("Can not get host information from " + _host.getIp());
             }
-        } else if (type == BroadcastDomainType.Storage) {
-            if (uri == null) {
-                return network.getNetwork();
-            } else {
-                final long vlan = Long.parseLong(BroadcastDomainType.getValue(uri));
-                return enableVlanNetwork(conn, vlan, network);
+            if (!hostRec.address.equals(_host.getIp())) {
+                final String msg = "Host " + _host.getIp() + " seems be reinstalled, please remove this host and readd";
+                s_logger.error(msg);
+                throw new ConfigurationException(msg);
             }
-        } else if (type == BroadcastDomainType.Lswitch) {
-            // Nicira Logical Switch
-            return network.getNetwork();
-        } else if (uri != null && type == BroadcastDomainType.Pvlan) {
-            assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Pvlan;
-            // should we consider moving this NetUtils method to BroadcastDomainType?
-            final long vlan = Long.parseLong(NetUtils.getPrimaryPvlanFromUri(uri));
-            return enableVlanNetwork(conn, vlan, network);
-        }
-
-        throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri());
-    }
-
-    private String getOvsTunnelNetworkName(final String broadcastUri) {
-        if (broadcastUri.contains(".")) {
-            final String[] parts = broadcastUri.split("\\.");
-            return "OVS-DR-VPC-Bridge"+parts[0];
-        } else {
+        } finally {
             try {
-                return "OVSTunnel" + broadcastUri;
+                Session.logout(conn);
             } catch (final Exception e) {
-                return null;
             }
         }
     }
 
-    public VIF createVif(final Connection conn, final String vmName, final VM vm, final VirtualMachineTO vmSpec, final NicTO nic) throws XmlRpcException, XenAPIException {
-        assert nic.getUuid() != null : "Nic should have a uuid value";
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Creating VIF for " + vmName + " on nic " + nic);
-        }
-        VIF.Record vifr = new VIF.Record();
-        vifr.VM = vm;
-        vifr.device = Integer.toString(nic.getDeviceId());
-        vifr.MAC = nic.getMac();
-
-        // Nicira needs these IDs to find the NIC
-        vifr.otherConfig = new HashMap<String, String>();
-        vifr.otherConfig.put("nicira-iface-id", nic.getUuid());
-        vifr.otherConfig.put("nicira-vm-id", vm.getUuid(conn));
-        // Provide XAPI with the cloudstack vm and nic uids.
-        vifr.otherConfig.put("cloudstack-nic-id", nic.getUuid());
-        if (vmSpec != null) {
-            vifr.otherConfig.put("cloudstack-vm-id", vmSpec.getUuid());
+    @Override
+    public ExecutionResult cleanupCommand(final NetworkElementCommand cmd) {
+        if (cmd instanceof IpAssocCommand && !(cmd instanceof IpAssocVpcCommand)) {
+            return cleanupNetworkElementCommand((IpAssocCommand)cmd);
         }
+        return new ExecutionResult(true, null);
+    }
 
-        // OVS plugin looks at network UUID in the vif 'otherconfig' details to group VIF's & tunnel ports as part of tier
-        // when bridge is setup for distributed routing
-        vifr.otherConfig.put("cloudstack-network-id", nic.getNetworkUuid());
 
-        // Nuage Vsp needs Virtual Router IP to be passed in the otherconfig
-        // get the virtual router IP information from broadcast uri
-        final URI broadcastUri = nic.getBroadcastUri();
-        if (broadcastUri != null && broadcastUri.getScheme().equalsIgnoreCase(Networks.BroadcastDomainType.Vsp.scheme())) {
-            final String path = broadcastUri.getPath();
-            vifr.otherConfig.put("vsp-vr-ip", path.substring(1));
-        }
-        vifr.network = getNetwork(conn, nic);
-
-        if (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) {
-            vifr.qosAlgorithmType = "ratelimit";
-            vifr.qosAlgorithmParams = new HashMap<String, String>();
-            // convert mbs to kilobyte per second
-            vifr.qosAlgorithmParams.put("kbps", Integer.toString(nic.getNetworkRateMbps() * 128));
-        }
+    public boolean cleanupHaltedVms(final Connection conn) throws XenAPIException, XmlRpcException {
+        final Host host = Host.getByUuid(conn, _host.getUuid());
+        final Map<VM, VM.Record> vms = VM.getAllRecords(conn);
+        boolean success = true;
+        if(vms != null && !vms.isEmpty()) {
+            for (final Map.Entry<VM, VM.Record> entry : vms.entrySet()) {
+                final VM vm = entry.getKey();
+                final VM.Record vmRec = entry.getValue();
+                if (vmRec.isATemplate || vmRec.isControlDomain) {
+                    continue;
+                }
 
-        vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT;
-        final VIF vif = VIF.create(conn, vifr);
-        if (s_logger.isDebugEnabled()) {
-            vifr = vif.getRecord(conn);
-            if(vifr !=  null) {
-                s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId());
+                if (VmPowerState.HALTED.equals(vmRec.powerState) && vmRec.affinity.equals(host) && !isAlienVm(vm, conn)) {
+                    try {
+                        vm.destroy(conn);
+                    } catch (final Exception e) {
+                        s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to ", e);
+                        success = false;
+                    }
+                }
             }
         }
-
-        return vif;
+        return success;
     }
 
-    public void prepareISO(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException {
+    protected ExecutionResult cleanupNetworkElementCommand(final IpAssocCommand cmd) {
+        final Connection conn = getConnection();
+        final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
+        final String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+        try {
+            final IpAddressTO[] ips = cmd.getIpAddresses();
+            final int ipsCount = ips.length;
+            for (final IpAddressTO ip : ips) {
 
-        final Set<VM> vms = VM.getByNameLabel(conn, vmName);
-        if (vms == null || vms.size() != 1) {
-            throw new CloudRuntimeException("There are " + (vms == null ? "0" : vms.size()) + " VMs named " + vmName);
-        }
-        final VM vm = vms.iterator().next();
-        final Set<VBD> vbds = vm.getVBDs(conn);
-        for (final VBD vbd : vbds) {
-            final VBD.Record vbdr = vbd.getRecord(conn);
-            if (vbdr.type == Types.VbdType.CD && vbdr.empty == false) {
-                final VDI vdi = vbdr.VDI;
-                final SR sr = vdi.getSR(conn);
-                final Set<PBD> pbds = sr.getPBDs(conn);
-                if (pbds == null) {
-                    throw new CloudRuntimeException("There is no pbd for sr " + sr);
+                final VM router = getVM(conn, routerName);
+
+                final NicTO nic = new NicTO();
+                nic.setMac(ip.getVifMacAddress());
+                nic.setType(ip.getTrafficType());
+                if (ip.getBroadcastUri()== null) {
+                    nic.setBroadcastType(BroadcastDomainType.Native);
+                } else {
+                    final URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri());
+                    nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri));
+                    nic.setBroadcastUri(uri);
                 }
-                for (final PBD pbd : pbds) {
-                    final PBD.Record pbdr = pbd.getRecord(conn);
-                    if (pbdr.host.getUuid(conn).equals(_host.getUuid())) {
-                        return;
+                nic.setDeviceId(0);
+                nic.setNetworkRateMbps(ip.getNetworkRate());
+                nic.setName(ip.getNetworkName());
+
+                Network network = getNetwork(conn, nic);
+
+
+                // If we are disassociating the last IP address in the VLAN, we need
+                // to remove a VIF
+                boolean removeVif = false;
+
+                //there is only one ip in this public vlan and removing it, so remove the nic
+                if (ipsCount == 1 && !ip.isAdd()) {
+                    removeVif = true;
+                }
+
+                if (removeVif) {
+
+                    // Determine the correct VIF on DomR to associate/disassociate the
+                    // IP address with
+                    final VIF correctVif = getCorrectVif(conn, router, network);
+                    if (correctVif != null) {
+                        network = correctVif.getNetwork(conn);
+
+                        // Mark this vif to be removed from network usage
+                        networkUsage(conn, routerIp, "deleteVif", "eth" + correctVif.getDevice(conn));
+
+                        // Remove the VIF from DomR
+                        correctVif.unplug(conn);
+                        correctVif.destroy(conn);
+
+                        // Disable the VLAN network if necessary
+                        disableVlanNetwork(conn, network);
                     }
                 }
-                sr.setShared(conn, true);
-                final Host host = Host.getByUuid(conn, _host.getUuid());
-                final PBD.Record pbdr = pbds.iterator().next().getRecord(conn);
-                pbdr.host = host;
-                pbdr.uuid = "";
-                final PBD pbd = PBD.create(conn, pbdr);
-                pbdPlug(conn, pbd, pbd.getUuid(conn));
-                break;
             }
+        } catch (final Exception e) {
+            s_logger.debug("Ip Assoc failure on applying one ip due to exception:  ", e);
+            return new ExecutionResult(false, e.getMessage());
         }
+        return new ExecutionResult(true, null);
     }
 
-    protected VDI mount(final Connection conn, final String vmName, final DiskTO volume) throws XmlRpcException, XenAPIException {
-        final DataTO data = volume.getData();
-        final Volume.Type type = volume.getType();
-        if (type == Volume.Type.ISO) {
-            final TemplateObjectTO iso = (TemplateObjectTO)data;
-            final DataStoreTO store = iso.getDataStore();
-
-            if (store == null) {
-                //It's a fake iso
-                return null;
+    public void cleanupTemplateSR(final Connection conn) {
+        Set<PBD> pbds = null;
+        try {
+            final Host host = Host.getByUuid(conn, _host.getUuid());
+            pbds = host.getPBDs(conn);
+        } catch (final XenAPIException e) {
+            s_logger.warn("Unable to get the SRs " + e.toString(), e);
+            throw new CloudRuntimeException("Unable to get SRs " + e.toString(), e);
+        } catch (final Exception e) {
+            throw new CloudRuntimeException("Unable to get SRs " + e.getMessage(), e);
+        }
+        for (final PBD pbd : pbds) {
+            SR sr = null;
+            SR.Record srRec = null;
+            try {
+                sr = pbd.getSR(conn);
+                srRec = sr.getRecord(conn);
+            } catch (final Exception e) {
+                s_logger.warn("pbd.getSR get Exception due to ", e);
+                continue;
             }
-
-            //corer case, xenserver pv driver iso
-            final String templateName = iso.getName();
-            if (templateName.startsWith("xs-tools")) {
+            final String type = srRec.type;
+            if (srRec.shared) {
+                continue;
+            }
+            if (SRType.NFS.equals(type) || SRType.ISO.equals(type) && srRec.nameDescription.contains("template")) {
                 try {
-                    final Set<VDI> vdis = VDI.getByNameLabel(conn, templateName);
-                    if (vdis.isEmpty()) {
-                        throw new CloudRuntimeException("Could not find ISO with URL: " + templateName);
-                    }
-                    return vdis.iterator().next();
-                } catch (final XenAPIException e) {
-                    throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString());
+                    pbd.unplug(conn);
+                    pbd.destroy(conn);
+                    sr.forget(conn);
                 } catch (final Exception e) {
-                    throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString());
+                    s_logger.warn("forget SR catch Exception due to ", e);
                 }
             }
+        }
+    }
 
-            if (!(store instanceof NfsTO)) {
-                throw new CloudRuntimeException("only support mount iso on nfs");
-            }
-            final NfsTO nfsStore = (NfsTO)store;
-            final String isoPath = nfsStore.getUrl() + File.separator + iso.getPath();
-            final int index = isoPath.lastIndexOf("/");
+    public void cleanUpTmpDomVif(final Connection conn, final Network nw) throws XenAPIException, XmlRpcException {
 
-            final String mountpoint = isoPath.substring(0, index);
-            URI uri;
+        final Pair<VM, VM.Record> vm = getControlDomain(conn);
+        final VM dom0 = vm.first();
+        final Set<VIF> dom0Vifs = dom0.getVIFs(conn);
+        for (final VIF v : dom0Vifs) {
+            String vifName = "unknown";
             try {
-                uri = new URI(mountpoint);
-            } catch (final URISyntaxException e) {
-                throw new CloudRuntimeException("Incorrect uri " + mountpoint, e);
-            }
-            final SR isoSr = createIsoSRbyURI(conn, uri, vmName, false);
-
-            final String isoname = isoPath.substring(index + 1);
-
-            final VDI isoVdi = getVDIbyLocationandSR(conn, isoname, isoSr);
-
-            if (isoVdi == null) {
-                throw new CloudRuntimeException("Unable to find ISO " + isoPath);
+                final VIF.Record vifr = v.getRecord(conn);
+                if (v.getNetwork(conn).getUuid(conn).equals(nw.getUuid(conn))) {
+                    if(vifr != null) {
+                        final Map<String, String> config = vifr.otherConfig;
+                        vifName = config.get("nameLabel");
+                    }
+                    s_logger.debug("A VIF in dom0 for the network is found - so destroy the vif");
+                    v.destroy(conn);
+                    s_logger.debug("Destroy temp dom0 vif" + vifName + " success");
+                }
+            } catch (final Exception e) {
+                s_logger.warn("Destroy temp dom0 vif " + vifName + "failed", e);
             }
-            return isoVdi;
-        } else {
-            final VolumeObjectTO vol = (VolumeObjectTO)data;
-            return VDI.getByUuid(conn, vol.getPath());
         }
     }
 
-    public VBD createVbd(final Connection conn, final DiskTO volume, final String vmName, final VM vm, final BootloaderType bootLoaderType, VDI vdi) throws XmlRpcException, XenAPIException {
-        final Volume.Type type = volume.getType();
-
-        if (vdi == null) {
-            vdi = mount(conn, vmName, volume);
+    protected VDI cloudVDIcopy(final Connection conn, final VDI vdi, final SR sr, int wait) throws Exception {
+        Task task = null;
+        if (wait == 0) {
+            wait = 2 * 60 * 60;
         }
-
-        if (vdi != null) {
-            if ("detached".equals(vdi.getNameLabel(conn))) {
-                vdi.setNameLabel(conn, vmName + "-DATA");
-            }
-
-            final Map<String, String> smConfig = vdi.getSmConfig(conn);
-            for (final String key : smConfig.keySet()) {
-                if (key.startsWith("host_")) {
-                    vdi.removeFromSmConfig(conn, key);
-                    break;
+        try {
+            task = vdi.copyAsync(conn, sr);
+            // poll every 1 seconds , timeout after 2 hours
+            waitForTask(conn, task, 1000, (long)wait * 1000);
+            checkForSuccess(conn, task);
+            final VDI dvdi = Types.toVDI(task, conn);
+            return dvdi;
+        } finally {
+            if (task != null) {
+                try {
+                    task.destroy(conn);
+                } catch (final Exception e) {
+                    s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.getUuid() + ") due to " + e.toString());
                 }
             }
         }
-        final VBD.Record vbdr = new VBD.Record();
-        vbdr.VM = vm;
-        if (vdi != null) {
-            vbdr.VDI = vdi;
-        } else {
-            vbdr.empty = true;
-        }
-        if (type == Volume.Type.ROOT && bootLoaderType == BootloaderType.PyGrub) {
-            vbdr.bootable = true;
-        } else if (type == Volume.Type.ISO && bootLoaderType == BootloaderType.CD) {
-            vbdr.bootable = true;
-        }
-
-        vbdr.userdevice = Long.toString(volume.getDiskSeq());
-        if (volume.getType() == Volume.Type.ISO) {
-            vbdr.mode = Types.VbdMode.RO;
-            vbdr.type = Types.VbdType.CD;
-        } else if (volume.getType() == Volume.Type.ROOT) {
-            vbdr.mode = Types.VbdMode.RW;
-            vbdr.type = Types.VbdType.DISK;
-            vbdr.unpluggable = false;
-        } else {
-            vbdr.mode = Types.VbdMode.RW;
-            vbdr.type = Types.VbdType.DISK;
-            vbdr.unpluggable = true;
-        }
-        final VBD vbd = VBD.create(conn, vbdr);
+    }
 
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("VBD " + vbd.getUuid(conn) + " created for " + volume);
+    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
+            if(vm_map != null) {
+                for (final VM.Record record : vm_map.values()) {
+                    if (record.isControlDomain || record.isASnapshot || record.isATemplate) {
+                        continue; // Skip DOM0
+                    }
+                    vmMetaDatum.put(record.nameLabel, StringUtils.mapToString(record.platform));
+                }
+            }
+        } catch (final Throwable e) {
+            final String msg = "Unable to get vms through host " + _host.getUuid() + " due to to " + e.toString();
+            s_logger.warn(msg, e);
+            throw new CloudRuntimeException(msg);
         }
-
-        return vbd;
+        return vmMetaDatum;
     }
 
+    @Override
+    public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
+        _name = name;
 
-    private long getStaticMax(final String os, final boolean b, final long dynamicMinRam, final long dynamicMaxRam){
-        final long recommendedValue = CitrixHelper.getXenServerStaticMax(os, b);
-        if(recommendedValue == 0){
-            s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal");
-            return dynamicMaxRam;
-        }
-        final long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam);  // XS constraint for stability
-        if (dynamicMaxRam > staticMax){ // XS contraint that dynamic max <= static max
-            s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + ", can lead to stability issues. Setting static max as much as dynamic max ");
-            return dynamicMaxRam;
+        try {
+            _dcId = Long.parseLong((String)params.get("zone"));
+        } catch (final NumberFormatException e) {
+            throw new ConfigurationException("Unable to get the zone " + params.get("zone"));
         }
-        return staticMax;
-    }
 
+        _host.setUuid((String)params.get("guid"));
 
-    private long getStaticMin(final String os, final boolean b, final long dynamicMinRam, final long dynamicMaxRam) {
-        final long recommendedValue = CitrixHelper.getXenServerStaticMin(os, b);
-        if (recommendedValue == 0) {
-            s_logger.warn("No recommended value found for dynamic min");
-            return dynamicMinRam;
-        }
+        _name = _host.getUuid();
+        _host.setIp((String)params.get("ipaddress"));
 
-        if (dynamicMinRam < recommendedValue) {   // XS contraint that dynamic min > static min
-            s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues");
+        _username = (String)params.get("username");
+        _password.add((String)params.get("password"));
+        _pod = (String)params.get("pod");
+        _cluster = (String)params.get("cluster");
+        _privateNetworkName = (String)params.get("private.network.device");
+        _publicNetworkName = (String)params.get("public.network.device");
+        _guestNetworkName = (String)params.get("guest.network.device");
+        _instance = (String)params.get("instance.name");
+        _securityGroupEnabled = Boolean.parseBoolean((String)params.get("securitygroupenabled"));
+
+        _linkLocalPrivateNetworkName = (String)params.get("private.linkLocal.device");
+        if (_linkLocalPrivateNetworkName == null) {
+            _linkLocalPrivateNetworkName = "cloud_link_local_network";
         }
-        return dynamicMinRam;
-    }
 
+        _storageNetworkName1 = (String)params.get("storage.network.device1");
+        _storageNetworkName2 = (String)params.get("storage.network.device2");
 
-    public HashMap<String, HashMap<String, VgpuTypesInfo>> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException {
-        return null;
-    }
+        _heartbeatTimeout = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.timeout"), 120);
+        _heartbeatInterval = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.interval"), 60);
 
-    public void createVGPU(final Connection conn, final StartCommand cmd, final VM vm, final GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException {
-    }
+        String value = (String)params.get("wait");
+        _wait = NumbersUtil.parseInt(value, 600);
 
-    public VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmSpec, final Host host) throws XenAPIException, XmlRpcException {
-        final String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getPlatformEmulator(), vmSpec.getBootloader() == BootloaderType.CD);
-        final Set<VM> templates = VM.getByNameLabel(conn, guestOsTypeName);
-        if ( templates == null || templates.isEmpty()) {
-            throw new CloudRuntimeException("Cannot find template " + guestOsTypeName + " on XenServer host");
-        }
-        assert templates.size() == 1 : "Should only have 1 template but found " + templates.size();
-        final VM template = templates.iterator().next();
+        value = (String)params.get("migratewait");
+        _migratewait = NumbersUtil.parseInt(value, 3600);
 
-        final VM.Record vmr = template.getRecord(conn);
-        vmr.affinity = host;
-        vmr.otherConfig.remove("disks");
-        vmr.otherConfig.remove("default_template");
-        vmr.otherConfig.remove("mac_seed");
-        vmr.isATemplate = false;
-        vmr.nameLabel = vmSpec.getName();
-        vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY;
-        vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY;
-        vmr.otherConfig.put("vm_uuid", vmSpec.getUuid());
-        vmr.VCPUsMax = (long) vmSpec.getCpus(); // FIX ME: In case of dynamic scaling this VCPU max should be the minumum of
-        // recommended value for that template and capacity remaining on host
+        _maxNics = NumbersUtil.parseInt((String)params.get("xenserver.nics.max"), 7);
 
-        if (isDmcEnabled(conn, host) && vmSpec.isEnableDynamicallyScaleVm()) {
-            //scaling is allowed
-            vmr.memoryStaticMin = getStaticMin(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD, vmSpec.getMinRam(), vmSpec.getMaxRam());
-            vmr.memoryStaticMax = getStaticMax(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD, vmSpec.getMinRam(), vmSpec.getMaxRam());
-            vmr.memoryDynamicMin = vmSpec.getMinRam();
-            vmr.memoryDynamicMax = vmSpec.getMaxRam();
-            if (guestOsTypeName.toLowerCase().contains("windows")) {
-                vmr.VCPUsMax = (long) vmSpec.getCpus();
-            } else {
-                if (vmSpec.getVcpuMaxLimit() != null) {
-                    vmr.VCPUsMax = (long) vmSpec.getVcpuMaxLimit();
-                }
-            }
-        } else {
-            //scaling disallowed, set static memory target
-            if (vmSpec.isEnableDynamicallyScaleVm() && !isDmcEnabled(conn, host)) {
-                s_logger.warn("Host " + host.getHostname(conn) + " does not support dynamic scaling, so the vm " + vmSpec.getName() + " is not dynamically scalable");
-            }
-            vmr.memoryStaticMin = vmSpec.getMinRam();
-            vmr.memoryStaticMax = vmSpec.getMaxRam();
-            vmr.memoryDynamicMin = vmSpec.getMinRam();;
-            vmr.memoryDynamicMax = vmSpec.getMaxRam();
+        if (_pod == null) {
+            throw new ConfigurationException("Unable to get the pod");
+        }
 
-            vmr.VCPUsMax = (long) vmSpec.getCpus();
+        if (_host.getIp() == null) {
+            throw new ConfigurationException("Unable to get the host address");
         }
 
-        vmr.VCPUsAtStartup = (long) vmSpec.getCpus();
-        vmr.consoles.clear();
+        if (_username == null) {
+            throw new ConfigurationException("Unable to get the username");
+        }
 
-        final VM vm = VM.create(conn, vmr);
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Created VM " + vm.getUuid(conn) + " for " + vmSpec.getName());
+        if (_password.peek() == null) {
+            throw new ConfigurationException("Unable to get the password");
         }
 
-        final Map<String, String> vcpuParams = new HashMap<String, String>();
+        if (_host.getUuid() == null) {
+            throw new ConfigurationException("Unable to get the uuid");
+        }
 
-        final Integer speed = vmSpec.getMinSpeed();
-        if (speed != null) {
+        CheckXenHostInfo();
 
-            int cpuWeight = _maxWeight; // cpu_weight
-            int utilization = 0; // max CPU cap, default is unlimited
+        storageHandler = buildStorageHandler();
 
-            // weight based allocation, CPU weight is calculated per VCPU
-            cpuWeight = (int)(speed * 0.99 / _host.getSpeed() * _maxWeight);
-            if (cpuWeight > _maxWeight) {
-                cpuWeight = _maxWeight;
-            }
+        _vrResource = new VirtualRoutingResource(this);
+        if (!_vrResource.configure(name, params)) {
+            throw new ConfigurationException("Unable to configure VirtualRoutingResource");
+        }
+        return true;
+    }
 
-            if (vmSpec.getLimitCpuUse()) {
-                // CPU cap is per VM, so need to assign cap based on the number of vcpus
-                utilization = (int)(vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus() / _host.getSpeed() * 100);
+    /**
+     * This method creates a XenServer network and configures it for being used as a L2-in-L3 tunneled network
+     */
+    public synchronized Network configureTunnelNetwork(final Connection conn, final Long networkId, final long hostId, final String bridgeName) {
+        try {
+            final Network nw = findOrCreateTunnelNetwork(conn, bridgeName);
+            //Invoke plugin to setup the bridge which will be used by this network
+            final String bridge = nw.getBridge(conn);
+            final Map<String, String> nwOtherConfig = nw.getOtherConfig(conn);
+            final String configuredHosts = nwOtherConfig.get("ovs-host-setup");
+            boolean configured = false;
+            if (configuredHosts != null) {
+                final String hostIdsStr[] = configuredHosts.split(",");
+                for (final String hostIdStr : hostIdsStr) {
+                    if (hostIdStr.equals(((Long)hostId).toString())) {
+                        configured = true;
+                        break;
+                    }
+                }
             }
 
-            vcpuParams.put("weight", Integer.toString(cpuWeight));
-            vcpuParams.put("cap", Integer.toString(utilization));
+            if (!configured) {
+                String result;
+                if (bridgeName.startsWith("OVS-DR-VPC-Bridge")) {
+                    result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge,
+                            "key", bridgeName,
+                            "xs_nw_uuid", nw.getUuid(conn),
+                            "cs_host_id", ((Long)hostId).toString());
+                } else {
+                    result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge,
+                            "key", bridgeName,
+                            "xs_nw_uuid", nw.getUuid(conn),
+                            "cs_host_id", ((Long)hostId).toString());
+                }
 
+                //Note down the fact that the ovs bridge has been setup
+                final String[] res = result.split(":");
+                if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
+                    //TODO: Should make this error not fatal?
+                    throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge );
+                }
+            }
+            return nw;
+        } catch (final Exception e) {
+            s_logger.warn("createandConfigureTunnelNetwork failed", e);
+            return null;
         }
+    }
 
-        if (vcpuParams.size() > 0) {
-            vm.setVCPUsParams(conn, vcpuParams);
-        }
+    public String connect(final Connection conn, final String vmname, final String ipAddress) {
+        return connect(conn, vmname, ipAddress, 3922);
+    }
 
-        final String bootArgs = vmSpec.getBootArgs();
-        if (bootArgs != null && bootArgs.length() > 0) {
-            String pvargs = vm.getPVArgs(conn);
-            pvargs = pvargs + vmSpec.getBootArgs().replaceAll(" ", "%");
+    public String connect(final Connection conn, final String vmName, final String ipAddress, final int port) {
+        for (int i = 0; i <= _retry; i++) {
+            try {
+                final Set<VM> vms = VM.getByNameLabel(conn, vmName);
+                if (vms.size() < 1) {
+                    final String msg = "VM " + vmName + " is not running";
+                    s_logger.warn(msg);
+                    return msg;
+                }
+            } catch (final Exception e) {
+                final String msg = "VM.getByNameLabel " + vmName + " failed due to " + e.toString();
+                s_logger.warn(msg, e);
+                return msg;
+            }
             if (s_logger.isDebugEnabled()) {
-                s_logger.debug("PV args are " + pvargs);
+                s_logger.debug("Trying to connect to " + ipAddress + " attempt " + i + " of " + _retry);
+            }
+            if (pingdomr(conn, ipAddress, Integer.toString(port))) {
+                return null;
+            }
+            try {
+                Thread.sleep(_sleep);
+            } catch (final InterruptedException e) {
             }
-            vm.setPVArgs(conn, pvargs);
         }
+        final String msg = "Timeout, Unable to logon to " + ipAddress;
+        s_logger.debug(msg);
 
-        if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
-            if (vmSpec.getBootloader() == BootloaderType.CD) {
-                final DiskTO[] disks = vmSpec.getDisks();
-                for (final DiskTO disk : disks) {
-                    if (disk.getType() == Volume.Type.ISO) {
-                        final TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
-                        final String osType = iso.getGuestOsType();
-                        if (osType != null) {
-                            final String isoGuestOsName = getGuestOsType(osType, vmSpec.getPlatformEmulator(), vmSpec.getBootloader() == BootloaderType.CD);
-                            if (!isoGuestOsName.equals(guestOsTypeName)) {
-                                vmSpec.setBootloader(BootloaderType.PyGrub);
-                            }
-                        }
-                    }
-                }
-            }
-            if (vmSpec.getBootloader() == BootloaderType.CD) {
-                vm.setPVBootloader(conn, "eliloader");
-                if (!vm.getOtherConfig(conn).containsKey("install-repository")) {
-                    vm.addToOtherConfig(conn, "install-repository", "cdrom");
-                }
-            } else if (vmSpec.getBootloader() == BootloaderType.PyGrub) {
-                vm.setPVBootloader(conn, "pygrub");
+        return msg;
+    }
+
+    public String copyVhdFromSecondaryStorage(final Connection conn, final String mountpoint, final String sruuid, final int wait) {
+        final String nameLabel = "cloud-" + UUID.randomUUID().toString();
+        final String results =
+                callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel);
+        String errMsg = null;
+        if (results == null || results.isEmpty()) {
+            errMsg = "copy_vhd_from_secondarystorage return null";
+        } else {
+            final String[] tmp = results.split("#");
+            final String status = tmp[0];
+            if (status.equals("0")) {
+                return tmp[1];
             } else {
-                vm.destroy(conn);
-                throw new CloudRuntimeException("Unable to handle boot loader type: " + vmSpec.getBootloader());
+                errMsg = tmp[1];
             }
         }
-        try {
-            finalizeVmMetaData(vm, conn, vmSpec);
-        } catch (final Exception e) {
-            throw new CloudRuntimeException("Unable to finalize VM MetaData: " + vmSpec);
+        final String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1);
+        if (killCopyProcess(conn, source)) {
+            destroyVDIbyNameLabel(conn, nameLabel);
         }
-        return vm;
+        s_logger.warn(errMsg);
+        throw new CloudRuntimeException(errMsg);
     }
 
+    @Override
+    public ExecutionResult createFileInVR(final String routerIp, final String path, final String filename, final String content) {
+        final Connection conn = getConnection();
+        final String hostPath = "/tmp/";
 
-    protected void finalizeVmMetaData(final VM vm, final Connection conn, final VirtualMachineTO vmSpec) throws Exception {
-
-        final Map<String, String> details = vmSpec.getDetails();
-        if (details != null) {
-            final String platformstring = details.get("platform");
-            if (platformstring != null && !platformstring.isEmpty()) {
-                final Map<String, String> platform = StringUtils.stringToMap(platformstring);
-                vm.setPlatform(conn, platform);
-            } else {
-                final String timeoffset = details.get("timeoffset");
-                if (timeoffset != null) {
-                    final Map<String, String> platform = vm.getPlatform(conn);
-                    platform.put("timeoffset", timeoffset);
-                    vm.setPlatform(conn, platform);
-                }
-                final String coresPerSocket = details.get("cpu.corespersocket");
-                if (coresPerSocket != null) {
-                    final Map<String, String> platform = vm.getPlatform(conn);
-                    platform.put("cores-per-socket", coresPerSocket);
-                    vm.setPlatform(conn, platform);
-                }
-            }
-            if ( !BootloaderType.CD.equals(vmSpec.getBootloader())) {
-                final String xenservertoolsversion = details.get("hypervisortoolsversion");
-                if ((xenservertoolsversion == null || !xenservertoolsversion.equalsIgnoreCase("xenserver61")) && vmSpec.getGpuDevice() == null) {
-                    final Map<String, String> platform = vm.getPlatform(conn);
-                    platform.remove("device_id");
-                    vm.setPlatform(conn, platform);
-                }
-            }
+        s_logger.debug("Copying VR with ip " + routerIp +" config file into host "+ _host.getIp() );
+        try {
+            SshHelper.scpTo(_host.getIp(), 22, _username, null, _password.peek(), hostPath, content.getBytes(Charset.defaultCharset()), filename, null);
+        } catch (final Exception e) {
+            s_logger.warn("scp VR config file into host " + _host.getIp() + " failed with exception " + e.getMessage().toString());
         }
+
+        final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path);
+        s_logger.debug ("VR Config file " + filename + " got created in VR, ip " + routerIp + " with content \n" + content);
+
+        return new ExecutionResult(

<TRUNCATED>