otto(o...@apache.org) syncing feature/METRON-1136-extensions-parsers with master
Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/43646650 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/43646650 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/43646650 Branch: refs/heads/feature/METRON-1136-extensions-parsers Commit: 4364665002756c1193cf834f3a2f53d774122760 Parents: ffcb91e Author: ottofowler <> Authored: Wed Aug 30 11:07:03 2017 -0400 Committer: otto <o...@apache.org> Committed: Wed Aug 30 11:07:03 2017 -0400 ---------------------------------------------------------------------- .gitignore | 2 +- metron-analytics/metron-maas-common/pom.xml | 11 + .../metron/maas/functions/MaaSFunctions.java | 324 +++++++++++++++++++ metron-analytics/metron-maas-service/README.md | 21 +- metron-analytics/metron-maas-service/pom.xml | 11 - .../metron/maas/functions/MaaSFunctions.java | 324 ------------------- .../org/apache/metron/maas/service/Client.java | 15 + .../apache/metron/maas/service/Constants.java | 5 +- .../metron/maas/service/runner/Runner.java | 9 +- .../metron/maas/submit/ModelSubmission.java | 5 + .../METRON/CURRENT/role_command_order.json | 2 + .../configuration/metron-indexing-env.xml | 2 +- .../configuration/metron-profiler-env.xml | 155 +++++++++ .../common-services/METRON/CURRENT/metainfo.xml | 43 +++ .../package/scripts/params/params_linux.py | 25 ++ .../package/scripts/params/status_params.py | 11 + .../package/scripts/profiler_commands.py | 194 +++++++++++ .../CURRENT/package/scripts/profiler_master.py | 94 ++++++ .../package/templates/profiler.properties.j2 | 47 +++ .../METRON/CURRENT/service_advisor.py | 5 + .../METRON/CURRENT/themes/metron_theme.json | 198 +++++++++++- .../roles/ambari_config/vars/single_node_vm.yml | 7 +- .../roles/ambari_config/vars/small_cluster.yml | 5 +- metron-interface/metron-alerts/README.md | 22 +- .../metron-alerts/alerts-server-e2e.js | 31 +- .../e2e/alerts-list/alerts-list.e2e-spec.ts | 17 +- .../configure-table/configure-table.e2e-spec.ts | 15 +- .../save-search/save-search.e2e-spec.ts | 11 + .../metron-alerts/e2e/login/login.e2e-spec.ts | 44 +++ .../metron-alerts/e2e/login/login.po.ts | 65 ++++ .../metron-alerts/e2e/utils/e2e_util.ts | 30 ++ .../metron-alerts/protractor.conf.js | 13 +- metron-interface/metron-alerts/proxy.conf.json | 4 +- .../metron-alerts/scripts/alerts-server.js | 12 +- .../scripts/start-server-for-e2e.sh | 3 +- .../metron-alerts/src/_variables.scss | 3 + .../alert-details/alert-details.component.html | 4 +- .../alert-details/alert-details.component.ts | 44 ++- .../alert-details/alerts-details.routing.ts | 2 +- .../alerts-list/alerts-list.component.html | 6 +- .../alerts/alerts-list/alerts-list.component.ts | 32 +- .../alerts/alerts-list/alerts-list.module.ts | 2 +- .../src/app/alerts/alerts-list/query-builder.ts | 18 +- .../metron-alerts/src/app/app-routing.module.ts | 12 +- .../metron-alerts/src/app/app.component.html | 5 +- .../metron-alerts/src/app/app.component.scss | 12 + .../metron-alerts/src/app/app.component.ts | 8 + .../metron-alerts/src/app/app.module.ts | 14 +- .../src/app/login/login.component.html | 28 ++ .../src/app/login/login.component.scss | 55 ++++ .../src/app/login/login.component.spec.ts | 65 ++++ .../src/app/login/login.component.ts | 43 +++ .../metron-alerts/src/app/login/login.module.ts | 28 ++ .../src/app/login/login.routing.ts | 25 ++ .../metron-alerts/src/app/model/alert-source.ts | 52 +++ .../metron-alerts/src/app/model/alert.ts | 45 +-- .../src/app/model/search-request.ts | 12 +- .../metron-alerts/src/app/model/sort-field.ts | 21 ++ .../src/app/service/alert.service.ts | 13 +- .../src/app/service/authentication.service.ts | 91 ++++++ .../src/app/service/data-source.ts | 5 +- .../service/elasticsearch-localstorage-impl.ts | 11 +- .../src/app/service/rest-api-impl.ts | 46 +++ .../metron-alerts/src/app/shared/auth-guard.ts | 50 +++ .../metron-alerts/src/app/shared/login-guard.ts | 40 +++ .../src/app/utils/elasticsearch-utils.ts | 2 +- .../metron-alerts/src/app/utils/httpUtil.ts | 6 +- .../src/environments/environment.prod.ts | 3 +- .../transformation/StellarTransformation.java | 11 + .../StellarTransformationTest.java | 47 +++ metron-platform/metron-parsers/README.md | 43 +++ 71 files changed, 2177 insertions(+), 509 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index 2d048d7..bcb3642 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,5 @@ tmp/** tmp/**/* temp/** temp/**/* - +metron-interface/metron-alerts/node/ repodata/ http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-common/pom.xml ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-common/pom.xml b/metron-analytics/metron-maas-common/pom.xml index 13fb7b9..6921e51 100644 --- a/metron-analytics/metron-maas-common/pom.xml +++ b/metron-analytics/metron-maas-common/pom.xml @@ -34,6 +34,17 @@ </properties> <dependencies> <dependency> + <groupId>org.apache.metron</groupId> + <artifactId>stellar-common</artifactId> + <version>${project.parent.version}</version> + <exclusions> + <exclusion> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-auth</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.2</version> http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-common/src/main/java/org/apache/metron/maas/functions/MaaSFunctions.java ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-common/src/main/java/org/apache/metron/maas/functions/MaaSFunctions.java b/metron-analytics/metron-maas-common/src/main/java/org/apache/metron/maas/functions/MaaSFunctions.java new file mode 100644 index 0000000..eacb64d --- /dev/null +++ b/metron-analytics/metron-maas-common/src/main/java/org/apache/metron/maas/functions/MaaSFunctions.java @@ -0,0 +1,324 @@ +/** + * 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.metron.maas.functions; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.lang.invoke.MethodHandles; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import org.apache.curator.framework.CuratorFramework; +import org.apache.metron.maas.config.Endpoint; +import org.apache.metron.maas.config.MaaSConfig; +import org.apache.metron.maas.config.ModelEndpoint; +import org.apache.metron.maas.discovery.ServiceDiscoverer; +import org.apache.metron.maas.util.ConfigUtil; +import org.apache.metron.maas.util.RESTUtil; +import org.apache.metron.stellar.common.utils.JSONUtils; +import org.apache.metron.stellar.dsl.Context; +import org.apache.metron.stellar.dsl.ParseException; +import org.apache.metron.stellar.dsl.Stellar; +import org.apache.metron.stellar.dsl.StellarFunction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MaaSFunctions { + protected static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private static class ModelCacheKey { + String name; + String version; + String method; + Map<String, String> args; + public ModelCacheKey(String name, String version, String method, Map<String, String> args) { + this.name = name; + this.version = version; + this.method = method; + this.args = args; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ModelCacheKey that = (ModelCacheKey) o; + + if (name != null ? !name.equals(that.name) : that.name != null) return false; + if (version != null ? !version.equals(that.version) : that.version != null) return false; + if (method != null ? !method.equals(that.method) : that.method != null) return false; + return args != null ? args.equals(that.args) : that.args == null; + + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (version != null ? version.hashCode() : 0); + result = 31 * result + (method != null ? method.hashCode() : 0); + result = 31 * result + (args != null ? args.hashCode() : 0); + return result; + } + } + + @Stellar(name="MODEL_APPLY" + , namespace="MAAS" + , description = "Returns the output of a model deployed via Model as a Service. NOTE: Results are cached locally for 10 minutes." + , params = { "endpoint - A map containing the name, version, and url for the REST endpoint" + , "function - The optional endpoint path; default is 'apply'" + , "model_args - A Dictionary of arguments for the model (these become request params)" + } + , returns = "The output of the model deployed as a REST endpoint in Map form. Assumes REST endpoint returns a JSON Map." + ) + public static class ModelApply implements StellarFunction { + private boolean isInitialized = false; + private ServiceDiscoverer discoverer; + private Cache<ModelCacheKey, Map<String, Object> > resultCache; + public ModelApply() { + resultCache = CacheBuilder.newBuilder() + .concurrencyLevel(4) + .weakKeys() + .maximumSize(100000) + .expireAfterWrite(10, TimeUnit.MINUTES) + .build(); + } + + @Override + public Object apply(List<Object> args, Context context) throws ParseException { + if(args.size() < 2) { + throw new ParseException("Unable to execute model_apply. " + + "Expected arguments: endpoint_map:map, " + + " [endpoint method:string], model_args:map" + ); + } + if(!isInitialized) { + return null; + } + int i = 0; + if(args.size() == 0) { + return null; + } + Object endpointObj = args.get(i++); + Map endpoint = null; + String modelName; + String modelVersion; + String modelUrl; + if(endpointObj instanceof Map) { + endpoint = (Map)endpointObj; + modelName = endpoint.get("name") + ""; + modelVersion = endpoint.get("version") + ""; + modelUrl = endpoint.get("url") + ""; + } + else { + return null; + } + String modelFunction = "apply"; + Map<String, String> modelArgs = new HashMap<>(); + if(args.get(i) instanceof String) { + String func = (String)args.get(i); + if(endpoint.containsKey("endpoint:" + func)) { + modelFunction = "" + endpoint.get("endpoint:" + func); + } + else { + modelFunction = func; + } + i++; + } + + if(args.get(i) instanceof Map) { + if(endpoint.containsKey("endpoint:apply")) { + modelFunction = "" + endpoint.get("endpoint:apply"); + } + modelArgs = (Map)args.get(i); + } + if( modelName == null + || modelVersion == null + || modelFunction == null + ) { + return null; + } + ModelCacheKey cacheKey = new ModelCacheKey(modelName, modelVersion, modelFunction, modelArgs); + Map<String, Object> ret = resultCache.getIfPresent(cacheKey); + if(ret != null) { + return ret; + } + else { + String url = modelUrl; + if (url.endsWith("/")) { + url = url.substring(0, url.length() - 1); + } + if (modelFunction.startsWith("/")) { + modelFunction = modelFunction.substring(1); + } + try { + URL u = new URL(url + "/" + modelFunction); + + String results = RESTUtil.INSTANCE.getRESTJSONResults(u, modelArgs); + ret = JSONUtils.INSTANCE.load(results, new TypeReference<Map<String, Object>>() { + }); + resultCache.put(cacheKey, ret); + return ret; + } catch (Exception e) { + LOG.error(e.getMessage(), e); + if (discoverer != null) { + try { + URL u = new URL(modelUrl); + discoverer.blacklist(u); + } catch (MalformedURLException e1) { + } + } + } + } + return null; + } + + @Override + public synchronized void initialize(Context context) { + + try { + Optional<ServiceDiscoverer> discovererOpt = (Optional) (context.getCapability(Context.Capabilities.SERVICE_DISCOVERER)); + if (discovererOpt.isPresent()) { + discoverer = discovererOpt.get(); + } + else { + Optional<Object> clientOptional = context.getCapability(Context.Capabilities.ZOOKEEPER_CLIENT); + CuratorFramework client = null; + if (clientOptional.isPresent() && clientOptional.get() instanceof CuratorFramework) { + client = (CuratorFramework) clientOptional.get(); + } else { + throw new IllegalStateException("Unable to initialize function: Cannot find zookeeper client."); + } + discoverer = createDiscoverer(client); + } + } + catch(Exception ex) { + LOG.error(ex.getMessage(), ex); + } + finally { + //We always want to set initialize to true because we don't want to keep trying to initialize over and over + isInitialized = true; + } + } + + @Override + public boolean isInitialized() { + return isInitialized; + } + } + + private static ServiceDiscoverer createDiscoverer(CuratorFramework client) throws Exception { + MaaSConfig config = ConfigUtil.INSTANCE.read(client, "/metron/maas/config", new MaaSConfig(), MaaSConfig.class); + ServiceDiscoverer discoverer = new ServiceDiscoverer(client, config.getServiceRoot()); + discoverer.start(); + return discoverer; + } + + @Stellar(name="GET_ENDPOINT" + , namespace="MAAS" + , description="Inspects ZooKeeper and returns a map containing the name, version and url for the model referred to by the input parameters." + , params = { + "model_name - The name of the model" + ,"model_version - The optional version of the model. If the model version is not specified, the most current version is used." + } + , returns = "A map containing the name, version, and url for the REST endpoint (fields named name, version and url). " + + "Note that the output of this function is suitable for input into the first argument of MAAS_MODEL_APPLY." + ) + public static class GetEndpoint implements StellarFunction { + ServiceDiscoverer discoverer; + private boolean isInitialized = false; + private boolean isValidState = false; + + @Override + public Object apply(List<Object> args, Context context) throws ParseException { + if(!isValidState) { + LOG.error("Invalid state: Unable to find ServiceDiscoverer service."); + return null; + } + String modelName = null; + String modelVersion = null; + if(args.size() >= 1) { + modelName = args.get(0).toString(); + } + if(args.size() >= 2) + { + modelVersion = args.get(1).toString(); + } + if(modelName == null) { + return null; + } + try { + ModelEndpoint ep = null; + if (modelVersion == null) { + ep = discoverer.getEndpoint(modelName); + } else { + ep = discoverer.getEndpoint(modelName, modelVersion); + } + return ep == null ? null : endpointToMap(ep.getName(), ep.getVersion(), ep.getEndpoint()); + } + catch(Exception ex) { + LOG.error("Unable to discover endpoint: {}", ex.getMessage(), ex); + return null; + } + } + + public static Map<String, String> endpointToMap(String name, String version, Endpoint ep) { + Map<String, String> ret = new HashMap<>(); + ret.put("url", ep.getUrl()); + ret.put("name", name); + ret.put("version", version); + for(Map.Entry<String, String> kv : ep.getFunctions().entrySet()) { + ret.put("endpoint:" + kv.getKey(), kv.getValue()); + } + return ret; + } + + @Override + public synchronized void initialize(Context context) { + try { + Optional<Object> clientOptional = context.getCapability(Context.Capabilities.ZOOKEEPER_CLIENT); + CuratorFramework client = null; + if (clientOptional.isPresent() && clientOptional.get() instanceof CuratorFramework) { + client = (CuratorFramework) clientOptional.get(); + } else { + throw new IllegalStateException("Unable to initialize function: Cannot find zookeeper client."); + } + try { + discoverer = createDiscoverer(client); + context.addCapability(Context.Capabilities.SERVICE_DISCOVERER, () -> discoverer); + isValidState = true; + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new IllegalStateException("Unable to initialize MAAS_GET_ENDPOINT", e); + } + } + finally { + isInitialized = true; + } + } + + @Override + public boolean isInitialized() { + return isInitialized; + } + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-service/README.md ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-service/README.md b/metron-analytics/metron-maas-service/README.md index 30f785d..575c873 100644 --- a/metron-analytics/metron-maas-service/README.md +++ b/metron-analytics/metron-maas-service/README.md @@ -126,16 +126,29 @@ Now let's install some prerequisites: Start Squid via `service squid start` Now that we have flask and jinja, we can create a mock DGA service to deploy with MaaS: -* Download the files in [this](https://gist.github.com/cestella/cba10aff0f970078a4c2c8cade3a4d1a) gist into the `/root/mock_dga` directory -* Make `rest.sh` executable via `chmod +x /root/mock_dga/rest.sh` +* Download the files in [this](https://gist.github.com/cestella/cba10aff0f970078a4c2c8cade3a4d1a) gist into the `$HOME/mock_dga` directory +* Make `rest.sh` executable via `chmod +x $HOME/mock_dga/rest.sh` This service will treat `yahoo.com` and `amazon.com` as legit and everything else as malicious. The contract is that the REST service exposes an endpoint `/apply` and returns back JSON maps with a single key `is_malicious` which can be `malicious` or `legit`. ## Deploy Mock DGA Service via MaaS +The following presumes that you are a logged in as a user who has a +home directory in HDFS under `/user/$USER`. If you do not, please create one +and ensure the permissions are set appropriate: +``` +su - hdfs -c "hadoop fs -mkdir /user/$USER" +su - hdfs -c "hadoop fs -chown $USER:$USER /user/$USER" +``` +Or, in the common case for the `metron` user: +``` +su - hdfs -c "hadoop fs -mkdir /user/metron" +su - hdfs -c "hadoop fs -chown metron:metron /user/metron" +``` + Now let's start MaaS and deploy the Mock DGA Service: * Start MaaS via `$METRON_HOME/bin/maas_service.sh -zq node1:2181` -* Start one instance of the mock DGA model with 512M of memory via `$METRON_HOME/bin/maas_deploy.sh -zq node1:2181 -lmp /root/mock_dga -hmp /user/root/models -mo ADD -m 512 -n dga -v 1.0 -ni 1` +* Start one instance of the mock DGA model with 512M of memory via `$METRON_HOME/bin/maas_deploy.sh -zq node1:2181 -lmp $HOME/mock_dga -hmp /user/$USER/models -mo ADD -m 512 -n dga -v 1.0 -ni 1` * As a sanity check: * Ensure that the model is running via `$METRON_HOME/bin/maas_deploy.sh -zq node1:2181 -mo LIST`. You should see `Model dga @ 1.0` be displayed and under that a url such as (but not exactly) `http://node1:36161` * Try to hit the model via curl: `curl 'http://localhost:36161/apply?host=caseystella.com'` and ensure that it returns a JSON map indicating the domain is malicious. @@ -170,8 +183,6 @@ Now that we have a deployed model, let's adjust the configurations for the Squid * Edit the squid enrichment configuration at `$METRON_HOME/config/zookeeper/enrichments/squid.json` (this file will not exist, so create a new one) to make the threat triage adjust the level of risk based on the model output: ``` { - "index": "squid", - "batchSize": 1, "enrichment" : { "fieldMap": {} }, http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-service/pom.xml ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-service/pom.xml b/metron-analytics/metron-maas-service/pom.xml index 0ac9bac..4eeceae 100644 --- a/metron-analytics/metron-maas-service/pom.xml +++ b/metron-analytics/metron-maas-service/pom.xml @@ -49,17 +49,6 @@ <version>${global_kryo_serializers_version}</version> </dependency> <dependency> - <groupId>org.apache.metron</groupId> - <artifactId>stellar-common</artifactId> - <version>${project.parent.version}</version> - <exclusions> - <exclusion> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-auth</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-yarn-server-common</artifactId> <version>${hadoop.version}</version> http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/functions/MaaSFunctions.java ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/functions/MaaSFunctions.java b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/functions/MaaSFunctions.java deleted file mode 100644 index eacb64d..0000000 --- a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/functions/MaaSFunctions.java +++ /dev/null @@ -1,324 +0,0 @@ -/** - * 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.metron.maas.functions; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import java.lang.invoke.MethodHandles; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import org.apache.curator.framework.CuratorFramework; -import org.apache.metron.maas.config.Endpoint; -import org.apache.metron.maas.config.MaaSConfig; -import org.apache.metron.maas.config.ModelEndpoint; -import org.apache.metron.maas.discovery.ServiceDiscoverer; -import org.apache.metron.maas.util.ConfigUtil; -import org.apache.metron.maas.util.RESTUtil; -import org.apache.metron.stellar.common.utils.JSONUtils; -import org.apache.metron.stellar.dsl.Context; -import org.apache.metron.stellar.dsl.ParseException; -import org.apache.metron.stellar.dsl.Stellar; -import org.apache.metron.stellar.dsl.StellarFunction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MaaSFunctions { - protected static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private static class ModelCacheKey { - String name; - String version; - String method; - Map<String, String> args; - public ModelCacheKey(String name, String version, String method, Map<String, String> args) { - this.name = name; - this.version = version; - this.method = method; - this.args = args; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ModelCacheKey that = (ModelCacheKey) o; - - if (name != null ? !name.equals(that.name) : that.name != null) return false; - if (version != null ? !version.equals(that.version) : that.version != null) return false; - if (method != null ? !method.equals(that.method) : that.method != null) return false; - return args != null ? args.equals(that.args) : that.args == null; - - } - - @Override - public int hashCode() { - int result = name != null ? name.hashCode() : 0; - result = 31 * result + (version != null ? version.hashCode() : 0); - result = 31 * result + (method != null ? method.hashCode() : 0); - result = 31 * result + (args != null ? args.hashCode() : 0); - return result; - } - } - - @Stellar(name="MODEL_APPLY" - , namespace="MAAS" - , description = "Returns the output of a model deployed via Model as a Service. NOTE: Results are cached locally for 10 minutes." - , params = { "endpoint - A map containing the name, version, and url for the REST endpoint" - , "function - The optional endpoint path; default is 'apply'" - , "model_args - A Dictionary of arguments for the model (these become request params)" - } - , returns = "The output of the model deployed as a REST endpoint in Map form. Assumes REST endpoint returns a JSON Map." - ) - public static class ModelApply implements StellarFunction { - private boolean isInitialized = false; - private ServiceDiscoverer discoverer; - private Cache<ModelCacheKey, Map<String, Object> > resultCache; - public ModelApply() { - resultCache = CacheBuilder.newBuilder() - .concurrencyLevel(4) - .weakKeys() - .maximumSize(100000) - .expireAfterWrite(10, TimeUnit.MINUTES) - .build(); - } - - @Override - public Object apply(List<Object> args, Context context) throws ParseException { - if(args.size() < 2) { - throw new ParseException("Unable to execute model_apply. " + - "Expected arguments: endpoint_map:map, " + - " [endpoint method:string], model_args:map" - ); - } - if(!isInitialized) { - return null; - } - int i = 0; - if(args.size() == 0) { - return null; - } - Object endpointObj = args.get(i++); - Map endpoint = null; - String modelName; - String modelVersion; - String modelUrl; - if(endpointObj instanceof Map) { - endpoint = (Map)endpointObj; - modelName = endpoint.get("name") + ""; - modelVersion = endpoint.get("version") + ""; - modelUrl = endpoint.get("url") + ""; - } - else { - return null; - } - String modelFunction = "apply"; - Map<String, String> modelArgs = new HashMap<>(); - if(args.get(i) instanceof String) { - String func = (String)args.get(i); - if(endpoint.containsKey("endpoint:" + func)) { - modelFunction = "" + endpoint.get("endpoint:" + func); - } - else { - modelFunction = func; - } - i++; - } - - if(args.get(i) instanceof Map) { - if(endpoint.containsKey("endpoint:apply")) { - modelFunction = "" + endpoint.get("endpoint:apply"); - } - modelArgs = (Map)args.get(i); - } - if( modelName == null - || modelVersion == null - || modelFunction == null - ) { - return null; - } - ModelCacheKey cacheKey = new ModelCacheKey(modelName, modelVersion, modelFunction, modelArgs); - Map<String, Object> ret = resultCache.getIfPresent(cacheKey); - if(ret != null) { - return ret; - } - else { - String url = modelUrl; - if (url.endsWith("/")) { - url = url.substring(0, url.length() - 1); - } - if (modelFunction.startsWith("/")) { - modelFunction = modelFunction.substring(1); - } - try { - URL u = new URL(url + "/" + modelFunction); - - String results = RESTUtil.INSTANCE.getRESTJSONResults(u, modelArgs); - ret = JSONUtils.INSTANCE.load(results, new TypeReference<Map<String, Object>>() { - }); - resultCache.put(cacheKey, ret); - return ret; - } catch (Exception e) { - LOG.error(e.getMessage(), e); - if (discoverer != null) { - try { - URL u = new URL(modelUrl); - discoverer.blacklist(u); - } catch (MalformedURLException e1) { - } - } - } - } - return null; - } - - @Override - public synchronized void initialize(Context context) { - - try { - Optional<ServiceDiscoverer> discovererOpt = (Optional) (context.getCapability(Context.Capabilities.SERVICE_DISCOVERER)); - if (discovererOpt.isPresent()) { - discoverer = discovererOpt.get(); - } - else { - Optional<Object> clientOptional = context.getCapability(Context.Capabilities.ZOOKEEPER_CLIENT); - CuratorFramework client = null; - if (clientOptional.isPresent() && clientOptional.get() instanceof CuratorFramework) { - client = (CuratorFramework) clientOptional.get(); - } else { - throw new IllegalStateException("Unable to initialize function: Cannot find zookeeper client."); - } - discoverer = createDiscoverer(client); - } - } - catch(Exception ex) { - LOG.error(ex.getMessage(), ex); - } - finally { - //We always want to set initialize to true because we don't want to keep trying to initialize over and over - isInitialized = true; - } - } - - @Override - public boolean isInitialized() { - return isInitialized; - } - } - - private static ServiceDiscoverer createDiscoverer(CuratorFramework client) throws Exception { - MaaSConfig config = ConfigUtil.INSTANCE.read(client, "/metron/maas/config", new MaaSConfig(), MaaSConfig.class); - ServiceDiscoverer discoverer = new ServiceDiscoverer(client, config.getServiceRoot()); - discoverer.start(); - return discoverer; - } - - @Stellar(name="GET_ENDPOINT" - , namespace="MAAS" - , description="Inspects ZooKeeper and returns a map containing the name, version and url for the model referred to by the input parameters." - , params = { - "model_name - The name of the model" - ,"model_version - The optional version of the model. If the model version is not specified, the most current version is used." - } - , returns = "A map containing the name, version, and url for the REST endpoint (fields named name, version and url). " + - "Note that the output of this function is suitable for input into the first argument of MAAS_MODEL_APPLY." - ) - public static class GetEndpoint implements StellarFunction { - ServiceDiscoverer discoverer; - private boolean isInitialized = false; - private boolean isValidState = false; - - @Override - public Object apply(List<Object> args, Context context) throws ParseException { - if(!isValidState) { - LOG.error("Invalid state: Unable to find ServiceDiscoverer service."); - return null; - } - String modelName = null; - String modelVersion = null; - if(args.size() >= 1) { - modelName = args.get(0).toString(); - } - if(args.size() >= 2) - { - modelVersion = args.get(1).toString(); - } - if(modelName == null) { - return null; - } - try { - ModelEndpoint ep = null; - if (modelVersion == null) { - ep = discoverer.getEndpoint(modelName); - } else { - ep = discoverer.getEndpoint(modelName, modelVersion); - } - return ep == null ? null : endpointToMap(ep.getName(), ep.getVersion(), ep.getEndpoint()); - } - catch(Exception ex) { - LOG.error("Unable to discover endpoint: {}", ex.getMessage(), ex); - return null; - } - } - - public static Map<String, String> endpointToMap(String name, String version, Endpoint ep) { - Map<String, String> ret = new HashMap<>(); - ret.put("url", ep.getUrl()); - ret.put("name", name); - ret.put("version", version); - for(Map.Entry<String, String> kv : ep.getFunctions().entrySet()) { - ret.put("endpoint:" + kv.getKey(), kv.getValue()); - } - return ret; - } - - @Override - public synchronized void initialize(Context context) { - try { - Optional<Object> clientOptional = context.getCapability(Context.Capabilities.ZOOKEEPER_CLIENT); - CuratorFramework client = null; - if (clientOptional.isPresent() && clientOptional.get() instanceof CuratorFramework) { - client = (CuratorFramework) clientOptional.get(); - } else { - throw new IllegalStateException("Unable to initialize function: Cannot find zookeeper client."); - } - try { - discoverer = createDiscoverer(client); - context.addCapability(Context.Capabilities.SERVICE_DISCOVERER, () -> discoverer); - isValidState = true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); - throw new IllegalStateException("Unable to initialize MAAS_GET_ENDPOINT", e); - } - } - finally { - isInitialized = true; - } - } - - @Override - public boolean isInitialized() { - return isInitialized; - } - } -} http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Client.java ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Client.java b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Client.java index c2d8906..9cabf21 100644 --- a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Client.java +++ b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Client.java @@ -24,6 +24,7 @@ import java.util.*; import java.util.function.Function; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import org.apache.commons.cli.*; import org.apache.commons.cli.CommandLine; @@ -558,6 +559,7 @@ public class Client { // Copy the application master jar to the filesystem // Create a local resource to point to the destination jar path FileSystem fs = FileSystem.get(conf); + createMaaSDirectory(fs, appId.toString()); Path ajPath = addToLocalResources(fs, appMasterJar, appMasterJarPath, appId.toString(), localResources, null); // Set the log4j properties if needed @@ -789,6 +791,18 @@ public class Client { yarnClient.killApplication(appId); } + private void createMaaSDirectory(FileSystem fs, String appId) throws IOException { + for(Path p : ImmutableList.of(new Path(fs.getHomeDirectory(), appName) + , new Path(fs.getHomeDirectory(), appName + "/" + appId) + ) + ) { + if(!fs.exists(p)) { + fs.mkdirs(p); + fs.setPermission(p, new FsPermission((short)0755)); + } + } + } + private Path addToLocalResources(FileSystem fs, String fileSrcPath, String fileDstPath, String appId, Map<String, LocalResource> localResources, String resources) throws IOException { @@ -808,6 +822,7 @@ public class Client { } else { fs.copyFromLocalFile(new Path(fileSrcPath), dst); } + fs.setPermission(dst, new FsPermission((short)0755)); FileStatus scFileStatus = fs.getFileStatus(dst); LocalResource scRsrc = LocalResource.newInstance( http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Constants.java ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Constants.java b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Constants.java index ac2c950..d032511 100644 --- a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Constants.java +++ b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/Constants.java @@ -31,5 +31,8 @@ public class Constants { * Environment key name denoting the timeline domain ID. */ public static final String TIMELINEDOMAIN = "TIMELINEDOMAIN"; - + /* + The filename which communicates the endpoint information for a deployed model + */ + public static final String ENDPOINT_DAT = "endpoint.dat"; } http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/runner/Runner.java ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/runner/Runner.java b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/runner/Runner.java index cc297d2..8f0b9e5 100644 --- a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/runner/Runner.java +++ b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/service/runner/Runner.java @@ -33,6 +33,7 @@ import org.apache.curator.utils.CloseableUtils; import org.apache.curator.x.discovery.*; import org.apache.curator.x.discovery.details.JsonInstanceSerializer; import org.apache.metron.maas.config.Endpoint; +import org.apache.metron.maas.service.Constants; import org.apache.metron.maas.util.ConfigUtil; import org.apache.metron.maas.config.MaaSConfig; import org.apache.metron.maas.config.ModelEndpoint; @@ -202,7 +203,11 @@ public class Runner { serviceDiscovery.start(); File cwd = new File(script).getParentFile(); - final String cmd = new File(cwd, script).getAbsolutePath(); + File scriptFile = new File(cwd, script); + if(scriptFile.exists() && !scriptFile.canExecute()) { + scriptFile.setExecutable(true); + } + final String cmd = scriptFile.getAbsolutePath(); try { p = new ProcessBuilder(cmd).directory(cwd).start(); @@ -299,7 +304,7 @@ public class Runner { private static Endpoint readEndpoint(File cwd) throws Exception { String content = ""; - File f = new File(cwd, "endpoint.dat"); + File f = new File(cwd, Constants.ENDPOINT_DAT); for(int i = 0;i < NUM_ATTEMPTS;i++) { if(f.exists()) { try { http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/submit/ModelSubmission.java ---------------------------------------------------------------------- diff --git a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/submit/ModelSubmission.java b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/submit/ModelSubmission.java index ebfa904..fcae40a 100644 --- a/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/submit/ModelSubmission.java +++ b/metron-analytics/metron-maas-service/src/main/java/org/apache/metron/maas/submit/ModelSubmission.java @@ -33,6 +33,7 @@ import org.apache.hadoop.fs.Path; import org.apache.log4j.PropertyConfigurator; import org.apache.metron.maas.config.*; import org.apache.metron.maas.discovery.ServiceDiscoverer; +import org.apache.metron.maas.service.Constants; import org.apache.metron.maas.service.Log4jPropertyHelper; import org.apache.metron.maas.util.ConfigUtil; import org.apache.metron.maas.queue.Queue; @@ -247,6 +248,10 @@ public class ModelSubmission { fs.mkdirs(hdfsPath); } for(File f : localDir.listFiles()) { + if(f.getName().equals(Constants.ENDPOINT_DAT)) { + //skip the endpoint if it exists accidentally, we don't want to localize that. + continue; + } Path p = new Path(hdfsPath, f.getName()); FSDataOutputStream out = fs.create(p); BufferedInputStream in = new BufferedInputStream(new FileInputStream(f)); http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/addon-services/METRON/CURRENT/role_command_order.json ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/addon-services/METRON/CURRENT/role_command_order.json b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/addon-services/METRON/CURRENT/role_command_order.json index 820179a..015f026 100755 --- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/addon-services/METRON/CURRENT/role_command_order.json +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/addon-services/METRON/CURRENT/role_command_order.json @@ -5,11 +5,13 @@ "_comment" : "dependencies for all cases", "METRON_INDEXING-INSTALL" : ["METRON_PARSERS-INSTALL"], "METRON_ENRICHMENT-INSTALL": ["METRON_INDEXING-INSTALL"], + "METRON_PROFILER-INSTALL": ["METRON_ENRICHMENT-INSTALL"], "METRON_REST-INSTALL": ["METRON_PARSERS-INSTALL"], "METRON_PARSERS-START" : ["NAMENODE-START", "ZOOKEEPER_SERVER-START", "KAFKA_BROKER-START", "STORM_REST_API-START","METRON_ENRICHMENT_MASTER-START"], "METRON_ENRICHMENT_MASTER-START" : ["NAMENODE-START", "ZOOKEEPER_SERVER-START", "KAFKA_BROKER-START", "STORM_REST_API-START", "HBASE_MASTER-START", "HBASE_REGIONSERVER-START"], "METRON_ENRICHMENT_SERVICE_CHECK-SERVICE_CHECK" : ["METRON_ENRICHMENT_MASTER-START"], "METRON_INDEXING-START" : ["NAMENODE-START", "ZOOKEEPER_SERVER-START", "KAFKA_BROKER-START", "STORM_REST_API-START","METRON_PARSERS-START"], + "METRON_PROFILER-START" : ["NAMENODE-START", "ZOOKEEPER_SERVER-START", "KAFKA_BROKER-START", "HBASE_MASTER-START", "HBASE_REGIONSERVER-START", "METRON_ENRICHMENT-INSTALL"], "METRON_REST-START": ["KAFKA_BROKER-START","STORM_REST_API-START","ZOOKEEPER_SERVER-START","NAMENODE-START","METRON_PARSERS-INSTALL","METRON_INDEXING-INSTALL","METRON_ENRICHMENT-INSTALL"], "METRON_MANAGEMENT_UI-START": ["METRON_REST-START"], "STORM_REST_API-STOP" : ["METRON_ENRICHMENT_MASTER-STOP","METRON_PARSERS-STOP","METRON_INDEXING-STOP","METRON_REST-STOP","METRON_MANAGEMENT_UI-STOP"], http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-indexing-env.xml ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-indexing-env.xml b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-indexing-env.xml index e36730a..6abbe77 100644 --- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-indexing-env.xml +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-indexing-env.xml @@ -59,7 +59,7 @@ <description>Indexing Writer Class Name</description> <value>org.apache.metron.elasticsearch.writer.ElasticsearchWriter</value> <display-name>Indexing Writer Class Name</display-name> - </property> + </property> <property> <name>update_table</name> <description>The HBase table which will hold edits to indexed data</description> http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-profiler-env.xml ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-profiler-env.xml b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-profiler-env.xml new file mode 100644 index 0000000..c7f6ce2 --- /dev/null +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/configuration/metron-profiler-env.xml @@ -0,0 +1,155 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> +<!-- + 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. +--> +<configuration supports_final="true"> + <property> + <name>profiler_kafka_start</name> + <value>UNCOMMITTED_EARLIEST</value> + <description>One of EARLIEST, LATEST, UNCOMMITTED_EARLIEST, UNCOMMITTED_LATEST</description> + <display-name>Input Topic Start</display-name> + <value-attributes> + <type>value-list</type> + <entries> + <entry> + <value>EARLIEST</value> + </entry> + <entry> + <value>LATEST</value> + </entry> + <entry> + <value>UNCOMMITTED_EARLIEST</value> + </entry> + <entry> + <value>UNCOMMITTED_LATEST</value> + </entry> + </entries> + <selection-cardinality>1</selection-cardinality> + </value-attributes> + </property> + <property> + <name>profiler_period_duration</name> + <value>15</value> + <description>The duration of each profile period. This value should be defined along with profiler.period.duration.units</description> + <display-name>Period Duration</display-name> + </property> + <property> + <name>profiler_period_units</name> + <value>MINUTES</value> + <description>The units used to specify the profiler.period.duration. This value should be defined along with profiler.period.duration.</description> + <display-name>Period Units</display-name> + <value-attributes> + <type>value-list</type> + <entries> + <entry> + <value>DAYS</value> + </entry> + <entry> + <value>HOURS</value> + </entry> + <entry> + <value>MINUTES</value> + </entry> + <entry> + <value>SECONDS</value> + </entry> + </entries> + <selection-cardinality>1</selection-cardinality> + </value-attributes> + + </property> + <property> + <name>profiler_ttl</name> + <value>30</value> + <description>If a message has not been applied to a Profile in this period of time, the Profile will be terminated and its resources will be cleaned up. This value should be defined along with profiler.ttl.units. + This time-to-live does not affect the persisted Profile data in HBase. It only affects the state stored in memory during the execution of the latest profile period. This state will be deleted if the time-to-live is exceeded. + </description> + <display-name>Time to Live</display-name> + </property> + <property> + <name>profiler_ttl_units</name> + <value>MINUTES</value> + <description>The units used to specify the profiler.ttl.</description> + <display-name>Time To Live Units</display-name> + <value-attributes> + <type>value-list</type> + <entries> + <entry> + <value>DAYS</value> + </entry> + <entry> + <value>HOURS</value> + </entry> + <entry> + <value>MINUTES</value> + </entry> + <entry> + <value>SECONDS</value> + </entry> + </entries> + <selection-cardinality>1</selection-cardinality> + </value-attributes> + + + </property> + <property> + <name>profiler_hbase_table</name> + <value>profiler</value> + <description>The name of the HBase table that profile data is written to. The Profiler expects that the table exists and is writable.</description> + <display-name>HBase Table</display-name> + </property> + <property> + <name>profiler_hbase_cf</name> + <value>P</value> + <description>The column family used to store profile data in HBase.</description> + <display-name>HBase Table Column Family</display-name> + </property> + <property> + <name>profiler_hbase_batch</name> + <value>10</value> + <description>The number of puts that are written to HBase in a single batch.</description> + <display-name>HBase Batch Size</display-name> + </property> + <property> + <name>profiler_hbase_flush_interval</name> + <value>30</value> + <description>The maximum number of seconds between batch writes to HBase.</description> + <display-name>HBase Flush Interval</display-name> + </property> + <property> + <name>profiler_topology_worker_childopts</name> + <value/> + <description>Extra topology child opts for the storm topology.</description> + <display-name>topology.worker.childopts</display-name> + <value-attributes> + <empty-value-valid>true</empty-value-valid> + </value-attributes> + </property> + <property> + <name>profiler_topology_workers</name> + <value>1</value> + <description>The profiler storm topology workers</description> + <display-name>Number of Workers</display-name> + </property> + <property> + <name>profiler_acker_executors</name> + <value>1</value> + <description>The profiler storm topology acker executors</description> + <display-name>Number of Acker Executors</display-name> + </property> +</configuration> http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml index 77f247c..2844605 100644 --- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml @@ -119,6 +119,46 @@ </component> <component> + <name>METRON_PROFILER</name> + <displayName>Metron Profiler</displayName> + <category>MASTER</category> + <cardinality>1</cardinality> + <versionAdvertised>false</versionAdvertised> + <dependencies> + <dependency> + <name>HBASE/HBASE_CLIENT</name> + <scope>host</scope> + <auto-deploy> + <enabled>true</enabled> + </auto-deploy> + </dependency> + <dependency> + <name>ZOOKEEPER/ZOOKEEPER_SERVER</name> + <scope>cluster</scope> + <auto-deploy> + <enabled>true</enabled> + </auto-deploy> + </dependency> + <dependency> + <name>KAFKA/KAFKA_BROKER</name> + <scope>host</scope> + <auto-deploy> + <enabled>true</enabled> + </auto-deploy> + </dependency> + </dependencies> + <commandScript> + <script>scripts/profiler_master.py</script> + <scriptType>PYTHON</scriptType> + <timeout>600</timeout> + </commandScript> + <configuration-dependencies> + <config-type>metron-enrichment-env</config-type> + <config-type>metron-profiler-env</config-type> + </configuration-dependencies> + </component> + + <component> <name>METRON_INDEXING</name> <displayName>Metron Indexing</displayName> <category>MASTER</category> @@ -321,6 +361,9 @@ <name>metron-enrichment</name> </package> <package> + <name>metron-profiler</name> + </package> + <package> <name>metron-indexing</name> </package> <package> http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py index e9426db..abbddc5 100755 --- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py @@ -180,6 +180,7 @@ enrichment_cf = status_params.enrichment_cf update_table = status_params.update_table update_cf = status_params.update_cf + threatintel_table = status_params.threatintel_table threatintel_cf = status_params.threatintel_cf @@ -210,6 +211,7 @@ security_enabled = status_params.security_enabled client_jaas_path = metron_home + '/client_jaas.conf' client_jaas_arg = '-Djava.security.auth.login.config=' + metron_home + '/client_jaas.conf' enrichment_topology_worker_childopts = client_jaas_arg if security_enabled else '' +profiler_topology_worker_childopts = client_jaas_arg if security_enabled else '' indexing_topology_worker_childopts = client_jaas_arg if security_enabled else '' metron_jvm_flags += (' ' + client_jaas_arg) if security_enabled else '' topology_auto_credentials = config['configurations']['storm-site'].get('nimbus.credential.renewers.classes', []) @@ -260,6 +262,29 @@ threat_intel_stellar_parallelism = config['configurations']['metron-enrichment-e threat_intel_join_parallelism = config['configurations']['metron-enrichment-env']['threat_intel_join_parallelism'] kafka_writer_parallelism = config['configurations']['metron-enrichment-env']['kafka_writer_parallelism'] +# Profiler + +metron_profiler_topology = 'profiler' +profiler_input_topic = config['configurations']['metron-enrichment-env']['enrichment_output_topic'] +profiler_kafka_start = config['configurations']['metron-profiler-env']['profiler_kafka_start'] +profiler_period_duration = config['configurations']['metron-profiler-env']['profiler_period_duration'] +profiler_period_units = config['configurations']['metron-profiler-env']['profiler_period_units'] +profiler_ttl = config['configurations']['metron-profiler-env']['profiler_ttl'] +profiler_ttl_units = config['configurations']['metron-profiler-env']['profiler_ttl_units'] +profiler_hbase_batch = config['configurations']['metron-profiler-env']['profiler_hbase_batch'] +profiler_hbase_flush_interval = config['configurations']['metron-profiler-env']['profiler_hbase_flush_interval'] +profiler_topology_workers = config['configurations']['metron-profiler-env']['profiler_topology_workers'] +profiler_acker_executors = config['configurations']['metron-profiler-env']['profiler_acker_executors'] +profiler_hbase_table = config['configurations']['metron-profiler-env']['profiler_hbase_table'] +profiler_hbase_cf = config['configurations']['metron-profiler-env']['profiler_hbase_cf'] +profiler_configured_flag_file = status_params.profiler_configured_flag_file +profiler_acl_configured_flag_file = status_params.indexing_acl_configured_flag_file +profiler_hbase_configured_flag_file = status_params.profiler_hbase_configured_flag_file +profiler_hbase_acl_configured_flag_file = status_params.profiler_hbase_acl_configured_flag_file +if not len(profiler_topology_worker_childopts) == 0: + profiler_topology_worker_childopts += ' ' +profiler_topology_worker_childopts += config['configurations']['metron-profiler-env']['profiler_topology_worker_childopts'] + # Indexing indexing_kafka_start = config['configurations']['metron-indexing-env']['indexing_kafka_start'] indexing_input_topic = status_params.indexing_input_topic http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py index 215d808..76f8570 100644 --- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py @@ -61,6 +61,17 @@ threatintel_cf = 't' update_table = 'metron_update' update_cf = 't' +# Profiler +metron_profiler_topology = 'profiler' +profiler_input_topic = config['configurations']['metron-enrichment-env']['enrichment_output_topic'] +profiler_hbase_table = config['configurations']['metron-profiler-env']['profiler_hbase_table'] +profiler_hbase_cf = config['configurations']['metron-profiler-env']['profiler_hbase_cf'] +profiler_configured_flag_file = metron_zookeeper_config_path + '/../metron_profiler_configured' +profiler_acl_configured_flag_file = metron_zookeeper_config_path + '/../metron_profiler_acl_configured' +profiler_hbase_configured_flag_file = metron_zookeeper_config_path + '/../metron_profiler_hbase_configured' +profiler_hbase_acl_configured_flag_file = metron_zookeeper_config_path + '/../metron_profiler_hbase_acl_configured' + + # Indexing metron_indexing_topology = 'indexing' indexing_input_topic = config['configurations']['metron-indexing-env']['indexing_input_topic'] http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/profiler_commands.py ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/profiler_commands.py b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/profiler_commands.py new file mode 100644 index 0000000..ddd66cb --- /dev/null +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/profiler_commands.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +""" +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 os +import time + +from resource_management.core.logger import Logger +from resource_management.core.resources.system import Execute, File + +import metron_service +import metron_security + + +# Wrap major operations and functionality in this class +class ProfilerCommands: + __params = None + __profiler_topic = None + __profiler_topology = None + __configured = False + __acl_configured = False + __hbase_configured = False + __hbase_acl_configured = False + + def __init__(self, params): + if params is None: + raise ValueError("params argument is required for initialization") + self.__params = params + self.__profiler_topology = params.metron_profiler_topology + self.__profiler_topic = params.profiler_input_topic + self.__configured = os.path.isfile(self.__params.profiler_configured_flag_file) + self.__acl_configured = os.path.isfile(self.__params.profiler_acl_configured_flag_file) + self.__hbase_configured = os.path.isfile(self.__params.profiler_hbase_configured_flag_file) + self.__hbase_acl_configured = os.path.isfile(self.__params.profiler_hbase_acl_configured_flag_file) + + def is_configured(self): + return self.__configured + + def is_acl_configured(self): + return self.__acl_configured + + def set_configured(self): + File(self.__params.profiler_configured_flag_file, + content="", + owner=self.__params.metron_user, + mode=0755) + + def is_hbase_configured(self): + return self.__hbase_configured + + def is_hbase_acl_configured(self): + return self.__hbase_acl_configured + + def set_hbase_configured(self): + Logger.info("Setting HBase Configured to True") + File(self.__params.profiler_hbase_configured_flag_file, + content="", + owner=self.__params.metron_user, + mode=0755) + + def set_hbase_acl_configured(self): + Logger.info("Setting HBase ACL Configured to True") + File(self.__params.profiler_hbase_acl_configured_flag_file, + content="", + owner=self.__params.metron_user, + mode=0755) + + def create_hbase_tables(self): + Logger.info("Creating HBase Tables") + if self.__params.security_enabled: + metron_security.kinit(self.__params.kinit_path_local, + self.__params.hbase_keytab_path, + self.__params.hbase_principal_name, + execute_user=self.__params.hbase_user) + cmd = "echo \"create '{0}','{1}'\" | hbase shell -n" + add_table_cmd = cmd.format(self.__params.profiler_hbase_table, self.__params.profiler_hbase_cf) + Execute(add_table_cmd, + tries=3, + try_sleep=5, + logoutput=False, + path='/usr/sbin:/sbin:/usr/local/bin:/bin:/usr/bin', + user=self.__params.hbase_user + ) + + Logger.info("Done creating HBase Tables") + self.set_hbase_configured() + + def set_hbase_acls(self): + Logger.info("Setting HBase ACLs") + if self.__params.security_enabled: + metron_security.kinit(self.__params.kinit_path_local, + self.__params.hbase_keytab_path, + self.__params.hbase_principal_name, + execute_user=self.__params.hbase_user) + cmd = "echo \"grant '{0}', 'RW', '{1}'\" | hbase shell -n" + add_table_acl_cmd = cmd.format(self.__params.metron_user, self.__params.profiler_hbase_table) + Execute(add_table_acl_cmd, + tries=3, + try_sleep=5, + logoutput=False, + path='/usr/sbin:/sbin:/usr/local/bin:/bin:/usr/bin', + user=self.__params.hbase_user + ) + + Logger.info("Done setting HBase ACLs") + self.set_hbase_acl_configured() + + def set_acl_configured(self): + File(self.__params.profiler_acl_configured_flag_file, + content="", + owner=self.__params.metron_user, + mode=0755) + + def start_profiler_topology(self, env): + Logger.info('Starting ' + self.__profiler_topology) + + if not self.is_topology_active(env): + if self.__params.security_enabled: + metron_security.kinit(self.__params.kinit_path_local, + self.__params.metron_keytab_path, + self.__params.metron_principal_name, + execute_user=self.__params.metron_user) + start_cmd_template = """{0}/bin/start_profiler_topology.sh \ + -s {1} \ + -z {2}""" + Execute(start_cmd_template.format(self.__params.metron_home, + self.__profiler_topology, + self.__params.zookeeper_quorum), + user=self.__params.metron_user) + + else: + Logger.info('Profiler topology already running') + + Logger.info('Finished starting profiler topology') + + def stop_profiler_topology(self, env): + Logger.info('Stopping ' + self.__profiler_topology) + + if self.is_topology_active(env): + if self.__params.security_enabled: + metron_security.kinit(self.__params.kinit_path_local, + self.__params.metron_keytab_path, + self.__params.metron_principal_name, + execute_user=self.__params.metron_user) + stop_cmd = 'storm kill ' + self.__profiler_topology + Execute(stop_cmd, user=self.__params.metron_user) + + else: + Logger.info("Profiler topology already stopped") + + Logger.info('Done stopping profiler topologies') + + def restart_profiler_topology(self, env): + Logger.info('Restarting the profiler topologies') + self.stop_profiler_topology(env) + + # Wait for old topology to be cleaned up by Storm, before starting again. + retries = 0 + topology_active = self.is_topology_active(env) + while self.is_topology_active(env) and retries < 3: + Logger.info('Existing topology still active. Will wait and retry') + time.sleep(10) + retries += 1 + + if not topology_active: + Logger.info('Waiting for storm kill to complete') + time.sleep(30) + self.start_profiler_topology(env) + Logger.info('Done restarting the profiler topologies') + else: + Logger.warning('Retries exhausted. Existing topology not cleaned up. Aborting topology start.') + + def is_topology_active(self, env): + env.set_params(self.__params) + active = True + topologies = metron_service.get_running_topologies(self.__params) + is_running = False + if self.__profiler_topology in topologies: + is_running = topologies[self.__profiler_topology] in ['ACTIVE', 'REBALANCING'] + active &= is_running + return active http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/profiler_master.py ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/profiler_master.py b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/profiler_master.py new file mode 100644 index 0000000..4946ab0 --- /dev/null +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/profiler_master.py @@ -0,0 +1,94 @@ +""" +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 os +from resource_management.core.exceptions import ComponentIsNotRunning +from resource_management.core.logger import Logger +from resource_management.core.resources.system import Execute +from resource_management.core.resources.system import File +from resource_management.core.source import Template +from resource_management.libraries.functions.format import format +from resource_management.core.source import StaticFile +from resource_management.libraries.functions import format as ambari_format +from resource_management.libraries.script import Script + +from metron_security import storm_security_setup +import metron_service +from profiler_commands import ProfilerCommands + + +class Profiler(Script): + __configured = False + + def install(self, env): + from params import params + env.set_params(params) + self.install_packages(env) + + def configure(self, env, upgrade_type=None, config_dir=None): + from params import params + env.set_params(params) + + Logger.info("Running profiler configure") + File(format("{metron_config_path}/profiler.properties"), + content=Template("profiler.properties.j2"), + owner=params.metron_user, + group=params.metron_group + ) + + commands = ProfilerCommands(params) + metron_service.load_global_config(params) + + if not commands.is_configured(): + commands.set_configured() + + if not commands.is_hbase_configured(): + commands.create_hbase_tables() + if params.security_enabled and not commands.is_hbase_acl_configured(): + commands.set_hbase_acls() + + Logger.info("Calling security setup") + storm_security_setup(params) + + def start(self, env, upgrade_type=None): + from params import params + env.set_params(params) + self.configure(env) + commands = ProfilerCommands(params) + commands.start_profiler_topology(env) + + def stop(self, env, upgrade_type=None): + from params import params + env.set_params(params) + commands = ProfilerCommands(params) + commands.stop_profiler_topology(env) + + def status(self, env): + from params import status_params + env.set_params(status_params) + commands = ProfilerCommands(status_params) + if not commands.is_topology_active(env): + raise ComponentIsNotRunning() + + def restart(self, env): + from params import params + env.set_params(params) + self.configure(env) + commands = ProfilerCommands(params) + commands.restart_profiler_topology(env) + +if __name__ == "__main__": + Profiler().execute() http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/profiler.properties.j2 ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/profiler.properties.j2 b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/profiler.properties.j2 new file mode 100644 index 0000000..cf2ad58 --- /dev/null +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/profiler.properties.j2 @@ -0,0 +1,47 @@ +# +# +# 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. +# +# + +##### Storm ##### + +topology.worker.childopts={{profiler_topology_worker_childopts}} + +##### Profiler ##### + +profiler.input.topic={{enrichment_output_topic}} +profiler.output.topic={{enrichment_input_topic}} +profiler.period.duration={{profiler_period_duration}} +profiler.period.duration.units={{profiler_period_units}} +profiler.workers={{profiler_topology_workers}} +profiler.executors={{profiler_acker_executors}} +profiler.ttl={{profiler_ttl}} +profiler.ttl.units={{profiler_ttl_units}} +profiler.hbase.salt.divisor=1000 +profiler.hbase.table={{profiler_hbase_table}} +profiler.hbase.column.family={{profiler_hbase_cf}} +profiler.hbase.batch={{profiler_hbase_batch}} +profiler.hbase.flush.interval.seconds={{profiler_hbase_flush_interval}} + +##### Kafka ##### + +kafka.zk={{zookeeper_quorum}} +kafka.broker={{kafka_brokers}} +# One of EARLIEST, LATEST, UNCOMMITTED_EARLIEST, UNCOMMITTED_LATEST +kafka.start={{profiler_kafka_start}} +kafka.security.protocol={{kafka_security_protocol}} http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/service_advisor.py ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/service_advisor.py b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/service_advisor.py index 4a95e63..2fb1ab0 100644 --- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/service_advisor.py +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/service_advisor.py @@ -43,6 +43,7 @@ class METRON${metron.short.version}ServiceAdvisor(service_advisor.ServiceAdvisor metronParsersHost = self.getHosts(componentsList, "METRON_PARSERS")[0] metronEnrichmentMaster = self.getHosts(componentsList, "METRON_ENRICHMENT_MASTER")[0] + metronProfilerMaster = self.getHosts(componentsList, "METRON_PROFILER")[0] metronIndexingHost = self.getHosts(componentsList, "METRON_INDEXING")[0] metronRESTHost = self.getHosts(componentsList, "METRON_REST")[0] @@ -76,6 +77,10 @@ class METRON${metron.short.version}ServiceAdvisor(service_advisor.ServiceAdvisor message = "Metron Indexing must be co-located with Metron Parsers on {0}".format(metronParsersHost) items.append({ "type": 'host-component', "level": 'ERROR', "message": message, "component-name": 'METRON_INDEXING', "host": metronIndexingHost }) + if metronParsersHost != metronProfilerHost: + message = "Metron Profiler must be co-located with Metron Parsers on {0}".format(metronParsersHost) + items.append({ "type": 'host-component', "level": 'ERROR', "message": message, "component-name": 'METRON_PROFILER', "host": metronProfilerHost }) + # Enrichment Master also needs ZK Client, but this is already guaranteed by being colocated with Parsers Master if metronParsersHost not in zookeeperClientHosts: message = "Metron must be co-located with an instance of Zookeeper Client" http://git-wip-us.apache.org/repos/asf/metron/blob/43646650/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/themes/metron_theme.json ---------------------------------------------------------------------- diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/themes/metron_theme.json b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/themes/metron_theme.json index ce352a4..748feb8 100644 --- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/themes/metron_theme.json +++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/themes/metron_theme.json @@ -65,7 +65,7 @@ "display-name": "Enrichment", "layout": { "tab-columns": "1", - "tab-rows": "4", + "tab-rows": "3", "sections": [ { "name": "section-enrichment-adapters", @@ -132,7 +132,7 @@ "display-name": "Indexing", "layout": { "tab-columns": "1", - "tab-rows": "3", + "tab-rows": "4", "sections": [ { "name": "section-indexing-kafka", @@ -155,7 +155,7 @@ }, { "name": "section-indexing-update", - "row-index": "0", + "row-index": "1", "column-index": "0", "row-span": "1", "column-span": "1", @@ -174,7 +174,7 @@ }, { "name": "section-indexing-storm", - "row-index": "1", + "row-index": "2", "column-index": "0", "row-span": "1", "column-span": "1", @@ -193,7 +193,7 @@ }, { "name": "section-indexing-hdfs", - "row-index": "2", + "row-index": "3", "column-index": "0", "row-span": "1", "column-span": "1", @@ -214,6 +214,73 @@ } }, { + "name": "profiler", + "display-name": "Profiler", + "layout": { + "tab-columns": "1", + "tab-rows": "3", + "sections": [ + { + "name": "section-profiler-kafka", + "row-index": "0", + "column-index": "0", + "row-span": "1", + "column-span": "1", + "section-columns": "1", + "section-rows": "1", + "subsections": [ + { + "name": "subsection-profiler-kafka", + "display-name": "Kafka", + "row-index": "0", + "column-index": "0", + "row-span": "1", + "column-span": "1" + } + ] + }, + { + "name": "section-profiler-setup", + "row-index": "1", + "column-index": "0", + "row-span": "1", + "column-span": "1", + "section-columns": "1", + "section-rows": "1", + "subsections": [ + { + "name": "subsection-profiler-setup", + "display-name": "Profiler Setup", + "row-index": "0", + "column-index": "0", + "row-span": "1", + "column-span": "1" + } + ] + }, + { + "name": "section-profiler-storm", + "row-index": "2", + "column-index": "0", + "row-span": "1", + "column-span": "1", + "section-columns": "1", + "section-rows": "1", + "subsections": [ + { + "name": "subsection-profiler-storm", + "display-name": "Storm", + "row-index": "0", + "column-index": "0", + "row-span": "1", + "column-span": "1" + } + ] + } + ] + } + }, + { "name": "rest", "display-name": "REST", "layout": { @@ -454,6 +521,54 @@ }, { + "config": "metron-profiler-env/profiler_kafka_start", + "subsection-name": "subsection-profiler-kafka" + }, + { + "config": "metron-profiler-env/profiler_period_duration", + "subsection-name": "subsection-profiler-setup" + }, + { + "config": "metron-profiler-env/profiler_period_units", + "subsection-name": "subsection-profiler-setup" + }, + { + "config": "metron-profiler-env/profiler_ttl", + "subsection-name": "subsection-profiler-setup" + }, + { + "config": "metron-profiler-env/profiler_ttl_units", + "subsection-name": "subsection-profiler-setup" + }, + { + "config": "metron-profiler-env/profiler_hbase_table", + "subsection-name": "subsection-profiler-setup" + }, + { + "config": "metron-profiler-env/profiler_hbase_cf", + "subsection-name": "subsection-profiler-setup" + }, + { + "config": "metron-profiler-env/profiler_hbase_batch", + "subsection-name": "subsection-profiler-setup" + }, + { + "config": "metron-profiler-env/profiler_hbase_flush_interval", + "subsection-name": "subsection-profiler-setup" + }, + { + "config": "metron-profiler-env/profiler_topology_worker_childopts", + "subsection-name": "subsection-profiler-storm" + }, + { + "config": "metron-profiler-env/profiler_topology_workers", + "subsection-name": "subsection-profiler-storm" + }, + { + "config": "metron-profiler-env/profiler_acker_executors", + "subsection-name": "subsection-profiler-storm" + }, + { "config": "metron-rest-env/metron_rest_port", "subsection-name": "subsection-rest" }, @@ -780,7 +895,78 @@ "type": "text-field" } }, - + { + "config": "metron-profiler-env/profiler_kafka_start", + "widget": { + "type": "combo" + } + }, + { + "config": "metron-profiler-env/profiler_period_duration", + "widget": { + "type": "text-field" + } + }, + { + "config": "metron-profiler-env/profiler_period_units", + "widget": { + "type": "combo" + } + }, + { + "config": "metron-profiler-env/profiler_ttl", + "widget": { + "type": "text-field" + } + }, + { + "config": "metron-profiler-env/profiler_ttl_units", + "widget": { + "type": "combo" + } + }, + { + "config": "metron-profiler-env/profiler_hbase_table", + "widget": { + "type": "text-field" + } + }, + { + "config": "metron-profiler-env/profiler_hbase_cf", + "widget": { + "type": "text-field" + } + }, + { + "config": "metron-profiler-env/profiler_hbase_batch", + "widget": { + "type": "text-field" + } + }, + { + "config": "metron-profiler-env/profiler_hbase_flush_interval", + "widget": { + "type": "text-field" + } + }, + { + "config": "metron-profiler-env/profiler_topology_worker_childopts", + "widget": { + "type": "text-field" + } + }, + { + "config": "metron-profiler-env/profiler_topology_workers", + "widget": { + "type": "text-field" + } + }, + { + "config": "metron-profiler-env/profiler_acker_executors", + "widget": { + "type": "text-field" + } + }, { "config": "metron-rest-env/metron_rest_port",