| // 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.hyperv; |
| |
| import java.net.InetAddress; |
| import java.net.URI; |
| import java.net.UnknownHostException; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.UUID; |
| |
| import javax.ejb.Local; |
| import javax.inject.Inject; |
| import javax.naming.ConfigurationException; |
| |
| import org.apache.log4j.Logger; |
| |
| import com.cloud.agent.api.Command; |
| import com.cloud.agent.api.StartupVMMAgentCommand; |
| import com.cloud.agent.transport.Request; |
| import com.cloud.alert.AlertManager; |
| import com.cloud.dc.ClusterDetailsDao; |
| import com.cloud.dc.ClusterVO; |
| import com.cloud.dc.dao.ClusterDao; |
| import com.cloud.exception.DiscoveryException; |
| import com.cloud.host.Host; |
| import com.cloud.host.HostVO; |
| import com.cloud.host.dao.HostDao; |
| import com.cloud.hypervisor.Hypervisor; |
| import com.cloud.hypervisor.Hypervisor.HypervisorType; |
| import com.cloud.hypervisor.hyperv.resource.HypervDummyResourceBase; |
| import com.cloud.resource.Discoverer; |
| import com.cloud.resource.DiscovererBase; |
| import com.cloud.resource.ResourceManager; |
| import com.cloud.resource.ServerResource; |
| import com.cloud.utils.nio.HandlerFactory; |
| import com.cloud.utils.nio.Link; |
| import com.cloud.utils.nio.NioClient; |
| import com.cloud.utils.nio.Task; |
| import com.cloud.utils.nio.Task.Type; |
| |
| @Local(value=Discoverer.class) |
| public class HypervServerDiscoverer extends DiscovererBase implements Discoverer, HandlerFactory{ |
| private static final Logger s_logger = Logger.getLogger(HypervServerDiscoverer.class); |
| private int _waitTime = 1; |
| |
| @Inject ClusterDao _clusterDao; |
| @Inject AlertManager _alertMgr; |
| @Inject ClusterDetailsDao _clusterDetailsDao; |
| @Inject HostDao _hostDao = null; |
| @Inject ResourceManager _resourceMgr; |
| Link _link; |
| |
| @SuppressWarnings("static-access") |
| @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 { |
| |
| if(s_logger.isInfoEnabled()) { |
| s_logger.info("Discover host. dc: " + dcId + ", pod: " + podId + ", cluster: " + clusterId + ", uri host: " + url.getHost()); |
| } |
| |
| if(podId == null) { |
| if(s_logger.isInfoEnabled()) { |
| s_logger.info("No pod is assigned, skipping the discovery in Hyperv discoverer"); |
| } |
| return null; |
| } |
| |
| if (!url.getScheme().equals("http")) { |
| String msg = "urlString is not http so HypervServerDiscoverer taking care of the discovery for this: " + url; |
| s_logger.debug(msg); |
| return null; |
| } |
| |
| ClusterVO cluster = _clusterDao.findById(clusterId); |
| if(cluster == null || cluster.getHypervisorType() != HypervisorType.Hyperv) { |
| if(s_logger.isInfoEnabled()) { |
| s_logger.info("invalid cluster id or cluster is not for Hyperv hypervisors"); |
| } |
| return null; |
| } |
| String clusterName = cluster.getName(); |
| |
| try { |
| |
| String hostname = url.getHost(); |
| InetAddress ia = InetAddress.getByName(hostname); |
| String agentIp = ia.getHostAddress(); |
| String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString(); |
| String guidWithTail = guid + "-HypervResource";/*tail added by agent.java*/ |
| if (_resourceMgr.findHostByGuid(guidWithTail) != null) { |
| s_logger.debug("Skipping " + agentIp + " because " + guidWithTail + " is already in the database."); |
| return null; |
| } |
| |
| // bootstrap SCVMM agent to connect back to management server |
| NioClient _connection = new NioClient("HypervAgentClient", url.getHost(), 9000, 1, this); |
| _connection.start(); |
| |
| StartupVMMAgentCommand cmd = new StartupVMMAgentCommand( |
| dcId, |
| podId, |
| clusterName, |
| guid, |
| InetAddress.getLocalHost().getHostAddress(), |
| "8250", |
| HypervServerDiscoverer.class.getPackage().getImplementationVersion()); |
| |
| // send bootstrap command to agent running on SCVMM host |
| s_logger.info("sending bootstrap request to SCVMM agent on host "+ url.getHost()); |
| Request request = new Request(0, 0, cmd, false); |
| |
| // :FIXME without sleep link.send failing why?????? |
| Thread.currentThread().sleep(5000); |
| _link.send(request.toBytes()); |
| |
| //wait for SCVMM agent to connect back |
| HostVO connectedHost = waitForHostConnect(dcId, podId, clusterId, guidWithTail); |
| if (connectedHost == null) |
| { |
| s_logger.info("SCVMM agent did not connect back after sending bootstrap request"); |
| return null; |
| } |
| |
| //disconnect |
| s_logger.info("SCVMM agent connected back after sending bootstrap request"); |
| _connection.stop(); |
| |
| Map<HypervDummyResourceBase, Map<String, String>> resources = new HashMap<HypervDummyResourceBase, Map<String, String>>(); |
| Map<String, String> details = new HashMap<String, String>(); |
| Map<String, Object> params = new HashMap<String, Object>(); |
| HypervDummyResourceBase resource = new HypervDummyResourceBase(); |
| |
| details.put("url", url.getHost()); |
| details.put("username", username); |
| details.put("password", password); |
| resources.put(resource, details); |
| |
| params.put("zone", Long.toString(dcId)); |
| params.put("pod", Long.toString(podId)); |
| params.put("cluster", Long.toString(clusterId)); |
| |
| resource.configure("Hyperv", params); |
| return resources; |
| } catch (ConfigurationException e) { |
| _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, "Unable to add " + url.getHost(), "Error is " + e.getMessage()); |
| s_logger.warn("Unable to instantiate " + url.getHost(), e); |
| } catch (UnknownHostException e) { |
| _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, "Unable to add " + url.getHost(), "Error is " + e.getMessage()); |
| s_logger.warn("Unable to instantiate " + url.getHost(), e); |
| } catch (Exception e) { |
| s_logger.info("exception " + e.toString()); |
| } |
| return null; |
| } |
| |
| @Override |
| public void postDiscovery(List<HostVO> hosts, long msId) { |
| // do nothing |
| } |
| |
| @Override |
| public boolean matchHypervisor(String hypervisor) { |
| if(hypervisor == null) { |
| return true; |
| } |
| |
| return Hypervisor.HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor); |
| } |
| |
| @Override |
| public Hypervisor.HypervisorType getHypervisorType() { |
| return Hypervisor.HypervisorType.Hyperv; |
| } |
| |
| @Override |
| public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { |
| super.configure(name, params); |
| return true; |
| } |
| |
| @Override |
| public Task create(Type type, Link link, byte[] data) { |
| _link = link; |
| return new BootStrapTakHandler(type, link, data); |
| } |
| |
| private HostVO waitForHostConnect(long dcId, long podId, long clusterId, String guid) { |
| for (int i = 0; i < _waitTime *2; i++) { |
| List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId); |
| for (HostVO host : hosts) { |
| if (host.getGuid().equalsIgnoreCase(guid)) { |
| return host; |
| } |
| } |
| try { |
| Thread.sleep(30000); |
| } catch (InterruptedException e) { |
| s_logger.debug("Failed to sleep: " + e.toString()); |
| } |
| } |
| s_logger.debug("Timeout, to wait for the host connecting to mgt svr, assuming it is failed"); |
| return null; |
| } |
| |
| // class to handle the bootstrap command from the management server |
| public class BootStrapTakHandler extends Task { |
| |
| public BootStrapTakHandler(Task.Type type, Link link, byte[] data) { |
| super(type, link, data); |
| s_logger.info("created new BootStrapTakHandler"); |
| } |
| |
| protected void processRequest(final Link link, final Request request) { |
| final Command[] cmds = request.getCommands(); |
| Command cmd = cmds[0]; |
| } |
| |
| @Override |
| protected void doTask(Task task) throws Exception { |
| final Type type = task.getType(); |
| s_logger.info("recieved task of type "+type.toString() +" in BootStrapTakHandler"); |
| } |
| } |
| } |
| |
| |