You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by av...@apache.org on 2017/11/02 21:41:46 UTC

ambari git commit: AMBARI-22359 : Fix Serialization issues in Metric Definition Service (avijayan).

Repository: ambari
Updated Branches:
  refs/heads/branch-3.0-ams a42cbc5f3 -> 9431d568f


AMBARI-22359 : Fix Serialization issues in Metric Definition Service (avijayan).


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9431d568
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9431d568
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9431d568

Branch: refs/heads/branch-3.0-ams
Commit: 9431d568ffa9095cca88656fbe27629db1b7be81
Parents: a42cbc5
Author: Aravindan Vijayan <av...@hortonworks.com>
Authored: Thu Nov 2 14:41:38 2017 -0700
Committer: Aravindan Vijayan <av...@hortonworks.com>
Committed: Thu Nov 2 14:41:38 2017 -0700

----------------------------------------------------------------------
 .../src/main/resources/config.yml               |   4 +-
 .../app/AnomalyDetectionAppConfig.scala         |  10 +-
 .../metrics/adservice/common/Season.scala       |   4 +-
 .../MetricCollectorConfiguration.scala          |  10 -
 .../MetricDefinitionServiceConfiguration.scala  |  34 +++
 .../MetricManagerServiceConfiguration.scala     |  34 ---
 .../db/PhoenixAnomalyStoreAccessor.scala        |   8 +-
 .../adservice/metadata/ADMetadataProvider.scala |  12 +-
 .../adservice/metadata/MetricDefinition.scala   |  52 ++++-
 .../metadata/MetricDefinitionService.scala      |  64 ++++++
 .../metadata/MetricDefinitionServiceImpl.scala  | 211 +++++++++++++++++++
 .../metadata/MetricManagerService.scala         |  64 ------
 .../metadata/MetricManagerServiceImpl.scala     | 183 ----------------
 .../metadata/MetricSourceDefinition.scala       |  38 +---
 .../app/AnomalyDetectionAppConfigTest.scala     |   2 +-
 .../metrics/adservice/common/SeasonTest.scala   |   4 +-
 .../metadata/MetricDefinitionServiceTest.scala  | 130 ++++++++++++
 .../metadata/MetricManagerServiceTest.scala     | 130 ------------
 .../metadata/MetricSourceDefinitionTest.scala   |  11 +-
 19 files changed, 515 insertions(+), 490 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/resources/config.yml
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/resources/config.yml b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/resources/config.yml
index 6953745..920c50c 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/resources/config.yml
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/resources/config.yml
@@ -20,8 +20,8 @@ server:
 logging:
   type: external
 
-metricManagerService:
-  inputDefinitionDirectory: /etc/adservice/conf/input-definitions-directory
+metricDefinitionService:
+  inputDefinitionDirectory: /etc/ambari-metrics-anomaly-detection/conf
 
 metricsCollector:
   hostPortList: host1:6188,host2:6188

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfig.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfig.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfig.scala
index be8d027..c1ef0d1 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfig.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfig.scala
@@ -20,7 +20,7 @@ package org.apache.ambari.metrics.adservice.app
 
 import javax.validation.Valid
 
-import org.apache.ambari.metrics.adservice.configuration.{AdServiceConfiguration, HBaseConfiguration, MetricCollectorConfiguration, MetricManagerServiceConfiguration}
+import org.apache.ambari.metrics.adservice.configuration.{AdServiceConfiguration, HBaseConfiguration, MetricCollectorConfiguration, MetricDefinitionServiceConfiguration}
 
 import com.fasterxml.jackson.annotation.JsonProperty
 
