You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mu...@apache.org on 2012/06/27 01:39:10 UTC
[4/8] Moving out XenServer support code into plugins/hypervisors/xen
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/550b2257/plugins/hypervisors/xen/src/com/cloud/ha/XenServerFencer.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/ha/XenServerFencer.java b/plugins/hypervisors/xen/src/com/cloud/ha/XenServerFencer.java
new file mode 100755
index 0000000..c9c701a
--- /dev/null
+++ b/plugins/hypervisors/xen/src/com/cloud/ha/XenServerFencer.java
@@ -0,0 +1,121 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by 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.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.ha;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+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.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.Inject;
+import com.cloud.vm.VMInstanceVO;
+
+@Local(value=FenceBuilder.class)
+public class XenServerFencer implements FenceBuilder {
+ private static final Logger s_logger = Logger.getLogger(XenServerFencer.class);
+ String _name;
+
+ @Inject HostDao _hostDao;
+ @Inject AgentManager _agentMgr;
+ @Inject ResourceManager _resourceMgr;
+
+ @Override
+ public Boolean fenceOff(VMInstanceVO vm, HostVO 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/incubator-cloudstack/blob/550b2257/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
new file mode 100644
index 0000000..f9e1c89
--- /dev/null
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
@@ -0,0 +1,61 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by 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.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.hypervisor;
+
+import javax.ejb.Local;
+
+import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.storage.GuestOSVO;
+import com.cloud.storage.Storage;
+import com.cloud.storage.dao.GuestOSDao;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.template.VirtualMachineTemplate.BootloaderType;
+import com.cloud.utils.component.Inject;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Local(value=HypervisorGuru.class)
+public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru {
+ @Inject GuestOSDao _guestOsDao;
+
+ protected XenServerGuru() {
+ super();
+ }
+
+ @Override
+ public HypervisorType getHypervisorType() {
+ return HypervisorType.XenServer;
+ }
+
+ @Override
+ public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> 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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/550b2257/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
new file mode 100755
index 0000000..8a6c605
--- /dev/null
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
@@ -0,0 +1,704 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by 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.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.hypervisor.xen.discoverer;
+
+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;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import javax.persistence.EntityExistsException;
+
+import org.apache.log4j.Logger;
+import org.apache.xmlrpc.XmlRpcException;
+
+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.PoolEjectCommand;
+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.DataCenterDao;
+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.xen.resource.CitrixResourceBase;
+import com.cloud.hypervisor.xen.resource.XcpServerResource;
+import com.cloud.hypervisor.xen.resource.XenServer56FP1Resource;
+import com.cloud.hypervisor.xen.resource.XenServer56Resource;
+import com.cloud.hypervisor.xen.resource.XenServer56SP2Resource;
+import com.cloud.hypervisor.xen.resource.XenServer600Resource;
+import com.cloud.hypervisor.xen.resource.XenServer602Resource;
+import com.cloud.hypervisor.xen.resource.XenServerConnectionPool;
+import com.cloud.resource.Discoverer;
+import com.cloud.resource.DiscovererBase;
+import com.cloud.resource.ResourceManager;
+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.storage.dao.VMTemplateHostDao;
+import com.cloud.user.Account;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.SearchCriteria2;
+import com.cloud.utils.db.SearchCriteriaService;
+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.Pool;
+import com.xensource.xenapi.Session;
+import com.xensource.xenapi.Types.SessionAuthenticationFailed;
+import com.xensource.xenapi.Types.XenAPIException;
+
+@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;
+
+ @Inject protected AlertManager _alertMgr;
+ @Inject protected AgentManager _agentMgr;
+ @Inject VMTemplateDao _tmpltDao;
+ @Inject VMTemplateHostDao _vmTemplateHostDao;
+ @Inject ResourceManager _resourceMgr;
+ @Inject HostPodDao _podDao;
+ @Inject DataCenterDao _dcDao;
+
+ protected XcpServerDiscoverer() {
+ }
+
+ void setClusterGuid(ClusterVO cluster, String guid) {
+ cluster.setGuid(guid);
+ try {
+ _clusterDao.update(cluster.getId(), cluster);
+ } catch (EntityExistsException e) {
+ SearchCriteriaService<ClusterVO, ClusterVO> sc = SearchCriteria2.create(ClusterVO.class);
+ sc.addAnd(sc.getEntity().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;
+ }
+ }
+
+ @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 {
+ List<HostVO> eHosts = _resourceMgr.listAllHostsInCluster(clusterId);
+ if( eHosts.size() > 0 ) {
+ HostVO eHost = eHosts.get(0);
+ _hostDao.loadDetails(eHost);
+ }
+ String hostname = url.getHost();
+ InetAddress ia = InetAddress.getByName(hostname);
+ String hostIp = ia.getHostAddress();
+ Queue<String> pass=new LinkedList<String>();
+ pass.add(password);
+ String masterIp = _connPool.getMasterIp(hostIp, username, pass);
+ conn = _connPool.masterConnect(masterIp, 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);
+
+ /*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)) {
+ if (hosts.size() == 1) {
+ if (!addHostsToPool(conn, hostIp, clusterId)) {
+ String msg = "Unable to add host(" + hostIp + ") to cluster " + clusterId;
+ s_logger.warn(msg);
+ throw new DiscoveryException(msg);
+ }
+ } else {
+ String msg = "Host (" + hostIp + ") is already in pool(" + poolUuid + "), can to join pool(" + clu.getGuid() + ")";
+ 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 ) {
+ }
+ 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.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");
+ String xenVersion = record.softwareVersion.get("xen");
+ String hostOS = record.softwareVersion.get("product_brand");
+ 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);
+ 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);
+ }
+
+
+ params.put("wait", Integer.toString(_wait));
+ details.put("wait", Integer.toString(_wait));
+ params.put("migratewait", _configDao.getValue(Config.MigrateWait.toString()));
+ params.put(Config.InstanceName.toString().toLowerCase(), _instance);
+ details.put(Config.InstanceName.toString().toLowerCase(), _instance);
+ try {
+ resource.configure("Xen Server", params);
+ } catch (ConfigurationException e) {
+ _alertMgr.sendAlert(AlertManager.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 boolean addHostsToPool(Connection conn, String hostIp, Long clusterId) throws XenAPIException, XmlRpcException, DiscoveryException {
+
+ List<HostVO> hosts;
+ hosts = _resourceMgr.listAllHostsInCluster(clusterId);
+
+ String masterIp = null;
+ String username = null;
+ String password = null;
+ Queue<String> pass=new LinkedList<String>();
+ for (HostVO host : hosts) {
+ _hostDao.loadDetails(host);
+ username = host.getDetail("username");
+ password = host.getDetail("password");
+ pass.add(password);
+ String address = host.getPrivateIpAddress();
+ Connection hostConn = _connPool.slaveConnect(address, username, pass);
+ if (hostConn == null) {
+ continue;
+ }
+ try {
+ Set<Pool> pools = Pool.getAll(hostConn);
+ Pool pool = pools.iterator().next();
+ masterIp = pool.getMaster(hostConn).getAddress(hostConn);
+ break;
+
+ } catch (Exception e ) {
+ s_logger.warn("Can not get master ip address from host " + address);
+ } finally {
+ try{
+ Session.localLogout(hostConn);
+ } catch (Exception e ) {
+ }
+ hostConn.dispose();
+ hostConn = null;
+ }
+ }
+
+ if (masterIp == null) {
+ s_logger.warn("Unable to reach the pool master of the existing cluster");
+ throw new CloudRuntimeException("Unable to reach the pool master of the existing cluster");
+ }
+
+ if( !_connPool.joinPool(conn, hostIp, masterIp, username, pass) ){
+ s_logger.warn("Unable to join the pool");
+ throw new DiscoveryException("Unable to join the pool");
+ }
+ return true;
+ }
+
+ protected CitrixResourceBase createServerResource(long dcId, Long podId, Host.Record record) {
+ String prodBrand = record.softwareVersion.get("product_brand").trim();
+ String prodVersion = record.softwareVersion.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") ))
+ return new XcpServerResource();
+
+ if(prodBrand.equals("XenServer") && prodVersion.equals("5.6.0"))
+ return new XenServer56Resource();
+
+ if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0"))
+ return new XenServer600Resource();
+
+ if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.2"))
+ return new XenServer602Resource();
+
+ 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();
+ }
+ }
+
+ String msg = "Only support XCP 1.0.0, 1.1.0, 1.5 beta; XenServer 5.6, XenServer 5.6 FP1, XenServer 5.6 SP2, Xenserver 6.0, 6.0.2 but this one is " + prodBrand + " " + prodVersion;
+ _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, msg, msg);
+ s_logger.debug(msg);
+ throw new RuntimeException(msg);
+ }
+
+ protected void serverConfig() {
+ String value = _params.get(Config.XenSetupMultipath.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.XenPublicNetwork.key());
+ _privateNic = _params.get(Config.XenPrivateNetwork.key());
+
+ _storageNic1 = _params.get(Config.XenStorageNetwork1.key());
+ _storageNic2 = _params.get(Config.XenStorageNetwork2.key());
+
+ _guestNic = _params.get(Config.XenGuestNetwork.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.XenSetupMultipath.key());
+ Boolean.parseBoolean(value);
+
+ value = _params.get("xen.check.hvm");
+ _checkHvm = value == null ? true : Boolean.parseBoolean(value);
+
+ _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 = new VMTemplateVO(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(HostVO 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 " + cmd.getPod();
+ 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("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("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();
+ }
+ }
+ if( resource == null ){
+ String msg = "Only support XCP 1.0.0, 1.1.0, 1.5 beta; XenServer 5.6, 5.6 FP1, 5.6 SP2 and Xenserver 6.0 , 6.0.2 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 {
+ SetupAnswer answer = (SetupAnswer)_agentMgr.send(agentId, setup);
+ if (answer != null && answer.getResult()) {
+ host.setSetup(true);
+ host.setLastPinged((System.currentTimeMillis()>>10) - 5 * 60 );
+ _hostDao.update(host.getId(), host);
+ if ( 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);
+ if (host.getClusterId() != null) {
+ List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(com.cloud.host.Host.Type.Routing, host.getClusterId(), host.getPodId(), host.getDataCenterId());
+ boolean success = true;
+ for (HostVO thost : hosts) {
+ if (thost.getId() == host.getId()) {
+ continue;
+ }
+
+ long thostId = thost.getId();
+ PoolEjectCommand eject = new PoolEjectCommand(host.getGuid());
+ Answer answer = _agentMgr.easySend(thostId, eject);
+ if (answer != null && answer.getResult()) {
+ s_logger.debug("Eject Host: " + host.getId() + " from " + thostId + " Succeed");
+ success = true;
+ break;
+ } else {
+ success = false;
+ s_logger.warn("Eject Host: " + host.getId() + " from " + thostId + " failed due to " + (answer != null ? answer.getDetails() : "no answer"));
+ }
+ }
+ if (!success) {
+ String msg = "Unable to eject host " + host.getGuid() + " due to there is no host up in this cluster, please execute xe pool-eject host-uuid="
+ + host.getGuid() + "in this host " + host.getPrivateIpAddress();
+ s_logger.warn(msg);
+ _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Unable to eject host " + host.getGuid(), msg);
+ }
+ }
+
+ return new DeleteHostAnswer(true);
+ }
+
+ @Override
+ public boolean stop() {
+ _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
+ return super.stop();
+ }
+}