You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by ji...@apache.org on 2020/01/21 22:05:58 UTC

[helix] branch helix-cloud updated: Add Helix properties factory and class (#653)

This is an automated email from the ASF dual-hosted git repository.

jiajunwang pushed a commit to branch helix-cloud
in repository https://gitbox.apache.org/repos/asf/helix.git


The following commit(s) were added to refs/heads/helix-cloud by this push:
     new 10ee359  Add Helix properties factory and class (#653)
10ee359 is described below

commit 10ee359942d7219558e692b848039a14e173b735
Author: zhangmeng916 <56...@users.noreply.github.com>
AuthorDate: Tue Jan 21 14:05:50 2020 -0800

    Add Helix properties factory and class (#653)
    
    - Add Helix property singleton factory. The factory returns Helix property with default values, and clients may override these values;
    - Add Helix manager property. It further holds Helix cloud properties and some other properties specific to the manager, defined in helix-manager.properties file.
    - Add Helix cloud property. It holds cloud related properties, which comes from cloud config and client specified file, e.g., for Azure, the file is azure-cloud.properties.
---
 .../main/java/org/apache/helix/ConfigAccessor.java |   2 -
 .../java/org/apache/helix/HelixCloudProperty.java  | 183 +++++++++++++++++++++
 .../java/org/apache/helix/HelixManagerFactory.java |   2 +-
 .../org/apache/helix/HelixManagerProperty.java     |  74 +++++++++
 .../org/apache/helix/HelixPropertyFactory.java     |  79 +++++++++
 .../java/org/apache/helix/SystemPropertyKeys.java  |   8 +
 .../cloud/azure/AzureCloudInstanceInformation.java |  18 +-
 .../helix/manager/zk/ParticipantManager.java       |  10 ++
 .../apache/helix/manager/zk/ZKHelixManager.java    |  17 +-
 .../java/org/apache/helix/model/CloudConfig.java   |  36 +++-
 .../src/main/resources/azure-cloud.properties      |  25 +++
 .../src/main/resources/helix-manager.properties    |  24 +++
 12 files changed, 453 insertions(+), 25 deletions(-)

diff --git a/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java b/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
index 97bfb34..e1d6399 100644
--- a/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
+++ b/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
@@ -609,9 +609,7 @@ public class ConfigAccessor {
 
   /**
    * Get RestConfig of the given cluster.
-   *
    * @param clusterName The cluster
-   *
    * @return The instance of {@link RESTConfig}
    */
   public RESTConfig getRESTConfig(String clusterName) {
diff --git a/helix-core/src/main/java/org/apache/helix/HelixCloudProperty.java b/helix-core/src/main/java/org/apache/helix/HelixCloudProperty.java
new file mode 100644
index 0000000..554c595
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/HelixCloudProperty.java
@@ -0,0 +1,183 @@
+package org.apache.helix;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import org.apache.helix.cloud.constants.CloudProvider;
+import org.apache.helix.model.CloudConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Hold helix cloud properties read from CloudConfig and user defined files. Clients may override
+ * the fields from their application.
+ */
+public class HelixCloudProperty {
+  private static final Logger LOG = LoggerFactory.getLogger(HelixCloudProperty.class.getName());
+  private static final String AZURE_CLOUD_PROPERTY_FILE = SystemPropertyKeys.AZURE_CLOUD_PROPERTIES;
+  private static final String CLOUD_INFO_SOURCE = "cloud_info_source";
+  private static final String CLOUD_INFO_PROCESSFOR_NAME = "cloud_info_processor_name";
+  private static final String CLOUD_MAX_RETRY = "cloud_max_retry";
+  private static final String CONNECTION_TIMEOUT_MS = "connection_timeout_ms";
+  private static final String REQUEST_TIMEOUT_MS = "request_timeout_ms";
+
+  // Denote whether the instance is considered as in a cloud environment.
+  private boolean _isCloudEnabled;
+
+  // Unique id of the cloud environment where the instance is in.
+  private String _cloudId;
+
+  // Cloud environment provider, e.g. Azure, AWS, GCP, etc.
+  private String _cloudProvider;
+
+  // The sources where the cloud instance information can be retrieved from.
+  private List<String> _cloudInfoSources;
+
+  // The name of the function that will fetch and parse cloud instance information.
+  private String _cloudInfoProcessorName;
+
+  // Http max retry times when querying the cloud instance information from cloud environment.
+  private int _cloudMaxRetry;
+
+  // Http connection time when querying the cloud instance information from cloud environment.
+  private long _cloudConnectionTimeout;
+
+  // Http request timeout when querying the cloud instance information from cloud environment.
+  private long _cloudRequestTimeout;
+
+  // Other customized properties that may be used.
+  private Properties _customizedCloudProperties = new Properties();
+
+  /**
+   * Initialize Helix Cloud Property based on the provider
+   * @param
+   */
+  public HelixCloudProperty(CloudConfig cloudConfig) {
+    setCloudEndabled(cloudConfig.isCloudEnabled());
+    if (cloudConfig.isCloudEnabled()) {
+      setCloudId(cloudConfig.getCloudID());
+      setCloudProvider(cloudConfig.getCloudProvider());
+      switch (CloudProvider.valueOf(cloudConfig.getCloudProvider())) {
+      case AZURE:
+        Properties azureProperties = new Properties();
+        try {
+          InputStream stream = Thread.currentThread().getContextClassLoader()
+              .getResourceAsStream(AZURE_CLOUD_PROPERTY_FILE);
+          azureProperties.load(stream);
+        } catch (IOException e) {
+          String errMsg =
+              "failed to open Helix Azure cloud properties file: " + AZURE_CLOUD_PROPERTY_FILE;
+          throw new IllegalArgumentException(errMsg, e);
+        }
+        LOG.info("Successfully loaded Helix Azure cloud properties: {}", azureProperties);
+        setCloudInfoSources(
+            Collections.singletonList(azureProperties.getProperty(CLOUD_INFO_SOURCE)));
+        setCloudInfoProcessorName(azureProperties.getProperty(CLOUD_INFO_PROCESSFOR_NAME));
+        setCloudMaxRetry(Integer.valueOf(azureProperties.getProperty(CLOUD_MAX_RETRY)));
+        setCloudConnectionTimeout(Long.valueOf(azureProperties.getProperty(CONNECTION_TIMEOUT_MS)));
+        setCloudRequestTimeout(Long.valueOf(azureProperties.getProperty(REQUEST_TIMEOUT_MS)));
+        break;
+      case CUSTOMIZED:
+        setCloudInfoSources(cloudConfig.getCloudInfoSources());
+        setCloudInfoProcessorName(cloudConfig.getCloudInfoProcessorName());
+        break;
+      default:
+        throw new HelixException(
+            String.format("Unsupported cloud provider: %s", cloudConfig.getCloudProvider()));
+      }
+    }
+  }
+
+  public boolean getCloudEnabled() {
+    return _isCloudEnabled;
+  }
+
+  public String getCloudId() {
+    return _cloudId;
+  }
+
+  public String getCloudProvider() {
+    return _cloudProvider;
+  }
+
+  public List<String> getCloudInfoSources() {
+    return _cloudInfoSources;
+  }
+
+  public String getCloudInfoProcessorName() {
+    return _cloudInfoProcessorName;
+  }
+
+  public int getCloudMaxRetry() {
+    return _cloudMaxRetry;
+  }
+
+  public long getCloudConnectionTimeout() {
+    return _cloudConnectionTimeout;
+  }
+
+  public long getCloudRequestTimeout() {
+    return _cloudRequestTimeout;
+  }
+
+  public Properties getCustomizedCloudProperties() {
+    return _customizedCloudProperties;
+  }
+
+  public void setCloudEndabled(boolean isCloudEnabled) {
+    _isCloudEnabled = isCloudEnabled;
+  }
+
+  public void setCloudId(String cloudId) {
+    _cloudId = cloudId;
+  }
+
+  public void setCloudProvider(String cloudProvider) {
+    _cloudProvider = cloudProvider;
+  }
+
+  public void setCloudInfoSources(List<String> sources) {
+    _cloudInfoSources = sources;
+  }
+
+  public void setCloudInfoProcessorName(String cloudInfoProcessorName) {
+    _cloudInfoProcessorName = cloudInfoProcessorName;
+  }
+
+  public void setCloudMaxRetry(int cloudMaxRetry) {
+    _cloudMaxRetry = cloudMaxRetry;
+  }
+
+  public void setCloudConnectionTimeout(long cloudConnectionTimeout) {
+    _cloudConnectionTimeout = cloudConnectionTimeout;
+  }
+
+  public void setCloudRequestTimeout(long cloudRequestTimeout) {
+    _cloudRequestTimeout = cloudRequestTimeout;
+  }
+
+  public void setCustomizedCloudProperties(Properties customizedCloudProperties) {
+    _customizedCloudProperties.putAll(customizedCloudProperties);
+  }
+}
diff --git a/helix-core/src/main/java/org/apache/helix/HelixManagerFactory.java b/helix-core/src/main/java/org/apache/helix/HelixManagerFactory.java
index 7d8038d..ee53c1d 100644
--- a/helix-core/src/main/java/org/apache/helix/HelixManagerFactory.java
+++ b/helix-core/src/main/java/org/apache/helix/HelixManagerFactory.java
@@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory;
  * Obtain one of a set of Helix cluster managers, organized by the backing system.
  */
 public final class HelixManagerFactory {
-  private static final Logger logger = LoggerFactory.getLogger(HelixManagerFactory.class);
+  private static final Logger LOG = LoggerFactory.getLogger(HelixManagerFactory.class);
 
   /**
    * Construct a zk-based cluster manager that enforces all types (PARTICIPANT, CONTROLLER, and
diff --git a/helix-core/src/main/java/org/apache/helix/HelixManagerProperty.java b/helix-core/src/main/java/org/apache/helix/HelixManagerProperty.java
new file mode 100644
index 0000000..2ec26a7
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/HelixManagerProperty.java
@@ -0,0 +1,74 @@
+package org.apache.helix;
+
+/*
+ * 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.
+ */
+
+import java.util.Properties;
+import org.apache.helix.model.CloudConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Hold Helix manager properties. The manager properties further hold Helix cloud properties
+ * and some other properties specific for the manager.
+ */
+public class HelixManagerProperty {
+  private static final Logger LOG = LoggerFactory.getLogger(HelixManagerProperty.class.getName());
+  private String _version;
+  private long _healthReportLatency;
+  private HelixCloudProperty _helixCloudProperty;
+
+  /**
+   * Initialize Helix manager property with default value
+   * @param helixManagerProperties helix manager related properties input as a map
+   * @param cloudConfig cloudConfig read from Zookeeper
+   */
+  public HelixManagerProperty(Properties helixManagerProperties, CloudConfig cloudConfig) {
+    _helixCloudProperty = new HelixCloudProperty(cloudConfig);
+    setVersion(helixManagerProperties.getProperty(SystemPropertyKeys.HELIX_MANAGER_VERSION));
+    setHealthReportLatency(
+        helixManagerProperties.getProperty(SystemPropertyKeys.PARTICIPANT_HEALTH_REPORT_LATENCY));
+  }
+
+  public HelixCloudProperty getHelixCloudProperty() {
+    return _helixCloudProperty;
+  }
+
+  public String getVersion() {
+    return _version;
+  }
+
+  public long getHealthReportLatency() {
+    return _healthReportLatency;
+  }
+
+  public void setHelixCloudProperty(HelixCloudProperty helixCloudProperty) {
+    _helixCloudProperty = helixCloudProperty;
+  }
+
+  public void setVersion(String version) {
+    _version = version;
+  }
+
+  public void setHealthReportLatency(String latency) {
+    _healthReportLatency = Long.valueOf(latency);
+  }
+
+  // TODO: migrate all other participant related properties to this file.
+}
diff --git a/helix-core/src/main/java/org/apache/helix/HelixPropertyFactory.java b/helix-core/src/main/java/org/apache/helix/HelixPropertyFactory.java
new file mode 100644
index 0000000..fa394a2
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/HelixPropertyFactory.java
@@ -0,0 +1,79 @@
+package org.apache.helix;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import org.apache.helix.model.CloudConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Singleton factory that builds different types of Helix property, e.g. Helix manager property.
+ */
+public final class HelixPropertyFactory {
+  private static final Logger LOG = LoggerFactory.getLogger(HelixPropertyFactory.class);
+  private static final String HELIX_PARTICIPANT_PROPERTY_FILE =
+      SystemPropertyKeys.HELIX_MANAGER_PROPERTIES;
+
+  private static class SingletonHelper {
+    private static final HelixPropertyFactory INSTANCE = new HelixPropertyFactory();
+  }
+
+  public static HelixPropertyFactory getInstance() {
+    return SingletonHelper.INSTANCE;
+  }
+
+  /**
+   * Retrieve Helix manager property. It returns the property object with default values.
+   * Clients may override these values.
+   */
+  public HelixManagerProperty getHelixManagerProperty(String zkAddress, String clusterName) {
+    ConfigAccessor configAccessor = new ConfigAccessor(zkAddress);
+    CloudConfig cloudConfig;
+    // The try-catch logic is for backward compatibility reason only. Even if the cluster is not set
+    // up yet, constructing a new ZKHelixManager should not throw an exception
+    try {
+      cloudConfig =
+          configAccessor.getCloudConfig(clusterName) == null ? buildEmptyCloudConfig(clusterName)
+              : configAccessor.getCloudConfig(clusterName);
+    } catch (HelixException e) {
+      cloudConfig = buildEmptyCloudConfig(clusterName);
+    }
+    Properties properties = new Properties();
+    try {
+      InputStream stream = Thread.currentThread().getContextClassLoader()
+          .getResourceAsStream(HELIX_PARTICIPANT_PROPERTY_FILE);
+      properties.load(stream);
+    } catch (IOException e) {
+      String errMsg = String.format("failed to open Helix participant properties file: %s",
+          HELIX_PARTICIPANT_PROPERTY_FILE);
+      throw new IllegalArgumentException(errMsg, e);
+    }
+    LOG.info("HelixPropertyFactory successfully loaded helix participant properties: {}",
+        properties);
+    return new HelixManagerProperty(properties, cloudConfig);
+  }
+
+  public static CloudConfig buildEmptyCloudConfig(String clusterName) {
+    return new CloudConfig.Builder().setCloudEnabled(false).build();
+  }
+}
diff --git a/helix-core/src/main/java/org/apache/helix/SystemPropertyKeys.java b/helix-core/src/main/java/org/apache/helix/SystemPropertyKeys.java
index 1a6a797..b1735a0 100644
--- a/helix-core/src/main/java/org/apache/helix/SystemPropertyKeys.java
+++ b/helix-core/src/main/java/org/apache/helix/SystemPropertyKeys.java
@@ -1,6 +1,14 @@
 package org.apache.helix;
 
 public class SystemPropertyKeys {
+  // Used to compose default values in HelixManagerProperty
+  public static final String HELIX_MANAGER_PROPERTIES = "helix-manager.properties";
+
+  public static final String HELIX_MANAGER_VERSION = "clustermanager.version";
+
+  // Used to compose default values in HelixCloudProperty when cloud provider is Azure
+  public static final String AZURE_CLOUD_PROPERTIES = "azure-cloud.properties";
+
   // Task Driver
   public static final String TASK_CONFIG_LIMITATION = "helixTask.configsLimitation";
 
diff --git a/helix-core/src/main/java/org/apache/helix/cloud/azure/AzureCloudInstanceInformation.java b/helix-core/src/main/java/org/apache/helix/cloud/azure/AzureCloudInstanceInformation.java
index 511f3e3..f7fd657 100644
--- a/helix-core/src/main/java/org/apache/helix/cloud/azure/AzureCloudInstanceInformation.java
+++ b/helix-core/src/main/java/org/apache/helix/cloud/azure/AzureCloudInstanceInformation.java
@@ -48,24 +48,18 @@ public class AzureCloudInstanceInformation implements CloudInstanceInformation {
       return new AzureCloudInstanceInformation(_cloudInstanceInfoMap);
     }
 
-    /**
-     * Default constructor
-     */
-    public Builder() {
-    }
-
-    public Builder setInstanceName(String v) {
-      _cloudInstanceInfoMap.put(CloudInstanceField.INSTANCE_NAME.name(), v);
+    public Builder setInstanceName(String name) {
+      _cloudInstanceInfoMap.put(CloudInstanceField.INSTANCE_NAME.name(), name);
       return this;
     }
 
-    public Builder setFaultDomain(String v) {
-      _cloudInstanceInfoMap.put(CloudInstanceField.FAULT_DOMAIN.name(), v);
+    public Builder setFaultDomain(String faultDomain) {
+      _cloudInstanceInfoMap.put(CloudInstanceField.FAULT_DOMAIN.name(), faultDomain);
       return this;
     }
 
-    public Builder setInstanceSetName(String v) {
-      _cloudInstanceInfoMap.put(CloudInstanceField.INSTANCE_SET_NAME.name(), v);
+    public Builder setInstanceSetName(String instanceSetName) {
+      _cloudInstanceInfoMap.put(CloudInstanceField.INSTANCE_SET_NAME.name(), instanceSetName);
       return this;
     }
 
diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManager.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManager.java
index 76cb791..9c5d602 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManager.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ParticipantManager.java
@@ -33,6 +33,7 @@ import org.apache.helix.ConfigAccessor;
 import org.apache.helix.HelixAdmin;
 import org.apache.helix.HelixException;
 import org.apache.helix.HelixManager;
+import org.apache.helix.HelixManagerProperty;
 import org.apache.helix.InstanceType;
 import org.apache.helix.LiveInstanceInfoProvider;
 import org.apache.helix.PreConnectCallback;
@@ -76,9 +77,17 @@ public class ParticipantManager {
   final StateMachineEngine _stateMachineEngine;
   final LiveInstanceInfoProvider _liveInstanceInfoProvider;
   final List<PreConnectCallback> _preConnectCallbacks;
+  final HelixManagerProperty _helixManagerProperty;
 
+  @Deprecated
   public ParticipantManager(HelixManager manager, HelixZkClient zkclient, int sessionTimeout,
       LiveInstanceInfoProvider liveInstanceInfoProvider, List<PreConnectCallback> preConnectCallbacks) {
+    this(manager, zkclient, sessionTimeout, liveInstanceInfoProvider, preConnectCallbacks, null);
+  }
+
+  public ParticipantManager(HelixManager manager, HelixZkClient zkclient, int sessionTimeout,
+      LiveInstanceInfoProvider liveInstanceInfoProvider, List<PreConnectCallback> preConnectCallbacks,
+      HelixManagerProperty helixManagerProperty) {
     _zkclient = zkclient;
     _manager = manager;
     _clusterName = manager.getClusterName();
@@ -94,6 +103,7 @@ public class ParticipantManager {
     _stateMachineEngine = manager.getStateMachineEngine();
     _liveInstanceInfoProvider = liveInstanceInfoProvider;
     _preConnectCallbacks = preConnectCallbacks;
+    _helixManagerProperty = helixManagerProperty;
   }
 
   /**
diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java
index df2dccc..693dc17 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java
@@ -41,6 +41,8 @@ import org.apache.helix.HelixDataAccessor;
 import org.apache.helix.HelixException;
 import org.apache.helix.HelixManager;
 import org.apache.helix.HelixManagerProperties;
+import org.apache.helix.HelixManagerProperty;
+import org.apache.helix.HelixPropertyFactory;
 import org.apache.helix.HelixTimerTask;
 import org.apache.helix.InstanceType;
 import org.apache.helix.LiveInstanceInfoProvider;
@@ -106,6 +108,7 @@ public class ZKHelixManager implements HelixManager, IZkStateListener {
   private final List<PreConnectCallback> _preConnectCallbacks;
   protected final List<CallbackHandler> _handlers;
   private final HelixManagerProperties _properties;
+  private final HelixManagerProperty _helixManagerProperty;
   private final HelixManagerStateListener _stateListener;
 
   /**
@@ -202,9 +205,16 @@ public class ZKHelixManager implements HelixManager, IZkStateListener {
 
   public ZKHelixManager(String clusterName, String instanceName, InstanceType instanceType,
       String zkAddress, HelixManagerStateListener stateListener) {
+    this(clusterName, instanceName, instanceType, zkAddress, stateListener,
+        HelixPropertyFactory.getInstance().getHelixManagerProperty(zkAddress, clusterName));
+  }
+
+  public ZKHelixManager(String clusterName, String instanceName, InstanceType instanceType,
+      String zkAddress, HelixManagerStateListener stateListener,
+      HelixManagerProperty helixManagerProperty) {
 
-    LOG.info(
-        "Create a zk-based cluster manager. zkSvr: " + zkAddress + ", clusterName: " + clusterName + ", instanceName: " + instanceName + ", type: " + instanceType);
+    LOG.info("Create a zk-based cluster manager. zkSvr: " + zkAddress + ", clusterName: "
+        + clusterName + ", instanceName: " + instanceName + ", type: " + instanceType);
 
     _zkAddress = zkAddress;
     _clusterName = clusterName;
@@ -244,6 +254,7 @@ public class ZKHelixManager implements HelixManager, IZkStateListener {
     }
 
     _stateListener = stateListener;
+    _helixManagerProperty = helixManagerProperty;
 
     /**
      * use system property if available
@@ -1203,7 +1214,7 @@ public class ZKHelixManager implements HelixManager, IZkStateListener {
     }
     _participantManager =
         new ParticipantManager(this, _zkclient, _sessionTimeout, _liveInstanceInfoProvider,
-            _preConnectCallbacks);
+            _preConnectCallbacks, _helixManagerProperty);
     _participantManager.handleNewSession();
   }
 
diff --git a/helix-core/src/main/java/org/apache/helix/model/CloudConfig.java b/helix-core/src/main/java/org/apache/helix/model/CloudConfig.java
index f6c279c..79c7330 100644
--- a/helix-core/src/main/java/org/apache/helix/model/CloudConfig.java
+++ b/helix-core/src/main/java/org/apache/helix/model/CloudConfig.java
@@ -71,6 +71,26 @@ public class CloudConfig extends HelixProperty {
     _record.setMapFields(record.getMapFields());
   }
 
+  /**
+   * Instantiate the config using each field individually.
+   * Users should use CloudConfig.Builder to create CloudConfig.
+   * @param cluster
+   * @param enabled
+   * @param cloudID
+   */
+  public CloudConfig(String cluster, boolean enabled, CloudProvider cloudProvider, String cloudID,
+      List<String> cloudInfoSource, String cloudProcessorName) {
+    super(cluster);
+    _record.setBooleanField(CloudConfigProperty.CLOUD_ENABLED.name(), enabled);
+    if (enabled == true) {
+      _record.setSimpleField(CloudConfigProperty.CLOUD_PROVIDER.name(), cloudProvider.name());
+      _record.setSimpleField(CloudConfigProperty.CLOUD_ID.name(), cloudID);
+      if (cloudProvider.equals(CloudProvider.CUSTOMIZED)) {
+        _record.setSimpleField(CloudConfigProperty.CLOUD_INFO_PROCESSOR_NAME.name(), cloudProcessorName);
+        _record.setListField(CloudConfigProperty.CLOUD_INFO_SOURCE.name(), cloudInfoSource);
+      }
+    }
+  }
 
   /**
    * Enable/Disable the CLOUD_ENABLED field.
@@ -226,14 +246,16 @@ public class CloudConfig extends HelixProperty {
     }
 
     private void validate() {
-      if (this.getCloudProvider() == null) {
-        throw new HelixException(
-            "This Cloud Configuration is Invalid. The Cloud Provider is missing from the config.");
-      } else if (this.getCloudProvider().equals(CloudProvider.CUSTOMIZED.name())) {
-        if (this.getCloudInfoProcessorName() == null || this.getCloudInfoSources() == null
-            || this.getCloudInfoSources().size() == 0) {
+      if (this.getCloudEnabled()) {
+        if (this.getCloudProvider() == null) {
           throw new HelixException(
-              "This Cloud Configuration is Invalid. CUSTOMIZED provider has been chosen without defining CloudInfoProcessorName or CloudInfoSources");
+              "This Cloud Configuration is Invalid. The Cloud Provider is missing from the config.");
+        } else if (this.getCloudProvider().equals(CloudProvider.CUSTOMIZED.name())) {
+          if (this.getCloudInfoProcessorName() == null || this.getCloudInfoSources() == null
+              || this.getCloudInfoSources().size() == 0) {
+            throw new HelixException(
+                "This Cloud Configuration is Invalid. CUSTOMIZED provider has been chosen without defining CloudInfoProcessorName or CloudInfoSources");
+          }
         }
       }
     }
diff --git a/helix-core/src/main/resources/azure-cloud.properties b/helix-core/src/main/resources/azure-cloud.properties
new file mode 100644
index 0000000..b5321fc
--- /dev/null
+++ b/helix-core/src/main/resources/azure-cloud.properties
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+# This is the globally fixed value for Azure Metadata Instance Service endpoint
+cloud_info_source=http://169.254.169.254/metadata/instance?api-version=2019-06-04
+cloud_info_processor_name=AzureCloudInstanceInformationProcessor
+cloud_max_retry=5
+connection_timeout_ms=5000
+request_timeout_ms=5000
\ No newline at end of file
diff --git a/helix-core/src/main/resources/helix-manager.properties b/helix-core/src/main/resources/helix-manager.properties
new file mode 100644
index 0000000..eafcb3a
--- /dev/null
+++ b/helix-core/src/main/resources/helix-manager.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+clustermanager.version=${project.version}
+
+minimum_supported_version.participant=0.4
+
+helixmanager.participantHealthReport.reportLatency=60000
\ No newline at end of file