/***************************************************************************
* Copyright (c) 2012-2015 VMware, Inc. All Rights Reserved.
* Licensed 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 com.vmware.bdd.specpolicy;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.URL;
import java.util.Collections;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.configuration.ConfigurationUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import com.google.gson.Gson;
import com.vmware.aurora.global.Configuration;
import com.vmware.bdd.apitypes.ClusterCreate;
import com.vmware.bdd.apitypes.ClusterType;
import com.vmware.bdd.exception.BddException;
import com.vmware.bdd.utils.AuAssert;
import com.vmware.bdd.utils.CommonUtil;
import com.vmware.bdd.utils.Constants;
import com.vmware.bdd.utils.Version;
public class ClusterSpecFactory {
private enum MAPREDUCE_VERSION {
V1, V2
}
private enum HDP_VERSION {
V1, V2_0, V2_1, V2_2, V2_3, UNKNOWN
}
private static final Logger logger = Logger
.getLogger(ClusterSpecFactory.class);
private static final String DEFAULT_TEMPLATE_SPEC_SUFFIX = "-default-template-spec.json";
private static final String HDFS_TEMPLATE_SPEC = "hdfs-template-spec.json";
private static final String HDFS_MAPRED_TEMPLATE_SPEC =
"hdfs-mapred-template-spec.json";
private static final String HDFS_YARN_TEMPLATE_SPEC =
"hdfs-yarn-template-spec.json";
private static final String HDFS_HBASE_TEMPLATE_SPEC =
"hdfs-hbase-template-spec.json";
private static final String HDFS_MAPRED_MAPR_TEMPLATE_SPEC =
"hdfs-mapred-mapr-template-spec.json";
private static final String HDFS_MAPRED_MAPR_V3_TEMPLATE_SPEC =
"hdfs-mapred-mapr-v3-template-spec.json";
private static final String HDFS_HBASE_MAPR_TEMPLATE_SPEC =
"hdfs-hbase-mapr-template-spec.json";
private static final String HDFS_HBASE_MAPR_V3_TEMPLATE_SPEC =
"hdfs-hbase-mapr-v3-template-spec.json";
private static final String HDFS_GPHD_TEMPLATE_SPEC =
"hdfs-gphd-template-spec.json";
private static final String HDFS_MAPRED_GPHD_TEMPLATE_SPEC =
"hdfs-mapred-gphd-template-spec.json";
private static final String HDFS_HBASE_GPHD_TEMPLATE_SPEC =
"hdfs-hbase-gphd-template-spec.json";
private static final String CM_HDFS_MAPRED_TEMPLATE_SPEC =
"cm-hdfs-mapred-template-spec.json";
private static final String CM_HDFS_YARN_TEMPLATE_SPEC =
"cm-hdfs-yarn-template-spec.json";
private static final String CM_HBASE_TEMPLATE_SPEC =
"cm-hbase-template-spec.json";
private static final String AM_HDFS_V1_TEMPLATE_SPEC =
"am-hdfs-v1-template-spec.json";
private static final String AM_HDFS_V2_TEMPLATE_SPEC =
"am-hdfs-v2-template-spec.json";
private static final String AM_HDFS_MAPRED_TEMPLATE_SPEC =
"am-hdfs-mapred-template-spec.json";
private static final String AM_HDP_2_0_HDFS_YARN_TEMPLATE_SPEC =
"am-hdp-2-0-hdfs-yarn-template-spec.json";
private static final String AM_HDP_2_1_HDFS_YARN_TEMPLATE_SPEC =
"am-hdp-2-1-hdfs-yarn-template-spec.json";
private static final String AM_HDP_2_2_HDFS_YARN_TEMPLATE_SPEC =
"am-hdp-2-2-hdfs-yarn-template-spec.json";
private static final String AM_HDP_2_3_HDFS_YARN_TEMPLATE_SPEC =
"am-hdp-2-3-hdfs-yarn-template-spec.json";
private static final String AM_HDP_CUSTOMIZED_HDFS_YARN_TEMPLATE_SPEC =
"am-hdp-customized-hdfs-yarn-template-spec.json";
private static final String AM_HDP_V1_HBASE_TEMPLATE_SPEC =
"am-hdp-1-hbase-template-spec.json";
private static final String AM_HDP_2_0_HBASE_TEMPLATE_SPEC =
"am-hdp-2-0-hbase-template-spec.json";
private static final String AM_HDP_2_1_HBASE_TEMPLATE_SPEC =
"am-hdp-2-1-hbase-template-spec.json";
private static final String AM_HDP_2_2_HBASE_TEMPLATE_SPEC =
"am-hdp-2-2-hbase-template-spec.json";
private static final String AM_HDP_2_3_HBASE_TEMPLATE_SPEC =
"am-hdp-2-3-hbase-template-spec.json";
private static final String AM_HDP_CUSTOMIZED_HBASE_TEMPLATE_SPEC =
"am-hdp-customized-hbase-template-spec.json";
private static final String AM_HDFS_PURE_HBASE_TEMPLATE_SPEC =
"am-hdfs-pure-hbase-template-spec.json";
private static File locateSpecFile(String filename, String appManagerType) {
// try to locate file directly
File specFile = new File(filename);
if (specFile.exists()) {
return specFile;
}
// search ${serengeti.home.dir}/conf directory
String homeDir = System.getProperties().getProperty("serengeti.home.dir");
if (homeDir != null && !homeDir.trim().isEmpty()) {
StringBuilder builder = new StringBuilder();
builder.append(homeDir).append(File.separator).append("conf")
.append(File.separator).append(appManagerType).append(File.separator)
.append("spec-templates").append(File.separator).append(filename);
specFile = new File(builder.toString());
}
if (!specFile.exists()) {
logger.warn("template cluster file does not exist: " + specFile.getAbsolutePath());
// search in class paths
URL filePath = ConfigurationUtils.locate(filename);
if (filePath != null) {
specFile = ConfigurationUtils.fileFromURL(filePath);
}
}
if (!specFile.exists()) {
throw BddException.INTERNAL(null, "Can not find template cluster spec file " + filename);
}
return specFile;
}
/**
* Load and create cluster from spec file
*
* @return cluster spec
*/
public static ClusterCreate loadFromFile(File file)
throws FileNotFoundException {
Reader fileReader = null;
try {
fileReader = new FileReader(file);
Gson gson = new Gson();
return gson.fromJson(fileReader, ClusterCreate.class);
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
logger.error("Failed to release buffer: " + e.getMessage());
}
}
}
}
/**
* Create default cluster spec.
*
* @param type
* cluster type
* @return default cluster spec
* @throws FileNotFoundException
*/
public static ClusterCreate createDefaultSpec(ClusterType type,
String vendor, String distroVersion, String appManagerType) throws FileNotFoundException {
// loading from file each time is slow but fine
if (vendor.trim().equalsIgnoreCase(Constants.MAPR_VENDOR)) {
boolean isMapr3 = Version.compare(distroVersion, "4") < 0;
switch (type) {
case HDFS_MAPRED:
return loadFromFile(locateSpecFile(isMapr3 ? HDFS_MAPRED_MAPR_V3_TEMPLATE_SPEC : HDFS_MAPRED_MAPR_TEMPLATE_SPEC, appManagerType));
case HDFS_HBASE:
return loadFromFile(locateSpecFile(isMapr3 ? HDFS_HBASE_MAPR_V3_TEMPLATE_SPEC : HDFS_HBASE_MAPR_TEMPLATE_SPEC, appManagerType));
default:
throw BddException.INVALID_PARAMETER("cluster type", type);
}
} else if (vendor.trim().equalsIgnoreCase(Constants.GPHD_VENDOR)) {
switch (type) {
case HDFS:
return loadFromFile(locateSpecFile(HDFS_GPHD_TEMPLATE_SPEC, appManagerType));
case HDFS_MAPRED:
return loadFromFile(locateSpecFile(HDFS_MAPRED_GPHD_TEMPLATE_SPEC, appManagerType));
case HDFS_HBASE:
return loadFromFile(locateSpecFile(HDFS_HBASE_GPHD_TEMPLATE_SPEC, appManagerType));
default:
throw BddException.INVALID_PARAMETER("cluster type", type);
}
} else if (Constants.AMBARI_PLUGIN_TYPE.equals(appManagerType)
&& vendor.trim().equalsIgnoreCase(Constants.HDP_VENDOR)) {
MAPREDUCE_VERSION mr = getDefaultMapReduceVersion(vendor, distroVersion);
HDP_VERSION hdpVersion = getDefaultHdfsVersion(vendor, distroVersion);
if (type == null) {
if (mr == MAPREDUCE_VERSION.V1) {
return loadFromFile(locateSpecFile(AM_HDFS_MAPRED_TEMPLATE_SPEC, appManagerType));
} else {
if (hdpVersion == HDP_VERSION.V2_0) {
return loadFromFile(locateSpecFile(AM_HDP_2_0_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_1) {
return loadFromFile(locateSpecFile(AM_HDP_2_1_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_2) {
return loadFromFile(locateSpecFile(AM_HDP_2_2_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_3) {
return loadFromFile(locateSpecFile(AM_HDP_2_3_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
} else {
return loadFromFile(locateSpecFile(AM_HDP_CUSTOMIZED_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
}
}
}
switch (type) {
case HDFS:
if (hdpVersion == HDP_VERSION.V1) {
return loadFromFile(locateSpecFile(AM_HDFS_V1_TEMPLATE_SPEC, appManagerType));
} else {
return loadFromFile(locateSpecFile(AM_HDFS_V2_TEMPLATE_SPEC, appManagerType));
}
case HDFS_MAPRED:
if (mr == MAPREDUCE_VERSION.V1) {
return loadFromFile(locateSpecFile(AM_HDFS_MAPRED_TEMPLATE_SPEC, appManagerType));
} else {
if (hdpVersion == HDP_VERSION.V2_0) {
return loadFromFile(locateSpecFile(AM_HDP_2_0_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_1) {
return loadFromFile(locateSpecFile(AM_HDP_2_1_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_2) {
return loadFromFile(locateSpecFile(AM_HDP_2_2_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_3) {
return loadFromFile(locateSpecFile(AM_HDP_2_3_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
} else {
return loadFromFile(locateSpecFile(AM_HDP_CUSTOMIZED_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
}
}
case HDFS_HBASE:
if (Configuration.getBoolean(Constants.AMBARI_HBASE_DEPEND_ON_MAPREDUCE)) {
if (hdpVersion == HDP_VERSION.V1) {
return loadFromFile(locateSpecFile(AM_HDP_V1_HBASE_TEMPLATE_SPEC, appManagerType));
} else {
if (hdpVersion == HDP_VERSION.V2_0) {
return loadFromFile(locateSpecFile(AM_HDP_2_0_HBASE_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_1) {
return loadFromFile(locateSpecFile(AM_HDP_2_1_HBASE_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_2){
return loadFromFile(locateSpecFile(AM_HDP_2_2_HBASE_TEMPLATE_SPEC, appManagerType));
} else if (hdpVersion == HDP_VERSION.V2_3){
return loadFromFile(locateSpecFile(AM_HDP_2_3_HBASE_TEMPLATE_SPEC, appManagerType));
} else {
return loadFromFile(locateSpecFile(AM_HDP_CUSTOMIZED_HBASE_TEMPLATE_SPEC, appManagerType));
}
}
} else {
return loadFromFile(locateSpecFile(AM_HDFS_PURE_HBASE_TEMPLATE_SPEC, appManagerType));
}
default:
throw BddException.INVALID_PARAMETER("cluster type", type);
}
} else {
MAPREDUCE_VERSION mr =
getDefaultMapReduceVersion(vendor, distroVersion);
if (Constants.CLOUDERA_MANAGER_PLUGIN_TYPE.equals(appManagerType)) {
if (type.equals(ClusterType.HDFS_HBASE)) {
return loadFromFile(locateSpecFile(CM_HBASE_TEMPLATE_SPEC, appManagerType));
}
if (mr == MAPREDUCE_VERSION.V1) {
return loadFromFile(locateSpecFile(CM_HDFS_MAPRED_TEMPLATE_SPEC, appManagerType));
} else {
return loadFromFile(locateSpecFile(CM_HDFS_YARN_TEMPLATE_SPEC, appManagerType));
}
}
switch (type) {
case HDFS:
return loadFromFile(locateSpecFile(HDFS_TEMPLATE_SPEC, appManagerType));
case HDFS_MAPRED:
if (mr == MAPREDUCE_VERSION.V1) {
return loadFromFile(locateSpecFile(HDFS_MAPRED_TEMPLATE_SPEC, appManagerType));
} else {
return loadFromFile(locateSpecFile(HDFS_YARN_TEMPLATE_SPEC, appManagerType));
}
case HDFS_HBASE:
return loadFromFile(locateSpecFile(HDFS_HBASE_TEMPLATE_SPEC, appManagerType));
default:
return loadFromFile(locateSpecFile(vendor.toLowerCase() + DEFAULT_TEMPLATE_SPEC_SUFFIX, appManagerType));
}
}
}
private static MAPREDUCE_VERSION getDefaultMapReduceVersion(String vendor,
String distroVersion) {
if (vendor.trim().equalsIgnoreCase(Constants.DEFAULT_VENDOR)) {
return MAPREDUCE_VERSION.V2;
}
if (vendor.trim().equalsIgnoreCase(Constants.APACHE_VENDOR)) {
return MAPREDUCE_VERSION.V1;
}
if (vendor.trim().equalsIgnoreCase(Constants.BIGTOP_VENDOR)) {
return MAPREDUCE_VERSION.V2;
}
if (vendor.trim().equalsIgnoreCase(Constants.CDH_VENDOR)) {
if (distroVersion.startsWith("5")) {
return MAPREDUCE_VERSION.V2;
} else {
return MAPREDUCE_VERSION.V1;
}
}
if (vendor.trim().equalsIgnoreCase(Constants.HDP_VENDOR)) {
if (distroVersion.startsWith("2")) {
return MAPREDUCE_VERSION.V2;
} else {
return MAPREDUCE_VERSION.V1;
}
}
if (vendor.trim().equalsIgnoreCase(Constants.INTEL_VENDOR)) {
if (distroVersion.startsWith("3")) {
return MAPREDUCE_VERSION.V2;
} else {
return MAPREDUCE_VERSION.V1;
}
}
if (vendor.trim().equalsIgnoreCase(Constants.PHD_VENDOR)) {
return MAPREDUCE_VERSION.V2;
}
if (vendor.trim().equalsIgnoreCase(Constants.MAPR_VENDOR)) {
return MAPREDUCE_VERSION.V1;
}
if (vendor.trim().equalsIgnoreCase(Constants.GPHD_VENDOR)) {
return MAPREDUCE_VERSION.V1;
}
logger.error("Unknown distro vendor, return default mapreduce version 2");
return MAPREDUCE_VERSION.V2;
}
private static HDP_VERSION getDefaultHdfsVersion(String vendor,
String distroVersion) {
if (vendor.trim().equalsIgnoreCase(Constants.HDP_VENDOR)) {
if (Version.compare(distroVersion, "1.0") >= 0 && Version.compare(distroVersion, "2.0") < 0) {
return HDP_VERSION.V1;
} else if (Version.compare(distroVersion, "2.0") >= 0 && Version.compare(distroVersion, "2.1") < 0) {
return HDP_VERSION.V2_0;
} else if (Version.compare(distroVersion, "2.1") >= 0 && Version.compare(distroVersion, "2.2") < 0) {
return HDP_VERSION.V2_1;
} else if (Version.compare(distroVersion, "2.2") >= 0 && Version.compare(distroVersion, "2.3") < 0) {
return HDP_VERSION.V2_2;
} else if (Version.compare(distroVersion, "2.3") >= 0 && Version.compare(distroVersion, "2.4") < 0) {
return HDP_VERSION.V2_3;
} else {
return HDP_VERSION.UNKNOWN;
}
}
logger.error("Unknown distro HDP version");
return HDP_VERSION.UNKNOWN;
}
/**
* There are two approach to create a cluster: 1) specify a cluster type and
* optionally overwriting the parameters 2) specify a customized spec with
* cluster type not specified
*
* @param spec
* spec with customized field
* @return customized cluster spec
* @throws FileNotFoundException
*/
public static ClusterCreate getCustomizedSpec(ClusterCreate spec, String appManagerType)
throws FileNotFoundException {
if (!ArrayUtils.isEmpty(spec.getNodeGroups())) {
spec.setSpecFile(true);
}
if (spec.isSpecFile()) {
return spec;
}
ClusterCreate newSpec =
createDefaultSpec(spec.getType(), spec.getDistroVendor(), spec.getDistroVersion(), appManagerType);
// --name
if (spec.getName() != null) {
newSpec.setName(spec.getName());
}
//--password
newSpec.setPassword(spec.getPassword());
// --appManager
if(!CommonUtil.isBlank(spec.getAppManager())) {
newSpec.setAppManager(spec.getAppManager());
}
// --locaRepoURL
if(!CommonUtil.isBlank(spec.getLocalRepoURL())) {
newSpec.setLocalRepoURL(spec.getLocalRepoURL());
}
// --distro
if (spec.getDistro() != null) {
newSpec.setDistro(spec.getDistro());
}
//vendor
if (spec.getDistroVendor() != null) {
newSpec.setDistroVendor(spec.getDistroVendor());
}
//version
if (spec.getDistroVersion() != null) {
newSpec.setDistroVersion(spec.getDistroVersion());
}
// template name
if (spec.getTemplateName() != null) {
newSpec.setTemplateName(spec.getTemplateName());
}
// --dsNames
if (spec.getDsNames() != null) {
newSpec.setDsNames(spec.getDsNames());
}
// --rpNames
if (spec.getRpNames() != null) {
newSpec.setRpNames(spec.getRpNames());
}
// --networkConfig
if (spec.getNetworkConfig() != null) {
newSpec.setNetworkConfig(spec.getNetworkConfig());
}
// --topology
if (spec.getTopologyPolicy() != null) {
newSpec.setTopologyPolicy(spec.getTopologyPolicy());
}
if(MapUtils.isNotEmpty(spec.getInfrastructure_config())) {
newSpec.setInfrastructure_config(spec.getInfrastructure_config());
}
return newSpec;
}
}