| // 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.ovm3.resources; |
| |
| import java.io.IOException; |
| 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.inject.Inject; |
| import javax.naming.ConfigurationException; |
| |
| import org.apache.log4j.Logger; |
| |
| 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.StartupCommand; |
| import com.cloud.agent.api.StartupRoutingCommand; |
| import com.cloud.configuration.Config; |
| 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.HostInfo; |
| 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.hypervisor.ovm3.objects.Connection; |
| import com.cloud.hypervisor.ovm3.objects.Linux; |
| import com.cloud.hypervisor.ovm3.objects.Ovm3ResourceException; |
| 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.utils.db.QueryBuilder; |
| import com.cloud.utils.db.SearchCriteria; |
| import com.cloud.utils.exception.CloudRuntimeException; |
| import com.cloud.utils.ssh.SSHCmdHelper; |
| |
| public class Ovm3Discoverer extends DiscovererBase implements Discoverer, |
| Listener, ResourceStateAdapter { |
| private static final Logger LOGGER = Logger.getLogger(Ovm3Discoverer.class); |
| protected String publicNetworkDevice; |
| protected String privateNetworkDevice; |
| protected String guestNetworkDevice; |
| protected String storageNetworkDevice; |
| |
| @Inject |
| ClusterDao clusterDao; |
| @Inject |
| ClusterDetailsDao clusterDetailsDao; |
| @Inject |
| ResourceManager resourceMgr; |
| @Inject |
| AgentManager agentMgr; |
| @Inject |
| HostDao hostDao = null; |
| |
| protected Ovm3Discoverer() { |
| } |
| |
| @Override |
| public boolean configure(String name, Map<String, Object> params) |
| throws ConfigurationException { |
| boolean success = super.configure(name, params); |
| if (!success) { |
| return false; |
| } |
| |
| /* these are in Config.java */ |
| publicNetworkDevice = _params.get(Config.Ovm3PublicNetwork.key()); |
| privateNetworkDevice = _params.get(Config.Ovm3PrivateNetwork.key()); |
| guestNetworkDevice = _params.get(Config.Ovm3GuestNetwork.key()); |
| storageNetworkDevice = _params.get(Config.Ovm3StorageNetwork.key()); |
| resourceMgr.registerResourceStateAdapter(this.getClass() |
| .getSimpleName(), this); |
| return true; |
| } |
| |
| @Override |
| public boolean stop() { |
| resourceMgr.unregisterResourceStateAdapter(this.getClass() |
| .getSimpleName()); |
| return super.stop(); |
| } |
| |
| private boolean checkIfExisted(String guid) { |
| QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class); |
| sc.and(sc.entity().getGuid(), SearchCriteria.Op.EQ, guid); |
| sc.and(sc.entity().getHypervisorType(), SearchCriteria.Op.EQ, |
| HypervisorType.Ovm3); |
| List<HostVO> hosts = sc.list(); |
| return !hosts.isEmpty(); |
| } |
| |
| private boolean CheckUrl(URI url) throws DiscoveryException { |
| if ("http".equals(url.getScheme()) || "https".equals(url.getScheme())) { |
| String msg = "Discovering " + url + ": " + _params; |
| LOGGER.debug(msg); |
| } else { |
| String msg = "urlString is not http(s) so we're not taking care of the discovery for this: " |
| + url; |
| LOGGER.info(msg); |
| throw new DiscoveryException(msg); |
| } |
| return true; |
| } |
| |
| @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 { |
| Connection c = null; |
| |
| CheckUrl(url); |
| if (clusterId == null) { |
| String msg = "must specify cluster Id when add host"; |
| LOGGER.info(msg); |
| throw new DiscoveryException(msg); |
| } |
| |
| if (podId == null) { |
| String msg = "must specify pod Id when add host"; |
| LOGGER.info(msg); |
| throw new DiscoveryException(msg); |
| } |
| |
| ClusterVO cluster = clusterDao.findById(clusterId); |
| if (cluster == null |
| || (cluster.getHypervisorType() != HypervisorType.Ovm3)) { |
| String msg = "invalid cluster id or cluster is not for Ovm3 hypervisors"; |
| LOGGER.info(msg); |
| throw new DiscoveryException(msg); |
| } else { |
| LOGGER.debug("cluster: " + cluster); |
| } |
| |
| String agentUsername = _params.get("agentusername"); |
| if (agentUsername == null) { |
| String msg = "Agent user name must be specified"; |
| LOGGER.info(msg); |
| throw new DiscoveryException(msg); |
| } |
| |
| String agentPassword = _params.get("agentpassword"); |
| if (agentPassword == null) { |
| String msg = "Agent password must be specified"; |
| LOGGER.info(msg); |
| throw new DiscoveryException(msg); |
| } |
| |
| String agentPort = _params.get("agentport"); |
| if (agentPort == null) { |
| String msg = "Agent port must be specified"; |
| LOGGER.info(msg); |
| throw new DiscoveryException(msg); |
| } |
| |
| try { |
| String hostname = url.getHost(); |
| |
| InetAddress ia = InetAddress.getByName(hostname); |
| String hostIp = ia.getHostAddress(); |
| String guid = UUID.nameUUIDFromBytes(hostIp.getBytes("UTF8")) |
| .toString(); |
| |
| if (checkIfExisted(guid)) { |
| String msg = "The host " + hostIp + " has been added before"; |
| LOGGER.info(msg); |
| throw new DiscoveryException(msg); |
| } |
| |
| LOGGER.debug("Ovm3 discover is going to disover host having guid " |
| + guid); |
| |
| ClusterVO clu = clusterDao.findById(clusterId); |
| if (clu.getGuid() == null) { |
| clu.setGuid(UUID.randomUUID().toString()); |
| } |
| clusterDao.update(clusterId, clu); |
| Map<String, String> clusterDetails = clusterDetailsDao |
| .findDetails(clusterId); |
| String ovm3vip = (clusterDetails.get("ovm3vip") == null) ? "" |
| : clusterDetails.get("ovm3vip"); |
| String ovm3pool = (clusterDetails.get("ovm3pool") == null) ? "false" |
| : clusterDetails.get("ovm3pool"); |
| String ovm3cluster = (clusterDetails.get("ovm3cluster") == null) ? "false" |
| : clusterDetails.get("ovm3cluster"); |
| |
| /* should perhaps only make this connect to the agent port ? */ |
| com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection( |
| hostIp, 22); |
| sshConnection.connect(null, 60000, 60000); |
| sshConnection = SSHCmdHelper.acquireAuthorizedConnection(hostIp, |
| username, password); |
| if (sshConnection == null) { |
| String msg = "Cannot Ssh to Ovm3 host(IP=" + hostIp |
| + ", username=" + username |
| + ", password=*******), discovery failed"; |
| LOGGER.warn(msg); |
| throw new DiscoveryException(msg); |
| } |
| |
| Map<String, String> details = new HashMap<String, String>(); |
| Ovm3HypervisorResource ovmResource = new Ovm3HypervisorResource(); |
| details.put("ip", hostIp); |
| details.put("host", hostname); |
| details.put("username", username); |
| details.put("password", password); |
| details.put("zone", Long.toString(dcId)); |
| details.put("guid", guid); |
| details.put("pod", Long.toString(podId)); |
| details.put("cluster", Long.toString(clusterId)); |
| details.put("agentusername", agentUsername); |
| details.put("agentpassword", agentPassword); |
| details.put("agentport", agentPort.toString()); |
| details.put("ovm3vip", ovm3vip); |
| details.put("ovm3pool", ovm3pool); |
| details.put("ovm3cluster", ovm3cluster); |
| |
| if (publicNetworkDevice != null) { |
| details.put("public.network.device", publicNetworkDevice); |
| } |
| if (privateNetworkDevice != null) { |
| details.put("private.network.device", privateNetworkDevice); |
| } |
| if (guestNetworkDevice != null) { |
| details.put("guest.network.device", guestNetworkDevice); |
| } |
| if (storageNetworkDevice != null) { |
| details.put("storage.network.device", storageNetworkDevice); |
| } |
| |
| Map<String, Object> params = new HashMap<String, Object>(); |
| params.putAll(details); |
| |
| ovmResource.configure(hostname, params); |
| ovmResource.start(); |
| |
| c = new Connection(hostIp, Integer.parseInt(agentPort), |
| agentUsername, agentPassword); |
| |
| /* After resource start, we are able to execute our agent api */ |
| Linux host = new Linux(c); |
| details.put("agentVersion", host.getAgentVersion()); |
| details.put(HostInfo.HOST_OS_KERNEL_VERSION, |
| host.getHostKernelRelease()); |
| details.put(HostInfo.HOST_OS, host.getHostOs()); |
| details.put(HostInfo.HOST_OS_VERSION, host.getHostOsVersion()); |
| details.put(HostInfo.HYPERVISOR_VERSION, |
| host.getHypervisorVersion()); |
| |
| Map<Ovm3HypervisorResource, Map<String, String>> resources = new HashMap<Ovm3HypervisorResource, Map<String, String>>(); |
| resources.put(ovmResource, details); |
| return resources; |
| } catch (UnknownHostException e) { |
| LOGGER.error( |
| "Host name resolve failed exception, Unable to discover Ovm3 host: " |
| + url.getHost(), e); |
| return null; |
| } catch (ConfigurationException e) { |
| LOGGER.error( |
| "Configure resource failed, Unable to discover Ovm3 host: " |
| + url.getHost(), e); |
| return null; |
| } catch (IOException | Ovm3ResourceException e) { |
| LOGGER.error("Unable to discover Ovm3 host: " + url.getHost(), e); |
| return null; |
| } |
| } |
| |
| @Override |
| public void postDiscovery(List<HostVO> hosts, long msId) |
| throws CloudRuntimeException { |
| LOGGER.debug("postDiscovery: " + hosts); |
| } |
| |
| @Override |
| public boolean matchHypervisor(String hypervisor) { |
| return HypervisorType.Ovm3.toString().equalsIgnoreCase(hypervisor); |
| } |
| |
| @Override |
| public HypervisorType getHypervisorType() { |
| return HypervisorType.Ovm3; |
| } |
| |
| @Override |
| public HostVO createHostVOForConnectedAgent(HostVO host, |
| StartupCommand[] cmd) { |
| LOGGER.debug("createHostVOForConnectedAgent: " + host); |
| return null; |
| } |
| |
| @Override |
| public boolean processAnswers(long agentId, long seq, Answer[] answers) { |
| LOGGER.debug("processAnswers: " + agentId); |
| return false; |
| } |
| |
| @Override |
| public boolean processCommands(long agentId, long seq, Command[] commands) { |
| LOGGER.debug("processCommands: " + agentId); |
| return false; |
| } |
| |
| @Override |
| public AgentControlAnswer processControlCommand(long agentId, |
| AgentControlCommand cmd) { |
| LOGGER.debug("processControlCommand: " + agentId); |
| return null; |
| } |
| |
| @Override |
| public void processHostAdded(long hostId) { |
| } |
| |
| /* for reconnecting */ |
| @Override |
| public void processConnect(Host host, StartupCommand cmd, |
| boolean forRebalance) { |
| LOGGER.debug("processConnect"); |
| } |
| |
| @Override |
| public boolean processDisconnect(long agentId, Status state) { |
| LOGGER.debug("processDisconnect"); |
| return false; |
| } |
| |
| @Override |
| public void processHostAboutToBeRemoved(long hostId) { |
| } |
| |
| @Override |
| public void processHostRemoved(long hostId, long clusterId) { |
| } |
| |
| @Override |
| public boolean isRecurring() { |
| return false; |
| } |
| |
| @Override |
| public int getTimeout() { |
| LOGGER.debug("getTimeout"); |
| return 0; |
| } |
| |
| @Override |
| public boolean processTimeout(long agentId, long seq) { |
| LOGGER.debug("processTimeout: " + agentId); |
| return false; |
| } |
| |
| @Override |
| public HostVO createHostVOForDirectConnectAgent(HostVO host, |
| StartupCommand[] startup, ServerResource resource, |
| Map<String, String> details, List<String> hostTags) { |
| LOGGER.debug("createHostVOForDirectConnectAgent: " + host); |
| StartupCommand firstCmd = startup[0]; |
| if (!(firstCmd instanceof StartupRoutingCommand)) { |
| return null; |
| } |
| |
| StartupRoutingCommand ssCmd = (StartupRoutingCommand) firstCmd; |
| if (ssCmd.getHypervisorType() != HypervisorType.Ovm3) { |
| return null; |
| } |
| |
| return resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.Ovm3, |
| details, hostTags); |
| } |
| |
| @Override |
| public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, |
| boolean isForceDeleteStorage) throws UnableDeleteHostException { |
| LOGGER.debug("deleteHost: " + host); |
| if (host.getType() != com.cloud.host.Host.Type.Routing |
| || host.getHypervisorType() != HypervisorType.Ovm3) { |
| return null; |
| } |
| |
| resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage); |
| return new DeleteHostAnswer(true); |
| } |
| |
| } |