mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Add console proxy management state, support certificate upload, all done except UI
This commit is contained in:
parent
1a6d78eae4
commit
e69774e13a
@ -20,7 +20,6 @@ package com.cloud.agent.resource.consoleproxy;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -52,7 +51,7 @@ import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupProxyCommand;
|
||||
import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
|
||||
import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
|
||||
import com.cloud.agent.api.proxy.UpdateCertificateCommand;
|
||||
import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand;
|
||||
import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
|
||||
import com.cloud.exception.AgentControlChannelException;
|
||||
import com.cloud.host.Host;
|
||||
@ -99,68 +98,17 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
|
||||
return new ReadyAnswer((ReadyCommand)cmd);
|
||||
} else if(cmd instanceof CheckHealthCommand) {
|
||||
return new CheckHealthAnswer((CheckHealthCommand)cmd, true);
|
||||
} else if(cmd instanceof UpdateCertificateCommand) {
|
||||
return execute((UpdateCertificateCommand)cmd);
|
||||
}
|
||||
else {
|
||||
} else if(cmd instanceof StartConsoleProxyAgentHttpHandlerCommand) {
|
||||
return execute((StartConsoleProxyAgentHttpHandlerCommand)cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(final UpdateCertificateCommand cmd) {
|
||||
boolean success = false;
|
||||
String errorStr = null;
|
||||
String successStr = null;
|
||||
try
|
||||
{
|
||||
String certificate = cmd.getCertificate();
|
||||
//write the cert to /etc/cloud/consoleproxy/cert/
|
||||
boolean dirCreated = false;
|
||||
boolean dirExists = false;
|
||||
boolean forNewProxy = cmd.isForNewProxy();
|
||||
String strDirectory = "/etc/cloud/consoleproxy/cert/";
|
||||
String filePath = "/etc/cloud/consoleproxy/cert/customcert";
|
||||
if(forNewProxy){
|
||||
dirCreated = (new File(strDirectory)).mkdirs();
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Directory: " + strDirectory + " created");
|
||||
if(dirCreated){
|
||||
success = copyCertToDirectory(certificate, filePath);
|
||||
successStr = "Successfully created cert at /etc/cloud/consoleproxy/cert/ from the listener flow for new console proxy starting up";
|
||||
}
|
||||
}
|
||||
else{
|
||||
File dir = new File(strDirectory);
|
||||
dirExists = dir.exists();
|
||||
if(!dirExists){
|
||||
dirCreated = (new File(strDirectory)).mkdirs();
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Directory: " + strDirectory + " created");
|
||||
}
|
||||
if (dirExists || dirCreated)
|
||||
{
|
||||
success = copyCertToDirectory(certificate, filePath);
|
||||
successStr = "Successfully created cert at /etc/cloud/consoleproxy/cert/ from the UploadCustomCert cmd flow for existing console proxy";
|
||||
}
|
||||
}
|
||||
}catch (SecurityException se){
|
||||
errorStr = "Unable to upload cert in console proxy resource due to directory creation failure";
|
||||
s_logger.error(errorStr,se);
|
||||
success = false;
|
||||
}catch (IOException ioe){
|
||||
errorStr = "Unable to write cert to the location /etc/cloud/consoleproxy/cert/ ";
|
||||
s_logger.error(errorStr,ioe);
|
||||
success = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
errorStr = "Unable to upload cert in console proxy resource";
|
||||
s_logger.error(errorStr,e);
|
||||
success = false;
|
||||
}
|
||||
|
||||
return new Answer(cmd, success, errorStr!=null?errorStr:successStr);
|
||||
}
|
||||
private Answer execute(StartConsoleProxyAgentHttpHandlerCommand cmd) {
|
||||
launchConsoleProxy(cmd.getKeystoreBits(), cmd.getKeystorePassword());
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
private void disableRpFilter() {
|
||||
try {
|
||||
@ -321,7 +269,6 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Receive proxyVmId in ConsoleProxyResource configuration as " + _proxyVmId);
|
||||
|
||||
launchConsoleProxy();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -369,7 +316,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
|
||||
return _name;
|
||||
}
|
||||
|
||||
private void launchConsoleProxy() {
|
||||
private void launchConsoleProxy(final byte[] ksBits, final String ksPassword) {
|
||||
final Object resource = this;
|
||||
|
||||
_consoleProxyMain = new Thread(new Runnable() {
|
||||
@ -377,8 +324,8 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
|
||||
try {
|
||||
Class<?> consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy");
|
||||
try {
|
||||
Method method = consoleProxyClazz.getMethod("startWithContext", Properties.class, Object.class);
|
||||
method.invoke(null, _properties, resource);
|
||||
Method method = consoleProxyClazz.getMethod("startWithContext", Properties.class, Object.class, byte[].class, String.class);
|
||||
method.invoke(null, _properties, resource, ksBits, ksPassword);
|
||||
} catch (SecurityException e) {
|
||||
s_logger.error("Unable to launch console proxy due to SecurityException");
|
||||
System.exit(ExitStatus.Error.value());
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package com.cloud.agent.api.proxy;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class StartConsoleProxyAgentHttpHandlerCommand extends Command {
|
||||
private byte[] keystoreBits;
|
||||
private String keystorePassword;
|
||||
|
||||
public StartConsoleProxyAgentHttpHandlerCommand() {
|
||||
super();
|
||||
}
|
||||
|
||||
public StartConsoleProxyAgentHttpHandlerCommand(byte[] ksBits, String ksPassword) {
|
||||
this.keystoreBits = ksBits;
|
||||
this.keystorePassword = ksPassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public byte[] getKeystoreBits() {
|
||||
return keystoreBits;
|
||||
}
|
||||
|
||||
public void setKeystoreBits(byte[] keystoreBits) {
|
||||
this.keystoreBits = keystoreBits;
|
||||
}
|
||||
|
||||
public String getKeystorePassword() {
|
||||
return keystorePassword;
|
||||
}
|
||||
|
||||
public void setKeystorePassword(String keystorePassword) {
|
||||
this.keystorePassword = keystorePassword;
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.agent.api.proxy;
|
||||
|
||||
|
||||
/**
|
||||
* UpdateCertificateCommand implements one-shot updation of the certificate to be applied by the user
|
||||
*/
|
||||
public class UpdateCertificateCommand extends ProxyCommand {
|
||||
|
||||
private String certificate; //certificate to be applied
|
||||
private boolean forNewProxy; //denotes if this is called from the listener flow
|
||||
|
||||
public UpdateCertificateCommand() {
|
||||
this.forNewProxy = false;
|
||||
}
|
||||
|
||||
public UpdateCertificateCommand(String certificate, boolean forNewProxy) {
|
||||
this.certificate = certificate;
|
||||
this.forNewProxy = forNewProxy;
|
||||
}
|
||||
|
||||
public String getCertificate() {
|
||||
return this.certificate;
|
||||
}
|
||||
|
||||
public boolean isForNewProxy() {
|
||||
return forNewProxy;
|
||||
}
|
||||
|
||||
public void setForNewProxy(boolean forNewProxy) {
|
||||
this.forNewProxy = forNewProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -31,6 +31,8 @@ public class ApiConstants {
|
||||
public static final String BOOTABLE = "bootable";
|
||||
public static final String CATEGORY = "category";
|
||||
public static final String CERTIFICATE = "certificate";
|
||||
public static final String PRIVATE_KEY = "privatekey";
|
||||
public static final String DOMAIN_SUFFIX = "domainsuffix";
|
||||
public static final String CIDR = "cidr";
|
||||
public static final String CIDR_LIST = "cidrlist";
|
||||
public static final String CLEANUP = "cleanup";
|
||||
|
||||
@ -38,9 +38,23 @@ public class UploadCustomCertificateCmd extends BaseAsyncCmd {
|
||||
@Parameter(name=ApiConstants.CERTIFICATE,type=CommandType.STRING,required=true,description="the custom cert to be uploaded")
|
||||
private String certificate;
|
||||
|
||||
@Parameter(name=ApiConstants.PRIVATE_KEY,type=CommandType.STRING,required=true,description="the private key for the certificate")
|
||||
private String privateKey;
|
||||
|
||||
@Parameter(name=ApiConstants.DOMAIN_SUFFIX,type=CommandType.STRING,required=true,description="DNS domain suffix that the certificate is granted for")
|
||||
private String domainSuffix;
|
||||
|
||||
public String getCertificate() {
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public String getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public String getDomainSuffix() {
|
||||
return domainSuffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
|
||||
@ -60,10 +60,4 @@ then
|
||||
maxmem=$eightypcnt
|
||||
fi
|
||||
|
||||
EXTRA=
|
||||
if [ -f certs/realhostip.keystore ]
|
||||
then
|
||||
EXTRA="-Djavax.net.ssl.trustStore=$(dirname $0)/certs/realhostip.keystore -Djavax.net.ssl.trustStorePassword=vmops.com"
|
||||
fi
|
||||
|
||||
java -mx${maxmem}m ${EXTRA} -cp $CP com.cloud.agent.AgentShell $keyvalues $@
|
||||
java -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues $@
|
||||
|
||||
@ -45,15 +45,17 @@ import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
public class ConsoleProxy {
|
||||
private static final Logger s_logger = Logger.getLogger(ConsoleProxy.class);
|
||||
/*
|
||||
private static final int MAX_STRONG_TEMPLATE_CACHE_SIZE = 100;
|
||||
private static final int MAX_SOFT_TEMPLATE_CACHE_SIZE = 100;
|
||||
*/
|
||||
|
||||
public static final int KEYBOARD_RAW = 0;
|
||||
public static final int KEYBOARD_COOKED = 1;
|
||||
|
||||
public static Object context;
|
||||
|
||||
// this has become more ugly, to store keystore info passed from management server (we now use management server managed keystore to support
|
||||
// dynamically changing to customer supplied certificate)
|
||||
public static byte[] ksBits;
|
||||
public static String ksPassword;
|
||||
|
||||
public static Method authMethod;
|
||||
public static Method reportMethod;
|
||||
public static Method ensureRouteMethod;
|
||||
@ -165,8 +167,9 @@ public class ConsoleProxy {
|
||||
try {
|
||||
Class<?> clz = Class.forName(factoryClzName);
|
||||
try {
|
||||
return (ConsoleProxyServerFactory)clz.newInstance();
|
||||
|
||||
ConsoleProxyServerFactory factory = (ConsoleProxyServerFactory)clz.newInstance();
|
||||
factory.init(ConsoleProxy.ksBits, ConsoleProxy.ksPassword);
|
||||
return factory;
|
||||
} catch (InstantiationException e) {
|
||||
s_logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
@ -237,7 +240,7 @@ public class ConsoleProxy {
|
||||
}
|
||||
}
|
||||
|
||||
public static void startWithContext(Properties conf, Object context) {
|
||||
public static void startWithContext(Properties conf, Object context, byte[] ksBits, String ksPassword) {
|
||||
s_logger.info("Start console proxy with context");
|
||||
if(conf != null) {
|
||||
for(Object key : conf.keySet()) {
|
||||
@ -250,6 +253,8 @@ public class ConsoleProxy {
|
||||
|
||||
// Using reflection to setup private/secure communication channel towards management server
|
||||
ConsoleProxy.context = context;
|
||||
ConsoleProxy.ksBits = ksBits;
|
||||
ConsoleProxy.ksPassword = ksPassword;
|
||||
try {
|
||||
Class<?> contextClazz = Class.forName("com.cloud.agent.resource.consoleproxy.ConsoleProxyResource");
|
||||
authMethod = contextClazz.getDeclaredMethod("authenticateConsoleAccess", String.class, String.class, String.class, String.class, String.class);
|
||||
|
||||
@ -18,23 +18,29 @@
|
||||
|
||||
package com.cloud.consoleproxy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
|
||||
import com.cloud.console.Logger;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
public class ConsoleProxyBaseServerFactoryImpl implements ConsoleProxyServerFactory {
|
||||
private static final Logger s_logger = Logger.getLogger(ConsoleProxyBaseServerFactoryImpl.class);
|
||||
|
||||
@Override
|
||||
public void init(byte[] ksBits, String ksPassword) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServer createHttpServerInstance(int port) throws IOException {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("create HTTP server instance at port: " + port);
|
||||
return HttpServer.create(new InetSocketAddress(port), 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLServerSocket createSSLServerSocket(int port) throws IOException {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("SSL server socket is not supported in ConsoleProxyBaseServerFactoryImpl");
|
||||
|
||||
@ -18,17 +18,10 @@
|
||||
|
||||
package com.cloud.consoleproxy;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
@ -49,74 +42,62 @@ public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFa
|
||||
|
||||
private SSLContext sslContext = null;
|
||||
|
||||
public ConsoleProxySecureServerFactoryImpl() {
|
||||
try {
|
||||
s_logger.info("Start initializing SSL");
|
||||
|
||||
char[] passphrase = "vmops.com".toCharArray();
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
ks.load(ConsoleProxy.class.getResourceAsStream("/realhostip.keystore"), passphrase);
|
||||
//custom cert logic begins //
|
||||
try {
|
||||
//check if there is any custom cert added at /etc/cloud/consoleproxy/cert/
|
||||
String certPath = "/etc/cloud/consoleproxy/cert/customcert";
|
||||
//now generate a cert
|
||||
FileInputStream fis = new FileInputStream(certPath);
|
||||
BufferedInputStream bis = new BufferedInputStream(fis);
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
|
||||
while (bis.available() > 1) {
|
||||
Certificate cert = cf.generateCertificate(bis);
|
||||
if(s_logger.isDebugEnabled()){
|
||||
s_logger.debug("The custom certificate generated is:"+cert.toString());
|
||||
}
|
||||
//get the existing cert chain
|
||||
Certificate[] chain = ks.getCertificateChain("realhostip");
|
||||
Certificate[] newChain = new Certificate[chain.length+1];
|
||||
newChain[0] = cert;//make custom cert the default
|
||||
System.arraycopy(chain, 0, newChain, 1, chain.length);
|
||||
Key key = ks.getKey("realhostip", passphrase);
|
||||
ks.setKeyEntry("realhostip", key, passphrase, newChain);
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Custom SSL cert added successfully to the keystore cert chain");
|
||||
}
|
||||
} catch (FileNotFoundException fnf) {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to find the custom cert file at /etc/cloud/consoleproxy/cert/customcert",fnf);
|
||||
} catch (IOException ioe){
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to read the custom cert file at /etc/cloud/consoleproxy/cert/customcert",ioe);
|
||||
}catch (KeyStoreException kse){
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to add custom cert file at /etc/cloud/consoleproxy/cert/customcert to the keystore",kse);
|
||||
}catch (CertificateException ce){
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to generate certificate from the file /etc/cloud/consoleproxy/cert/customcert",ce);
|
||||
}catch (Exception e){
|
||||
//catch other excpns
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to add custom cert file at /etc/cloud/consoleproxy/cert/customcert to the keystore",e);
|
||||
}
|
||||
//custom cert logic ends //
|
||||
|
||||
s_logger.info("SSL certificate loaded");
|
||||
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
kmf.init(ks, passphrase);
|
||||
s_logger.info("Key manager factory is initialized");
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(ks);
|
||||
s_logger.info("Trust manager factory is initialized");
|
||||
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
s_logger.info("SSL context is initialized");
|
||||
} catch (Exception ioe) {
|
||||
s_logger.error(ioe.toString(), ioe);
|
||||
}
|
||||
public ConsoleProxySecureServerFactoryImpl() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void init(byte[] ksBits, String ksPassword) {
|
||||
s_logger.info("Start initializing SSL");
|
||||
|
||||
if(ksBits == null) {
|
||||
try {
|
||||
s_logger.info("Initializing SSL from built-in default certificate");
|
||||
|
||||
char[] passphrase = "vmops.com".toCharArray();
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
ks.load(ConsoleProxy.class.getResourceAsStream("/realhostip.keystore"), passphrase);
|
||||
|
||||
s_logger.info("SSL certificate loaded");
|
||||
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
kmf.init(ks, passphrase);
|
||||
s_logger.info("Key manager factory is initialized");
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(ks);
|
||||
s_logger.info("Trust manager factory is initialized");
|
||||
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
s_logger.info("SSL context is initialized");
|
||||
} catch (Exception ioe) {
|
||||
s_logger.error(ioe.toString(), ioe);
|
||||
}
|
||||
} else {
|
||||
char[] passphrase = ksPassword != null ? ksPassword.toCharArray() : null;
|
||||
try {
|
||||
s_logger.info("Initializing SSL from passed-in certificate");
|
||||
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
ks.load(new ByteArrayInputStream(ksBits), passphrase);
|
||||
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
kmf.init(ks, passphrase);
|
||||
s_logger.info("Key manager factory is initialized");
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(ks);
|
||||
s_logger.info("Trust manager factory is initialized");
|
||||
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
s_logger.info("SSL context is initialized");
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unable to init factory due to exception ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HttpServer createHttpServerInstance(int port) throws IOException {
|
||||
try {
|
||||
HttpsServer server = HttpsServer.create(new InetSocketAddress(port), 5);
|
||||
|
||||
@ -18,13 +18,14 @@
|
||||
|
||||
package com.cloud.consoleproxy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
public interface ConsoleProxyServerFactory {
|
||||
public interface ConsoleProxyServerFactory {
|
||||
void init(byte[] ksBits, String ksPassword);
|
||||
HttpServer createHttpServerInstance(int port) throws IOException;
|
||||
SSLServerSocket createSSLServerSocket(int port) throws IOException;
|
||||
}
|
||||
|
||||
@ -96,6 +96,10 @@ public enum Config {
|
||||
ConsoleProxySessionTimeout("Console Proxy", AgentManager.class, Integer.class, "consoleproxy.session.timeout", "300000", "Timeout(in milliseconds) that console proxy tries to maintain a viewer session before it times out the session for no activity", null),
|
||||
ConsoleProxyDisableRpFilter("Console Proxy", AgentManager.class, Integer.class, "consoleproxy.disable.rpfilter", "true", "disable rp_filter on console proxy VM public interface", null),
|
||||
ConsoleProxyLaunchMax("Console Proxy", AgentManager.class, Integer.class, "consoleproxy.launch.max", "10", "maximum number of console proxy instances per zone can be launched", null),
|
||||
ConsoleProxyManagementState("Console Proxy", AgentManager.class, String.class, "consoleproxy.management.state", com.cloud.consoleproxy.ConsoleProxyManagementState.Auto.toString(),
|
||||
"console proxy service management state", null),
|
||||
ConsoleProxyManagementLastState("Console Proxy", AgentManager.class, String.class, "consoleproxy.management.state.last", com.cloud.consoleproxy.ConsoleProxyManagementState.Auto.toString(),
|
||||
"last console proxy service management state", null),
|
||||
|
||||
// Snapshots
|
||||
SnapshotHourlyMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.max.hourly", "8", "Maximum hourly snapshots for a volume", null),
|
||||
|
||||
@ -67,6 +67,8 @@ import com.cloud.host.dao.DetailsDaoImpl;
|
||||
import com.cloud.host.dao.HostDaoImpl;
|
||||
import com.cloud.host.dao.HostTagsDaoImpl;
|
||||
import com.cloud.hypervisor.HypervisorGuruManagerImpl;
|
||||
import com.cloud.keystore.KeystoreDaoImpl;
|
||||
import com.cloud.keystore.KeystoreManagerImpl;
|
||||
import com.cloud.maint.UpgradeManagerImpl;
|
||||
import com.cloud.maint.dao.AgentUpgradeDaoImpl;
|
||||
import com.cloud.network.NetworkManagerImpl;
|
||||
@ -263,6 +265,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
||||
addDao("StoragePoolWorkDao", StoragePoolWorkDaoImpl.class);
|
||||
addDao("HostTagsDao", HostTagsDaoImpl.class);
|
||||
addDao("NetworkDomainDao", NetworkDomainDaoImpl.class);
|
||||
addDao("KeystoreDao", KeystoreDaoImpl.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -281,6 +284,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
||||
addManager("network manager", NetworkManagerImpl.class);
|
||||
addManager("download manager", DownloadMonitorImpl.class);
|
||||
addManager("upload manager", UploadMonitorImpl.class);
|
||||
addManager("keystore manager", KeystoreManagerImpl.class);
|
||||
addManager("console proxy manager", AgentBasedStandaloneConsoleProxyManager.class);
|
||||
addManager("secondary storage vm manager", SecondaryStorageManagerImpl.class);
|
||||
addManager("vm manager", UserVmManagerImpl.class);
|
||||
|
||||
@ -187,7 +187,7 @@ public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, Virtu
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
|
||||
}
|
||||
@ -267,6 +267,23 @@ public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, Virtu
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setManagementState(ConsoleProxyManagementState state) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsoleProxyManagementState getManagementState() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeLastManagementState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return _name;
|
||||
@ -279,13 +296,7 @@ public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, Virtu
|
||||
}
|
||||
return VirtualMachineName.getConsoleProxyId(vmName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyCustomCertToNewProxy(StartupProxyCommand cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ConsoleProxyVO findByName(String name) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
@ -35,5 +35,5 @@ public interface AgentHook {
|
||||
void onAgentConnect(HostVO host, StartupCommand cmd);
|
||||
|
||||
public void onAgentDisconnect(long agentId, Status state);
|
||||
boolean applyCustomCertToNewProxy(StartupProxyCommand cmd);
|
||||
public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd);
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ public class ConsoleProxyListener implements Listener {
|
||||
_proxyMgr.onAgentConnect(host, cmd);
|
||||
|
||||
if (cmd instanceof StartupProxyCommand) {
|
||||
_proxyMgr.applyCustomCertToNewProxy((StartupProxyCommand)cmd);
|
||||
_proxyMgr.startAgentHttpHandlerInVM((StartupProxyCommand)cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.consoleproxy;
|
||||
|
||||
public enum ConsoleProxyManagementState {
|
||||
Auto,
|
||||
Manual,
|
||||
Suspending,
|
||||
ResetSuspending
|
||||
}
|
||||
|
||||
@ -40,6 +40,11 @@ public interface ConsoleProxyManager extends Manager {
|
||||
public static final int DEFAULT_PROXY_SESSION_TIMEOUT = 300000; // 5 minutes
|
||||
|
||||
public static final String ALERT_SUBJECT = "proxy-alert";
|
||||
public static final String CERTIFICATE_NAME = "CPVMCertificate";
|
||||
|
||||
public void setManagementState(ConsoleProxyManagementState state);
|
||||
public ConsoleProxyManagementState getManagementState();
|
||||
public void resumeLastManagementState();
|
||||
|
||||
public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId);
|
||||
|
||||
@ -47,7 +52,7 @@ public interface ConsoleProxyManager extends Manager {
|
||||
public boolean stopProxy(long proxyVmId);
|
||||
public boolean rebootProxy(long proxyVmId);
|
||||
public boolean destroyProxy(long proxyVmId);
|
||||
|
||||
|
||||
public void onLoadReport(ConsoleProxyLoadReportCommand cmd);
|
||||
public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd);
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@ -46,11 +47,10 @@ import com.cloud.agent.api.StopAnswer;
|
||||
import com.cloud.agent.api.check.CheckSshAnswer;
|
||||
import com.cloud.agent.api.check.CheckSshCommand;
|
||||
import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
|
||||
import com.cloud.agent.api.proxy.UpdateCertificateCommand;
|
||||
import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand;
|
||||
import com.cloud.agent.manager.Commands;
|
||||
import com.cloud.api.ServerApiException;
|
||||
import com.cloud.api.commands.DestroyConsoleProxyCmd;
|
||||
import com.cloud.certificate.CertificateVO;
|
||||
import com.cloud.certificate.dao.CertificateDao;
|
||||
import com.cloud.cluster.ClusterManager;
|
||||
import com.cloud.cluster.StackMaid;
|
||||
@ -82,6 +82,9 @@ import com.cloud.info.ConsoleProxyStatus;
|
||||
import com.cloud.info.RunningHostCountInfo;
|
||||
import com.cloud.info.RunningHostInfoAgregator;
|
||||
import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo;
|
||||
import com.cloud.keystore.KeystoreDao;
|
||||
import com.cloud.keystore.KeystoreManager;
|
||||
import com.cloud.keystore.KeystoreVO;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.network.NetworkVO;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
@ -107,6 +110,7 @@ import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.GlobalLock;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.events.SubscriptionMgr;
|
||||
@ -225,6 +229,55 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
private Map<Long, ConsoleProxyLoadInfo> _zoneVmCountMap; // map <zone id, info about running VMs count in zone>
|
||||
|
||||
private final GlobalLock _allocProxyLock = GlobalLock.getInternLock(getAllocProxyLockName());
|
||||
|
||||
private String keyContent =
|
||||
"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALV5vGlkiWwoZX4hTRplPXP8qtST\n" +
|
||||
"hwZhko8noeY5vf8ECwmd+vrCTw/JvnOtkx/8oYNbg/SeUt1EfOsk6gqJdBblGFBZRMcUJlIpqE9z\n" +
|
||||
"uv68U9G8Gfi/qvRSY336hibw0J5bZ4vn1QqmyHDB+Czea9AjFUV7AEVG15+vED7why+/AgMBAAEC\n" +
|
||||
"gYBmFBPnNKYYMKDmUdUNA+WNWJK/ADzzWe8WlzR6TACTcbLDthl289WFC/YVG42mcHRpbxDKiEQU\n" +
|
||||
"MnIR0rHTO34Qb/2HcuyweStU2gqR6omxBvMnFpJr90nD1HcOMJzeLHsphau0/EmKKey+gk4PyieD\n" +
|
||||
"KqTM7LTjjHv8xPM4n+WAAQJBAOMNCeFKlJ4kMokWhU74B5/w/NGyT1BHUN0VmilHSiJC8JqS4BiI\n" +
|
||||
"ZpAeET3VmilO6QTGh2XVhEDGteu3uZR6ipUCQQDMnRzMgQ/50LFeIQo4IBtwlEouczMlPQF4c21R\n" +
|
||||
"1d720moxILVPT0NJZTQUDDmmgbL+B7CgtcCR2NlP5sKPZVADAkEAh4Xq1cy8dMBKYcVNgNtPQcqI\n" +
|
||||
"PWpfKR3ISI5yXB0vRNAL6Vet5zbTcUZhKDVtNSbis3UEsGYH8NorEC2z2cpjGQJANhJi9Ow6c5Mh\n" +
|
||||
"/DURBUn+1l5pyCKrZnDbvaALSLATLvjmFTuGjoHszy2OeKnOZmEqExWnKKE/VYuPyhy6V7i3TwJA\n" +
|
||||
"f8skDgtPK0OsBCa6IljPaHoWBjPc4kFkSTSS1d56hUcWSikTmiuKdLyBb85AADSZYsvHWrte4opN\n" +
|
||||
"dhNukMJuRA==\n";
|
||||
|
||||
private String certContent =
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIE3jCCA8agAwIBAgIFAqv56tIwDQYJKoZIhvcNAQEFBQAwgcoxCzAJBgNVBAYT\n" +
|
||||
"AlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYD\n" +
|
||||
"VQQKExFHb0RhZGR5LmNvbSwgSW5jLjEzMDEGA1UECxMqaHR0cDovL2NlcnRpZmlj\n" +
|
||||
"YXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5MTAwLgYDVQQDEydHbyBEYWRkeSBT\n" +
|
||||
"ZWN1cmUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxETAPBgNVBAUTCDA3OTY5Mjg3\n" +
|
||||
"MB4XDTA5MDIxMTA0NTc1NloXDTEyMDIwNzA1MTEyM1owWTEZMBcGA1UECgwQKi5y\n" +
|
||||
"ZWFsaG9zdGlwLmNvbTEhMB8GA1UECwwYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVk\n" +
|
||||
"MRkwFwYDVQQDDBAqLnJlYWxob3N0aXAuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GN\n" +
|
||||
"ADCBiQKBgQC1ebxpZIlsKGV+IU0aZT1z/KrUk4cGYZKPJ6HmOb3/BAsJnfr6wk8P\n" +
|
||||
"yb5zrZMf/KGDW4P0nlLdRHzrJOoKiXQW5RhQWUTHFCZSKahPc7r+vFPRvBn4v6r0\n" +
|
||||
"UmN9+oYm8NCeW2eL59UKpshwwfgs3mvQIxVFewBFRtefrxA+8IcvvwIDAQABo4IB\n" +
|
||||
"vTCCAbkwDwYDVR0TAQH/BAUwAwEBADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\n" +
|
||||
"BQUHAwIwDgYDVR0PAQH/BAQDAgWgMDIGA1UdHwQrMCkwJ6AloCOGIWh0dHA6Ly9j\n" +
|
||||
"cmwuZ29kYWRkeS5jb20vZ2RzMS0yLmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0B\n" +
|
||||
"BxcBMDkwNwYIKwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j\n" +
|
||||
"b20vcmVwb3NpdG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0\n" +
|
||||
"cDovL29jc3AuZ29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlm\n" +
|
||||
"aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNy\n" +
|
||||
"dDAfBgNVHSMEGDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAq\n" +
|
||||
"LnJlYWxob3N0aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUHxwmdK5w\n" +
|
||||
"9/YVeZ/3fHyi6nQfzoYwDQYJKoZIhvcNAQEFBQADggEBABv/XinvId6oWXJtmku+\n" +
|
||||
"7m90JhSVH0ycoIGjgdaIkcExQGP08MCilbUsPcbhLheSFdgn/cR4e1MP083lacoj\n" +
|
||||
"OGauY7b8f/cuquGkT49Ns14awPlEzRjjycQEjjLxFEuL5CFWa2t2gKRE1dSfhDQ+\n" +
|
||||
"fJ6GBCs1XgZLuhkKS8fPf+YmG2ZjHzYDjYoSx7paDXgEm+kbYIZdCK51lA0BUAjP\n" +
|
||||
"9ZMGhsu/PpAbh5U/DtcIqxY0xeqD4TeGsBzXg6uLhv+jKHDtXg5fYPe+z0n5DCEL\n" +
|
||||
"k0fLF4+i/pt9hVCz0QrZ28RUhXf825+EOL0Gw+Uzt+7RV2cCaJrlu4cDrDom2FRy\n" +
|
||||
"E8I=\n" +
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
@Inject private KeystoreDao _ksDao;
|
||||
@Inject private KeystoreManager _ksMgr;
|
||||
private Random _random = new Random(System.currentTimeMillis());
|
||||
|
||||
@Override
|
||||
public ConsoleProxyInfo assignProxy(final long dataCenterId, final long vmId) {
|
||||
@ -267,8 +320,12 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
s_logger.warn("Assigned console proxy does not have a valid public IP address");
|
||||
return null;
|
||||
}
|
||||
|
||||
KeystoreVO ksVo = _ksDao.findByName(ConsoleProxyManager.CERTIFICATE_NAME);
|
||||
assert(ksVo != null);
|
||||
|
||||
return new ConsoleProxyInfo(proxy.isSslEnabled(), proxy.getPublicIpAddress(), _consoleProxyPort, proxy.getPort(), _configDao.getValue("consoleproxy.url.domain"));
|
||||
return new ConsoleProxyInfo(proxy.isSslEnabled(), proxy.getPublicIpAddress(), _consoleProxyPort, proxy.getPort(),
|
||||
ksVo.getDomainSuffix());
|
||||
}
|
||||
|
||||
public ConsoleProxyVO doAssignProxy(long dataCenterId, long vmId) {
|
||||
@ -864,12 +921,11 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
}
|
||||
|
||||
private boolean reserveStandbyCapacity() {
|
||||
String value = _configDao.getValue(Config.SystemVMAutoReserveCapacity.key());
|
||||
if (value != null && value.equalsIgnoreCase("true")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
ConsoleProxyManagementState state = getManagementState();
|
||||
if(state == null || state != ConsoleProxyManagementState.Auto)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean allowToLaunchNew(long dcId) {
|
||||
@ -1047,7 +1103,83 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override @DB
|
||||
public void setManagementState(ConsoleProxyManagementState state) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
txn.start();
|
||||
|
||||
ConsoleProxyManagementState lastState = getManagementState();
|
||||
if(lastState == null) {
|
||||
txn.commit();
|
||||
return;
|
||||
}
|
||||
|
||||
if(lastState != state) {
|
||||
_configDao.update(Config.ConsoleProxyManagementLastState.key(), lastState.toString());
|
||||
_configDao.update(Config.ConsoleProxyManagementState.key(), state.toString());
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
} catch (Throwable e) {
|
||||
txn.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsoleProxyManagementState getManagementState() {
|
||||
String value = _configDao.getValue(Config.ConsoleProxyManagementState.key());
|
||||
if(value != null) {
|
||||
ConsoleProxyManagementState state = ConsoleProxyManagementState.valueOf(value);
|
||||
|
||||
if(state == null) {
|
||||
s_logger.error("Invalid console proxy management state: " + value);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
s_logger.error("Invalid console proxy management state: " + value);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @DB
|
||||
public void resumeLastManagementState() {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
txn.start();
|
||||
ConsoleProxyManagementState state = getManagementState();
|
||||
ConsoleProxyManagementState lastState = getLastManagementState();
|
||||
if(lastState == null) {
|
||||
txn.commit();
|
||||
return;
|
||||
}
|
||||
|
||||
if(lastState != state) {
|
||||
_configDao.update(Config.ConsoleProxyManagementState.key(), lastState.toString());
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
} catch (Throwable e) {
|
||||
txn.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
private ConsoleProxyManagementState getLastManagementState() {
|
||||
String value = _configDao.getValue(Config.ConsoleProxyManagementLastState.key());
|
||||
if(value != null) {
|
||||
ConsoleProxyManagementState state = ConsoleProxyManagementState.valueOf(value);
|
||||
|
||||
if(state == null) {
|
||||
s_logger.error("Invalid console proxy management state: " + value);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
s_logger.error("Invalid console proxy management state: " + value);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rebootProxy(long proxyVmId) {
|
||||
final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
|
||||
@ -1095,7 +1227,22 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
private String getAllocProxyLockName() {
|
||||
return "consoleproxy.alloc";
|
||||
}
|
||||
|
||||
|
||||
private void prepareDefaultCertificate() {
|
||||
GlobalLock lock = GlobalLock.getInternLock("consoleproxy.cert.setup");
|
||||
try {
|
||||
if(lock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
|
||||
KeystoreVO ksVo = _ksDao.findByName(CERTIFICATE_NAME);
|
||||
if(ksVo == null) {
|
||||
_ksDao.save(CERTIFICATE_NAME, certContent, keyContent, "realhostip.com");
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
} finally {
|
||||
lock.releaseRef();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
@ -1157,6 +1304,8 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
if (_instance == null) {
|
||||
_instance = "DEFAULT";
|
||||
}
|
||||
|
||||
prepareDefaultCertificate();
|
||||
|
||||
Map<String, String> agentMgrConfigs = configDao.getConfiguration("AgentManager", params);
|
||||
_mgmt_host = agentMgrConfigs.get("host");
|
||||
@ -1346,42 +1495,41 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
_consoleProxyDao.update(proxy.getId(), proxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyCustomCertToNewProxy(StartupProxyCommand cmd) {
|
||||
// this is the case for updating cust cert on each new starting proxy, if such cert exists
|
||||
// get cert from db
|
||||
CertificateVO cert = _certDao.listAll().get(0);
|
||||
|
||||
if (cert.getUpdated().equalsIgnoreCase("Y")) {
|
||||
String certStr = cert.getCertificate();
|
||||
long proxyVmId = (cmd).getProxyVmId();
|
||||
ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId);
|
||||
// find corresponding host
|
||||
if (consoleProxy != null) {
|
||||
HostVO consoleProxyHost = _hostDao.findConsoleProxyHost(consoleProxy.getName(), Type.ConsoleProxy);
|
||||
// now send a command to console proxy host
|
||||
UpdateCertificateCommand certCmd = new UpdateCertificateCommand(certStr, true);
|
||||
try {
|
||||
Answer updateCertAns = _agentMgr.send(consoleProxyHost.getId(), certCmd);
|
||||
if (updateCertAns.getResult() == true) {
|
||||
// we have the cert copied over on cpvm
|
||||
rebootProxy(consoleProxy.getId());
|
||||
// when cp reboots, the context will be reinit with the new cert
|
||||
s_logger.info("Successfully rebooted console proxy resource after custom certificate application for proxy:" + cmd.getProxyVmId());
|
||||
return true;
|
||||
}
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Unable to send update certificate command to the console proxy resource for proxy:" + cmd.getProxyVmId(), e);
|
||||
return false;
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Unable to send update certificate command to the console proxy resource for proxy:" + cmd.getProxyVmId(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;// no cert entry in the db record
|
||||
}
|
||||
return false;// cert already applied in previous cycles
|
||||
public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) {
|
||||
StartConsoleProxyAgentHttpHandlerCommand cmd = null;
|
||||
if(_configDao.isPremium()) {
|
||||
String storePassword = String.valueOf(_random.nextLong());
|
||||
byte[] ksBits = _ksMgr.getKeystoreBits(ConsoleProxyManager.CERTIFICATE_NAME, ConsoleProxyManager.CERTIFICATE_NAME,
|
||||
storePassword);
|
||||
|
||||
assert(ksBits != null);
|
||||
if(ksBits == null) {
|
||||
s_logger.error("Could not find and construct a valid SSL certificate");
|
||||
}
|
||||
cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, storePassword);
|
||||
} else {
|
||||
cmd = new StartConsoleProxyAgentHttpHandlerCommand();
|
||||
}
|
||||
|
||||
try {
|
||||
long proxyVmId = startupCmd.getProxyVmId();
|
||||
ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId);
|
||||
assert(consoleProxy != null);
|
||||
HostVO consoleProxyHost = _hostDao.findConsoleProxyHost(consoleProxy.getName(), Type.ConsoleProxy);
|
||||
|
||||
Answer answer = _agentMgr.send(consoleProxyHost.getId(), cmd);
|
||||
if(answer == null || !answer.getResult()) {
|
||||
s_logger.error("Console proxy agent reported that it failed to execute http handling startup command");
|
||||
} else {
|
||||
s_logger.info("Successfully sent out command to start HTTP handling in console proxy agent");
|
||||
}
|
||||
} catch(AgentUnavailableException e) {
|
||||
s_logger.error("Unable to send http handling startup command to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e);
|
||||
} catch(OperationTimedoutException e) {
|
||||
s_logger.error("Unable to send http handling startup command(time out) to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e);
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception when sending http handling startup command(time out) to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1428,11 +1576,48 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
_zoneVmCountMap.put(info.getId(), info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void scanManagementState() {
|
||||
ConsoleProxyManagementState state = getManagementState();
|
||||
if(state != null) {
|
||||
switch(state) {
|
||||
case Auto:
|
||||
case Manual:
|
||||
case Suspending:
|
||||
break;
|
||||
|
||||
case ResetSuspending:
|
||||
handleResetSuspending();
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleResetSuspending() {
|
||||
List<ConsoleProxyVO> runningProxies = _consoleProxyDao.getProxyListInStates(State.Running);
|
||||
for(ConsoleProxyVO proxy : runningProxies) {
|
||||
s_logger.info("Stop console proxy " + proxy.getId() + " because of we are currently in ResetSuspending management mode");
|
||||
this.stopProxy(proxy.getId());
|
||||
}
|
||||
|
||||
// check if it is time to resume
|
||||
List<ConsoleProxyVO> proxiesInTransition = _consoleProxyDao.getProxyListInStates(State.Running, State.Starting, State.Stopping);
|
||||
if(proxiesInTransition.size() == 0) {
|
||||
s_logger.info("All previous console proxy VMs in transition mode ceased the mode, we will now resume to last management state");
|
||||
this.resumeLastManagementState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScan() {
|
||||
if (!reserveStandbyCapacity()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
public boolean canScan() {
|
||||
// take the chance to do management-state management
|
||||
scanManagementState();
|
||||
|
||||
if(!reserveStandbyCapacity()) {
|
||||
if(s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Reserving standby capacity is disable, skip capacity scan");
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -31,9 +31,8 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Local(value={KeystoreDao.class})
|
||||
public class KeystoreDaoImpl extends GenericDaoBase<KeystoreVO, Long> implements KeystoreDao {
|
||||
|
||||
protected final SearchBuilder<KeystoreVO> FindByNameSearch;
|
||||
|
||||
|
||||
public KeystoreDaoImpl() {
|
||||
FindByNameSearch = createSearchBuilder();
|
||||
FindByNameSearch.and("name", FindByNameSearch.entity().getName(), Op.EQ);
|
||||
@ -49,7 +48,6 @@ public class KeystoreDaoImpl extends GenericDaoBase<KeystoreVO, Long> implements
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public void save(String name, String certificate, String key, String domainSuffix) {
|
||||
|
||||
@ -21,6 +21,7 @@ package com.cloud.keystore;
|
||||
import com.cloud.utils.component.Manager;
|
||||
|
||||
public interface KeystoreManager extends Manager {
|
||||
boolean validateCertificate(String certificate, String key, String domainSuffix);
|
||||
void saveCertificate(String name, String certificate, String key, String domainSuffix);
|
||||
byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword);
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
package com.cloud.keystore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
@ -64,6 +65,29 @@ public class KeystoreManagerImpl implements KeystoreManager {
|
||||
return _name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateCertificate(String certificate, String key, String domainSuffix) {
|
||||
if(certificate == null || certificate.isEmpty() ||
|
||||
key == null || key.isEmpty() ||
|
||||
domainSuffix == null || domainSuffix.isEmpty()) {
|
||||
s_logger.error("Invalid parameter found in (certificate, key, domainSuffix) tuple for domain: " + domainSuffix);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
String ksPassword = "passwordForValidation";
|
||||
byte[] ksBits = CertificateHelper.buildAndSaveKeystore(domainSuffix, certificate, key, ksPassword);
|
||||
KeyStore ks = CertificateHelper.loadKeystore(ksBits, ksPassword);
|
||||
if(ks != null)
|
||||
return true;
|
||||
|
||||
s_logger.error("Unabled to construct keystore for domain: " + domainSuffix);
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Certificate validation failed due to exception for domain: " + domainSuffix, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveCertificate(String name, String certificate, String key, String domainSuffix) {
|
||||
if(name == null || name.isEmpty() ||
|
||||
@ -72,7 +96,6 @@ public class KeystoreManagerImpl implements KeystoreManager {
|
||||
domainSuffix == null || domainSuffix.isEmpty())
|
||||
throw new CloudRuntimeException("invalid parameter in saveCerticate");
|
||||
|
||||
|
||||
_ksDao.save(name, certificate, key, domainSuffix);
|
||||
}
|
||||
|
||||
|
||||
@ -122,7 +122,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
||||
// Get init
|
||||
String init = _configDao.getValue("init");
|
||||
|
||||
if (init.equals("false")) {
|
||||
if (init == null || init.equals("false")) {
|
||||
s_logger.debug("ConfigurationServer is saving default values to the database.");
|
||||
|
||||
// Save default Configuration Table values
|
||||
|
||||
@ -17,12 +17,6 @@
|
||||
*/
|
||||
package com.cloud.server;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
@ -32,9 +26,6 @@ import java.net.URLEncoder;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
@ -62,10 +53,8 @@ import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.GetVncPortAnswer;
|
||||
import com.cloud.agent.api.GetVncPortCommand;
|
||||
import com.cloud.agent.api.proxy.UpdateCertificateCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.alert.Alert;
|
||||
@ -135,7 +124,6 @@ import com.cloud.async.dao.AsyncJobDao;
|
||||
import com.cloud.capacity.Capacity;
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.capacity.dao.CapacityDao;
|
||||
import com.cloud.certificate.CertificateVO;
|
||||
import com.cloud.certificate.dao.CertificateDao;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
@ -143,6 +131,7 @@ import com.cloud.configuration.ConfigurationVO;
|
||||
import com.cloud.configuration.ResourceLimitVO;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.configuration.dao.ResourceLimitDao;
|
||||
import com.cloud.consoleproxy.ConsoleProxyManagementState;
|
||||
import com.cloud.consoleproxy.ConsoleProxyManager;
|
||||
import com.cloud.dc.AccountVlanMapVO;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
@ -168,11 +157,9 @@ import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.EventUtils;
|
||||
import com.cloud.event.EventVO;
|
||||
import com.cloud.event.dao.EventDao;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.CloudAuthenticationException;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ManagementServerException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
@ -184,6 +171,7 @@ import com.cloud.host.Status;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.info.ConsoleProxyInfo;
|
||||
import com.cloud.keystore.KeystoreManager;
|
||||
import com.cloud.network.IPAddressVO;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.network.NetworkVO;
|
||||
@ -256,7 +244,6 @@ import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.exception.ExecutionException;
|
||||
import com.cloud.utils.net.MacAddress;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.utils.ssh.SSHKeysHelper;
|
||||
@ -339,6 +326,8 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
private final CertificateDao _certDao;
|
||||
private final SSHKeyPairDao _sshKeyPairDao;
|
||||
|
||||
private final KeystoreManager _ksMgr;
|
||||
|
||||
private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));
|
||||
|
||||
private final StatsCollector _statsCollector;
|
||||
@ -410,7 +399,8 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
_sshKeyPairDao = locator.getDao(SSHKeyPairDao.class);
|
||||
_itMgr = locator.getManager(VirtualMachineManager.class);
|
||||
_networkMgr = locator.getManager(NetworkManager.class);
|
||||
|
||||
_ksMgr = locator.getManager(KeystoreManager.class);
|
||||
|
||||
_userAuthenticators = locator.getAdapters(UserAuthenticator.class);
|
||||
if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
|
||||
s_logger.error("Unable to find an user authenticator.");
|
||||
@ -4566,141 +4556,15 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
return EventUtils.saveEvent(userId, accountId, level, type, description, startEventId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
@Override @DB
|
||||
public String uploadCertificate(UploadCustomCertificateCmd cmd) {
|
||||
CertificateVO cert = null;
|
||||
Long certVOId = null;
|
||||
try {
|
||||
Transaction.currentTxn();
|
||||
String certificate = cmd.getCertificate();
|
||||
cert = _certDao.listAll().get(0); // always 1 record in db (from the deploydb time)
|
||||
cert = _certDao.acquireInLockTable(cert.getId());
|
||||
if (cert == null) {
|
||||
String msg = "Unable to obtain lock on the cert from uploadCertificate()";
|
||||
s_logger.error(msg);
|
||||
throw new ConcurrentOperationException(msg);
|
||||
} else {
|
||||
if (cert.getUpdated().equalsIgnoreCase("Y")) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("A custom certificate already exists in the DB, will replace it with the new one being uploaded");
|
||||
}
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No custom certificate exists in the DB, will upload a new one");
|
||||
}
|
||||
}
|
||||
|
||||
// validate if the cert follows X509 format, if not, don't persist to db
|
||||
InputStream is = new ByteArrayInputStream(certificate.getBytes("UTF-8"));
|
||||
BufferedInputStream bis = new BufferedInputStream(is);
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
while (bis.available() > 1) {
|
||||
Certificate localCert = cf.generateCertificate(bis);// throws certexception if not valid cert format
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("The custom certificate generated for validation is:" + localCert.toString());
|
||||
}
|
||||
}
|
||||
|
||||
certVOId = _certDao.persistCustomCertToDb(certificate, cert, this.getId());// 0 implies failure
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Custom certificate persisted to the DB");
|
||||
}
|
||||
}
|
||||
|
||||
if (certVOId != 0) {
|
||||
// certficate uploaded to db successfully
|
||||
// get a list of all Console proxies from the cp table
|
||||
List<ConsoleProxyVO> cpList = _consoleProxyDao.listAll();
|
||||
if (cpList.size() == 0) {
|
||||
String msg = "Unable to find any console proxies in the system for certificate update";
|
||||
s_logger.warn(msg);
|
||||
throw new ExecutionException(msg);
|
||||
}
|
||||
// get a list of all hosts in host table for type cp
|
||||
List<HostVO> cpHosts = _hostDao.listByType(com.cloud.host.Host.Type.ConsoleProxy);
|
||||
if (cpHosts.size() == 0) {
|
||||
String msg = "Unable to find any console proxy hosts in the system for certificate update";
|
||||
s_logger.warn(msg);
|
||||
throw new ExecutionException(msg);
|
||||
}
|
||||
// create a hashmap for fast lookup
|
||||
Map<String, Long> hostNameToHostIdMap = new HashMap<String, Long>();
|
||||
// updated console proxies id list
|
||||
List<Long> updatedCpIdList = new ArrayList<Long>();
|
||||
for (HostVO cpHost : cpHosts) {
|
||||
hostNameToHostIdMap.put(cpHost.getName(), cpHost.getId());
|
||||
}
|
||||
for (ConsoleProxyVO cp : cpList) {
|
||||
Long cpHostId = hostNameToHostIdMap.get(cp.getName());
|
||||
// now send a command to each console proxy host
|
||||
UpdateCertificateCommand certCmd = new UpdateCertificateCommand(_certDao.findById(certVOId).getCertificate(), false);
|
||||
try {
|
||||
Answer updateCertAns = _agentMgr.send(cpHostId, certCmd);
|
||||
if (updateCertAns.getResult() == true) {
|
||||
// we have the cert copied over on cpvm
|
||||
_consoleProxyMgr.rebootProxy(cp.getId());
|
||||
// when cp reboots, the context will be reinit with the new cert
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Successfully updated custom certificate on console proxy vm id:" + cp.getId() + " ,console proxy host id:" + cpHostId);
|
||||
}
|
||||
updatedCpIdList.add(cp.getId());
|
||||
}
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Unable to send update certificate command to the console proxy resource as agent is unavailable for console proxy vm id:" + cp.getId()
|
||||
+ " ,console proxy host id:" + cpHostId, e);
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Unable to send update certificate command to the console proxy resource as there was a timeout for console proxy vm id:" + cp.getId()
|
||||
+ " ,console proxy host id:" + cpHostId, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (updatedCpIdList.size() == cpList.size()) {
|
||||
// success case, all updated
|
||||
return ("Updated:" + updatedCpIdList.size() + " out of:" + cpList.size() + " console proxies");
|
||||
} else {
|
||||
// failure case, if even one update fails
|
||||
throw new ManagementServerException("Updated:" + updatedCpIdList.size() + " out of:" + cpList.size() + " console proxies with successfully updated console proxy ids being:"
|
||||
+ (updatedCpIdList.size() > 0 ? updatedCpIdList.toString() : ""));
|
||||
}
|
||||
} else {
|
||||
throw new ManagementServerException("Unable to persist custom certificate to the cloud db");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Failed to successfully update the cert across console proxies on management server:" + this.getId());
|
||||
if (e instanceof ExecutionException) {
|
||||
throw new CloudRuntimeException(e.getMessage());
|
||||
} else if (e instanceof ManagementServerException) {
|
||||
throw new CloudRuntimeException(e.getMessage());
|
||||
} else if (e instanceof IndexOutOfBoundsException) {
|
||||
String msg = "Custom certificate record in the db deleted; this should never happen. Please create a new record in the certificate table";
|
||||
s_logger.error(msg, e);
|
||||
throw new CloudRuntimeException(msg);
|
||||
} else if (e instanceof FileNotFoundException) {
|
||||
String msg = "Invalid file path for custom cert found during cert validation";
|
||||
s_logger.error(msg, e);
|
||||
throw new InvalidParameterValueException(msg);
|
||||
} else if (e instanceof CertificateException) {
|
||||
String msg = "The file format for custom cert does not conform to the X.509 specification";
|
||||
s_logger.error(msg, e);
|
||||
throw new CloudRuntimeException(msg);
|
||||
} else if (e instanceof UnsupportedEncodingException) {
|
||||
String msg = "Unable to encode the certificate into UTF-8 input stream for validation";
|
||||
s_logger.error(msg, e);
|
||||
throw new CloudRuntimeException(msg);
|
||||
} else if (e instanceof IOException) {
|
||||
String msg = "Cannot generate input stream during custom cert validation";
|
||||
s_logger.error(msg, e);
|
||||
throw new CloudRuntimeException(msg);
|
||||
} else {
|
||||
String msg = "Cannot upload custom certificate, internal error.";
|
||||
s_logger.error(msg, e);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
|
||||
} finally {
|
||||
_certDao.releaseFromLockTable(cert.getId());
|
||||
}
|
||||
if(!_ksMgr.validateCertificate(cmd.getCertificate(), cmd.getPrivateKey(), cmd.getDomainSuffix()))
|
||||
throw new InvalidParameterValueException("Failed to pass certificate validation check");
|
||||
|
||||
_ksMgr.saveCertificate(ConsoleProxyManager.CERTIFICATE_NAME, cmd.getCertificate(), cmd.getPrivateKey(), cmd.getDomainSuffix());
|
||||
|
||||
_consoleProxyMgr.setManagementState(ConsoleProxyManagementState.ResetSuspending);
|
||||
return "Certificate has been updated, we will stop all running console proxy VMs for certificate propagation";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user