Connected config gathering to CloudStack
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/49cd4fa3 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/49cd4fa3 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/49cd4fa3 Branch: refs/heads/master Commit: 49cd4fa380dcea548b50987ddf15c38031615f4e Parents: 90cfca0 Author: Alex Huang <alex.hu...@citrix.com> Authored: Tue Aug 6 11:03:38 2013 -0700 Committer: Alex Huang <alex.hu...@citrix.com> Committed: Wed Aug 7 16:41:04 2013 -0700 ---------------------------------------------------------------------- .../apache/cloudstack/config/Configuration.java | 63 ++++++++++++++++++-- .../com/cloud/cluster/ClusterManagerImpl.java | 4 +- .../cluster/ClusterServiceServletAdapter.java | 2 +- .../framework/config/ConfigDepot.java | 2 + .../framework/config/ConfigDepotAdmin.java | 7 +++ .../framework/config/ConfigDepotImpl.java | 29 ++++++++- .../cloudstack/framework/config/ConfigKey.java | 12 ++-- .../framework/config/Configurable.java | 8 +++ .../framework/config/ConfigurationVO.java | 2 +- .../framework/config/ScopedConfigValue.java | 43 +++++++++++++ .../cloud/agent/manager/AgentManagerImpl.java | 13 ++-- .../manager/ClusteredAgentManagerImpl.java | 8 +-- .../cloud/server/ConfigurationServerImpl.java | 4 ++ 13 files changed, 166 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/api/src/org/apache/cloudstack/config/Configuration.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/config/Configuration.java b/api/src/org/apache/cloudstack/config/Configuration.java index 8657832..97cc8c4 100644 --- a/api/src/org/apache/cloudstack/config/Configuration.java +++ b/api/src/org/apache/cloudstack/config/Configuration.java @@ -16,18 +16,69 @@ // under the License. package org.apache.cloudstack.config; +import java.util.Date; + +/** + * Configuration represents one global configuration parameter for CloudStack. + * Its scope should indicate whether this parameter can be set at different + * organization levels in CloudStack. + * + */ public interface Configuration { - public String getCategory(); + /** + * @return Category of the parameter. + */ + String getCategory(); + + /** + * @return Server instance that uses this parameter. + */ + String getInstance(); + + /** + * @return Component that introduced this parameter. + */ + String getComponent(); + + /** + * @return Name of the parameter. + */ + String getName(); - public String getInstance(); + /** + * @return Value set by the administrator. Defaults to the defaultValue. + */ + String getValue(); - public String getComponent(); + /** + * @return Description of the value and the range of the value. + */ + String getDescription(); - public String getName(); + /** + * @return Default value for this parameter. Cannot be null. + */ + String getDefaultValue(); - public String getValue(); + /** + * @return Scope for the parameter. Null indicates that this parameter is + * always global. A non-null value indicates that this parameter can be + * set at a certain organization level. + */ + String getScope(); - public String getDescription(); + /** + * @return can the configuration parameter be changed without restarting the server. + */ + boolean isDynamic(); + /** + * @return The date this VO was updated by the components. Note that this is not + * a date for when an administrator updates the value. This is when the system + * updated this value. By searching on this field gives you all the config + * parameters that have changed in an upgrade. Null value indicates that this + * parameter is no longer used and can be deleted. + */ + Date getUpdated(); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java ---------------------------------------------------------------------- diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java b/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java index 046a1dc..41b619c 100644 --- a/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java +++ b/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java @@ -1028,9 +1028,9 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager { } protected final ConfigKey<Integer> HeartBeatInterval = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.interval", "management-server", - "1500", "Interval to check for the heart beat between management server nodes", false, "Seconds"); + "1500", "Interval to check for the heart beat between management server nodes", false); protected final ConfigKey<Integer> HeartBeatThreshold = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.threshold", "management-server", - "150000", "Threshold before self-fence the management server", true, "Seconds"); + "150000", "Threshold before self-fence the management server", true); @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java ---------------------------------------------------------------------- diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java index fc86e4d..87e92f5 100644 --- a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java +++ b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java @@ -126,7 +126,7 @@ public class ClusterServiceServletAdapter extends AdapterBase implements Cluster } private final ConfigKey<Integer> ClusterMessageTimeOut = new ConfigKey<Integer>(Integer.class, "cluster.message.timeout.seconds", "Advance", "300", - "Time (in seconds) to wait before a inter-management server message post times out.", true, "Seconds"); + "Time (in seconds) to wait before a inter-management server message post times out.", true); private void init() throws ConfigurationException { if(_mshostDao != null) http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepot.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepot.java b/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepot.java index e2c1305..98363f3 100644 --- a/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepot.java +++ b/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepot.java @@ -22,4 +22,6 @@ package org.apache.cloudstack.framework.config; */ public interface ConfigDepot { <T> ConfigValue<T> get(ConfigKey<T> key); + + <T> ScopedConfigValue<T> getScopedValue(ConfigKey<T> key); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotAdmin.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotAdmin.java b/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotAdmin.java index 8dac77f..b4d3773 100644 --- a/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotAdmin.java +++ b/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotAdmin.java @@ -23,6 +23,13 @@ import java.util.List; * */ public interface ConfigDepotAdmin { + /** + * Create configurations if there are new config parameters. + * Update configurations if the parameter settings have been changed. + * All configurations that have been updated/created will have the same timestamp in the updated field. + * All previous configurations that should be obsolete will have a null updated field. + * @see Configuration + */ void populateConfigurations(); List<String> getComponentsInDepot(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotImpl.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotImpl.java b/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotImpl.java index 42b4ab6..df79d9d 100644 --- a/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotImpl.java +++ b/framework/config/src/org/apache/cloudstack/framework/config/ConfigDepotImpl.java @@ -27,7 +27,25 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import com.cloud.utils.db.EntityManager; /** - * DepotImpl implements the ConfigDepot interface + * ConfigDepotImpl implements the ConfigDepot and ConfigDepotAdmin interface. + * Its functionalities include: + * - Control how dynamic config values are cached and refreshed. + * - Control how scoped config values are stored. + * - Gather all of the Configurable interfaces and insert their config + * variables into the config table. + * - Hide the data source where configs are stored and retrieved. + * + * When dealing with this class, we must be very careful on cluster situations. + * + * TODO: + * - Move the rest of the changes to the config table to here. + * - Implement ScopedConfigValue + * - Move the code to set scoped configuration values to here. + * - Add the code to mark the rows in configuration table without + * the corresponding keys to be null. + * - Move all of the configurations to using ConfigDepot + * - Completely eliminate Config.java + * - Figure out the correct categories. * */ class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin { @@ -49,6 +67,13 @@ class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin { } @Override + public <T> ScopedConfigValue<T> getScopedValue(ConfigKey<T> config) { + assert (config.scope() != null) : "Did you notice the configuration you're trying to retrieve is not scoped?"; + return new ScopedConfigValue<T>(_entityMgr, config); + } + + + @Override public void populateConfigurations() { Date date = new Date(); for (Configurable configurable : _configurables) { @@ -70,8 +95,6 @@ class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin { } } } - - // TODO: Missing code to remove the updated field if the a configurationVO's name cannot be found any more. } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java b/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java index f47d302..cef226c 100644 --- a/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java +++ b/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java @@ -16,14 +16,12 @@ // under the License. package org.apache.cloudstack.framework.config; +import com.cloud.org.Grouping; + /** * ConfigKey supplants the original Config.java. It is just a class * declaration where others can declare their config variables. * - * TODO: This class should be moved to a framework project where the gathering - * of these configuration keys should be done by a config server. I - * don't have time yet to do this. Ask me about it if you want to work - * in this area. Right now, we'll just work with the actual names. */ public class ConfigKey<T> { @@ -49,7 +47,7 @@ public class ConfigKey<T> { return _description; } - public String scope() { + public Class<? extends Grouping> scope() { return _scope; } @@ -66,11 +64,11 @@ public class ConfigKey<T> { private final String _name; private final String _defaultValue; private final String _description; - private final String _scope; // Parameter can be at different levels (Zone/cluster/pool/account), by default every parameter is at global + private final Class<? extends Grouping> _scope; // Parameter can be at different levels (Zone/cluster/pool/account), by default every parameter is at global private final boolean _isDynamic; public ConfigKey(Class<T> type, String name, String category, String defaultValue, String description, boolean isDynamic, - String scope) { + Class<? extends Grouping> scope) { _category = category; _type = type; _name = name; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/config/src/org/apache/cloudstack/framework/config/Configurable.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/Configurable.java b/framework/config/src/org/apache/cloudstack/framework/config/Configurable.java index 8dc5af9..f99e8a1 100644 --- a/framework/config/src/org/apache/cloudstack/framework/config/Configurable.java +++ b/framework/config/src/org/apache/cloudstack/framework/config/Configurable.java @@ -16,6 +16,14 @@ // under the License. package org.apache.cloudstack.framework.config; +/** + * Configurable can be implemented by components to insert their own + * configuration keys. + * + * CloudStack will gather all of these configurations at startup and insert + * them into the configuration table. + * + */ public interface Configurable { String getConfigComponentName(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/config/src/org/apache/cloudstack/framework/config/ConfigurationVO.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ConfigurationVO.java b/framework/config/src/org/apache/cloudstack/framework/config/ConfigurationVO.java index a21ccbc..ad2b582 100644 --- a/framework/config/src/org/apache/cloudstack/framework/config/ConfigurationVO.java +++ b/framework/config/src/org/apache/cloudstack/framework/config/ConfigurationVO.java @@ -80,7 +80,7 @@ public class ConfigurationVO implements Configuration { this(key.category(), "DEFAULT", component, key.key(), key.defaultValue(), key.description()); defaultValue = key.defaultValue(); dynamic = key.isDynamic(); - scope = key.scope(); + scope = key.scope().getName(); } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/framework/config/src/org/apache/cloudstack/framework/config/ScopedConfigValue.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ScopedConfigValue.java b/framework/config/src/org/apache/cloudstack/framework/config/ScopedConfigValue.java new file mode 100644 index 0000000..4631521 --- /dev/null +++ b/framework/config/src/org/apache/cloudstack/framework/config/ScopedConfigValue.java @@ -0,0 +1,43 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.framework.config; + +import com.cloud.dc.DataCenter; +import com.cloud.dc.Pod; +import com.cloud.org.Cluster; +import com.cloud.org.Grouping; +import com.cloud.utils.db.EntityManager; + +public class ScopedConfigValue<T> extends ConfigValue<T> { + public T getValueForScope(long scopeId) { + // TODO: In order to complete this the details for zone, pod, cluster + // needs to have interfaces. Then you can use the EntityManager to + // retrieve those information. + Class<? extends Grouping> scope = _config.scope(); + if (scope == DataCenter.class) { + } else if (scope == Pod.class) { + + } else if (scope == Cluster.class) { + + } + return null; + } + + protected ScopedConfigValue(EntityManager entityMgr, ConfigKey<T> key) { + super(entityMgr, key); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/server/src/com/cloud/agent/manager/AgentManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index 690c96e..01c2137 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -179,17 +179,16 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl protected ConfigDepot _configDepot; protected final ConfigKey<Integer> Workers = new ConfigKey<Integer>(Integer.class, "workers", "Advance", "5", - "Number of worker threads handling remote agent connections.", false, "5-Max Thread Limit"); - protected final ConfigKey<Integer> Port = new ConfigKey<Integer>(Integer.class, "port", "Advance", "8250", "Port to listen on for remote agent connections.", false, - "Usable port range"); + "Number of worker threads handling remote agent connections.", false); + protected final ConfigKey<Integer> Port = new ConfigKey<Integer>(Integer.class, "port", "Advance", "8250", "Port to listen on for remote agent connections.", false); protected final ConfigKey<Integer> PingInterval = new ConfigKey<Integer>(Integer.class, "ping.interval", "Advance", "60", - "Interval to send application level pings to make sure the connection is still working", false, "Seconds"); + "Interval to send application level pings to make sure the connection is still working", false); protected final ConfigKey<Float> PingTimeout = new ConfigKey<Float>(Float.class, "ping.timeout", "Advance", "2.5", - "Multiplier to ping.interval before announcing an agent has timed out", true, null); + "Multiplier to ping.interval before announcing an agent has timed out", true); protected final ConfigKey<Integer> Wait = new ConfigKey<Integer>(Integer.class, "wait", "Advance", "1800", - "Time in seconds to wait for control commands to return", true, "Seconds"); + "Time in seconds to wait for control commands to return", true); protected final ConfigKey<Integer> AlertWait = new ConfigKey<Integer>(Integer.class, "alert.wait", "Advance", "1800", - "Seconds to wait before alerting on a disconnected agent", true, "Seconds"); + "Seconds to wait before alerting on a disconnected agent", true); protected final ConfigKey<Integer> DirectAgentLoadSize = new ConfigKey<Integer>(Integer.class, "direct.agent.load.size", "Advance", "16", "The number of direct agents to load each time", false, null); protected final ConfigKey<Integer> DirectAgentPoolSize = new ConfigKey<Integer>(Integer.class, "direct.agent.pool.size", "Advance", "500", http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java index 506e640..742d798 100755 --- a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java @@ -134,13 +134,13 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } protected final ConfigKey<Boolean> EnableLB = new ConfigKey<Boolean>(Boolean.class, "agent.lb.enabled", "Advanced", "false", - "Enable agent load balancing between management server nodes", true, "True/False"); + "Enable agent load balancing between management server nodes", true); protected final ConfigKey<Double> ConnectedAgentThreshold = new ConfigKey<Double>(Double.class, "agent.load.threshold", "Advanced", "0.7", - "What percentage of the agents can be held by one management server before load balancing happens", true, "0-1"); + "What percentage of the agents can be held by one management server before load balancing happens", true); protected final ConfigKey<Integer> LoadSize = new ConfigKey<Integer>(Integer.class, "direct.agent.load.size", "Advanced", "16", - "How many agents to connect to in each round", true, ""); + "How many agents to connect to in each round", true); protected final ConfigKey<Integer> ScanInterval = new ConfigKey<Integer>(Integer.class, "direct.agent.scan.interval", "Advanced", "90", - "Interval between scans to load agents", false, "Seconds"); + "Interval between scans to load agents", false); protected ConfigValue<Boolean> _agentLBEnabled; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49cd4fa3/server/src/com/cloud/server/ConfigurationServerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 98290f6..bc9b23d 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -46,6 +46,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; +import org.apache.cloudstack.framework.config.ConfigDepotAdmin; import org.apache.cloudstack.framework.config.ConfigurationVO; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; @@ -142,6 +143,8 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @Inject private ClusterDetailsDao _clusterDetailsDao; @Inject private StoragePoolDetailsDao _storagePoolDetailsDao; @Inject private AccountDetailsDao _accountDetailsDao; + @Inject + protected ConfigDepotAdmin _configDepotAdmin; public ConfigurationServerImpl() { setRunLevel(ComponentLifecycle.RUN_LEVEL_FRAMEWORK_BOOTSTRAP); @@ -153,6 +156,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio try { persistDefaultValues(); + _configDepotAdmin.populateConfigurations(); } catch (InternalErrorException e) { throw new RuntimeException("Unhandled configuration exception", e); }