blob: 3f245273a272ea6cb7157408c3281bb82c835bff [file] [log] [blame]
// 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);
}
}