/* * 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. */ public void cpus(double cpu) { this.cpu = cpu; } /** * @return CPU count limit. */ public double cpusPerNode() { return cpuPerNode; } /** * Sets CPU 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(); props.load(new FileInputStream(cfg)); } 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"); } }