package org.ovirt.engine.core.services;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ovirt.engine.core.bll.interfaces.BackendInternal;
import org.ovirt.engine.core.common.businessentities.VdsStatic;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.common.queries.hostdeploy.RegisterVdsParameters;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.utils.PKIResources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RegisterServlet extends HttpServlet {
private static final Logger log = LoggerFactory.getLogger(RegisterServlet.class);
private static final int VDSM_PORT = 54321;
private static final int INTERFACE_VERSION = 1;
@Inject
private BackendInternal backend;
protected void getVersionV1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
log.info(
"Version request: source={}', secured='{}'",
request.getRemoteHost(),
request.isSecure()
);
try (PrintWriter out = response.getWriter()) {
response.setContentType("text/plain");
out.print(INTERFACE_VERSION);
}
}
protected void getPKITrustV1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
log.info(
"PKI Trust request: source='{}', secured='{}'",
request.getRemoteHost(),
request.isSecure()
);
try (PrintWriter out = response.getWriter()) {
response.setContentType(PKIResources.getCaCertificate().getContentType(PKIResources.Format.X509_PEM_CA));
out.print(PKIResources.getCaCertificate().toString(PKIResources.Format.X509_PEM_CA));
}
}
protected void getSSHTrustV1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
log.info(
"SSH Trust request: source='{}', secured='{}'",
request.getRemoteHost(),
request.isSecure()
);
try (PrintWriter out = response.getWriter()) {
response.setContentType(PKIResources.getEngineCertificate().getContentType(PKIResources.Format.OPENSSH_PUBKEY));
out.print(PKIResources.getEngineCertificate().toString(PKIResources.Format.OPENSSH_PUBKEY));
}
}
protected void doRegister(
String hostAddress,
int hostSSHPort,
String hostSSHKeyFingerprint,
String hostSSHUser,
int hostVdsPort,
String hostName,
String hostUniqueId
) {
if (hostSSHUser == null) {
hostSSHUser = "root";
}
if (hostName == null) {
hostName = hostAddress;
}
if (hostUniqueId == null) {
throw new RuntimeException("Unique id was not provided");
}
VdcQueryReturnValue queryReturnValue = backend.runInternalQuery(
VdcQueryType.RegisterVds,
new RegisterVdsParameters(
Guid.Empty,
hostAddress,
hostSSHPort,
hostSSHKeyFingerprint,
hostSSHUser,
hostName,
hostUniqueId,
hostVdsPort,
Guid.Empty
)
);
if (queryReturnValue == null) {
throw new RuntimeException("runInternalQuery failed (null)");
}
if (!queryReturnValue.getSucceeded()) {
String r = queryReturnValue.getExceptionString();
if (r == null) {
throw new RuntimeException("runInternalQuery failed (null)");
}
if (!r.equals(EngineMessage.VDS_STATUS_NOT_VALID_FOR_UPDATE.name())) {
throw new RuntimeException(String.format("runInternalQuery failed '%s'", r));
}
}
}
protected void registerV1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String hostAddress = request.getParameter("address");
String hostSSHPortString = request.getParameter("sshPort");
String hostSSHKeyFingerprint = request.getParameter("sshKeyFingerprint");
String hostSSHUser = request.getParameter("sshUser");
String hostVdsPortString = request.getParameter("vdsPort");
String hostName = request.getParameter("name");
String hostUniqueId = request.getParameter("uniqueId");
if (hostAddress == null) {
hostAddress = InetAddress.getByName(request.getRemoteHost()).getHostName();
}
int hostSSHPort = VdsStatic.DEFAULT_SSH_PORT;
if (hostSSHPortString != null) {
hostSSHPort = Integer.parseInt(hostSSHPortString);
}
int hostVdsPort = VDSM_PORT;
if (hostVdsPortString != null) {
hostVdsPort = Integer.parseInt(hostVdsPortString);
}
log.info(
"Registration request: source='{}', secured='{}', address='{}{}:{}', sshKeyFingerprint={}, vdsPort={}, name='{}', uniqueId='{}'",
request.getRemoteHost(),
request.isSecure(),
hostSSHUser != null ? hostSSHUser + "@" : "",
hostAddress,
hostSSHPort,
hostSSHKeyFingerprint,
hostVdsPort,
hostName,
hostUniqueId
);
doRegister(
hostAddress,
hostSSHPort,
hostSSHKeyFingerprint,
hostSSHUser,
hostVdsPort,
hostName,
hostUniqueId
);
try (PrintWriter out = response.getWriter()) {
response.setContentType("text/plain");
out.print("OK\n");
}
}
protected void doV1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String cmd = request.getParameter("command");
if (cmd == null) {
throw new RuntimeException("command parameter is missing");
}
if (cmd.equals("get-version")) {
getVersionV1(request, response);
}
else if (cmd.equals("get-pki-trust")) {
getPKITrustV1(request, response);
}
else if (cmd.equals("get-ssh-trust")) {
getSSHTrustV1(request, response);
}
else if (cmd.equals("register")) {
registerV1(request, response);
}
else {
throw new RuntimeException("Invalid command");
}
}
catch (Exception e) {
log.error("Registration failed: {}", e.getMessage());
log.debug("Exception", e);
response.sendError(response.SC_BAD_REQUEST, e.getMessage());
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int version = -1;
String versionString = request.getParameter("version");
if (versionString != null) {
try {
version = Integer.parseInt(versionString);
}
catch(NumberFormatException ignore) {}
}
switch(version) {
default:
String m = String.format("Invalid registration protocol version %s", version);
log.error(m);
response.sendError(response.SC_BAD_REQUEST, m);
break;
case 1:
doV1(request, response);
break;
}
}
}