| /* |
| * 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.ignite.mesos; |
| |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.net.Inet4Address; |
| import java.net.InetAddress; |
| import java.net.NetworkInterface; |
| import java.net.SocketException; |
| import java.util.Enumeration; |
| import java.util.Properties; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import java.util.regex.Pattern; |
| import java.util.regex.PatternSyntaxException; |
| |
| /** |
| * The class defines cluster configuration. This configuration created from properties file |
| * that passed on startup or environment variables. |
| * <p> |
| * If Mesos cluster working in Intranet or behind NAT then an access to local resources can be set |
| * by {@link #ignitePackagePath()} or {@link #ignitePackageUrl()} which should be available from nodes. |
| */ |
| public class ClusterProperties { |
| /** */ |
| private static final Logger log = Logger.getLogger(ClusterProperties.class.getSimpleName()); |
| |
| /** Unlimited. */ |
| public static final double UNLIMITED = Double.MAX_VALUE; |
| |
| /** */ |
| public static final String MESOS_MASTER_URL = "MESOS_MASTER_URL"; |
| |
| /** */ |
| public static final String DEFAULT_MESOS_MASTER_URL = "zk://localhost:2181/mesos"; |
| |
| /** Mesos master url. */ |
| private String mesosUrl = DEFAULT_MESOS_MASTER_URL; |
| |
| /** */ |
| public static final String IGNITE_JVM_OPTS = "IGNITE_JVM_OPTS"; |
| |
| /** JVM options. */ |
| private String jvmOpts = ""; |
| |
| /** */ |
| public static final String IGNITE_CLUSTER_NAME = "IGNITE_CLUSTER_NAME"; |
| |
| /** */ |
| public static final String DEFAULT_CLUSTER_NAME = "ignite-cluster"; |
| |
| /** Mesos master url. */ |
| private String clusterName = DEFAULT_CLUSTER_NAME; |
| |
| /** */ |
| public static final String IGNITE_HTTP_SERVER_HOST = "IGNITE_HTTP_SERVER_HOST"; |
| |
| /** Http server host. */ |
| private String httpSrvHost = null; |
| |
| /** */ |
| public static final String IGNITE_HTTP_SERVER_PORT = "IGNITE_HTTP_SERVER_PORT"; |
| |
| /** */ |
| public static final String DEFAULT_HTTP_SERVER_PORT = "48610"; |
| |
| /** Http server host. */ |
| private int httpSrvPort = Integer.valueOf(DEFAULT_HTTP_SERVER_PORT); |
| |
| /** */ |
| public static final String IGNITE_TOTAL_CPU = "IGNITE_TOTAL_CPU"; |
| |
| /** CPU limit. */ |
| private double cpu = UNLIMITED; |
| |
| /** */ |
| public static final String IGNITE_RUN_CPU_PER_NODE = "IGNITE_RUN_CPU_PER_NODE"; |
| |
| /** CPU limit. */ |
| private double cpuPerNode = UNLIMITED; |
| |
| /** */ |
| public static final String IGNITE_TOTAL_MEMORY = "IGNITE_TOTAL_MEMORY"; |
| |
| /** Memory limit. */ |
| private double mem = UNLIMITED; |
| |
| /** */ |
| public static final String IGNITE_MEMORY_PER_NODE = "IGNITE_MEMORY_PER_NODE"; |
| |
| /** Memory limit. */ |
| private double memPerNode = UNLIMITED; |
| |
| /** */ |
| public static final String IGNITE_TOTAL_DISK_SPACE = "IGNITE_TOTAL_DISK_SPACE"; |
| |
| /** Disk space limit. */ |
| private double disk = UNLIMITED; |
| |
| /** */ |
| public static final String IGNITE_DISK_SPACE_PER_NODE = "IGNITE_DISK_SPACE_PER_NODE"; |
| |
| /** Disk space limit. */ |
| private double diskPerNode = UNLIMITED; |
| |
| /** */ |
| public static final String IGNITE_NODE_COUNT = "IGNITE_NODE_COUNT"; |
| |
| /** Node count limit. */ |
| private double nodeCnt = UNLIMITED; |
| |
| /** */ |
| public static final String IGNITE_MIN_CPU_PER_NODE = "IGNITE_MIN_CPU_PER_NODE"; |
| |
| /** */ |
| public static final double DEFAULT_RESOURCE_MIN_CPU = 1; |
| |
| /** Min memory per node. */ |
| private double minCpu = DEFAULT_RESOURCE_MIN_CPU; |
| |
| /** */ |
| public static final String IGNITE_MIN_MEMORY_PER_NODE = "IGNITE_MIN_MEMORY_PER_NODE"; |
| |
| /** */ |
| public static final double DEFAULT_RESOURCE_MIN_MEM = 256; |
| |
| /** Min memory per node. */ |
| private double minMemory = DEFAULT_RESOURCE_MIN_MEM; |
| |
| /** */ |
| public static final String IGNITE_VERSION = "IGNITE_VERSION"; |
| |
| /** */ |
| public static final String DEFAULT_IGNITE_VERSION = "latest"; |
| |
| /** Ignite version. */ |
| private String igniteVer = DEFAULT_IGNITE_VERSION; |
| |
| /** */ |
| public static final String IGNITE_PACKAGE_URL = "IGNITE_PACKAGE_URL"; |
| |
| /** Ignite package url. */ |
| private String ignitePkgUrl; |
| |
| /** */ |
| public static final String IGNITE_PACKAGE_PATH = "IGNITE_PACKAGE_PATH"; |
| |
| /** Ignite package path. */ |
| private String ignitePkgPath; |
| |
| /** */ |
| public static final String IGNITE_WORK_DIR = "IGNITE_WORK_DIR"; |
| |
| /** */ |
| public static final String DEFAULT_IGNITE_WORK_DIR = "ignite-releases/"; |
| |
| /** Ignite version. */ |
| private String igniteWorkDir = DEFAULT_IGNITE_WORK_DIR; |
| |
| /** */ |
| public static final String IGNITE_USERS_LIBS = "IGNITE_USERS_LIBS"; |
| |
| /** Path to users libs. */ |
| private String userLibs = null; |
| |
| /** */ |
| public static final String IGNITE_USERS_LIBS_URL = "IGNITE_USERS_LIBS_URL"; |
| |
| /** URL to users libs. */ |
| private String userLibsUrl = null; |
| |
| /** */ |
| public static final String LICENCE_URL = "LICENCE_URL"; |
| |
| /** Licence url. */ |
| private String licenceUrl = null; |
| |
| /** */ |
| public static final String IGNITE_CONFIG_XML = "IGNITE_XML_CONFIG"; |
| |
| /** Ignite config. */ |
| private String igniteCfg = null; |
| |
| /** */ |
| public static final String IGNITE_CONFIG_XML_URL = "IGNITE_CONFIG_XML_URL"; |
| |
| /** */ |
| public static final String IGNITE_HTTP_SERVER_IDLE_TIMEOUT = "IGNITE_HTTP_SERVER_IDLE_TIMEOUT"; |
| |
| /** */ |
| public static final long IGNITE_HTTP_SERVER_IDLE_TIMEOUT_DEFAULT = 30000L; |
| |
| /** Jetty idle timeout. */ |
| private long idleTimeout = IGNITE_HTTP_SERVER_IDLE_TIMEOUT_DEFAULT; |
| |
| /** Url to ignite config. */ |
| private String igniteCfgUrl = null; |
| |
| /** */ |
| public static final String IGNITE_HOSTNAME_CONSTRAINT = "IGNITE_HOSTNAME_CONSTRAINT"; |
| |
| /** Url to ignite config. */ |
| private Pattern hostnameConstraint = null; |
| |
| /** */ |
| public ClusterProperties() { |
| // No-op. |
| } |
| |
| /** |
| * @return Cluster name. |
| */ |
| public String clusterName() { |
| return clusterName; |
| } |
| |
| /** |
| * @return CPU count limit. |
| */ |
| public double cpus() { |
| return cpu; |
| } |
| |
| /** |
| * Sets CPU count limit. |
| * |
| * @param cpu CPU count limit. |
| */ |
| public void cpus(double cpu) { |
| this.cpu = cpu; |
| } |
| |
| /** |
| * @return CPU count limit. |
| */ |
| public double cpusPerNode() { |
| return cpuPerNode; |
| } |
| |
| /** |
| * Sets CPU count limit. |
| * |
| * @param cpu CPU per node count limit. |
| */ |
| public void cpusPerNode(double cpu) { |
| this.cpuPerNode = cpu; |
| } |
| |
| /** |
| * @return mem limit. |
| */ |
| public double memory() { |
| return mem; |
| } |
| |
| /** |
| * Sets mem limit. |
| * |
| * @param mem Memory. |
| */ |
| public void memory(double mem) { |
| this.mem = mem; |
| } |
| |
| /** |
| * @return mem limit. |
| */ |
| public double memoryPerNode() { |
| return memPerNode; |
| } |
| |
| /** |
| * Sets mem limit. |
| * |
| * @param mem Memory. |
| */ |
| public void memoryPerNode(double mem) { |
| this.memPerNode = mem; |
| } |
| |
| /** |
| * @return JVM opts for ignite. |
| */ |
| public String jmvOpts() { |
| return this.jvmOpts; |
| } |
| |
| /** |
| * @return disk limit. |
| */ |
| public double disk() { |
| return disk; |
| } |
| |
| /** |
| * @return disk limit per node. |
| */ |
| public double diskPerNode() { |
| return diskPerNode; |
| } |
| |
| /** |
| * @return instance count limit. |
| */ |
| public double instances() { |
| return nodeCnt; |
| } |
| |
| /** |
| * @return min memory per node. |
| */ |
| public double minMemoryPerNode() { |
| return minMemory; |
| } |
| |
| /** |
| * Sets min memory. |
| * |
| * @param minMemory Min memory. |
| */ |
| public void minMemoryPerNode(double minMemory) { |
| this.minMemory = minMemory; |
| } |
| |
| /** |
| * Sets hostname constraint. |
| * |
| * @param ptrn Hostname pattern. |
| */ |
| public void hostnameConstraint(Pattern ptrn) { |
| this.hostnameConstraint = ptrn; |
| } |
| |
| /** |
| * @return min cpu count per node. |
| */ |
| public double minCpuPerNode() { |
| return minCpu; |
| } |
| |
| /** |
| * Sets min cpu count per node. |
| * |
| * @param minCpu min cpu count per node. |
| */ |
| public void minCpuPerNode(double minCpu) { |
| this.minCpu = minCpu; |
| } |
| |
| /** |
| * @return Ignite version. |
| */ |
| public String igniteVer() { |
| return igniteVer; |
| } |
| |
| /** |
| * @return Working directory. |
| */ |
| public String igniteWorkDir() { |
| return igniteWorkDir; |
| } |
| |
| /** |
| * @return User's libs. |
| */ |
| public String userLibs() { |
| return userLibs; |
| } |
| |
| /** |
| * @return Ignite configuration. |
| */ |
| public String igniteCfg() { |
| return igniteCfg; |
| } |
| |
| /** |
| * @return Master url. |
| */ |
| public String masterUrl() { |
| return mesosUrl; |
| } |
| |
| /** |
| * @return Http server host. |
| */ |
| public String httpServerHost() { |
| return httpSrvHost; |
| } |
| |
| /** |
| * @return Http server port. |
| */ |
| public int httpServerPort() { |
| return httpSrvPort; |
| } |
| |
| /** |
| * Sets the maximum Idle time for a http connection, which will be used for |
| * jetty server. The server provides resources for ignite mesos framework such as |
| * ignite archive, user's libs, configurations and etc. |
| * |
| * @return Http server idle timeout. |
| */ |
| public long idleTimeout() { |
| return idleTimeout; |
| } |
| |
| /** |
| * URL to ignite package. The URL should to point at valid apache ignite archive. |
| * This property can be useful if using own apache ignite build. |
| * |
| * @return Url to ignite package. |
| */ |
| public String ignitePackageUrl() { |
| return ignitePkgUrl; |
| } |
| |
| /** |
| * Path on local file system to ignite archive. That can be useful when |
| * Mesos working in Intranet or behind NAT. |
| * |
| * @return Path on local host to ignite package. |
| */ |
| public String ignitePackagePath() { |
| return ignitePkgPath; |
| } |
| |
| /** |
| * @return Url to ignite configuration. |
| */ |
| public String igniteConfigUrl() { |
| return igniteCfgUrl; |
| } |
| |
| /** |
| * @return Url to users libs configuration. |
| */ |
| public String usersLibsUrl() { |
| return userLibsUrl; |
| } |
| |
| /** |
| * @return Url to licence. |
| */ |
| public String licenceUrl() { |
| return licenceUrl; |
| } |
| |
| /** |
| * @return Host name constraint. |
| */ |
| public Pattern hostnameConstraint() { |
| return hostnameConstraint; |
| } |
| |
| /** |
| * @param cfg path to config file. |
| * @return Cluster configuration. |
| */ |
| public static ClusterProperties from(String cfg) { |
| try { |
| Properties props = null; |
| |
| if (cfg != null) { |
| props = new Properties(); |
| |
| try (FileInputStream in = new FileInputStream(cfg)) { |
| props.load(in); |
| } |
| } |
| |
| ClusterProperties prop = new ClusterProperties(); |
| |
| prop.mesosUrl = getStringProperty(MESOS_MASTER_URL, props, DEFAULT_MESOS_MASTER_URL); |
| |
| prop.httpSrvHost = getStringProperty(IGNITE_HTTP_SERVER_HOST, props, getNonLoopbackAddress()); |
| |
| String port = System.getProperty("PORT0"); |
| |
| if (port != null && !port.isEmpty()) |
| prop.httpSrvPort = Integer.valueOf(port); |
| else |
| prop.httpSrvPort = Integer.valueOf(getStringProperty(IGNITE_HTTP_SERVER_PORT, props, |
| DEFAULT_HTTP_SERVER_PORT)); |
| |
| prop.clusterName = getStringProperty(IGNITE_CLUSTER_NAME, props, DEFAULT_CLUSTER_NAME); |
| |
| prop.userLibsUrl = getStringProperty(IGNITE_USERS_LIBS_URL, props, null); |
| prop.ignitePkgUrl = getStringProperty(IGNITE_PACKAGE_URL, props, null); |
| prop.ignitePkgPath = getStringProperty(IGNITE_PACKAGE_PATH, props, null); |
| prop.licenceUrl = getStringProperty(LICENCE_URL, props, null); |
| prop.igniteCfgUrl = getStringProperty(IGNITE_CONFIG_XML_URL, props, null); |
| |
| prop.cpu = getDoubleProperty(IGNITE_TOTAL_CPU, props, UNLIMITED); |
| prop.cpuPerNode = getDoubleProperty(IGNITE_RUN_CPU_PER_NODE, props, UNLIMITED); |
| prop.mem = getDoubleProperty(IGNITE_TOTAL_MEMORY, props, UNLIMITED); |
| prop.memPerNode = getDoubleProperty(IGNITE_MEMORY_PER_NODE, props, UNLIMITED); |
| prop.disk = getDoubleProperty(IGNITE_TOTAL_DISK_SPACE, props, UNLIMITED); |
| prop.diskPerNode = getDoubleProperty(IGNITE_DISK_SPACE_PER_NODE, props, 1024.0); |
| prop.nodeCnt = getDoubleProperty(IGNITE_NODE_COUNT, props, UNLIMITED); |
| prop.minCpu = getDoubleProperty(IGNITE_MIN_CPU_PER_NODE, props, DEFAULT_RESOURCE_MIN_CPU); |
| prop.minMemory = getDoubleProperty(IGNITE_MIN_MEMORY_PER_NODE, props, DEFAULT_RESOURCE_MIN_MEM); |
| |
| prop.jvmOpts = getStringProperty(IGNITE_JVM_OPTS, props, ""); |
| |
| prop.igniteVer = getStringProperty(IGNITE_VERSION, props, DEFAULT_IGNITE_VERSION); |
| prop.igniteWorkDir = getStringProperty(IGNITE_WORK_DIR, props, DEFAULT_IGNITE_WORK_DIR); |
| prop.igniteCfg = getStringProperty(IGNITE_CONFIG_XML, props, null); |
| prop.userLibs = getStringProperty(IGNITE_USERS_LIBS, props, null); |
| |
| String ptrn = getStringProperty(IGNITE_HOSTNAME_CONSTRAINT, props, null); |
| |
| prop.idleTimeout = getLongProperty(IGNITE_HTTP_SERVER_IDLE_TIMEOUT, props, IGNITE_HTTP_SERVER_IDLE_TIMEOUT_DEFAULT); |
| |
| if (ptrn != null) { |
| try { |
| prop.hostnameConstraint = Pattern.compile(ptrn); |
| } |
| catch (PatternSyntaxException e) { |
| log.log(Level.WARNING, "IGNITE_HOSTNAME_CONSTRAINT has invalid pattern. It will be ignore.", e); |
| } |
| } |
| |
| return prop; |
| } |
| catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| /** |
| * @param name Property name. |
| * @param fileProps Property file. |
| * @return Property value. |
| */ |
| private static double getDoubleProperty(String name, Properties fileProps, Double dfltVal) { |
| if (fileProps != null && fileProps.containsKey(name)) |
| return Double.valueOf(fileProps.getProperty(name)); |
| |
| String prop = System.getProperty(name); |
| |
| if (prop == null) |
| prop = System.getenv(name); |
| |
| return prop == null ? dfltVal : Double.valueOf(prop); |
| } |
| |
| /** |
| * @param name Property name. |
| * @param fileProps Property file. |
| * @return Property value. |
| */ |
| private static long getLongProperty(String name, Properties fileProps, Long dfltVal) { |
| if (fileProps != null && fileProps.containsKey(name)) |
| return Long.valueOf(fileProps.getProperty(name)); |
| |
| String prop = System.getProperty(name); |
| |
| if (prop == null) |
| prop = System.getenv(name); |
| |
| return prop == null ? dfltVal : Long.valueOf(prop); |
| } |
| |
| /** |
| * @param name Property name. |
| * @param fileProps Property file. |
| * @return Property value. |
| */ |
| private static String getStringProperty(String name, Properties fileProps, String dfltVal) { |
| if (fileProps != null && fileProps.containsKey(name)) |
| return fileProps.getProperty(name); |
| |
| String prop = System.getProperty(name); |
| |
| if (prop == null) |
| prop = System.getenv(name); |
| |
| return prop == null ? dfltVal : prop; |
| } |
| |
| /** |
| * Finds a local, non-loopback, IPv4 address |
| * |
| * @return The first non-loopback IPv4 address found, or <code>null</code> if no such addresses found |
| * @throws java.net.SocketException If there was a problem querying the network interfaces |
| */ |
| public static String getNonLoopbackAddress() throws SocketException { |
| Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); |
| |
| while (ifaces.hasMoreElements()) { |
| NetworkInterface iface = ifaces.nextElement(); |
| |
| Enumeration<InetAddress> addrs = iface.getInetAddresses(); |
| |
| while (addrs.hasMoreElements()) { |
| InetAddress addr = addrs.nextElement(); |
| |
| if (addr instanceof Inet4Address && !addr.isLoopbackAddress()) |
| return addr.getHostAddress(); |
| } |
| } |
| |
| throw new RuntimeException("Failed. Could not find non-loopback address"); |
| } |
| } |