| // 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 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.inject.Inject; |
| import javax.naming.ConfigurationException; |
| import javax.persistence.EntityExistsException; |
| |
| import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs; |
| 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.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.CitrixHelper; |
| import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; |
| import com.cloud.hypervisor.xenserver.resource.XcpOssResource; |
| 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.XenServer610Resource; |
| import com.cloud.hypervisor.xenserver.resource.XenServer620Resource; |
| import com.cloud.hypervisor.xenserver.resource.XenServer620SP1Resource; |
| import com.cloud.hypervisor.xenserver.resource.XenServer650Resource; |
| 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; |
| |
| |
| public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter { |
| private static final Logger s_logger = Logger.getLogger(XcpServerDiscoverer.class); |
| private int _wait; |
| private XenServerConnectionPool _connPool; |
| private boolean _checkHvm; |
| private boolean _setupMultipath; |
| private String _instance; |
| |
| @Inject |
| private AlertManager _alertMgr; |
| @Inject |
| private AgentManager _agentMgr; |
| @Inject |
| private VMTemplateDao _tmpltDao; |
| @Inject |
| private HostPodDao _podDao; |
| |
| private String xenServerIsoName = "xs-tools.iso"; |
| private String xenServerIsoDisplayText = "XenServer Tools Installer ISO (xen-pv-drv-iso)"; |
| |
| 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 != null && 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 = CitrixHelper.getProductVersion(record); |
| 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.XenServerHeartBeatTimeout.toString().toLowerCase(), _configDao.getValue(Config.XenServerHeartBeatTimeout.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(String prodBrand, String prodVersion, String prodVersionTextShort, String hotfix) { |
| // 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") || prodVersion.startsWith("1.6"))) { |
| return new XcpServerResource(); |
| } // 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 XenServer600Resource(); |
| } 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 != null && hotfix.equals(XenserverConfigs.XSHotFix62ESP1004)) { |
| return new Xenserver625Resource(); |
| } else if (hotfix != null && hotfix.equals(XenserverConfigs.XSHotFix62ESP1)) { |
| return new XenServer620SP1Resource(); |
| } else { |
| return new XenServer620Resource(); |
| } |
| } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) { |
| if ("5.6 SP2".equals(prodVersionTextShort.trim())) { |
| return new XenServer56SP2Resource(); |
| } else if ("5.6 FP1".equals(prodVersionTextShort.trim())) { |
| return new XenServer56FP1Resource(); |
| } |
| } else if (prodBrand.equals("XCP_Kronos")) { |
| return new XcpOssResource(); |
| } else if (prodBrand.equals("XenServer") || prodBrand.equals("XCP-ng")) { |
| final String[] items = prodVersion.split("\\."); |
| if ((Integer.parseInt(items[0]) > 6) || |
| (Integer.parseInt(items[0]) == 6 && Integer.parseInt(items[1]) >= 4)) { |
| s_logger.warn("defaulting to xenserver650 resource for product brand: " + prodBrand + " with product " + |
| "version: " + prodVersion); |
| //default to xenserver650 resource. |
| return new XenServer650Resource(); |
| } |
| } |
| 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, >6.4.0 but this one is " + |
| prodBrand + " " + prodVersion; |
| s_logger.warn(msg); |
| throw new RuntimeException(msg); |
| } |
| |
| |
| |
| 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 = CitrixHelper.getProductVersion(record); |
| |
| String prodVersionTextShort = record.softwareVersion.get("product_version_text_short"); |
| return createServerResource(prodBrand, prodVersion, prodVersionTextShort, hotfix); |
| } |
| |
| 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(); |
| |
| 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("xenserver.check.hvm"); |
| _checkHvm = Boolean.parseBoolean(value); |
| _connPool = XenServerConnectionPool.getInstance(); |
| |
| _agentMgr.registerForHostEvents(this, true, false, true); |
| |
| createXenServerToolsIsoEntryInDatabase(); |
| _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; |
| } |
| |
| /** |
| * Create the XenServer tools ISO entry in the database. |
| * If there is already an entry with 'isoName' equals to {@value #xenServerIsoName} , we update its 'displayText' to {@value #xenServerIsoDisplayText}. |
| * Otherwise, we create a new entry. |
| */ |
| protected void createXenServerToolsIsoEntryInDatabase() { |
| VMTemplateVO tmplt = _tmpltDao.findByTemplateName(xenServerIsoName); |
| if (tmplt == null) { |
| long id = _tmpltDao.getNextInSequence(Long.class, "id"); |
| VMTemplateVO template = VMTemplateVO.createPreHostIso(id, xenServerIsoName, xenServerIsoName, ImageFormat.ISO, true, true, TemplateType.PERHOST, null, null, true, 64, |
| Account.ACCOUNT_ID_SYSTEM, null, xenServerIsoDisplayText, false, 1, false, HypervisorType.XenServer); |
| _tmpltDao.persist(template); |
| } else { |
| long id = tmplt.getId(); |
| tmplt.setTemplateType(TemplateType.PERHOST); |
| tmplt.setUrl(null); |
| tmplt.setDisplayText(xenServerIsoDisplayText); |
| _tmpltDao.update(id, tmplt); |
| } |
| } |
| |
| @Override |
| public void processHostAdded(long hostId) { |
| } |
| |
| @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); |
| } |
| |
| Map<String, String> details = startup.getHostDetails(); |
| String prodBrand = details.get("product_brand").trim(); |
| String prodVersion = details.get("product_version").trim(); |
| String hotfix = details.get(XenserverConfigs.XS620HotFix); |
| String prodVersionTextShort = details.get("product_version_text_short"); |
| |
| String resource = createServerResource(prodBrand, prodVersion, prodVersionTextShort, hotfix).getClass().getName(); |
| |
| 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); |
| host.setHypervisorVersion(prodVersion); |
| _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 void processHostAboutToBeRemoved(long hostId) { |
| } |
| |
| @Override |
| public void processHostRemoved(long hostId, long clusterId) { |
| } |
| |
| @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(); |
| } |
| } |