You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by se...@apache.org on 2014/06/07 10:50:48 UTC

[08/16] Cleanup of Xen and XenServer terms. Cloned xen plugin creating a xenserver plugin, then removed xen plugin

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a8212d9e/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/spring-xenserver-compute-context.xml
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/spring-xenserver-compute-context.xml b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/spring-xenserver-compute-context.xml
new file mode 100644
index 0000000..d9d442b
--- /dev/null
+++ b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/spring-xenserver-compute-context.xml
@@ -0,0 +1,28 @@
+<!-- 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. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+    xmlns:aop="http://www.springframework.org/schema/aop"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+                      http://www.springframework.org/schema/context
+                      http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+    <bean id="XenServerFencer" class="com.cloud.ha.XenServerFencer">
+        <property name="name" value="XenServerFenceBuilder" />
+    </bean>
+
+    <bean id="XenServerGuru" class="com.cloud.hypervisor.XenServerGuru">
+        <property name="name" value="XenServerGuru" />
+    </bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a8212d9e/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/module.properties
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/module.properties b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/module.properties
new file mode 100644
index 0000000..10d0ecd
--- /dev/null
+++ b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/module.properties
@@ -0,0 +1,18 @@
+# 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.
+name=xenserver-discoverer
+parent=discoverer
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a8212d9e/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/spring-xenserver-discoverer-context.xml
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/spring-xenserver-discoverer-context.xml b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/spring-xenserver-discoverer-context.xml
new file mode 100644
index 0000000..5c76772
--- /dev/null
+++ b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/spring-xenserver-discoverer-context.xml
@@ -0,0 +1,25 @@
+<!-- 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. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+    xmlns:aop="http://www.springframework.org/schema/aop"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+                      http://www.springframework.org/schema/context
+                      http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+    <bean id="XcpServerDiscoverer"
+        class="com.cloud.hypervisor.xenserver.discoverer.XcpServerDiscoverer">
+        <property name="name" value="XCP Agent" />
+    </bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a8212d9e/plugins/hypervisors/xenserver/src/com/cloud/ha/XenServerFencer.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/ha/XenServerFencer.java b/plugins/hypervisors/xenserver/src/com/cloud/ha/XenServerFencer.java
new file mode 100755
index 0000000..28cba2b
--- /dev/null
+++ b/plugins/hypervisors/xenserver/src/com/cloud/ha/XenServerFencer.java
@@ -0,0 +1,129 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.ha;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.FenceAnswer;
+import com.cloud.agent.api.FenceCommand;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.resource.ResourceManager;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.vm.VirtualMachine;
+
+@Local(value = FenceBuilder.class)
+public class XenServerFencer extends AdapterBase implements FenceBuilder {
+    private static final Logger s_logger = Logger.getLogger(XenServerFencer.class);
+
+    @Inject
+    HostDao _hostDao;
+    @Inject
+    AgentManager _agentMgr;
+    @Inject
+    ResourceManager _resourceMgr;
+
+    @Override
+    public Boolean fenceOff(VirtualMachine vm, Host host) {
+        if (host.getHypervisorType() != HypervisorType.XenServer) {
+            s_logger.debug("Don't know how to fence non XenServer hosts " + host.getHypervisorType());
+            return null;
+        }
+
+        List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(host.getClusterId());
+        FenceCommand fence = new FenceCommand(vm, host);
+
+        for (HostVO h : hosts) {
+            if (h.getHypervisorType() == HypervisorType.XenServer) {
+                if (h.getStatus() != Status.Up) {
+                    continue;
+                }
+                if (h.getId() == host.getId()) {
+                    continue;
+                }
+                FenceAnswer answer;
+                try {
+                    Answer ans = _agentMgr.send(h.getId(), fence);
+                    if (!(ans instanceof FenceAnswer)) {
+                        s_logger.debug("Answer is not fenceanswer.  Result = " + ans.getResult() + "; Details = " + ans.getDetails());
+                        continue;
+                    }
+                    answer = (FenceAnswer)ans;
+                } catch (AgentUnavailableException e) {
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("Moving on to the next host because " + h.toString() + " is unavailable");
+                    }
+                    continue;
+                } catch (OperationTimedoutException e) {
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("Moving on to the next host because " + h.toString() + " is unavailable");
+                    }
+                    continue;
+                }
+                if (answer != null && answer.getResult()) {
+                    return true;
+                }
+            }
+        }
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Unable to fence off " + vm.toString() + " on " + host.toString());
+        }
+
+        return false;
+    }
+
+    public XenServerFencer() {
+        super();
+    }
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        _name = name;
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a8212d9e/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/XenServerGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/XenServerGuru.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/XenServerGuru.java
new file mode 100644
index 0000000..89e4ab5
--- /dev/null
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/XenServerGuru.java
@@ -0,0 +1,160 @@
+// 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.NfsTO;
+import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.storage.GuestOSVO;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.GuestOSDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.template.VirtualMachineTemplate.BootloaderType;
+import com.cloud.utils.Pair;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+
+import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+
+@Local(value = HypervisorGuru.class)
+public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru {
+    @Inject
+    GuestOSDao _guestOsDao;
+    @Inject
+    EndPointSelector endPointSelector;
+    @Inject
+    HostDao hostDao;
+    @Inject
+    VolumeDao _volumeDao;
+    @Inject
+    PrimaryDataStoreDao _storagePoolDao;
+    @Inject
+    VolumeDataFactory _volFactory;
+
+    protected XenServerGuru() {
+        super();
+    }
+
+    @Override
+    public HypervisorType getHypervisorType() {
+        return HypervisorType.XenServer;
+    }
+
+    @Override
+    public VirtualMachineTO implement(VirtualMachineProfile vm) {
+        BootloaderType bt = BootloaderType.PyGrub;
+        if (vm.getBootLoaderType() == BootloaderType.CD) {
+            bt = vm.getBootLoaderType();
+        }
+        VirtualMachineTO to = toVirtualMachineTO(vm);
+        to.setBootloader(bt);
+
+        // Determine the VM's OS description
+        GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
+        to.setOs(guestOS.getDisplayName());
+
+        return to;
+    }
+
+    @Override
+    public boolean trackVmHostChange() {
+        return true;
+    }
+
+    @Override
+    public List<Command> finalizeExpungeVolumes(VirtualMachine vm) {
+        List<Command> commands = new ArrayList<Command>();
+
+        List<VolumeVO> volumes = _volumeDao.findByInstance(vm.getId());
+
+        // it's OK in this case to send a detach command to the host for a root volume as this
+        // will simply lead to the SR that supports the root volume being removed
+        if (volumes != null) {
+            for (VolumeVO volume : volumes) {
+                StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
+
+                // storagePool should be null if we are expunging a volume that was never
+                // attached to a VM that was started (the "trick" for storagePool to be null
+                // is that none of the VMs this volume may have been attached to were ever started,
+                // so the volume was never assigned to a storage pool)
+                if (storagePool != null && storagePool.isManaged()) {
+                    DataTO volTO = _volFactory.getVolume(volume.getId()).getTO();
+                    DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getPath(), volume.getVolumeType());
+
+                    DettachCommand cmd = new DettachCommand(disk, vm.getInstanceName());
+
+                    cmd.setManaged(true);
+
+                    cmd.setStorageHost(storagePool.getHostAddress());
+                    cmd.setStoragePort(storagePool.getPort());
+
+                    cmd.set_iScsiName(volume.get_iScsiName());
+
+                    commands.add(cmd);
+                }
+            }
+        }
+
+        return commands;
+    }
+
+    @Override
+    public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command cmd) {
+        if (cmd instanceof CopyCommand) {
+            CopyCommand cpyCommand = (CopyCommand)cmd;
+            DataTO srcData = cpyCommand.getSrcTO();
+            DataTO destData = cpyCommand.getDestTO();
+
+            if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.TEMPLATE) {
+                DataStoreTO srcStore = srcData.getDataStore();
+                DataStoreTO destStore = destData.getDataStore();
+                if (srcStore instanceof NfsTO && destStore instanceof NfsTO) {
+                    HostVO host = hostDao.findById(hostId);
+                    EndPoint ep = endPointSelector.selectHypervisorHost(new ZoneScope(host.getDataCenterId()));
+                    host = hostDao.findById(ep.getId());
+                    hostDao.loadDetails(host);
+                    String snapshotHotFixVersion = host.getDetail(XenserverConfigs.XS620HotFix);
+                    if (snapshotHotFixVersion != null && snapshotHotFixVersion.equalsIgnoreCase(XenserverConfigs.XSHotFix62ESP1004)) {
+                        return new Pair<Boolean, Long>(Boolean.TRUE, new Long(ep.getId()));
+                    }
+                }
+            }
+        }
+        return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a8212d9e/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java
new file mode 100755
index 0000000..a01cbcb
--- /dev/null
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java
@@ -0,0 +1,726 @@
+// 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.discoverer;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.Listener;
+import com.cloud.agent.api.AgentControlAnswer;
+import com.cloud.agent.api.AgentControlCommand;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.SetupAnswer;
+import com.cloud.agent.api.SetupCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.alert.AlertManager;
+import com.cloud.configuration.Config;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.dao.HostPodDao;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.ConnectionException;
+import com.cloud.exception.DiscoveredWithErrorException;
+import com.cloud.exception.DiscoveryException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.host.HostEnvironment;
+import com.cloud.host.HostInfo;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
+import com.cloud.hypervisor.xenserver.resource.XcpOssResource;
+import com.cloud.hypervisor.xenserver.resource.XcpServer16Resource;
+import com.cloud.hypervisor.xenserver.resource.XcpServerResource;
+import com.cloud.hypervisor.xenserver.resource.XenServer56FP1Resource;
+import com.cloud.hypervisor.xenserver.resource.XenServer56Resource;
+import com.cloud.hypervisor.xenserver.resource.XenServer56SP2Resource;
+import com.cloud.hypervisor.xenserver.resource.XenServer600Resource;
+import com.cloud.hypervisor.xenserver.resource.XenServer602Resource;
+import com.cloud.hypervisor.xenserver.resource.XenServer610Resource;
+import com.cloud.hypervisor.xenserver.resource.XenServer620Resource;
+import com.cloud.hypervisor.xenserver.resource.XenServer620SP1Resource;
+import com.cloud.hypervisor.xenserver.resource.XenServerConnectionPool;
+import com.cloud.hypervisor.xenserver.resource.Xenserver625Resource;
+import com.cloud.resource.Discoverer;
+import com.cloud.resource.DiscovererBase;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.Storage.TemplateType;
+import com.cloud.storage.VMTemplateVO;
+import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.user.Account;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.QueryBuilder;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.exception.HypervisorVersionChangedException;
+import com.xensource.xenapi.Connection;
+import com.xensource.xenapi.Host;
+import com.xensource.xenapi.HostPatch;
+import com.xensource.xenapi.Pool;
+import com.xensource.xenapi.PoolPatch;
+import com.xensource.xenapi.Session;
+import com.xensource.xenapi.Types.SessionAuthenticationFailed;
+import com.xensource.xenapi.Types.UuidInvalid;
+import com.xensource.xenapi.Types.XenAPIException;
+import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs;
+import org.apache.log4j.Logger;
+import org.apache.xmlrpc.XmlRpcException;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import javax.persistence.EntityExistsException;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+
+@Local(value = Discoverer.class)
+public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter {
+    private static final Logger s_logger = Logger.getLogger(XcpServerDiscoverer.class);
+    protected String _publicNic;
+    protected String _privateNic;
+    protected String _storageNic1;
+    protected String _storageNic2;
+    protected int _wait;
+    protected XenServerConnectionPool _connPool;
+    protected boolean _checkHvm;
+    protected String _guestNic;
+    protected boolean _setupMultipath;
+    protected String _instance;
+    private String xs620snapshothotfix = "Xenserver-Vdi-Copy-HotFix";
+
+    @Inject
+    protected AlertManager _alertMgr;
+    @Inject
+    protected AgentManager _agentMgr;
+    @Inject
+    VMTemplateDao _tmpltDao;
+    @Inject
+    HostPodDao _podDao;
+
+    protected XcpServerDiscoverer() {
+    }
+
+    void setClusterGuid(ClusterVO cluster, String guid) {
+        cluster.setGuid(guid);
+        try {
+            _clusterDao.update(cluster.getId(), cluster);
+        } catch (EntityExistsException e) {
+            QueryBuilder<ClusterVO> sc = QueryBuilder.create(ClusterVO.class);
+            sc.and(sc.entity().getGuid(), Op.EQ, guid);
+            List<ClusterVO> clusters = sc.list();
+            ClusterVO clu = clusters.get(0);
+            List<HostVO> clusterHosts = _resourceMgr.listAllHostsInCluster(clu.getId());
+            if (clusterHosts == null || clusterHosts.size() == 0) {
+                clu.setGuid(null);
+                _clusterDao.update(clu.getId(), clu);
+                _clusterDao.update(cluster.getId(), cluster);
+                return;
+            }
+            throw e;
+        }
+    }
+
+    protected boolean poolHasHotFix(Connection conn, String hostIp, String hotFixUuid) {
+        try {
+            Map<Host, Host.Record> hosts = Host.getAllRecords(conn);
+            for (Map.Entry<Host, Host.Record> entry : hosts.entrySet()) {
+
+                Host.Record re = entry.getValue();
+                if (!re.address.equalsIgnoreCase(hostIp)){
+                    continue;
+                }
+                Set<HostPatch> patches = re.patches;
+                PoolPatch poolPatch = PoolPatch.getByUuid(conn, hotFixUuid);
+                for(HostPatch patch : patches) {
+                    PoolPatch pp = patch.getPoolPatch(conn);
+                    if (pp.equals(poolPatch) && patch.getApplied(conn)) {
+                        s_logger.debug("host " + hostIp + " does have " + hotFixUuid +" Hotfix.");
+                        return true;
+                    }
+                }
+            }
+            return false;
+        } catch (UuidInvalid e) {
+            s_logger.debug("host " + hostIp + " doesn't have " + hotFixUuid + " Hotfix");
+        } catch (Exception e) {
+            s_logger.debug("can't get patches information, consider it doesn't have " + hotFixUuid + " Hotfix");
+        }
+        return false;
+    }
+
+
+
+    @Override
+    public Map<? extends ServerResource, Map<String, String>>
+    find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List<String> hostTags) throws DiscoveryException {
+        Map<CitrixResourceBase, Map<String, String>> resources = new HashMap<CitrixResourceBase, Map<String, String>>();
+        Connection conn = null;
+        if (!url.getScheme().equals("http")) {
+            String msg = "urlString is not http so we're not taking care of the discovery for this: " + url;
+            s_logger.debug(msg);
+            return null;
+        }
+        if (clusterId == null) {
+            String msg = "must specify cluster Id when add host";
+            s_logger.debug(msg);
+            throw new RuntimeException(msg);
+        }
+
+        if (podId == null) {
+            String msg = "must specify pod Id when add host";
+            s_logger.debug(msg);
+            throw new RuntimeException(msg);
+        }
+
+        ClusterVO cluster = _clusterDao.findById(clusterId);
+        if (cluster == null || cluster.getHypervisorType() != HypervisorType.XenServer) {
+            if (s_logger.isInfoEnabled())
+                s_logger.info("invalid cluster id or cluster is not for XenServer hypervisors");
+            return null;
+        }
+
+        try {
+            String hostname = url.getHost();
+            InetAddress ia = InetAddress.getByName(hostname);
+            String hostIp = ia.getHostAddress();
+            Queue<String> pass = new LinkedList<String>();
+            pass.add(password);
+            conn = _connPool.getConnect(hostIp, username, pass);
+            if (conn == null) {
+                String msg = "Unable to get a connection to " + url;
+                s_logger.debug(msg);
+                throw new DiscoveryException(msg);
+            }
+
+            Set<Pool> pools = Pool.getAll(conn);
+            Pool pool = pools.iterator().next();
+            Pool.Record pr = pool.getRecord(conn);
+            String poolUuid = pr.uuid;
+            Map<Host, Host.Record> hosts = Host.getAllRecords(conn);
+            String latestHotFix = "";
+            if (poolHasHotFix(conn, hostIp, XenserverConfigs.XSHotFix62ESP1004)) {
+                latestHotFix = XenserverConfigs.XSHotFix62ESP1004;
+            } else if (poolHasHotFix(conn, hostIp, XenserverConfigs.XSHotFix62ESP1)) {
+                latestHotFix = XenserverConfigs.XSHotFix62ESP1;
+            }
+
+            /*set cluster hypervisor type to xenserver*/
+            ClusterVO clu = _clusterDao.findById(clusterId);
+            if (clu.getGuid() == null) {
+                setClusterGuid(clu, poolUuid);
+            } else {
+                List<HostVO> clusterHosts = _resourceMgr.listAllHostsInCluster(clusterId);
+                if (clusterHosts != null && clusterHosts.size() > 0) {
+                    if (!clu.getGuid().equals(poolUuid)) {
+                        String msg = "Please join the host " +  hostIp + " to XS pool  "
+                                       + clu.getGuid() + " through XC/XS before adding it through CS UI";
+                        s_logger.warn(msg);
+                        throw new DiscoveryException(msg);
+                    }
+                } else {
+                    setClusterGuid(clu, poolUuid);
+                }
+            }
+            // can not use this conn after this point, because this host may join a pool, this conn is retired
+            if (conn != null) {
+                try {
+                    Session.logout(conn);
+                } catch (Exception e) {
+                    s_logger.debug("Caught exception during logout", e);
+                }
+                conn.dispose();
+                conn = null;
+            }
+
+            poolUuid = clu.getGuid();
+            _clusterDao.update(clusterId, clu);
+
+            if (_checkHvm) {
+                for (Map.Entry<Host, Host.Record> entry : hosts.entrySet()) {
+                    Host.Record record = entry.getValue();
+
+                    boolean support_hvm = false;
+                    for (String capability : record.capabilities) {
+                        if (capability.contains("hvm")) {
+                            support_hvm = true;
+                            break;
+                        }
+                    }
+                    if (!support_hvm) {
+                        String msg = "Unable to add host " + record.address + " because it doesn't support hvm";
+                        _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, dcId, podId, msg, msg);
+                        s_logger.debug(msg);
+                        throw new RuntimeException(msg);
+                    }
+                }
+            }
+
+            for (Map.Entry<Host, Host.Record> entry : hosts.entrySet()) {
+                Host.Record record = entry.getValue();
+                String hostAddr = record.address;
+
+                String prodVersion = record.softwareVersion.get("product_version");
+                if (prodVersion == null) {
+                    prodVersion = record.softwareVersion.get("platform_version");
+                }
+                String xenVersion = record.softwareVersion.get("xen");
+                String hostOS = record.softwareVersion.get("product_brand");
+                if (hostOS == null) {
+                    hostOS = record.softwareVersion.get("platform_name");
+                }
+
+                String hostOSVer = prodVersion;
+                String hostKernelVer = record.softwareVersion.get("linux");
+
+                if (_resourceMgr.findHostByGuid(record.uuid) != null) {
+                    s_logger.debug("Skipping " + record.address + " because " + record.uuid + " is already in the database.");
+                    continue;
+                }
+
+                CitrixResourceBase resource = createServerResource(dcId, podId, record, latestHotFix);
+                s_logger.info("Found host " + record.hostname + " ip=" + record.address + " product version=" + prodVersion);
+
+                Map<String, String> details = new HashMap<String, String>();
+                Map<String, Object> params = new HashMap<String, Object>();
+                details.put("url", hostAddr);
+                details.put("username", username);
+                params.put("username", username);
+                details.put("password", password);
+                params.put("password", password);
+                params.put("zone", Long.toString(dcId));
+                params.put("guid", record.uuid);
+                params.put("pod", podId.toString());
+                params.put("cluster", clusterId.toString());
+                params.put("pool", poolUuid);
+                params.put("ipaddress", record.address);
+
+                details.put(HostInfo.HOST_OS, hostOS);
+                details.put(HostInfo.HOST_OS_VERSION, hostOSVer);
+                details.put(HostInfo.HOST_OS_KERNEL_VERSION, hostKernelVer);
+                details.put(HostInfo.HYPERVISOR_VERSION, xenVersion);
+
+                String privateNetworkLabel = _networkMgr.getDefaultManagementTrafficLabel(dcId, HypervisorType.XenServer);
+                String storageNetworkLabel = _networkMgr.getDefaultStorageTrafficLabel(dcId, HypervisorType.XenServer);
+
+                if (!params.containsKey("private.network.device") && privateNetworkLabel != null) {
+                    params.put("private.network.device", privateNetworkLabel);
+                    details.put("private.network.device", privateNetworkLabel);
+                }
+
+                if (!params.containsKey("storage.network.device1") && storageNetworkLabel != null) {
+                    params.put("storage.network.device1", storageNetworkLabel);
+                    details.put("storage.network.device1", storageNetworkLabel);
+                }
+
+                DataCenterVO zone = _dcDao.findById(dcId);
+                boolean securityGroupEnabled = zone.isSecurityGroupEnabled();
+                params.put("securitygroupenabled", Boolean.toString(securityGroupEnabled));
+
+                params.put("router.aggregation.command.each.timeout", _configDao.getValue(Config.RouterAggregationCommandEachTimeout.toString()));
+                params.put("wait", Integer.toString(_wait));
+                details.put("wait", Integer.toString(_wait));
+                params.put("migratewait", _configDao.getValue(Config.MigrateWait.toString()));
+                params.put(Config.XenServerMaxNics.toString().toLowerCase(), _configDao.getValue(Config.XenServerMaxNics.toString()));
+                params.put(Config.XenServerHeartBeatInterval.toString().toLowerCase(), _configDao.getValue(Config.XenServerHeartBeatInterval.toString()));
+                params.put(Config.InstanceName.toString().toLowerCase(), _instance);
+                details.put(Config.InstanceName.toString().toLowerCase(), _instance);
+                try {
+                    resource.configure("XenServer", params);
+                } catch (ConfigurationException e) {
+                    _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, dcId, podId, "Unable to add " + record.address, "Error is " + e.getMessage());
+                    s_logger.warn("Unable to instantiate " + record.address, e);
+                    continue;
+                }
+                resource.start();
+                resources.put(resource, details);
+            }
+        } catch (SessionAuthenticationFailed e) {
+            throw new DiscoveredWithErrorException("Authentication error");
+        } catch (XenAPIException e) {
+            s_logger.warn("XenAPI exception", e);
+            return null;
+        } catch (XmlRpcException e) {
+            s_logger.warn("Xml Rpc Exception", e);
+            return null;
+        } catch (UnknownHostException e) {
+            s_logger.warn("Unable to resolve the host name", e);
+            return null;
+        } catch (Exception e) {
+            s_logger.debug("other exceptions: " + e.toString(), e);
+            return null;
+        }
+        return resources;
+    }
+
+    String getPoolUuid(Connection conn) throws XenAPIException, XmlRpcException {
+        Map<Pool, Pool.Record> pools = Pool.getAllRecords(conn);
+        assert pools.size() == 1 : "Pools size is " + pools.size();
+        return pools.values().iterator().next().uuid;
+    }
+
+    protected void addSamePool(Connection conn, Map<CitrixResourceBase, Map<String, String>> resources) throws XenAPIException, XmlRpcException {
+        Map<Pool, Pool.Record> hps = Pool.getAllRecords(conn);
+        assert (hps.size() == 1) : "How can it be more than one but it's actually " + hps.size();
+
+        // This is the pool.
+        String poolUuid = hps.values().iterator().next().uuid;
+
+        for (Map<String, String> details : resources.values()) {
+            details.put("pool", poolUuid);
+        }
+    }
+
+
+    protected CitrixResourceBase createServerResource(long dcId, Long podId, Host.Record record, String hotfix) {
+        String prodBrand = record.softwareVersion.get("product_brand");
+        if (prodBrand == null) {
+            prodBrand = record.softwareVersion.get("platform_name").trim();
+        } else {
+            prodBrand = prodBrand.trim();
+        }
+
+        String prodVersion = record.softwareVersion.get("product_version");
+        if (prodVersion == null) {
+            prodVersion = record.softwareVersion.get("platform_version").trim();
+        } else {
+            prodVersion = prodVersion.trim();
+        }
+
+        // Xen Cloud Platform group of hypervisors
+        if (prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") || prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4"))) {
+            return new XcpServerResource();
+        } else if (prodBrand.equals("XCP") && prodVersion.startsWith("1.6")) {
+            return new XcpServer16Resource();
+        } // Citrix Xenserver group of hypervisors
+        else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.0"))
+            return new XenServer56Resource();
+        else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0"))
+            return new XenServer600Resource();
+        else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.2"))
+            return new XenServer602Resource();
+        else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0"))
+            return new XenServer610Resource();
+        else if (prodBrand.equals("XenServer") && prodVersion.equals("6.2.0")) {
+            if (hotfix.equals(XenserverConfigs.XSHotFix62ESP1004)) {
+                return new Xenserver625Resource();
+            } else if (hotfix.equals(XenserverConfigs.XSHotFix62ESP1)) {
+                return new XenServer620SP1Resource();
+            } else {
+                return new XenServer620Resource();
+            }
+        } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) {
+            String prodVersionTextShort = record.softwareVersion.get("product_version_text_short").trim();
+            if ("5.6 SP2".equals(prodVersionTextShort)) {
+                return new XenServer56SP2Resource();
+            } else if ("5.6 FP1".equals(prodVersionTextShort)) {
+                return new XenServer56FP1Resource();
+            }
+        } else if (prodBrand.equals("XCP_Kronos")) {
+            return new XcpOssResource();
+        }
+
+        String msg =
+                "Only support XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; XenServer 5.6,  XenServer 5.6 FP1, XenServer 5.6 SP2, Xenserver 6.0, 6.0.2, 6.1.0, 6.2.0 but this one is " +
+                        prodBrand + " " + prodVersion;
+        _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, dcId, podId, msg, msg);
+        s_logger.debug(msg);
+        throw new RuntimeException(msg);
+    }
+
+    protected void serverConfig() {
+        String value = _params.get(Config.XenServerSetupMultipath.key());
+        _setupMultipath = Boolean.parseBoolean(value);
+    }
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        super.configure(name, params);
+        serverConfig();
+
+        _publicNic = _params.get(Config.XenServerPublicNetwork.key());
+        _privateNic = _params.get(Config.XenServerPrivateNetwork.key());
+
+        _storageNic1 = _params.get(Config.XenServerStorageNetwork1.key());
+        _storageNic2 = _params.get(Config.XenServerStorageNetwork2.key());
+
+        _guestNic = _params.get(Config.XenServerGuestNetwork.key());
+
+        String value = _params.get(Config.XapiWait.toString());
+        _wait = NumbersUtil.parseInt(value, Integer.parseInt(Config.XapiWait.getDefaultValue()));
+
+        _instance = _params.get(Config.InstanceName.key());
+
+        value = _params.get(Config.XenServerSetupMultipath.key());
+        Boolean.parseBoolean(value);
+
+        value = _params.get("xenserver.check.hvm");
+        _checkHvm = false;
+        _connPool = XenServerConnectionPool.getInstance();
+
+        _agentMgr.registerForHostEvents(this, true, false, true);
+
+        createXsToolsISO();
+        _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
+        return true;
+    }
+
+    @Override
+    public boolean matchHypervisor(String hypervisor) {
+        if (hypervisor == null)
+            return true;
+        return Hypervisor.HypervisorType.XenServer.toString().equalsIgnoreCase(hypervisor);
+    }
+
+    @Override
+    public Hypervisor.HypervisorType getHypervisorType() {
+        return Hypervisor.HypervisorType.XenServer;
+    }
+
+    @Override
+    public void postDiscovery(List<HostVO> hosts, long msId) throws DiscoveryException {
+        //do nothing
+    }
+
+    @Override
+    public int getTimeout() {
+        return 0;
+    }
+
+    @Override
+    public boolean isRecurring() {
+        return false;
+    }
+
+    @Override
+    public boolean processAnswers(long agentId, long seq, Answer[] answers) {
+        return false;
+    }
+
+    @Override
+    public boolean processCommands(long agentId, long seq, Command[] commands) {
+        return false;
+    }
+
+    private void createXsToolsISO() {
+        String isoName = "xs-tools.iso";
+        VMTemplateVO tmplt = _tmpltDao.findByTemplateName(isoName);
+        Long id;
+        if (tmplt == null) {
+            id = _tmpltDao.getNextInSequence(Long.class, "id");
+            VMTemplateVO template =
+                    VMTemplateVO.createPreHostIso(id, isoName, isoName, ImageFormat.ISO, true, true, TemplateType.PERHOST, null, null, true, 64, Account.ACCOUNT_ID_SYSTEM,
+                            null, "xen-pv-drv-iso", false, 1, false, HypervisorType.XenServer);
+            _tmpltDao.persist(template);
+        } else {
+            id = tmplt.getId();
+            tmplt.setTemplateType(TemplateType.PERHOST);
+            tmplt.setUrl(null);
+            _tmpltDao.update(id, tmplt);
+        }
+    }
+
+    @Override
+    public void processConnect(com.cloud.host.Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
+        if (!(cmd instanceof StartupRoutingCommand)) {
+            return;
+        }
+        long agentId = agent.getId();
+
+        StartupRoutingCommand startup = (StartupRoutingCommand)cmd;
+        if (startup.getHypervisorType() != HypervisorType.XenServer) {
+            s_logger.debug("Not XenServer so moving on.");
+            return;
+        }
+
+        HostVO host = _hostDao.findById(agentId);
+
+        ClusterVO cluster = _clusterDao.findById(host.getClusterId());
+        if (cluster.getGuid() == null) {
+            cluster.setGuid(startup.getPool());
+            _clusterDao.update(cluster.getId(), cluster);
+        } else if (!cluster.getGuid().equals(startup.getPool())) {
+            String msg = "pool uuid for cluster " + cluster.getId() + " changed from " + cluster.getGuid() + " to " + startup.getPool();
+            s_logger.warn(msg);
+            throw new CloudRuntimeException(msg);
+        }
+        String resource = null;
+        Map<String, String> details = startup.getHostDetails();
+        String prodBrand = details.get("product_brand").trim();
+        String prodVersion = details.get("product_version").trim();
+
+        if (prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") || prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4"))) {
+            resource = XcpServerResource.class.getName();
+        } else if (prodBrand.equals("XCP") && prodVersion.startsWith("1.6")) {
+            resource = XcpServer16Resource.class.getName();
+        } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) {
+            resource = XenServer56Resource.class.getName();
+        } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0")) {
+            resource = XenServer600Resource.class.getName();
+        } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.2")) {
+            resource = XenServer602Resource.class.getName();
+        } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0")) {
+            resource = XenServer610Resource.class.getName();
+        } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.2.0")) {
+            String hotfix = details.get(XenserverConfigs.XS620HotFix);
+            if (hotfix != null && hotfix.equalsIgnoreCase(XenserverConfigs.XSHotFix62ESP1004)) {
+                resource = Xenserver625Resource.class.getName();
+            } else if (hotfix != null && hotfix.equalsIgnoreCase(XenserverConfigs.XSHotFix62ESP1)){
+                resource = XenServer620SP1Resource.class.getName();
+            } else {
+                resource = XenServer620Resource.class.getName();
+            }
+        } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) {
+            String prodVersionTextShort = details.get("product_version_text_short").trim();
+            if ("5.6 SP2".equals(prodVersionTextShort)) {
+                resource = XenServer56SP2Resource.class.getName();
+            } else if ("5.6 FP1".equals(prodVersionTextShort)) {
+                resource = XenServer56FP1Resource.class.getName();
+            }
+        } else if (prodBrand.equals("XCP_Kronos")) {
+            resource = XcpOssResource.class.getName();
+        }
+
+        if (resource == null) {
+            String msg =
+                    "Only support XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; XenServer 5.6, 5.6 FP1, 5.6 SP2 and Xenserver 6.0 , 6.0.2, 6.1.0, 6.2.0 but this one is " +
+                            prodBrand + " " + prodVersion;
+            s_logger.debug(msg);
+            throw new RuntimeException(msg);
+        }
+        if (!resource.equals(host.getResource())) {
+            String msg = "host " + host.getPrivateIpAddress() + " changed from " + host.getResource() + " to " + resource;
+            s_logger.debug(msg);
+            host.setResource(resource);
+            host.setSetup(false);
+            _hostDao.update(agentId, host);
+            throw new HypervisorVersionChangedException(msg);
+        }
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Setting up host " + agentId);
+        }
+        HostEnvironment env = new HostEnvironment();
+
+        SetupCommand setup = new SetupCommand(env);
+        if (_setupMultipath) {
+            setup.setMultipathOn();
+        }
+        if (!host.isSetup()) {
+            setup.setNeedSetup(true);
+        }
+
+        try {
+            Answer answer = _agentMgr.send(agentId, setup);
+            if (answer != null && answer.getResult() && answer instanceof SetupAnswer) {
+                host.setSetup(true);
+                host.setLastPinged((System.currentTimeMillis() >> 10) - 5 * 60);
+                _hostDao.update(host.getId(), host);
+                if (((SetupAnswer)answer).needReconnect()) {
+                    throw new ConnectionException(false, "Reinitialize agent after setup.");
+                }
+                return;
+            } else {
+                s_logger.warn("Unable to setup agent " + agentId + " due to " + ((answer != null) ? answer.getDetails() : "return null"));
+            }
+        } catch (AgentUnavailableException e) {
+            s_logger.warn("Unable to setup agent " + agentId + " because it became unavailable.", e);
+        } catch (OperationTimedoutException e) {
+            s_logger.warn("Unable to setup agent " + agentId + " because it timed out", e);
+        }
+        throw new ConnectionException(true, "Reinitialize agent after setup.");
+    }
+
+    @Override
+    public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
+        return null;
+    }
+
+    @Override
+    public boolean processDisconnect(long agentId, Status state) {
+        return false;
+    }
+
+    @Override
+    public boolean processTimeout(long agentId, long seq) {
+        return false;
+    }
+
+    @Override
+    public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details, List<String> hostTags) {
+        StartupCommand firstCmd = startup[0];
+        if (!(firstCmd instanceof StartupRoutingCommand)) {
+            return null;
+        }
+
+        StartupRoutingCommand ssCmd = ((StartupRoutingCommand)firstCmd);
+        if (ssCmd.getHypervisorType() != HypervisorType.XenServer) {
+            return null;
+        }
+
+        HostPodVO pod = _podDao.findById(host.getPodId());
+        DataCenterVO dc = _dcDao.findById(host.getDataCenterId());
+        s_logger.info("Host: " + host.getName() + " connected with hypervisor type: " + HypervisorType.XenServer + ". Checking CIDR...");
+        _resourceMgr.checkCIDR(pod, dc, ssCmd.getPrivateIpAddress(), ssCmd.getPrivateNetmask());
+        return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.XenServer, details, hostTags);
+    }
+
+    @Override
+    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
+        if (host.getType() != com.cloud.host.Host.Type.Routing || host.getHypervisorType() != HypervisorType.XenServer) {
+            return null;
+        }
+
+        _resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage);
+        return new DeleteHostAnswer(true);
+    }
+
+    @Override
+    protected HashMap<String, Object> buildConfigParams(HostVO host) {
+        HashMap<String, Object> params = super.buildConfigParams(host);
+        DataCenterVO zone = _dcDao.findById(host.getDataCenterId());
+        if (zone != null) {
+            boolean securityGroupEnabled = zone.isSecurityGroupEnabled();
+            params.put("securitygroupenabled", Boolean.toString(securityGroupEnabled));
+        }
+        return params;
+    }
+
+    @Override
+    public boolean stop() {
+        _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
+        return super.stop();
+    }
+}