From e7015cbc4c75d45a32db00e7672428cafd2aa777 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 17 Sep 2025 08:06:00 -0400 Subject: [PATCH] Move console proxy related global settings to Zone level (#11415) --- .../java/com/cloud/configuration/Config.java | 100 +-------- .../ConfigurationManagerImpl.java | 3 +- .../AgentBasedConsoleProxyManager.java | 10 +- .../com/cloud/consoleproxy/AgentHookBase.java | 19 +- .../consoleproxy/ConsoleProxyManager.java | 49 ++++- .../consoleproxy/ConsoleProxyManagerImpl.java | 194 +++++++++--------- .../ConsoleAccessManagerImpl.java | 2 +- .../ConfigurationManagerImplTest.java | 24 --- .../PremiumSecondaryStorageManagerImpl.java | 5 +- 9 files changed, 168 insertions(+), 238 deletions(-) diff --git a/server/src/main/java/com/cloud/configuration/Config.java b/server/src/main/java/com/cloud/configuration/Config.java index 443909ce319..6a05ce227a7 100644 --- a/server/src/main/java/com/cloud/configuration/Config.java +++ b/server/src/main/java/com/cloud/configuration/Config.java @@ -25,7 +25,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.framework.config.ConfigKey; import com.cloud.agent.AgentManager; -import com.cloud.consoleproxy.ConsoleProxyManager; import com.cloud.ha.HighAvailabilityManager; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.router.VpcVirtualNetworkApplianceManager; @@ -404,96 +403,6 @@ public enum Config { "service monitoring in router enable/disable option, default false", null), - // Console Proxy - ConsoleProxyCapacityStandby( - "Console Proxy", - AgentManager.class, - String.class, - "consoleproxy.capacity.standby", - "10", - "The minimal number of console proxy viewer sessions that system is able to serve immediately(standby capacity)", - null), - ConsoleProxyCapacityScanInterval( - "Console Proxy", - AgentManager.class, - String.class, - "consoleproxy.capacityscan.interval", - "30000", - "The time interval(in millisecond) to scan whether or not system needs more console proxy to ensure minimal standby capacity", - null), - ConsoleProxyCmdPort( - "Console Proxy", - AgentManager.class, - Integer.class, - "consoleproxy.cmd.port", - "8001", - "Console proxy command port that is used to communicate with management server", - null), - ConsoleProxyRestart( - "Console Proxy", - AgentManager.class, - Boolean.class, - "consoleproxy.restart", - "true", - "Console proxy restart flag, defaulted to true", - null), - ConsoleProxyUrlDomain( - "Console Proxy", - AgentManager.class, - String.class, - "consoleproxy.url.domain", - "", - "Console proxy url domain", - "domainName,privateip"), - ConsoleProxySessionMax( - "Console Proxy", - AgentManager.class, - Integer.class, - "consoleproxy.session.max", - String.valueOf(ConsoleProxyManager.DEFAULT_PROXY_CAPACITY), - "The max number of viewer sessions console proxy is configured to serve for", - null), - 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, - Boolean.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 SnapshotPollInterval( @@ -1587,14 +1496,6 @@ public enum Config { "false", "Should be set to true, if there will be multiple NetScaler devices providing EIP service in a zone", null), - ConsoleProxyServiceOffering( - "Advanced", - ManagementServer.class, - String.class, - "consoleproxy.service.offering", - null, - "Uuid of the service offering used by console proxy; if NULL - system offering will be used", - null), SecondaryStorageServiceOffering( "Advanced", ManagementServer.class, @@ -1799,6 +1700,7 @@ public enum Config { SSVMPSK("Hidden", ManagementServer.class, String.class, "upload.post.secret.key", "", "PSK with SSVM", null); + private final String _category; private final Class _componentClass; private final Class _type; diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index b86e8167435..409dd056ef7 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -49,6 +49,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.consoleproxy.ConsoleProxyManager; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.affinity.AffinityGroup; @@ -573,7 +574,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati configValuesForValidation.add("event.purge.interval"); configValuesForValidation.add("account.cleanup.interval"); configValuesForValidation.add("alert.wait"); - configValuesForValidation.add("consoleproxy.capacityscan.interval"); + configValuesForValidation.add(ConsoleProxyManager.ConsoleProxyCapacityScanInterval.key()); configValuesForValidation.add("expunge.interval"); configValuesForValidation.add("host.stats.interval"); configValuesForValidation.add("network.gc.interval"); diff --git a/server/src/main/java/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/main/java/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java index 863307035ee..a65d54e5346 100644 --- a/server/src/main/java/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java +++ b/server/src/main/java/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java @@ -120,12 +120,12 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); } - value = configs.get(ConsoleProxySslEnabled.key()); - if (value != null && value.equalsIgnoreCase("true")) { + Boolean sslEnabled = ConsoleProxySslEnabled.value(); + if (Boolean.TRUE.equals(sslEnabled)) { _sslEnabled = true; } - _consoleProxyUrlDomain = configs.get("consoleproxy.url.domain"); + _consoleProxyUrlDomain = ConsoleProxyUrlDomain.value(); _listener = new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr, _keysMgr, consoleAccessManager)); @@ -166,6 +166,8 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol urlPort = host.getProxyPort().intValue(); } + _sslEnabled = ConsoleProxySslEnabled.valueIn(dataCenterId); + _consoleProxyUrlDomain = ConsoleProxyUrlDomain.valueIn(dataCenterId); return new ConsoleProxyInfo(_sslEnabled, publicIp, _consoleProxyPort, urlPort, _consoleProxyUrlDomain); } else { logger.warn("Host that VM is running is no longer available, console access to VM {} will be temporarily unavailable.", userVm); @@ -189,7 +191,7 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol } @Override - public int getVncPort() { + public int getVncPort(Long dataCenterId) { return _consoleProxyPort; } diff --git a/server/src/main/java/com/cloud/consoleproxy/AgentHookBase.java b/server/src/main/java/com/cloud/consoleproxy/AgentHookBase.java index 93cf1e3f689..ff79115b904 100644 --- a/server/src/main/java/com/cloud/consoleproxy/AgentHookBase.java +++ b/server/src/main/java/com/cloud/consoleproxy/AgentHookBase.java @@ -20,6 +20,7 @@ package com.cloud.consoleproxy; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Date; +import java.util.Objects; import org.apache.cloudstack.consoleproxy.ConsoleAccessManager; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -41,7 +42,6 @@ import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupProxyCommand; import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand; -import com.cloud.configuration.Config; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; import com.cloud.host.Host; @@ -213,10 +213,16 @@ public abstract class AgentHookBase implements AgentHook { byte[] ksBits = null; - String consoleProxyUrlDomain = _configDao.getValue(Config.ConsoleProxyUrlDomain.key()); - String consoleProxySslEnabled = _configDao.getValue(ConsoleProxyManager.ConsoleProxySslEnabled.key()); - if (!StringUtils.isEmpty(consoleProxyUrlDomain) && !StringUtils.isEmpty(consoleProxySslEnabled) - && consoleProxySslEnabled.equalsIgnoreCase("true")) { + HostVO consoleProxyHost = findConsoleProxyHost(startupCmd); + + if (Objects.isNull(consoleProxyHost)) { + throw new IllegalStateException("Console proxy host is null"); + } + + Long datacenterId = consoleProxyHost.getDataCenterId(); + String consoleProxyUrlDomain = ConsoleProxyManager.ConsoleProxyUrlDomain.valueIn(datacenterId); + Boolean consoleProxySslEnabled = ConsoleProxyManager.ConsoleProxySslEnabled.valueIn(datacenterId); + if (!StringUtils.isEmpty(consoleProxyUrlDomain) && Boolean.TRUE.equals(consoleProxySslEnabled)) { ksBits = _ksMgr.getKeystoreBits(ConsoleProxyManager.CERTIFICATE_NAME, ConsoleProxyManager.CERTIFICATE_NAME, storePassword); //ks manager raises exception if ksBits are null, hence no need to explicltly handle the condition } else { @@ -227,9 +233,6 @@ public abstract class AgentHookBase implements AgentHook { cmd.setEncryptorPassword(getEncryptorPassword()); cmd.setIsSourceIpCheckEnabled(Boolean.parseBoolean(_configDao.getValue(ConsoleProxyManager.NoVncConsoleSourceIpCheckEnabled.key()))); - HostVO consoleProxyHost = findConsoleProxyHost(startupCmd); - - assert (consoleProxyHost != null); if (consoleProxyHost != null) { Answer answer = _agentMgr.send(consoleProxyHost.getId(), cmd); if (answer == null || !answer.getResult()) { diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManager.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManager.java index 88f3b30f96f..59819934e3a 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManager.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManager.java @@ -16,7 +16,9 @@ // under the License. package com.cloud.consoleproxy; +import java.util.Arrays; import java.util.Map; +import java.util.stream.Collectors; import org.apache.cloudstack.framework.config.ConfigKey; @@ -45,15 +47,52 @@ public interface ConsoleProxyManager extends Manager, ConsoleProxyService { String ALERT_SUBJECT = "proxy-alert"; String CERTIFICATE_NAME = "CPVMCertificate"; - ConfigKey ConsoleProxySslEnabled = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Boolean.class, "consoleproxy.sslEnabled", "false", - "Enable SSL for console proxy", false); + ConfigKey ConsoleProxySslEnabled = new ConfigKey<>(Boolean.class, "consoleproxy.sslEnabled", ConfigKey.CATEGORY_ADVANCED, "false", + "Enable SSL for console proxy", false, ConfigKey.Scope.Zone, null); - ConfigKey NoVncConsoleDefault = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Boolean.class, "novnc.console.default", "true", - "If true, noVNC console will be default console for virtual machines", true); + ConfigKey NoVncConsoleDefault = new ConfigKey<>(Boolean.class, "novnc.console.default", ConfigKey.CATEGORY_ADVANCED, "true", + "If true, noVNC console will be default console for virtual machines", false, ConfigKey.Scope.Zone, null); ConfigKey NoVncConsoleSourceIpCheckEnabled = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Boolean.class, "novnc.console.sourceip.check.enabled", "false", "If true, The source IP to access novnc console must be same as the IP in request to management server for console URL. Needs to reconnect CPVM to management server when this changes (via restart CPVM, or management server, or cloud service in CPVM)", false); + ConfigKey ConsoleProxyServiceOffering = new ConfigKey<>(String.class, "consoleproxy.service.offering", "Console Proxy", null, + "Uuid of the service offering used by console proxy; if NULL - system offering will be used", true, ConfigKey.Scope.Zone, null); + + ConfigKey ConsoleProxyCapacityStandby = new ConfigKey<>(String.class, "consoleproxy.capacity.standby", "Console Proxy", String.valueOf(DEFAULT_STANDBY_CAPACITY), + "The minimal number of console proxy viewer sessions that system is able to serve immediately(standby capacity)", false, ConfigKey.Scope.Zone, null); + + ConfigKey ConsoleProxyCapacityScanInterval = new ConfigKey<>(String.class, "consoleproxy.capacityscan.interval", "Console Proxy", "30000", + "The time interval(in millisecond) to scan whether or not system needs more console proxy to ensure minimal standby capacity", false, null); + + ConfigKey ConsoleProxyCmdPort = new ConfigKey<>(Integer.class, "consoleproxy.cmd.port", "Console Proxy", String.valueOf(DEFAULT_PROXY_CMD_PORT), + "Console proxy command port that is used to communicate with management server", false, ConfigKey.Scope.Zone, null); + + ConfigKey ConsoleProxyRestart = new ConfigKey<>(Boolean.class, "consoleproxy.restart", "Console Proxy", "true", + "Console proxy restart flag, defaults to true", true, ConfigKey.Scope.Zone, null); + + ConfigKey ConsoleProxyUrlDomain = new ConfigKey<>(String.class, "consoleproxy.url.domain", "Console Proxy", "", + "Console proxy url domain - domainName,privateip", false, ConfigKey.Scope.Zone, null); + + ConfigKey ConsoleProxySessionMax = new ConfigKey<>(Integer.class, "consoleproxy.session.max", "Console Proxy", String.valueOf(DEFAULT_PROXY_CAPACITY), + "The max number of viewer sessions console proxy is configured to serve for", true, ConfigKey.Scope.Zone, null); + + ConfigKey ConsoleProxySessionTimeout = new ConfigKey<>(Integer.class, "consoleproxy.session.timeout", "Console Proxy", String.valueOf(DEFAULT_PROXY_SESSION_TIMEOUT), + "Timeout(in milliseconds) that console proxy tries to maintain a viewer session before it times out the session for no activity", true, ConfigKey.Scope.Zone, null); + + ConfigKey ConsoleProxyDisableRpFilter = new ConfigKey<>(Boolean.class, "consoleproxy.disable.rpfilter", "Console Proxy", "true", + "disable rp_filter on console proxy VM public interface", true, ConfigKey.Scope.Zone, null); + + ConfigKey ConsoleProxyLaunchMax = new ConfigKey<>(Integer.class, "consoleproxy.launch.max", "Console Proxy", "10", + "maximum number of console proxy instances per zone can be launched", false, ConfigKey.Scope.Zone, null); + + String consoleProxyManagementStates = Arrays.stream(com.cloud.consoleproxy.ConsoleProxyManagementState.values()).map(Enum::name).collect(Collectors.joining(",")); + ConfigKey ConsoleProxyServiceManagementState = new ConfigKey(ConfigKey.CATEGORY_ADVANCED, String.class, "consoleproxy.management.state", com.cloud.consoleproxy.ConsoleProxyManagementState.Auto.toString(), + "console proxy service management state", false, ConfigKey.Kind.Select, consoleProxyManagementStates); + + ConfigKey ConsoleProxyManagementLastState = new ConfigKey(ConfigKey.CATEGORY_ADVANCED, String.class, "consoleproxy.management.state.last", com.cloud.consoleproxy.ConsoleProxyManagementState.Auto.toString(), + "last console proxy service management state", false, ConfigKey.Kind.Select, consoleProxyManagementStates); + void setManagementState(ConsoleProxyManagementState state); ConsoleProxyManagementState getManagementState(); @@ -72,6 +111,6 @@ public interface ConsoleProxyManager extends Manager, ConsoleProxyService { boolean destroyProxy(long proxyVmId); - int getVncPort(); + int getVncPort(Long dataCenterId); } diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 484193f2fcd..98fa8a4dcfd 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -230,20 +230,11 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy private ConsoleProxyListener consoleProxyListener; - private ServiceOfferingVO serviceOfferingVO; - private long capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL_IN_MILLISECONDS; - private int capacityPerProxy = ConsoleProxyManager.DEFAULT_PROXY_CAPACITY; - private int standbyCapacity = ConsoleProxyManager.DEFAULT_STANDBY_CAPACITY; private boolean useStorageVm; - private boolean disableRpFilter = false; private String instance; - private int proxySessionTimeoutValue = DEFAULT_PROXY_SESSION_TIMEOUT; - private boolean sslEnabled = false; - private String consoleProxyUrlDomain; - private SystemVmLoadScanner loadScanner; private Map zoneHostInfoMap; private Map zoneProxyCountMap; @@ -342,6 +333,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy logger.warn(String.format("SSL is enabled for console proxy [%s] but no server certificate found in database.", proxy.toString())); } + String consoleProxyUrlDomain = ConsoleProxyUrlDomain.valueIn(dataCenterId); ConsoleProxyInfo info; if (staticPublicIp == null) { info = new ConsoleProxyInfo(proxy.isSslEnabled(), proxy.getPublicIpAddress(), consoleProxyPort, proxy.getPort(), consoleProxyUrlDomain); @@ -374,6 +366,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } proxy = null; } else { + long capacityPerProxy = ConsoleProxySessionMax.valueIn(dataCenterId); if (consoleProxyDao.getProxyActiveLoad(proxy.getId()) < capacityPerProxy || hasPreviousSession(proxy, vm)) { if (logger.isDebugEnabled()) { logger.debug("Assign previous allocated console proxy for user vm: {}", vm); @@ -408,7 +401,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy if (vm.getProxyId() == null || vm.getProxyId() != proxy.getId()) { vmInstanceDao.updateProxyId(vm.getId(), proxy.getId(), DateUtil.currentGMTTime()); } - + boolean sslEnabled = isSslEnabled(dataCenterId); proxy.setSslEnabled(sslEnabled); if (sslEnabled) { proxy.setPort(443); @@ -451,6 +444,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } } + Integer proxySessionTimeoutValue = ConsoleProxySessionTimeout.valueIn(proxy.getDataCenterId()); return DateUtil.currentGMTTime().getTime() - vm.getProxyAssignTime().getTime() < proxySessionTimeoutValue; } else { logger.warn(String.format("Unable to retrieve load info from proxy [%s] on an overloaded proxy.", proxy.toString())); @@ -466,8 +460,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy return proxy; } - String restart = configurationDao.getValue(Config.ConsoleProxyRestart.key()); - if (!ignoreRestartSetting && restart != null && restart.equalsIgnoreCase("false")) { + Boolean restart = ConsoleProxyRestart.valueIn(proxy.getDataCenterId()); + if (!ignoreRestartSetting && Boolean.FALSE.equals(restart)) { return null; } @@ -500,6 +494,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy logger.debug("Assign console proxy from running pool for request from data center: {}", zone); } + long capacityPerProxy = ConsoleProxySessionMax.valueIn(dataCenterId); + ConsoleProxyAllocator allocator = getCurrentAllocator(); assert (allocator != null); List runningList = consoleProxyDao.getProxyListInStates(dataCenterId, State.Running); @@ -559,15 +555,16 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy return null; } - public ConsoleProxyVO startNew(long dataCenterId) throws ConcurrentOperationException { + public ConsoleProxyVO startNew(long dataCenterId) throws ConcurrentOperationException, ConfigurationException { if (logger.isDebugEnabled()) { logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); } if (!allowToLaunchNew(dataCenterId)) { - String configKey = Config.ConsoleProxyLaunchMax.key(); - logger.warn(String.format("The number of launched console proxys on zone [%s] has reached the limit [%s]. Limit set in [%s].", dataCenterId, configurationDao.getValue(configKey), configKey)); + String configKey = ConsoleProxyLaunchMax.key(); + Integer configValue = ConsoleProxyLaunchMax.valueIn(dataCenterId); + logger.warn(String.format("The number of launched console proxys on zone [%s] has reached the limit [%s]. Limit set in [%s].", dataCenterId, configValue, configKey)); return null; } @@ -690,7 +687,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy return proxy; } - protected Map createProxyInstance(long dataCenterId, List templates) throws ConcurrentOperationException { + protected Map createProxyInstance(long dataCenterId, List templates) throws ConcurrentOperationException, ConfigurationException { long id = consoleProxyDao.getNextInSequence(Long.class, "id"); String name = VirtualMachineName.getConsoleProxyName(id, instance); @@ -715,7 +712,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy networks.put(networkOrchestrationService.setupNetwork(systemAcct, offering, plan, null, null, false).get(0), new ArrayList<>()); } - ServiceOfferingVO serviceOffering = serviceOfferingVO; + ServiceOfferingVO serviceOffering = getConsoleProxyServiceOffering(dataCenterId); if (serviceOffering == null) { serviceOffering = serviceOfferingDao.findDefaultSystemOffering(ServiceOffering.consoleProxyDefaultOffUniqueName, ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId)); } @@ -814,13 +811,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy consoleProxyDao.getProxyListInStates(dcId, State.Starting, State.Running, State.Stopping, State.Stopped, State.Migrating, State.Shutdown, State.Unknown); - String value = configurationDao.getValue(Config.ConsoleProxyLaunchMax.key()); - int launchLimit = NumbersUtil.parseInt(value, 10); + int launchLimit = ConsoleProxyLaunchMax.valueIn(dcId); return l.size() < launchLimit; } - private boolean checkCapacity(ConsoleProxyLoadInfo proxyCountInfo, ConsoleProxyLoadInfo vmCountInfo) { - return proxyCountInfo.getCount() * capacityPerProxy - vmCountInfo.getCount() > standbyCapacity; + private boolean checkCapacity(ConsoleProxyLoadInfo proxyCountInfo, ConsoleProxyLoadInfo vmCountInfo, long dataCenterId) { + long capacityPerProxy = ConsoleProxySessionMax.valueIn(dataCenterId); + return proxyCountInfo.getCount() * capacityPerProxy - vmCountInfo.getCount() > getStandbyCapacity(dataCenterId); } private void allocCapacity(long dataCenterId) { @@ -842,7 +839,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy if (allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC_IN_SECONDS)) { try { proxy = startNew(dataCenterId); - } catch (ConcurrentOperationException e) { + } catch (ConcurrentOperationException | ConfigurationException e) { logger.warn("Unable to start new console proxy on zone [{}] due to [{}].", zone, e.getMessage(), e); } finally { allocProxyLock.unlock(); @@ -997,8 +994,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - configurationDao.update(Config.ConsoleProxyManagementLastState.key(), Config.ConsoleProxyManagementLastState.getCategory(), lastState.toString()); - configurationDao.update(Config.ConsoleProxyManagementState.key(), Config.ConsoleProxyManagementState.getCategory(), state.toString()); + configurationDao.update(ConsoleProxyManagementLastState.key(), ConsoleProxyManagementLastState.category(), lastState.toString()); + configurationDao.update(ConsoleProxyServiceManagementState.key(), ConsoleProxyServiceManagementState.category(), state.toString()); } }); } @@ -1009,8 +1006,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy @Override public ConsoleProxyManagementState getManagementState() { - String configKey = Config.ConsoleProxyManagementState.key(); - String value = configurationDao.getValue(configKey); + String configKey = ConsoleProxyServiceManagementState.key(); + String value = ConsoleProxyServiceManagementState.value(); if (value != null) { ConsoleProxyManagementState state = ConsoleProxyManagementState.valueOf(value); @@ -1035,7 +1032,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } if (lastState != state) { - configurationDao.update(Config.ConsoleProxyManagementState.key(), Config.ConsoleProxyManagementState.getCategory(), lastState.toString()); + configurationDao.update(ConsoleProxyServiceManagementState.key(), ConsoleProxyServiceManagementState.category(), lastState.toString()); } } catch (Exception e) { logger.error(String.format("Unable to resume last management state due to [%s].", e.getMessage()), e); @@ -1043,8 +1040,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } private ConsoleProxyManagementState getLastManagementState() { - String configKey = Config.ConsoleProxyManagementLastState.key(); - String value = configurationDao.getValue(configKey); + String configKey = ConsoleProxyManagementLastState.key(); + String value = ConsoleProxyManagementLastState.value(); if (value != null) { ConsoleProxyManagementState state = ConsoleProxyManagementState.valueOf(value); @@ -1117,8 +1114,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } @Override - public int getVncPort() { - return sslEnabled && _ksDao.findByName(ConsoleProxyManager.CERTIFICATE_NAME) != null ? 8443 : 8080; + public int getVncPort(Long dataCenterId) { + return isSslEnabled(dataCenterId) && _ksDao.findByName(ConsoleProxyManager.CERTIFICATE_NAME) != null ? 8443 : 8080; } private String getAllocProxyLockName() { @@ -1133,44 +1130,19 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy Map configs = configurationDao.getConfiguration("management-server", params); - String value = configs.get(ConsoleProxySslEnabled.key()); - if (value != null && value.equalsIgnoreCase("true")) { - sslEnabled = true; - } - - consoleProxyUrlDomain = configs.get(Config.ConsoleProxyUrlDomain.key()); - if( sslEnabled && (consoleProxyUrlDomain == null || consoleProxyUrlDomain.isEmpty())) { - logger.warn("Empty console proxy domain, explicitly disabling SSL"); - sslEnabled = false; - } - - value = configs.get(Config.ConsoleProxyCapacityScanInterval.key()); + String value = ConsoleProxyCapacityScanInterval.value(); capacityScanInterval = NumbersUtil.parseLong(value, DEFAULT_CAPACITY_SCAN_INTERVAL_IN_MILLISECONDS); - capacityPerProxy = NumbersUtil.parseInt(configs.get("consoleproxy.session.max"), DEFAULT_PROXY_CAPACITY); - standbyCapacity = NumbersUtil.parseInt(configs.get("consoleproxy.capacity.standby"), DEFAULT_STANDBY_CAPACITY); - proxySessionTimeoutValue = NumbersUtil.parseInt(configs.get("consoleproxy.session.timeout"), DEFAULT_PROXY_SESSION_TIMEOUT); - value = configs.get("consoleproxy.port"); if (value != null) { consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); } - value = configs.get(Config.ConsoleProxyDisableRpFilter.key()); - if (value != null && value.equalsIgnoreCase("true")) { - disableRpFilter = true; - } - value = configs.get("secondary.storage.vm"); if (value != null && value.equalsIgnoreCase("true")) { useStorageVm = true; } - if (logger.isInfoEnabled()) { - logger.info("Console proxy max session soft limit : " + capacityPerProxy); - logger.info("Console proxy standby capacity : " + standbyCapacity); - } - instance = configs.get("instance.name"); if (instance == null) { instance = "DEFAULT"; @@ -1187,37 +1159,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy virtualMachineManager.registerGuru(VirtualMachine.Type.ConsoleProxy, this); - String configKey = Config.ConsoleProxyServiceOffering.key(); - String cpvmSrvcOffIdStr = configs.get(configKey); - if (cpvmSrvcOffIdStr != null) { - serviceOfferingVO = serviceOfferingDao.findByUuid(cpvmSrvcOffIdStr); - if (serviceOfferingVO == null) { - try { - logger.debug(String.format("Unable to find a service offering by the UUID for console proxy VM with the value [%s] set in the configuration [%s]. Trying to find by the ID.", cpvmSrvcOffIdStr, configKey)); - serviceOfferingVO = serviceOfferingDao.findById(Long.parseLong(cpvmSrvcOffIdStr)); - } catch (NumberFormatException ex) { - logger.warn(String.format("Unable to find a service offering by the ID for console proxy VM with the value [%s] set in the configuration [%s]. The value is not a valid integer number. Error: [%s].", cpvmSrvcOffIdStr, configKey, ex.getMessage()), ex); - } - } - if (serviceOfferingVO == null) { - logger.warn(String.format("Unable to find a service offering by the UUID or ID for console proxy VM with the value [%s] set in the configuration [%s]", cpvmSrvcOffIdStr, configKey)); - } - } - - if (serviceOfferingVO == null || !serviceOfferingVO.isSystemUse()) { - int ramSize = NumbersUtil.parseInt(configurationDao.getValue("console.ram.size"), DEFAULT_PROXY_VM_RAMSIZE); - int cpuFreq = NumbersUtil.parseInt(configurationDao.getValue("console.cpu.mhz"), DEFAULT_PROXY_VM_CPUMHZ); - List offerings = serviceOfferingDao.createSystemServiceOfferings("System Offering For Console Proxy", - ServiceOffering.consoleProxyDefaultOffUniqueName, 1, ramSize, cpuFreq, 0, 0, false, null, - Storage.ProvisioningType.THIN, true, null, true, VirtualMachine.Type.ConsoleProxy, true); - - if (offerings == null || offerings.size() < 2) { - String msg = "Data integrity problem : System Offering For Console Proxy has been removed?"; - logger.error(msg); - throw new ConfigurationException(msg); - } - } - loadScanner = new SystemVmLoadScanner<>(this); loadScanner.initScan(STARTUP_DELAY_IN_MILLISECONDS, capacityScanInterval); resourceManager.registerResourceStateAdapter(this.getClass().getSimpleName(), this); @@ -1252,14 +1193,16 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy buf.append(" host=").append(StringUtils.toCSVList(indirectAgentLB.getManagementServerList(dest.getHost().getId(), dest.getDataCenter().getId(), null))); buf.append(" port=").append(managementPort); buf.append(" name=").append(profile.getVirtualMachine().getHostName()); - if (sslEnabled) { + if (isSslEnabled(dest.getDataCenter().getId())) { buf.append(" premium=true"); } - buf.append(" zone=").append(dest.getDataCenter().getId()); + Long datacenterId = dest.getDataCenter().getId(); + buf.append(" zone=").append(datacenterId); buf.append(" pod=").append(dest.getPod().getId()); buf.append(" guid=Proxy.").append(profile.getId()); buf.append(" proxy_vm=").append(profile.getId()); - if (disableRpFilter) { + Boolean disableRpFilter = ConsoleProxyDisableRpFilter.valueIn(datacenterId); + if (Boolean.TRUE.equals(disableRpFilter)) { buf.append(" disable_rp_filter=true"); } @@ -1319,7 +1262,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy buf.append(" dns2=").append(dc.getDns2()); } if (VirtualMachine.Type.ConsoleProxy == profile.getVirtualMachine().getType()) { - buf.append(" vncport=").append(getVncPort()); + buf.append(" vncport=").append(getVncPort(datacenterId)); } buf.append(" keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16))); String bootArgs = buf.toString(); @@ -1552,7 +1495,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy vmInfo = new ConsoleProxyLoadInfo(); } - if (!checkCapacity(proxyInfo, vmInfo)) { + if (!checkCapacity(proxyInfo, vmInfo, dataCenterId)) { if (logger.isDebugEnabled()) { logger.debug("Expand console proxy standby capacity for zone " + proxyInfo.getName()); } @@ -1627,7 +1570,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] { ConsoleProxySslEnabled, NoVncConsoleDefault, NoVncConsoleSourceIpCheckEnabled }; + return new ConfigKey[] { ConsoleProxySslEnabled, NoVncConsoleDefault, NoVncConsoleSourceIpCheckEnabled, ConsoleProxyServiceOffering, + ConsoleProxyCapacityStandby, ConsoleProxyCapacityScanInterval, ConsoleProxyCmdPort, ConsoleProxyRestart, ConsoleProxyUrlDomain, ConsoleProxySessionMax, ConsoleProxySessionTimeout, ConsoleProxyDisableRpFilter, ConsoleProxyLaunchMax, + ConsoleProxyManagementLastState, ConsoleProxyServiceManagementState }; } protected ConsoleProxyStatus parseJsonToConsoleProxyStatus(String json) throws JsonParseException { @@ -1661,4 +1606,65 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy consoleProxyDao.update(proxyVmId, count, DateUtil.currentGMTTime(), details); } + + private boolean isSslEnabled(Long dataCenterId) { + boolean sslEnabled = ConsoleProxySslEnabled.valueIn(dataCenterId); + String consoleProxyUrlDomain = ConsoleProxyUrlDomain.valueIn(dataCenterId); + if( sslEnabled && (consoleProxyUrlDomain == null || consoleProxyUrlDomain.isEmpty())) { + logger.warn("Empty console proxy domain, explicitly disabling SSL"); + sslEnabled = false; + } + return sslEnabled; + } + + private Integer getStandbyCapacity(Long datacenterId) { + return Integer.parseInt(ConsoleProxyCapacityStandby.valueIn(datacenterId)); + } + + private ServiceOfferingVO getConsoleProxyServiceOffering(Long datacenterId) throws ConfigurationException { + String configKey = ConsoleProxyServiceOffering.key(); + String cpvmSrvcOffIdStr = ConsoleProxyServiceOffering.valueIn(datacenterId); + String warningMessage = String.format("Unable to find a service offering by the UUID or ID for console proxy VM with the value [%s] set in the configuration [%s]", cpvmSrvcOffIdStr, configKey); + ServiceOfferingVO serviceOfferingVO = null; + if (cpvmSrvcOffIdStr != null) { + serviceOfferingVO = getServiceOfferingByUuidOrId(cpvmSrvcOffIdStr, warningMessage, configKey); + } + + if (serviceOfferingVO == null || !serviceOfferingVO.isSystemUse()) { + logger.debug("Service offering for console proxy VM is not set or not a system service offering. Creating a default service offering."); + createServiceOfferingForConsoleProxy(); + } + return serviceOfferingVO; + } + + private ServiceOfferingVO getServiceOfferingByUuidOrId(String cpvmSrvcOffIdStr, String warningMessage, String configKey) { + ServiceOfferingVO serviceOfferingVO = serviceOfferingDao.findByUuid(cpvmSrvcOffIdStr); + if (serviceOfferingVO == null) { + try { + logger.debug(warningMessage); + serviceOfferingVO = serviceOfferingDao.findById(Long.parseLong(cpvmSrvcOffIdStr)); + } catch (NumberFormatException ex) { + logger.warn(String.format("Unable to find a service offering by the ID for console proxy VM with the value [%s] set in the configuration [%s]. The value is not a valid integer number. Error: [%s].", cpvmSrvcOffIdStr, configKey, ex.getMessage()), ex); + } + } + if (serviceOfferingVO == null) { + logger.warn(warningMessage); + } + + return serviceOfferingVO; + } + + private void createServiceOfferingForConsoleProxy() throws ConfigurationException { + int ramSize = NumbersUtil.parseInt(configurationDao.getValue("console.ram.size"), DEFAULT_PROXY_VM_RAMSIZE); + int cpuFreq = NumbersUtil.parseInt(configurationDao.getValue("console.cpu.mhz"), DEFAULT_PROXY_VM_CPUMHZ); + List offerings = serviceOfferingDao.createSystemServiceOfferings("System Offering For Console Proxy", + ServiceOffering.consoleProxyDefaultOffUniqueName, 1, ramSize, cpuFreq, 0, 0, false, null, + Storage.ProvisioningType.THIN, true, null, true, VirtualMachine.Type.ConsoleProxy, true); + + if (offerings == null || offerings.size() < 2) { + String msg = "Data integrity problem : System Offering For Console Proxy has been removed?"; + logger.error(msg); + throw new ConfigurationException(msg); + } + } } diff --git a/server/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImpl.java b/server/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImpl.java index 2edb6bab001..dc33b3434d4 100644 --- a/server/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImpl.java @@ -476,7 +476,7 @@ public class ConsoleAccessManagerImpl extends ManagerBase implements ConsoleAcce ConsoleProxyClientParam param = generateConsoleProxyClientParam(parsedHostInfo, port, sid, tag, ticket, sessionUuid, addr, extraSecurityToken, vm, hostVo, details, portInfo, host, displayName); String token = encryptor.encryptObject(ConsoleProxyClientParam.class, param); - int vncPort = consoleProxyManager.getVncPort(); + int vncPort = consoleProxyManager.getVncPort(vm.getDataCenterId()); String url = generateConsoleAccessUrl(rootUrl, param, token, vncPort, vm, hostVo, details); diff --git a/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java b/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java index 9facfc04b41..1ffd7967eec 100644 --- a/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java +++ b/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java @@ -850,30 +850,6 @@ public class ConfigurationManagerImplTest { Assert.assertEquals(expectedResult, result); } - @Test - public void shouldValidateConfigRangeTestValueIsNullReturnFalse() { - boolean result = configurationManagerImplSpy.shouldValidateConfigRange(Config.ConsoleProxyUrlDomain.name(), null, Config.ConsoleProxyUrlDomain); - Assert.assertFalse(result); - } - - @Test - public void shouldValidateConfigRangeTestConfigIsNullReturnFalse() { - boolean result = configurationManagerImplSpy.shouldValidateConfigRange("", "test", null); - Assert.assertFalse(result); - } - - @Test - public void shouldValidateConfigRangeTestConfigDoesNotHaveARangeReturnFalse() { - boolean result = configurationManagerImplSpy.shouldValidateConfigRange(Config.ConsoleProxySessionMax.name(), "test", Config.ConsoleProxySessionMax); - Assert.assertFalse(result); - } - - @Test - public void shouldValidateConfigRangeTestValueIsNotNullAndConfigHasRangeReturnTrue() { - boolean result = configurationManagerImplSpy.shouldValidateConfigRange(Config.ConsoleProxySessionMax.name(), "test", Config.ConsoleProxyUrlDomain); - Assert.assertTrue(result); - } - @Test public void testResetConfigurations() { Long poolId = 1L; diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/PremiumSecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/PremiumSecondaryStorageManagerImpl.java index f4b72e53967..8c2a6bbd9a3 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/PremiumSecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/PremiumSecondaryStorageManagerImpl.java @@ -28,6 +28,7 @@ import javax.naming.ConfigurationException; import com.cloud.agent.api.Command; import com.cloud.configuration.Config; +import com.cloud.consoleproxy.ConsoleProxyManager; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; @@ -121,8 +122,8 @@ public class PremiumSecondaryStorageManagerImpl extends SecondaryStorageManagerI boolean suspendAutoLoading = !reserveStandbyCapacity(); if (!suspendAutoLoading) { // this is a hacking, has nothing to do with console proxy, it is just a flag that primary storage is being under maintenance mode - String restart = _configDao.getValue("consoleproxy.restart"); - if (restart != null && restart.equalsIgnoreCase("false")) { + Boolean restart = ConsoleProxyManager.ConsoleProxyRestart.valueIn(dataCenterId); + if (Boolean.FALSE.equals(restart)) { logger.debug("Capacity scan disabled purposefully, consoleproxy.restart = false. This happens when the primarystorage is in maintenance mode"); suspendAutoLoading = true; }