@@ -35,7 +35,7 @@ class AnomalyDetectionAppConfig extends Configuration {
    Metric Definition Service configuration
     */
   @Valid
-  private val metricManagerServiceConfiguration = new MetricManagerServiceConfiguration
+  private val metricDefinitionServiceConfiguration = new MetricDefinitionServiceConfiguration
 
   @Valid
   private val metricCollectorConfiguration = new MetricCollectorConfiguration
@@ -53,9 +53,9 @@ class AnomalyDetectionAppConfig extends Configuration {
     HBaseConfiguration.getHBaseConf
   }
 
-  @JsonProperty("metricManagerService")
-  def getMetricManagerServiceConfiguration: MetricManagerServiceConfiguration = {
-    metricManagerServiceConfiguration
+  @JsonProperty("metricDefinitionService")
+  def getMetricDefinitionServiceConfiguration: MetricDefinitionServiceConfiguration = {
+    metricDefinitionServiceConfiguration
   }
 
   @JsonProperty("adQueryService")

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/common/Season.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/common/Season.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/common/Season.scala
index aba2587..f875e3b 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/common/Season.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/common/Season.scala
@@ -112,11 +112,11 @@ object Season {
     validSeasons.toList
   }
 
-  def serialize(season: Season) : String = {
+  def toJson(season: Season) : String = {
     mapper.writeValueAsString(season)
   }
 
-  def deserialize(seasonString: String) : Season = {
+  def fromJson(seasonString: String) : Season = {
     mapper.readValue[Season](seasonString)
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricCollectorConfiguration.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricCollectorConfiguration.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricCollectorConfiguration.scala
index 50a0b72..9418897 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricCollectorConfiguration.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricCollectorConfiguration.scala
@@ -39,14 +39,4 @@ class MetricCollectorConfiguration {
   @JsonProperty
   def getMetadataEndpoint: String = metadataEndpoint
 
-  @JsonProperty
-  def setHostPortList(hostPortList: String): Unit = {
-    this.hostPortList = hostPortList
-  }
-
-  @JsonProperty
-  def setMetadataEndpoint(metadataEndpoint: String): Unit = {
-    this.metadataEndpoint = metadataEndpoint
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricDefinitionServiceConfiguration.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricDefinitionServiceConfiguration.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricDefinitionServiceConfiguration.scala
new file mode 100644
index 0000000..b560713
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricDefinitionServiceConfiguration.scala
@@ -0,0 +1,34 @@
+/*
+ * 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.ambari.metrics.adservice.configuration
+
+import javax.validation.constraints.NotNull
+
+import com.fasterxml.jackson.annotation.JsonProperty
+
+/**
+  * Class to capture the Metric Definition Service configuration.
+  */
+class MetricDefinitionServiceConfiguration {
+
+  @NotNull
+  private val inputDefinitionDirectory: String = ""
+
+  @JsonProperty
+  def getInputDefinitionDirectory: String = inputDefinitionDirectory
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricManagerServiceConfiguration.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricManagerServiceConfiguration.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricManagerServiceConfiguration.scala
deleted file mode 100644
index e5960d5..0000000
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/configuration/MetricManagerServiceConfiguration.scala
+++ /dev/null
@@ -1,34 +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.ambari.metrics.adservice.configuration
-
-import javax.validation.constraints.NotNull
-
-import com.fasterxml.jackson.annotation.JsonProperty
-
-/**
-  * Class to capture the Metric Definition Service configuration.
-  */
-class MetricManagerServiceConfiguration {
-
-  @NotNull
-  private val inputDefinitionDirectory: String = ""
-
-  @JsonProperty
-  def getInputDefinitionDirectory: String = inputDefinitionDirectory
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/db/PhoenixAnomalyStoreAccessor.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/db/PhoenixAnomalyStoreAccessor.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/db/PhoenixAnomalyStoreAccessor.scala
index 1191e90..36aea21 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/db/PhoenixAnomalyStoreAccessor.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/db/PhoenixAnomalyStoreAccessor.scala
@@ -94,11 +94,11 @@ object PhoenixAnomalyStoreAccessor  {
           val timestamp: Long = rs.getLong("ANOMALY_TIMESTAMP")
           val metricValue: Double = rs.getDouble("METRIC_VALUE")
           val methodType: AnomalyDetectionMethod = AnomalyDetectionMethod.withName(rs.getString("METHOD_NAME"))
-          val season: Season = Season.deserialize(rs.getString("SEASONAL_INFO"))
+          val season: Season = Season.fromJson(rs.getString("SEASONAL_INFO"))
           val anomalyScore: Double = rs.getDouble("ANOMALY_SCORE")
           val modelSnapshot: String = rs.getString("MODEL_PARAMETERS")
 
-          val metricKey: MetricKey = null //MetricManager.getMetricKeyFromUuid(uuid)
+          val metricKey: MetricKey = null //MetricManager.getMetricKeyFromUuid(uuid) //TODO
           val anomalyInstance: SingleMetricAnomalyInstance = new PointInTimeAnomalyInstance(metricKey, timestamp,
             metricValue, methodType, anomalyScore, season, modelSnapshot)
           anomalies.+=(anomalyInstance)
@@ -111,11 +111,11 @@ object PhoenixAnomalyStoreAccessor  {
           val referenceStart: Long = rs.getLong("TEST_PERIOD_START")
           val referenceEnd: Long = rs.getLong("TEST_PERIOD_END")
           val methodType: AnomalyDetectionMethod = AnomalyDetectionMethod.withName(rs.getString("METHOD_NAME"))
-          val season: Season = Season.deserialize(rs.getString("SEASONAL_INFO"))
+          val season: Season = Season.fromJson(rs.getString("SEASONAL_INFO"))
           val anomalyScore: Double = rs.getDouble("ANOMALY_SCORE")
           val modelSnapshot: String = rs.getString("MODEL_PARAMETERS")
 
-          val metricKey: MetricKey = null //MetricManager.getMetricKeyFromUuid(uuid)
+          val metricKey: MetricKey = null //MetricManager.getMetricKeyFromUuid(uuid) //TODO
           val anomalyInstance: SingleMetricAnomalyInstance = TrendAnomalyInstance(metricKey,
             TimeRange(anomalyStart, anomalyEnd),
             TimeRange(referenceStart, referenceEnd),

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/ADMetadataProvider.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/ADMetadataProvider.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/ADMetadataProvider.scala
index 801c5f5..3bcf4b0 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/ADMetadataProvider.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/ADMetadataProvider.scala
@@ -56,11 +56,13 @@ class ADMetadataProvider extends MetricMetadataProvider {
     val metricKeySet: scala.collection.mutable.Set[MetricKey] = scala.collection.mutable.Set.empty[MetricKey]
 
     for (metricDef <- metricSourceDefinition.metricDefinitions) {
-      for (hostPort <- metricCollectorHostPorts) {
-        val metricKeys: Set[MetricKey] = getKeysFromMetricsCollector(hostPort + metricMetadataPath, metricDef)
-        if (metricKeys != null) {
-          keysMap += (metricDef -> metricKeys)
-          metricKeySet.++(metricKeys)
+      if (metricDef.isValid) { //Skip requesting metric keys for invalid definitions.
+        for (hostPort <- metricCollectorHostPorts) {
+          val metricKeys: Set[MetricKey] = getKeysFromMetricsCollector(hostPort + metricMetadataPath, metricDef)
+          if (metricKeys != null) {
+            keysMap += (metricDef -> metricKeys)
+            metricKeySet.++(metricKeys)
+          }
         }
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinition.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinition.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinition.scala
index 0a5e51f..036867b 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinition.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinition.scala
@@ -18,9 +18,12 @@
 
 package org.apache.ambari.metrics.adservice.metadata
 
+import org.apache.commons.lang3.StringUtils
 /*
    {
        "metric-name": "mem_free",
+       "appId" : "HOST",
+       "hosts" : ["h1","h2"],
        "metric-description" : "Free memory on a Host.",
        "troubleshooting-info" : "Sudden drop / hike in free memory on a host.",
        "static-threshold" : 10,
@@ -28,12 +31,33 @@ package org.apache.ambari.metrics.adservice.metadata
 }
  */
 
-case class MetricDefinition (metricName: String,
-                             appId: String,
-                             hosts: List[String],
-                             metricDescription: String,
-                             troubleshootingInfo: String,
-                             staticThreshold: Double)  {
+@SerialVersionUID(1002L)
+class MetricDefinition extends Serializable {
+
+  var metricName: String = _
+  var appId: String = _
+  var hosts: List[String] = List.empty[String]
+  var metricDescription: String = ""
+  var troubleshootingInfo: String = ""
+  var staticThreshold: Double = _
+
+  //A Metric definition is valid if we can resolve a metricName and appId (defined or inherited) at runtime)
+  private var valid : Boolean = true
+
+  def this(metricName: String,
+           appId: String,
+           hosts: List[String],
+           metricDescription: String,
+           troubleshootingInfo: String,
+           staticThreshold: Double) = {
+    this
+    this.metricName = metricName
+    this.appId = appId
+    this.hosts = hosts
+    this.metricDescription = metricDescription
+    this.troubleshootingInfo = troubleshootingInfo
+    this.staticThreshold = staticThreshold
+  }
 
   @Override
   override def equals(obj: scala.Any): Boolean = {
@@ -46,10 +70,20 @@ case class MetricDefinition (metricName: String,
     if (!(metricName == that.metricName))
       return false
 
-    if (!(appId == that.appId))
-      return false
+    if (StringUtils.isNotEmpty(appId)) {
+      appId == that.appId
+    }
+    else {
+      StringUtils.isEmpty(that.appId)
+    }
+  }
+
+  def isValid: Boolean = {
+    valid
+  }
 
-    true
+  def makeInvalid() : Unit = {
+    valid = false
   }
 }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionService.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionService.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionService.scala
new file mode 100644
index 0000000..635dc60
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionService.scala
@@ -0,0 +1,64 @@
+/*
+ * 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.ambari.metrics.adservice.metadata
+
+trait MetricDefinitionService {
+
+  /**
+    * Given a 'UUID', return the metric key associated with it.
+    * @param uuid UUID
+    * @return
+    */
+  def getMetricKeyFromUuid(uuid: Array[Byte]) : MetricKey
+
+  /**
+    * Given a component definition name, return the definition associated with it.
+    * @param name component definition name
+    * @return
+    */
+  def getDefinitionByName(name: String) : MetricSourceDefinition
+
+  /**
+    * Add a new definition.
+    * @param definition component definition JSON
+    * @return
+    */
+  def addDefinition(definition: MetricSourceDefinition) : Boolean
+
+  /**
+    * Update a component definition by name. Only definitions which were added by API can be modified through API.
+    * @param definition component definition name
+    * @return
+    */
+  def updateDefinition(definition: MetricSourceDefinition) : Boolean
+
+  /**
+    * Delete a component definition by name. Only definitions which were added by API can be deleted through API.
+    * @param name component definition name
+    * @return
+    */
+  def deleteDefinitionByName(name: String) : Boolean
+
+  /**
+    * Given an appId, return set of definitions that are tracked for that appId.
+    * @param appId component definition appId
+    * @return
+    */
+  def getDefinitionByAppId(appId: String) : List[MetricSourceDefinition]
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionServiceImpl.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionServiceImpl.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionServiceImpl.scala
new file mode 100644
index 0000000..ffa9944
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionServiceImpl.scala
@@ -0,0 +1,211 @@
+/*
+ * 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.ambari.metrics.adservice.metadata
+
+import org.apache.ambari.metrics.adservice.app.AnomalyDetectionAppConfig
+import org.apache.ambari.metrics.adservice.db.AdMetadataStoreAccessor
+
+import com.google.inject.{Inject, Singleton}
+
+@Singleton
+class MetricDefinitionServiceImpl extends MetricDefinitionService {
+
+  @Inject
+  var adMetadataStoreAccessor: AdMetadataStoreAccessor = _
+
+  var configuration: AnomalyDetectionAppConfig = _
+  var metricMetadataProvider: MetricMetadataProvider = _
+
+  var metricSourceDefinitionMap: Map[String, MetricSourceDefinition] = Map()
+  var metricKeys: Set[MetricKey] = Set.empty[MetricKey]
+  var metricDefinitionMetricKeyMap: Map[MetricDefinition, Set[MetricKey]] = Map()
+
+  @Inject
+  def this (anomalyDetectionAppConfig: AnomalyDetectionAppConfig) = {
+    this ()
+    //TODO : Create AD Metadata instance here (or inject)
+    configuration = anomalyDetectionAppConfig
+    initializeService()
+  }
+
+  def this (anomalyDetectionAppConfig: AnomalyDetectionAppConfig, adMetadataStoreAccessor: AdMetadataStoreAccessor) = {
+    this ()
+    //TODO : Create AD Metadata instance here (or inject). Pass in Schema information.
+    configuration = anomalyDetectionAppConfig
+    this.adMetadataStoreAccessor = adMetadataStoreAccessor
+    initializeService()
+  }
+
+  def initializeService() : Unit = {
+
+    //Create AD Metadata Schema
+    //TODO Make sure AD Metadata DB is initialized here.
+
+    //Initialize Metric Metadata Provider
+    metricMetadataProvider = new ADMetadataProvider(configuration.getMetricCollectorConfiguration)
+
+    loadMetricSourceDefinitions()
+  }
+
+  def loadMetricSourceDefinitions() : Unit = {
+
+    //Load definitions from metadata store
+    val definitionsFromStore: List[MetricSourceDefinition] = adMetadataStoreAccessor.getSavedInputDefinitions
+    for (definition <- definitionsFromStore) {
+      validateAndSanitizeMetricSourceDefinition(definition)
+    }
+
+    //Load definitions from configs
+    val definitionsFromConfig: List[MetricSourceDefinition] = getInputDefinitionsFromConfig
+    for (definition <- definitionsFromConfig) {
+      validateAndSanitizeMetricSourceDefinition(definition)
+    }
+
+    //Union the 2 sources, with DB taking precedence.
+    //Save new definition list to DB.
+    metricSourceDefinitionMap = metricSourceDefinitionMap.++(combineDefinitionSources(definitionsFromConfig, definitionsFromStore))
+
+    //Reach out to AMS Metadata and get Metric Keys. Pass in List<CD> and get back (Map<MD,Set<MK>>, Set<MK>)
+    for (definition <- metricSourceDefinitionMap.values) {
+      val (definitionKeyMap: Map[MetricDefinition, Set[MetricKey]], keys: Set[MetricKey])= metricMetadataProvider.getMetricKeysForDefinitions(definition)
+      metricDefinitionMetricKeyMap = metricDefinitionMetricKeyMap.++(definitionKeyMap)
+      metricKeys = metricKeys.++(keys)
+    }
+  }
+
+  def getMetricKeyFromUuid(uuid: Array[Byte]): MetricKey = {
+    var key: MetricKey = null
+    for (metricKey <- metricKeys) {
+      if (metricKey.uuid.sameElements(uuid)) {
+        key = metricKey
+      }
+    }
+    key
+  }
+
+  @Override
+  def getDefinitionByName(name: String): MetricSourceDefinition = {
+    metricSourceDefinitionMap.apply(name)
+  }
+
+  @Override
+  def addDefinition(definition: MetricSourceDefinition): Boolean = {
+    if (metricSourceDefinitionMap.contains(definition.definitionName)) {
+      return false
+    }
+    definition.definitionSource = MetricSourceDefinitionType.API
+
+    val success: Boolean = adMetadataStoreAccessor.saveInputDefinition(definition)
+    if (success) {
+      metricSourceDefinitionMap += definition.definitionName -> definition
+    }
+    success
+  }
+
+  @Override
+  def updateDefinition(definition: MetricSourceDefinition): Boolean = {
+    if (!metricSourceDefinitionMap.contains(definition.definitionName)) {
+      return false
+    }
+
+    if (metricSourceDefinitionMap.apply(definition.definitionName).definitionSource != MetricSourceDefinitionType.API) {
+      return false
+    }
+
+    val success: Boolean = adMetadataStoreAccessor.saveInputDefinition(definition)
+    if (success) {
+      metricSourceDefinitionMap += definition.definitionName -> definition
+    }
+    success
+  }
+
+  @Override
+  def deleteDefinitionByName(name: String): Boolean = {
+    if (!metricSourceDefinitionMap.contains(name)) {
+      return false
+    }
+
+    val definition : MetricSourceDefinition = metricSourceDefinitionMap.apply(name)
+    if (definition.definitionSource != MetricSourceDefinitionType.API) {
+      return false
+    }
+
+    val success: Boolean = adMetadataStoreAccessor.removeInputDefinition(name)
+    if (success) {
+      metricSourceDefinitionMap += definition.definitionName -> definition
+    }
+    success
+  }
+
+  @Override
+  def getDefinitionByAppId(appId: String): List[MetricSourceDefinition] = {
+
+    val defList : List[MetricSourceDefinition] = metricSourceDefinitionMap.values.toList
+    defList.filter(_.appId == appId)
+  }
+
+  def combineDefinitionSources(configDefinitions: List[MetricSourceDefinition], dbDefinitions: List[MetricSourceDefinition])
+  : Map[String, MetricSourceDefinition] = {
+
+    var combinedDefinitionMap: scala.collection.mutable.Map[String, MetricSourceDefinition] =
+      scala.collection.mutable.Map.empty[String, MetricSourceDefinition]
+
+    for (definitionFromDb <- dbDefinitions) {
+      combinedDefinitionMap(definitionFromDb.definitionName) = definitionFromDb
+    }
+
+    for (definition <- configDefinitions) {
+      if (!dbDefinitions.contains(definition)) {
+        adMetadataStoreAccessor.saveInputDefinition(definition)
+        combinedDefinitionMap(definition.definitionName) = definition
+      }
+    }
+    combinedDefinitionMap.toMap
+  }
+
+  def getInputDefinitionsFromConfig: List[MetricSourceDefinition] = {
+    val configDirectory = configuration.getMetricDefinitionServiceConfiguration.getInputDefinitionDirectory
+    InputMetricDefinitionParser.parseInputDefinitionsFromDirectory(configDirectory)
+  }
+
+  def setAdMetadataStoreAccessor (adMetadataStoreAccessor: AdMetadataStoreAccessor) : Unit = {
+    this.adMetadataStoreAccessor = adMetadataStoreAccessor
+  }
+
+  def validateAndSanitizeMetricSourceDefinition(metricSourceDefinition: MetricSourceDefinition): Unit = {
+    val sourceLevelAppId: String = metricSourceDefinition.appId
+    val sourceLevelHostList: List[String] = metricSourceDefinition.hosts
+
+    for (metricDef <- metricSourceDefinition.metricDefinitions.toList) {
+      if (metricDef.appId == null) {
+        if (sourceLevelAppId == null || sourceLevelAppId.isEmpty) {
+          metricDef.makeInvalid()
+        } else {
+          metricDef.appId = sourceLevelAppId
+        }
+      }
+
+      if (metricDef.isValid && metricDef.hosts.isEmpty) {
+        if (sourceLevelHostList != null && sourceLevelHostList.nonEmpty) {
+          metricDef.hosts = sourceLevelHostList
+        }
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerService.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerService.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerService.scala
deleted file mode 100644
index 12bd7e4..0000000
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerService.scala
+++ /dev/null
@@ -1,64 +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.ambari.metrics.adservice.metadata
-
-trait MetricManagerService {
-
-  /**
-    * Given a 'UUID', return the metric key associated with it.
-    * @param uuid UUID
-    * @return
-    */
-  def getMetricKeyFromUuid(uuid: Array[Byte]) : MetricKey
-
-  /**
-    * Given a component definition name, return the definition associated with it.
-    * @param name component definition name
-    * @return
-    */
-  def getDefinitionByName(name: String) : MetricSourceDefinition
-
-  /**
-    * Add a new definition.
-    * @param definition component definition JSON
-    * @return
-    */
-  def addDefinition(definition: MetricSourceDefinition) : Boolean
-
-  /**
-    * Update a component definition by name. Only definitions which were added by API can be modified through API.
-    * @param definition component definition name
-    * @return
-    */
-  def updateDefinition(definition: MetricSourceDefinition) : Boolean
-
-  /**
-    * Delete a component definition by name. Only definitions which were added by API can be deleted through API.
-    * @param name component definition name
-    * @return
-    */
-  def deleteDefinitionByName(name: String) : Boolean
-
-  /**
-    * Given an appId, return set of definitions that are tracked for that appId.
-    * @param appId component definition appId
-    * @return
-    */
-  def getDefinitionByAppId(appId: String) : List[MetricSourceDefinition]
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerServiceImpl.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerServiceImpl.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerServiceImpl.scala
deleted file mode 100644
index ce02775..0000000
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerServiceImpl.scala
+++ /dev/null
@@ -1,183 +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.ambari.metrics.adservice.metadata
-
-import org.apache.ambari.metrics.adservice.app.AnomalyDetectionAppConfig
-import org.apache.ambari.metrics.adservice.db.AdMetadataStoreAccessor
-
-import com.google.inject.{Inject, Singleton}
-
-@Singleton
-class MetricManagerServiceImpl extends MetricManagerService {
-
-  @Inject
-  var adMetadataStoreAccessor: AdMetadataStoreAccessor = _
-
-  var configuration: AnomalyDetectionAppConfig = _
-  var metricMetadataProvider: MetricMetadataProvider = _
-
-  var metricSourceDefinitionMap: Map[String, MetricSourceDefinition] = Map()
-  var metricKeys: Set[MetricKey] = Set.empty[MetricKey]
-  var metricDefinitionMetricKeyMap: Map[MetricDefinition, Set[MetricKey]] = Map()
-
-  @Inject
-  def this (anomalyDetectionAppConfig: AnomalyDetectionAppConfig) = {
-    this ()
-    //TODO : Create AD Metadata instance here (or inject)
-    configuration = anomalyDetectionAppConfig
-    initializeService()
-  }
-
-  def this (anomalyDetectionAppConfig: AnomalyDetectionAppConfig, adMetadataStoreAccessor: AdMetadataStoreAccessor) = {
-    this ()
-    //TODO : Create AD Metadata instance here (or inject). Pass in Schema information.
-    configuration = anomalyDetectionAppConfig
-    this.adMetadataStoreAccessor = adMetadataStoreAccessor
-    initializeService()
-  }
-
-  def initializeService() : Unit = {
-
-    //Create AD Metadata Schema
-    //TODO Make sure AD Metadata DB is initialized here.
-
-    //Initialize Metric Metadata Provider
-    metricMetadataProvider = new ADMetadataProvider(configuration.getMetricCollectorConfiguration)
-
-    loadMetricSourceDefinitions()
-  }
-
-  def loadMetricSourceDefinitions() : Unit = {
-
-    //Load definitions from metadata store
-    val definitionsFromStore: List[MetricSourceDefinition] = adMetadataStoreAccessor.getSavedInputDefinitions
-
-    //Load definitions from configs
-    val definitionsFromConfig: List[MetricSourceDefinition] = getInputDefinitionsFromConfig
-
-    //Union the 2 sources, with DB taking precedence.
-    //Save new definition list to DB.
-    metricSourceDefinitionMap = metricSourceDefinitionMap.++(combineDefinitionSources(definitionsFromConfig, definitionsFromStore))
-
-      //Reach out to AMS Metadata and get Metric Keys. Pass in List<CD> and get back Map<MD,Set<MK>>
-    for (definition <- metricSourceDefinitionMap.values) {
-      val (definitionKeyMap: Map[MetricDefinition, Set[MetricKey]], keys: Set[MetricKey])= metricMetadataProvider.getMetricKeysForDefinitions(definition)
-      metricDefinitionMetricKeyMap = metricDefinitionMetricKeyMap.++(definitionKeyMap)
-      metricKeys = metricKeys.++(keys)
-    }
-  }
-
-  def getMetricKeyFromUuid(uuid: Array[Byte]): MetricKey = {
-    var key: MetricKey = null
-    for (metricKey <- metricKeys) {
-      if (metricKey.uuid.sameElements(uuid)) {
-        key = metricKey
-      }
-    }
-    key
-  }
-
-  @Override
-  def getDefinitionByName(name: String): MetricSourceDefinition = {
-    metricSourceDefinitionMap.apply(name)
-  }
-
-  @Override
-  def addDefinition(definition: MetricSourceDefinition): Boolean = {
-    if (metricSourceDefinitionMap.contains(definition.definitionName)) {
-      return false
-    }
-    definition.definitionSource = MetricSourceDefinitionType.API
-
-    val success: Boolean = adMetadataStoreAccessor.saveInputDefinition(definition)
-    if (success) {
-      metricSourceDefinitionMap += definition.definitionName -> definition
-    }
-    success
-  }
-
-  @Override
-  def updateDefinition(definition: MetricSourceDefinition): Boolean = {
-    if (!metricSourceDefinitionMap.contains(definition.definitionName)) {
-      return false
-    }
-
-    if (metricSourceDefinitionMap.apply(definition.definitionName).definitionSource != MetricSourceDefinitionType.API) {
-      return false
-    }
-
-    val success: Boolean = adMetadataStoreAccessor.saveInputDefinition(definition)
-    if (success) {
-      metricSourceDefinitionMap += definition.definitionName -> definition
-    }
-    success
-  }
-
-  @Override
-  def deleteDefinitionByName(name: String): Boolean = {
-    if (!metricSourceDefinitionMap.contains(name)) {
-      return false
-    }
-
-    val definition : MetricSourceDefinition = metricSourceDefinitionMap.apply(name)
-    if (definition.definitionSource != MetricSourceDefinitionType.API) {
-      return false
-    }
-
-    val success: Boolean = adMetadataStoreAccessor.removeInputDefinition(name)
-    if (success) {
-      metricSourceDefinitionMap += definition.definitionName -> definition
-    }
-    success
-  }
-
-  @Override
-  def getDefinitionByAppId(appId: String): List[MetricSourceDefinition] = {
-
-    val defList : List[MetricSourceDefinition] = metricSourceDefinitionMap.values.toList
-    defList.filter(_.appId == appId)
-  }
-
-  def combineDefinitionSources(configDefinitions: List[MetricSourceDefinition], dbDefinitions: List[MetricSourceDefinition])
-  : Map[String, MetricSourceDefinition] = {
-
-    var combinedDefinitionMap: scala.collection.mutable.Map[String, MetricSourceDefinition] =
-      scala.collection.mutable.Map.empty[String, MetricSourceDefinition]
-
-    for (definitionFromDb <- dbDefinitions) {
-      combinedDefinitionMap(definitionFromDb.definitionName) = definitionFromDb
-    }
-
-    for (definition <- configDefinitions) {
-      if (!dbDefinitions.contains(definition)) {
-        adMetadataStoreAccessor.saveInputDefinition(definition)
-        combinedDefinitionMap(definition.definitionName) = definition
-      }
-    }
-    combinedDefinitionMap.toMap
-  }
-
-  def getInputDefinitionsFromConfig: List[MetricSourceDefinition] = {
-    val configDirectory = configuration.getMetricManagerServiceConfiguration.getInputDefinitionDirectory
-    InputMetricDefinitionParser.parseInputDefinitionsFromDirectory(configDirectory)
-  }
-
-  def setAdMetadataStoreAccessor (adMetadataStoreAccessor: AdMetadataStoreAccessor) : Unit = {
-    this.adMetadataStoreAccessor = adMetadataStoreAccessor
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinition.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinition.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinition.scala
index 60198e0..47b1499 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinition.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/main/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinition.scala
@@ -22,10 +22,6 @@ import javax.xml.bind.annotation.XmlRootElement
 import org.apache.ambari.metrics.adservice.metadata.MetricSourceDefinitionType.MetricSourceDefinitionType
 import org.apache.ambari.metrics.adservice.model.AnomalyType.AnomalyType
 
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.scala.DefaultScalaModule
-import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
-
 /*
 {
  "definition-name": "host-memory",
@@ -45,27 +41,10 @@ import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
 }
 */
 
-/*
-
-On Startup
-Read input definitions directory, parse the JSONs
-Create / Update the metric definitions in DB
-Convert metric definitions to Map<MetricKey, MetricDefinition>
-
-What to do want to have in memory?
-Map of Metric Key -> List<Component Definitions>
-
-What do we use metric definitions for?
-Anomaly GET - Associate definition information as well.
-Definition CRUD - Get definition given definition name
-Get set of metrics that are being tracked
-Return definition information for a metric key
-Given a metric definition name, return set of metrics.
-
-*/
 
+@SerialVersionUID(10001L)
 @XmlRootElement
-class MetricSourceDefinition {
+class MetricSourceDefinition extends Serializable{
 
   var definitionName: String = _
   var appId: String = _
@@ -103,17 +82,4 @@ class MetricSourceDefinition {
     val that = obj.asInstanceOf[MetricSourceDefinition]
     definitionName.equals(that.definitionName)
   }
-}
-
-object MetricSourceDefinition {
-  val mapper = new ObjectMapper() with ScalaObjectMapper
-  mapper.registerModule(DefaultScalaModule)
-
-  def serialize(definition: MetricSourceDefinition) : String = {
-    mapper.writeValueAsString(definition)
-  }
-
-  def deserialize(definitionString: String) : MetricSourceDefinition = {
-    mapper.readValue[MetricSourceDefinition](definitionString)
-  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfigTest.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfigTest.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfigTest.scala
index 8e3a949..104ccea 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfigTest.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/app/AnomalyDetectionAppConfigTest.scala
@@ -44,7 +44,7 @@ class AnomalyDetectionAppConfigTest extends FunSuite {
 
     assert(config.isInstanceOf[AnomalyDetectionAppConfig])
 
-    assert(config.getMetricManagerServiceConfiguration.getInputDefinitionDirectory == "/etc/adservice/conf/input-definitions-directory")
+    assert(config.getMetricDefinitionServiceConfiguration.getInputDefinitionDirectory == "/etc/ambari-metrics-anomaly-detection/conf")
 
     assert(config.getMetricCollectorConfiguration.getHostPortList == "host1:6188,host2:6188")
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/common/SeasonTest.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/common/SeasonTest.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/common/SeasonTest.scala
index 4d542e8..a823c73 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/common/SeasonTest.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/common/SeasonTest.scala
@@ -78,9 +78,9 @@ class SeasonTest extends FunSuite {
   test("testSerialize") {
     val season1 : Season = Season(Range(Calendar.MONDAY,Calendar.FRIDAY), Range(9,17))
 
-    val seasonString = Season.serialize(season1)
+    val seasonString = Season.toJson(season1)
 
-    val season2 : Season = Season.deserialize(seasonString)
+    val season2 : Season = Season.fromJson(seasonString)
     assert(season1 == season2)
 
     val season3 : Season = Season(Range(Calendar.MONDAY,Calendar.THURSDAY), Range(9,17))

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionServiceTest.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionServiceTest.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionServiceTest.scala
new file mode 100644
index 0000000..d3454f2
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricDefinitionServiceTest.scala
@@ -0,0 +1,130 @@
+/**
+  * 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.ambari.metrics.adservice.metadata
+
+import org.apache.ambari.metrics.adservice.app.AnomalyDetectionAppConfig
+import org.apache.ambari.metrics.adservice.db.AdMetadataStoreAccessor
+import org.easymock.EasyMock.{anyObject, expect, expectLastCall, replay}
+import org.scalatest.FunSuite
+import org.scalatest.easymock.EasyMockSugar
+
+class MetricDefinitionServiceTest extends FunSuite {
+
+  test("testAddDefinition") {
+
+    val definitions : scala.collection.mutable.MutableList[MetricSourceDefinition] = scala.collection.mutable.MutableList.empty[MetricSourceDefinition]
+
+    for (i <- 1 to 3) {
+      val msd1 : MetricSourceDefinition = new MetricSourceDefinition("TestDefinition" + i, "testAppId", MetricSourceDefinitionType.API)
+      definitions.+=(msd1)
+    }
+
+    val newDef : MetricSourceDefinition = new MetricSourceDefinition("NewDefinition", "testAppId", MetricSourceDefinitionType.API)
+
+    val adMetadataStoreAccessor: AdMetadataStoreAccessor = EasyMockSugar.niceMock[AdMetadataStoreAccessor]
+    expect(adMetadataStoreAccessor.getSavedInputDefinitions).andReturn(definitions.toList).once()
+    expect(adMetadataStoreAccessor.saveInputDefinition(newDef)).andReturn(true).once()
+    replay(adMetadataStoreAccessor)
+
+    val metricDefinitionService: MetricDefinitionServiceImpl = new MetricDefinitionServiceImpl(new AnomalyDetectionAppConfig, adMetadataStoreAccessor)
+
+    metricDefinitionService.setAdMetadataStoreAccessor(adMetadataStoreAccessor)
+
+    metricDefinitionService.addDefinition(newDef)
+
+    assert(metricDefinitionService.metricSourceDefinitionMap.size == 4)
+    assert(metricDefinitionService.metricSourceDefinitionMap.get("testDefinition") != null)
+  }
+
+  test("testGetDefinitionByName") {
+    val definitions : scala.collection.mutable.MutableList[MetricSourceDefinition] = scala.collection.mutable.MutableList.empty[MetricSourceDefinition]
+
+    for (i <- 1 to 3) {
+      val msd1 : MetricSourceDefinition = new MetricSourceDefinition("TestDefinition" + i, "testAppId", MetricSourceDefinitionType.API)
+      definitions.+=(msd1)
+    }
+
+    val adMetadataStoreAccessor: AdMetadataStoreAccessor = EasyMockSugar.niceMock[AdMetadataStoreAccessor]
+    expect(adMetadataStoreAccessor.getSavedInputDefinitions).andReturn(definitions.toList).once()
+    replay(adMetadataStoreAccessor)
+
+    val metricDefinitionService: MetricDefinitionServiceImpl = new MetricDefinitionServiceImpl(new AnomalyDetectionAppConfig, adMetadataStoreAccessor)
+
+    metricDefinitionService.setAdMetadataStoreAccessor(adMetadataStoreAccessor)
+    for (i <- 1 to 3) {
+      val definition: MetricSourceDefinition = metricDefinitionService.getDefinitionByName("TestDefinition" + i)
+      assert(definition != null)
+    }
+  }
+
+  test("testGetDefinitionByAppId") {
+    val definitions : scala.collection.mutable.MutableList[MetricSourceDefinition] = scala.collection.mutable.MutableList.empty[MetricSourceDefinition]
+
+    for (i <- 1 to 3) {
+      var msd1 : MetricSourceDefinition = null
+      if (i == 2) {
+        msd1 = new MetricSourceDefinition("TestDefinition" + i, null, MetricSourceDefinitionType.API)
+      } else {
+        msd1 = new MetricSourceDefinition("TestDefinition" + i, "testAppId", MetricSourceDefinitionType.API)
+      }
+      definitions.+=(msd1)
+    }
+
+    val adMetadataStoreAccessor: AdMetadataStoreAccessor = EasyMockSugar.niceMock[AdMetadataStoreAccessor]
+    expect(adMetadataStoreAccessor.getSavedInputDefinitions).andReturn(definitions.toList).once()
+    replay(adMetadataStoreAccessor)
+
+    val metricDefinitionService: MetricDefinitionServiceImpl = new MetricDefinitionServiceImpl(new AnomalyDetectionAppConfig, adMetadataStoreAccessor)
+
+    metricDefinitionService.setAdMetadataStoreAccessor(adMetadataStoreAccessor)
+    val definitionsByAppId: List[MetricSourceDefinition] = metricDefinitionService.getDefinitionByAppId("testAppId")
+    assert(definitionsByAppId.size == 2)
+  }
+
+  test("testDeleteDefinitionByName") {
+    val definitions : scala.collection.mutable.MutableList[MetricSourceDefinition] = scala.collection.mutable.MutableList.empty[MetricSourceDefinition]
+
+    for (i <- 1 to 3) {
+      var msd1 : MetricSourceDefinition = null
+      if (i == 2) {
+        msd1 = new MetricSourceDefinition("TestDefinition" + i, null, MetricSourceDefinitionType.CONFIG)
+      } else {
+        msd1 = new MetricSourceDefinition("TestDefinition" + i, "testAppId", MetricSourceDefinitionType.API)
+      }
+      definitions.+=(msd1)
+    }
+
+    val adMetadataStoreAccessor: AdMetadataStoreAccessor = EasyMockSugar.niceMock[AdMetadataStoreAccessor]
+    expect(adMetadataStoreAccessor.getSavedInputDefinitions).andReturn(definitions.toList).once()
+    expect(adMetadataStoreAccessor.removeInputDefinition(anyObject[String])).andReturn(true).times(2)
+    replay(adMetadataStoreAccessor)
+
+    val metricDefinitionService: MetricDefinitionServiceImpl = new MetricDefinitionServiceImpl(new AnomalyDetectionAppConfig, adMetadataStoreAccessor)
+
+    metricDefinitionService.setAdMetadataStoreAccessor(adMetadataStoreAccessor)
+
+    var success: Boolean = metricDefinitionService.deleteDefinitionByName("TestDefinition1")
+    assert(success)
+    success = metricDefinitionService.deleteDefinitionByName("TestDefinition2")
+    assert(!success)
+    success = metricDefinitionService.deleteDefinitionByName("TestDefinition3")
+    assert(success)
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerServiceTest.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerServiceTest.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerServiceTest.scala
deleted file mode 100644
index 8e19a0f..0000000
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricManagerServiceTest.scala
+++ /dev/null
@@ -1,130 +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.ambari.metrics.adservice.metadata
-
-import org.apache.ambari.metrics.adservice.app.AnomalyDetectionAppConfig
-import org.apache.ambari.metrics.adservice.db.AdMetadataStoreAccessor
-import org.easymock.EasyMock.{anyObject, expect, expectLastCall, replay}
-import org.scalatest.FunSuite
-import org.scalatest.easymock.EasyMockSugar
-
-class MetricManagerServiceTest extends FunSuite {
-
-  test("testAddDefinition") {
-
-    val definitions : scala.collection.mutable.MutableList[MetricSourceDefinition] = scala.collection.mutable.MutableList.empty[MetricSourceDefinition]
-
-    for (i <- 1 to 3) {
-      val msd1 : MetricSourceDefinition = new MetricSourceDefinition("TestDefinition" + i, "testAppId", MetricSourceDefinitionType.API)
-      definitions.+=(msd1)
-    }
-
-    val newDef : MetricSourceDefinition = new MetricSourceDefinition("NewDefinition", "testAppId", MetricSourceDefinitionType.API)
-
-    val adMetadataStoreAccessor: AdMetadataStoreAccessor = EasyMockSugar.niceMock[AdMetadataStoreAccessor]
-    expect(adMetadataStoreAccessor.getSavedInputDefinitions).andReturn(definitions.toList).once()
-    expect(adMetadataStoreAccessor.saveInputDefinition(newDef)).andReturn(true).once()
-    replay(adMetadataStoreAccessor)
-
-    val metricManagerService: MetricManagerServiceImpl = new MetricManagerServiceImpl(new AnomalyDetectionAppConfig, adMetadataStoreAccessor)
-
-    metricManagerService.setAdMetadataStoreAccessor(adMetadataStoreAccessor)
-
-    metricManagerService.addDefinition(newDef)
-
-    assert(metricManagerService.metricSourceDefinitionMap.size == 4)
-    assert(metricManagerService.metricSourceDefinitionMap.get("testDefinition") != null)
-  }
-
-  test("testGetDefinitionByName") {
-    val definitions : scala.collection.mutable.MutableList[MetricSourceDefinition] = scala.collection.mutable.MutableList.empty[MetricSourceDefinition]
-
-    for (i <- 1 to 3) {
-      val msd1 : MetricSourceDefinition = new MetricSourceDefinition("TestDefinition" + i, "testAppId", MetricSourceDefinitionType.API)
-      definitions.+=(msd1)
-    }
-
-    val adMetadataStoreAccessor: AdMetadataStoreAccessor = EasyMockSugar.niceMock[AdMetadataStoreAccessor]
-    expect(adMetadataStoreAccessor.getSavedInputDefinitions).andReturn(definitions.toList).once()
-    replay(adMetadataStoreAccessor)
-
-    val metricManagerService: MetricManagerServiceImpl = new MetricManagerServiceImpl(new AnomalyDetectionAppConfig, adMetadataStoreAccessor)
-
-    metricManagerService.setAdMetadataStoreAccessor(adMetadataStoreAccessor)
-    for (i <- 1 to 3) {
-      val definition: MetricSourceDefinition = metricManagerService.getDefinitionByName("TestDefinition" + i)
-      assert(definition != null)
-    }
-  }
-
-  test("testGetDefinitionByAppId") {
-    val definitions : scala.collection.mutable.MutableList[MetricSourceDefinition] = scala.collection.mutable.MutableList.empty[MetricSourceDefinition]
-
-    for (i <- 1 to 3) {
-      var msd1 : MetricSourceDefinition = null
-      if (i == 2) {
-        msd1 = new MetricSourceDefinition("TestDefinition" + i, null, MetricSourceDefinitionType.API)
-      } else {
-        msd1 = new MetricSourceDefinition("TestDefinition" + i, "testAppId", MetricSourceDefinitionType.API)
-      }
-      definitions.+=(msd1)
-    }
-
-    val adMetadataStoreAccessor: AdMetadataStoreAccessor = EasyMockSugar.niceMock[AdMetadataStoreAccessor]
-    expect(adMetadataStoreAccessor.getSavedInputDefinitions).andReturn(definitions.toList).once()
-    replay(adMetadataStoreAccessor)
-
-    val metricManagerService: MetricManagerServiceImpl = new MetricManagerServiceImpl(new AnomalyDetectionAppConfig, adMetadataStoreAccessor)
-
-    metricManagerService.setAdMetadataStoreAccessor(adMetadataStoreAccessor)
-    val definitionsByAppId: List[MetricSourceDefinition] = metricManagerService.getDefinitionByAppId("testAppId")
-    assert(definitionsByAppId.size == 2)
-  }
-
-  test("testDeleteDefinitionByName") {
-    val definitions : scala.collection.mutable.MutableList[MetricSourceDefinition] = scala.collection.mutable.MutableList.empty[MetricSourceDefinition]
-
-    for (i <- 1 to 3) {
-      var msd1 : MetricSourceDefinition = null
-      if (i == 2) {
-        msd1 = new MetricSourceDefinition("TestDefinition" + i, null, MetricSourceDefinitionType.CONFIG)
-      } else {
-        msd1 = new MetricSourceDefinition("TestDefinition" + i, "testAppId", MetricSourceDefinitionType.API)
-      }
-      definitions.+=(msd1)
-    }
-
-    val adMetadataStoreAccessor: AdMetadataStoreAccessor = EasyMockSugar.niceMock[AdMetadataStoreAccessor]
-    expect(adMetadataStoreAccessor.getSavedInputDefinitions).andReturn(definitions.toList).once()
-    expect(adMetadataStoreAccessor.removeInputDefinition(anyObject[String])).andReturn(true).times(2)
-    replay(adMetadataStoreAccessor)
-
-    val metricManagerService: MetricManagerServiceImpl = new MetricManagerServiceImpl(new AnomalyDetectionAppConfig, adMetadataStoreAccessor)
-
-    metricManagerService.setAdMetadataStoreAccessor(adMetadataStoreAccessor)
-
-    var success: Boolean = metricManagerService.deleteDefinitionByName("TestDefinition1")
-    assert(success)
-    success = metricManagerService.deleteDefinitionByName("TestDefinition2")
-    assert(!success)
-    success = metricManagerService.deleteDefinitionByName("TestDefinition3")
-    assert(success)
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9431d568/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinitionTest.scala
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinitionTest.scala b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinitionTest.scala
index c4d639c..0149673 100644
--- a/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinitionTest.scala
+++ b/ambari-metrics/ambari-metrics-anomaly-detection-service/src/test/scala/org/apache/ambari/metrics/adservice/metadata/MetricSourceDefinitionTest.scala
@@ -17,6 +17,7 @@
 
 package org.apache.ambari.metrics.adservice.metadata
 
+import org.apache.commons.lang.SerializationUtils
 import org.scalatest.FunSuite
 
 class MetricSourceDefinitionTest extends FunSuite {
@@ -46,6 +47,10 @@ class MetricSourceDefinitionTest extends FunSuite {
     val msd1 : MetricSourceDefinition = new MetricSourceDefinition("testDefinition", "testAppId", MetricSourceDefinitionType.API)
     val msd2 : MetricSourceDefinition = new MetricSourceDefinition("testDefinition", "testAppId2", MetricSourceDefinitionType.API)
     assert(msd1 == msd2)
+
+    val msd3 : MetricSourceDefinition = new MetricSourceDefinition("testDefinition1", "testAppId", MetricSourceDefinitionType.API)
+    val msd4 : MetricSourceDefinition = new MetricSourceDefinition("testDefinition2", "testAppId2", MetricSourceDefinitionType.API)
+    assert(msd3 != msd4)
   }
 
   test("testRemoveMetricDefinition") {
@@ -61,10 +66,10 @@ class MetricSourceDefinitionTest extends FunSuite {
 
   test("serializeDeserialize") {
     val msd : MetricSourceDefinition = new MetricSourceDefinition("testDefinition", "testAppId", MetricSourceDefinitionType.API)
-    val msdString: String = MetricSourceDefinition.serialize(msd)
-    assert(msdString.nonEmpty)
+    val msdByteArray: Array[Byte] = SerializationUtils.serialize(msd)
+    assert(msdByteArray.nonEmpty)
 
-    val msd2: MetricSourceDefinition = MetricSourceDefinition.deserialize(msdString)
+    val msd2: MetricSourceDefinition = SerializationUtils.deserialize(msdByteArray).asInstanceOf[MetricSourceDefinition]
     assert(msd2 != null)
     assert(msd == msd2)