From 7fe7eaf5280dc249dd1f45eeb6db353352353fdc Mon Sep 17 00:00:00 2001 From: Jian Li Date: Mon, 31 Dec 2018 17:00:33 +0900 Subject: [PATCH] Add REST API for query/update/delete/enable/disable telemetry config 1. Add unit test for newly added REST APIs 2. Add codec and unit tests for TelemetryConfig 3. Split web package out from app package due to dep conflict Change-Id: I85f52b2a7d059622e98832843bc9613cb8befa98 --- .../web/OpenstackNodeWebResource.java | 2 +- apps/openstacktelemetry/BUILD | 1 + .../api}/DefaultFlowInfo.java | 31 ++- .../api}/DefaultStatsFlowRule.java | 3 +- .../api}/DefaultStatsInfo.java | 4 +- .../api}/DefaultTelemetryConfig.java | 2 +- .../api/TelemetryConfigAdminService.java | 7 + .../api}/DefaultFlowInfoTest.java | 4 +- .../api}/DefaultStatsFlowRuleTest.java | 3 +- .../api}/DefaultStatsInfoTest.java | 3 +- .../api}/DefaultTelemetryConfigTest.java | 2 +- apps/openstacktelemetry/app/BUILD | 10 +- .../TinaFlowInfoByteBufferCodec.java | 4 +- .../TinaMessageByteBufferCodec.java | 2 +- .../TinaStatsInfoByteBufferCodec.java | 4 +- .../codec/bytebuffer/package-info.java | 20 ++ .../OpensteckTelemetryViewMessageHandler.java | 2 +- .../impl/DistributedTelemetryConfigStore.java | 1 + .../impl/InfluxDbTelemetryManager.java | 2 +- .../impl/KafkaTelemetryManager.java | 9 +- .../impl/StatsFlowRuleManager.java | 3 + .../impl/TelemetryConfigManager.java | 10 + .../impl/XmlTelemetryConfigLoader.java | 16 +- .../src/main/resources/definitions/dummy.json | 2 - .../openstacktelemetry/impl/kafka-configs.xml | 4 +- .../TinaFlowInfoByteBufferCodecTest.java | 9 +- .../TinaStatsInfoByteBufferCodecTest.java | 7 +- .../DefaultGrpcTelemetryConfigTest.java | 2 +- .../DefaultInfluxDbTelemetryConfigTest.java | 2 +- .../DefaultKafkaTelemetryConfigTest.java | 2 +- .../DefaultPrometheusTelemetryConfigTest.java | 2 +- .../DefaultRestTelemetryConfigTest.java | 2 +- .../impl/DefaultInfluxRecordTest.java | 2 + .../DistributedTelemetryConfigStoreTest.java | 1 + apps/openstacktelemetry/web/BUILD | 19 ++ .../codec/rest}/FlowInfoJsonCodec.java | 4 +- .../codec/rest}/StatsFlowRuleJsonCodec.java | 31 ++- .../codec/rest}/StatsInfoJsonCodec.java | 4 +- .../codec/rest/TelemetryConfigJsonCodec.java | 131 +++++++++++ .../codec/rest}/package-info.java | 2 +- .../web/OpenstackTelemetryCodecRegister.java | 18 +- .../OpenstackTelemetryConfigWebResource.java | 212 +++++++++++++++++ .../web/OpenstackTelemetryWebApplication.java | 3 +- .../web/OpenstackTelemetryWebResource.java | 10 +- .../openstacktelemetry/web/package-info.java | 0 .../definitions/TelemetryConfig.json | 53 +++++ .../src/main/webapp/WEB-INF/web.xml | 0 .../codec/rest}/FlowInfoJsonCodecTest.java | 8 +- .../codec/rest}/FlowInfoJsonMatcher.java | 2 +- .../codec/rest}/StatsInfoJsonMatcher.java | 2 +- .../codec/rest/TelemetryConfigCodecTest.java | 175 ++++++++++++++ .../rest/TelemetryConfigJsonMatcher.java | 154 +++++++++++++ .../OpenstackTelemetryCodecRegisterTest.java | 11 +- ...enstackTelemetryConfigWebResourceTest.java | 217 ++++++++++++++++++ .../codec/rest/TelemetryConfig.json | 17 ++ .../openstack-telemetry-config-address.json | 5 + 56 files changed, 1162 insertions(+), 96 deletions(-) rename apps/openstacktelemetry/{app/src/main/java/org/onosproject/openstacktelemetry/impl => api/src/main/java/org/onosproject/openstacktelemetry/api}/DefaultFlowInfo.java (92%) rename apps/openstacktelemetry/{app/src/main/java/org/onosproject/openstacktelemetry/impl => api/src/main/java/org/onosproject/openstacktelemetry/api}/DefaultStatsFlowRule.java (98%) rename apps/openstacktelemetry/{app/src/main/java/org/onosproject/openstacktelemetry/impl => api/src/main/java/org/onosproject/openstacktelemetry/api}/DefaultStatsInfo.java (98%) rename apps/openstacktelemetry/{app/src/main/java/org/onosproject/openstacktelemetry/impl => api/src/main/java/org/onosproject/openstacktelemetry/api}/DefaultTelemetryConfig.java (99%) rename apps/openstacktelemetry/{app/src/test/java/org/onosproject/openstacktelemetry/impl => api/src/test/java/org/onosproject/openstacktelemetry/api}/DefaultFlowInfoTest.java (97%) rename apps/openstacktelemetry/{app/src/test/java/org/onosproject/openstacktelemetry/impl => api/src/test/java/org/onosproject/openstacktelemetry/api}/DefaultStatsFlowRuleTest.java (97%) rename apps/openstacktelemetry/{app/src/test/java/org/onosproject/openstacktelemetry/impl => api/src/test/java/org/onosproject/openstacktelemetry/api}/DefaultStatsInfoTest.java (97%) rename apps/openstacktelemetry/{app/src/test/java/org/onosproject/openstacktelemetry/impl => api/src/test/java/org/onosproject/openstacktelemetry/api}/DefaultTelemetryConfigTest.java (98%) rename apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/{ => bytebuffer}/TinaFlowInfoByteBufferCodec.java (97%) rename apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/{ => bytebuffer}/TinaMessageByteBufferCodec.java (97%) rename apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/{ => bytebuffer}/TinaStatsInfoByteBufferCodec.java (95%) create mode 100644 apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/package-info.java delete mode 100644 apps/openstacktelemetry/app/src/main/resources/definitions/dummy.json rename apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/{ => bytebuffer}/TinaFlowInfoByteBufferCodecTest.java (92%) rename apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/{ => bytebuffer}/TinaStatsInfoByteBufferCodecTest.java (90%) create mode 100644 apps/openstacktelemetry/web/BUILD rename apps/openstacktelemetry/{app/src/main/java/org/onosproject/openstacktelemetry/codec => web/src/main/java/org/onosproject/openstacktelemetry/codec/rest}/FlowInfoJsonCodec.java (98%) rename apps/openstacktelemetry/{app/src/main/java/org/onosproject/openstacktelemetry/codec => web/src/main/java/org/onosproject/openstacktelemetry/codec/rest}/StatsFlowRuleJsonCodec.java (80%) rename apps/openstacktelemetry/{app/src/main/java/org/onosproject/openstacktelemetry/codec => web/src/main/java/org/onosproject/openstacktelemetry/codec/rest}/StatsInfoJsonCodec.java (96%) create mode 100644 apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigJsonCodec.java rename apps/openstacktelemetry/{app/src/main/java/org/onosproject/openstacktelemetry/codec => web/src/main/java/org/onosproject/openstacktelemetry/codec/rest}/package-info.java (92%) rename apps/openstacktelemetry/{app => web}/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegister.java (80%) create mode 100644 apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryConfigWebResource.java rename apps/openstacktelemetry/{app => web}/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebApplication.java (88%) rename apps/openstacktelemetry/{app => web}/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebResource.java (94%) rename apps/openstacktelemetry/{app => web}/src/main/java/org/onosproject/openstacktelemetry/web/package-info.java (100%) create mode 100644 apps/openstacktelemetry/web/src/main/resources/definitions/TelemetryConfig.json rename apps/openstacktelemetry/{app => web}/src/main/webapp/WEB-INF/web.xml (100%) rename apps/openstacktelemetry/{app/src/test/java/org/onosproject/openstacktelemetry/codec => web/src/test/java/org/onosproject/openstacktelemetry/codec/rest}/FlowInfoJsonCodecTest.java (96%) rename apps/openstacktelemetry/{app/src/test/java/org/onosproject/openstacktelemetry/codec => web/src/test/java/org/onosproject/openstacktelemetry/codec/rest}/FlowInfoJsonMatcher.java (99%) rename apps/openstacktelemetry/{app/src/test/java/org/onosproject/openstacktelemetry/codec => web/src/test/java/org/onosproject/openstacktelemetry/codec/rest}/StatsInfoJsonMatcher.java (98%) create mode 100644 apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigCodecTest.java create mode 100644 apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigJsonMatcher.java rename apps/openstacktelemetry/{app => web}/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegisterTest.java (84%) create mode 100644 apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryConfigWebResourceTest.java create mode 100644 apps/openstacktelemetry/web/src/test/resources/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfig.json create mode 100644 apps/openstacktelemetry/web/src/test/resources/org/onosproject/openstacktelemetry/web/openstack-telemetry-config-address.json diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/web/OpenstackNodeWebResource.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/web/OpenstackNodeWebResource.java index 1b69f30e1d..0acdb88d1e 100644 --- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/web/OpenstackNodeWebResource.java +++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/web/OpenstackNodeWebResource.java @@ -101,7 +101,7 @@ public class OpenstackNodeWebResource extends AbstractWebResource { } /** - * Creates a set of openstack nodes' config from the JSON input stream. + * Updates a set of openstack nodes' config from the JSON input stream. * * @param input openstack nodes JSON input stream * @return 200 OK with the updated openstack node's config, 400 BAD_REQUEST diff --git a/apps/openstacktelemetry/BUILD b/apps/openstacktelemetry/BUILD index 8cbb47dd6f..5bd1683fd6 100644 --- a/apps/openstacktelemetry/BUILD +++ b/apps/openstacktelemetry/BUILD @@ -31,6 +31,7 @@ BUNDLES = [ "@com_google_code_gson_gson//jar", "//apps/openstacktelemetry/api:onos-apps-openstacktelemetry-api", "//apps/openstacktelemetry/app:onos-apps-openstacktelemetry-app", + "//apps/openstacktelemetry/web:onos-apps-openstacktelemetry-web", ] onos_app( diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultFlowInfo.java b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultFlowInfo.java similarity index 92% rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultFlowInfo.java rename to apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultFlowInfo.java index b0d3aad023..c0655e9cb1 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultFlowInfo.java +++ b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultFlowInfo.java @@ -13,21 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.impl; +package org.onosproject.openstacktelemetry.api; +import org.onlab.packet.IPv4; import org.onlab.packet.IpPrefix; import org.onlab.packet.MacAddress; import org.onlab.packet.TpPort; import org.onlab.packet.VlanId; import org.onosproject.net.DeviceId; -import org.onosproject.openstacktelemetry.api.FlowInfo; -import org.onosproject.openstacktelemetry.api.StatsInfo; import java.util.Objects; import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkNotNull; -import static org.onosproject.openstacktelemetry.util.OpenstackTelemetryUtil.getProtocolNameFromType; /** * Implementation class of FlowInfo. @@ -36,6 +34,11 @@ public final class DefaultFlowInfo implements FlowInfo { private static final String INGRESS_STATS = "Ingress Port :"; private static final String EGRESS_STATS = "Egress Port :"; + private static final String PROTOCOL_NAME_TCP = "tcp"; + private static final String PROTOCOL_NAME_UDP = "udp"; + private static final String PROTOCOL_NAME_ANY = "any"; + private static final int ARBITRARY_PROTOCOL = 0x0; + private final byte flowType; private final DeviceId deviceId; private final int inputInterfaceId; @@ -351,4 +354,24 @@ public final class DefaultFlowInfo implements FlowInfo { protocol, srcMac, dstMac, statsInfo); } } + + + /** + * Obtains protocol name from the protocol type. + * + * @param type transport protocol type + * @return transport protocol name + */ + private String getProtocolNameFromType(byte type) { + switch (type) { + case IPv4.PROTOCOL_TCP: + return PROTOCOL_NAME_TCP; + case IPv4.PROTOCOL_UDP: + return PROTOCOL_NAME_UDP; + case ARBITRARY_PROTOCOL: + return PROTOCOL_NAME_ANY; + default: + return PROTOCOL_NAME_ANY; + } + } } diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultStatsFlowRule.java b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultStatsFlowRule.java similarity index 98% rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultStatsFlowRule.java rename to apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultStatsFlowRule.java index 9ee84f8d3d..065ea63b27 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultStatsFlowRule.java +++ b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultStatsFlowRule.java @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.impl; +package org.onosproject.openstacktelemetry.api; import com.google.common.base.MoreObjects; import org.onlab.packet.IpPrefix; import org.onlab.packet.TpPort; -import org.onosproject.openstacktelemetry.api.StatsFlowRule; import java.util.Objects; diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultStatsInfo.java b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultStatsInfo.java similarity index 98% rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultStatsInfo.java rename to apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultStatsInfo.java index 6e085a2dd7..80ab0b92b8 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultStatsInfo.java +++ b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultStatsInfo.java @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.impl; - -import org.onosproject.openstacktelemetry.api.StatsInfo; +package org.onosproject.openstacktelemetry.api; import java.util.Objects; diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultTelemetryConfig.java b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultTelemetryConfig.java similarity index 99% rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultTelemetryConfig.java rename to apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultTelemetryConfig.java index d1304463cb..02c1e84171 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DefaultTelemetryConfig.java +++ b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/DefaultTelemetryConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.impl; +package org.onosproject.openstacktelemetry.api; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; diff --git a/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/TelemetryConfigAdminService.java b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/TelemetryConfigAdminService.java index 18ee89bf3e..c752f862dd 100644 --- a/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/TelemetryConfigAdminService.java +++ b/apps/openstacktelemetry/api/src/main/java/org/onosproject/openstacktelemetry/api/TelemetryConfigAdminService.java @@ -51,4 +51,11 @@ public interface TelemetryConfigAdminService extends TelemetryConfigService { * @param config telemetry configuration */ void updateTelemetryConfig(TelemetryConfig config); + + /** + * Removes an existing telemetry configuration with the given config name. + * + * @param name configuration name + */ + void removeTelemetryConfig(String name); } diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultFlowInfoTest.java b/apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultFlowInfoTest.java similarity index 97% rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultFlowInfoTest.java rename to apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultFlowInfoTest.java index 1d034151e2..0d49490ae8 100644 --- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultFlowInfoTest.java +++ b/apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultFlowInfoTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.impl; +package org.onosproject.openstacktelemetry.api; import com.google.common.testing.EqualsTester; import org.junit.Before; @@ -24,8 +24,6 @@ import org.onlab.packet.MacAddress; import org.onlab.packet.TpPort; import org.onlab.packet.VlanId; import org.onosproject.net.DeviceId; -import org.onosproject.openstacktelemetry.api.FlowInfo; -import org.onosproject.openstacktelemetry.api.StatsInfo; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultStatsFlowRuleTest.java b/apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultStatsFlowRuleTest.java similarity index 97% rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultStatsFlowRuleTest.java rename to apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultStatsFlowRuleTest.java index 54140dcd71..cadcd87f00 100644 --- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultStatsFlowRuleTest.java +++ b/apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultStatsFlowRuleTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.impl; +package org.onosproject.openstacktelemetry.api; import com.google.common.testing.EqualsTester; import org.junit.Before; @@ -21,7 +21,6 @@ import org.junit.Test; import org.onlab.packet.IpAddress; import org.onlab.packet.IpPrefix; import org.onlab.packet.TpPort; -import org.onosproject.openstacktelemetry.api.StatsFlowRule; import static org.junit.Assert.assertEquals; import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultStatsInfoTest.java b/apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultStatsInfoTest.java similarity index 97% rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultStatsInfoTest.java rename to apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultStatsInfoTest.java index bfe37454ac..9224374dd9 100644 --- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultStatsInfoTest.java +++ b/apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultStatsInfoTest.java @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.impl; +package org.onosproject.openstacktelemetry.api; import com.google.common.testing.EqualsTester; import org.junit.Before; import org.junit.Test; -import org.onosproject.openstacktelemetry.api.StatsInfo; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultTelemetryConfigTest.java b/apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultTelemetryConfigTest.java similarity index 98% rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultTelemetryConfigTest.java rename to apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultTelemetryConfigTest.java index 637f9fc167..6734cfa785 100644 --- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultTelemetryConfigTest.java +++ b/apps/openstacktelemetry/api/src/test/java/org/onosproject/openstacktelemetry/api/DefaultTelemetryConfigTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.impl; +package org.onosproject.openstacktelemetry.api; import com.google.common.collect.Maps; import com.google.common.testing.EqualsTester; diff --git a/apps/openstacktelemetry/app/BUILD b/apps/openstacktelemetry/app/BUILD index a0a9778212..91fd5aa0fb 100644 --- a/apps/openstacktelemetry/app/BUILD +++ b/apps/openstacktelemetry/app/BUILD @@ -1,4 +1,4 @@ -COMPILE_DEPS = CORE_DEPS + JACKSON + KRYO + REST + CLI + [ +COMPILE_DEPS = CORE_DEPS + JACKSON + KRYO + CLI + REST + [ "@kafka_clients//jar", "@jersey_client//jar", "@influxdb_java//jar", @@ -20,19 +20,13 @@ COMPILE_DEPS = CORE_DEPS + JACKSON + KRYO + REST + CLI + [ "//apps/openstacktelemetry/api:onos-apps-openstacktelemetry-api", ] -TEST_DEPS = TEST_ADAPTERS + TEST_REST + [ +TEST_DEPS = TEST_ADAPTERS + [ "//core/api:onos-api-tests", "//core/common:onos-core-common-tests", - "//web/api:onos-rest-tests", ] osgi_jar_with_tests( - api_description = "OpenStack Network Telemetry REST API", - api_package = "org.onosproject.openstacktelemetry.web", - api_title = "OpenStack Network Telemetry REST API", - api_version = "1.0", karaf_command_packages = ["org.onosproject.openstacktelemetry.cli"], test_deps = TEST_DEPS, - web_context = "/onos/openstacktelemetry", deps = COMPILE_DEPS, ) diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaFlowInfoByteBufferCodec.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodec.java similarity index 97% rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaFlowInfoByteBufferCodec.java rename to apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodec.java index 2ee625fbb5..759dd5abfe 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaFlowInfoByteBufferCodec.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodec.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.codec; +package org.onosproject.openstacktelemetry.codec.bytebuffer; import org.onlab.packet.IpAddress; import org.onlab.packet.IpAddress.Version; @@ -25,7 +25,7 @@ import org.onosproject.net.DeviceId; import org.onosproject.openstacktelemetry.api.ByteBufferCodec; import org.onosproject.openstacktelemetry.api.FlowInfo; import org.onosproject.openstacktelemetry.api.StatsInfo; -import org.onosproject.openstacktelemetry.impl.DefaultFlowInfo; +import org.onosproject.openstacktelemetry.api.DefaultFlowInfo; import java.nio.ByteBuffer; diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaMessageByteBufferCodec.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaMessageByteBufferCodec.java similarity index 97% rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaMessageByteBufferCodec.java rename to apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaMessageByteBufferCodec.java index 2be5f3e051..514bc2352d 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaMessageByteBufferCodec.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaMessageByteBufferCodec.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.codec; +package org.onosproject.openstacktelemetry.codec.bytebuffer; import org.onosproject.openstacktelemetry.api.FlowInfo; import org.onosproject.openstacktelemetry.api.TelemetryCodec; diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaStatsInfoByteBufferCodec.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodec.java similarity index 95% rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaStatsInfoByteBufferCodec.java rename to apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodec.java index ce3faa8c8b..456dc72cda 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/TinaStatsInfoByteBufferCodec.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodec.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.openstacktelemetry.codec; +package org.onosproject.openstacktelemetry.codec.bytebuffer; import org.onosproject.openstacktelemetry.api.ByteBufferCodec; import org.onosproject.openstacktelemetry.api.StatsInfo; -import org.onosproject.openstacktelemetry.impl.DefaultStatsInfo; +import org.onosproject.openstacktelemetry.api.DefaultStatsInfo; import java.nio.ByteBuffer; diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/package-info.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/package-info.java new file mode 100644 index 0000000000..b8ef80a460 --- /dev/null +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementations of the codec broker and openstack telemetry entity codecs. + */ +package org.onosproject.openstacktelemetry.codec.bytebuffer; \ No newline at end of file diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/gui/OpensteckTelemetryViewMessageHandler.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/gui/OpensteckTelemetryViewMessageHandler.java index dcb7082ae7..f6d9bdd454 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/gui/OpensteckTelemetryViewMessageHandler.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/gui/OpensteckTelemetryViewMessageHandler.java @@ -30,7 +30,7 @@ import org.onosproject.net.host.HostService; import org.onosproject.openstacktelemetry.api.FlowInfo; import org.onosproject.openstacktelemetry.api.StatsFlowRule; import org.onosproject.openstacktelemetry.api.StatsFlowRuleAdminService; -import org.onosproject.openstacktelemetry.impl.DefaultStatsFlowRule; +import org.onosproject.openstacktelemetry.api.DefaultStatsFlowRule; import org.onosproject.ui.RequestHandler; import org.onosproject.ui.UiConnection; import org.onosproject.ui.UiMessageHandler; diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DistributedTelemetryConfigStore.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DistributedTelemetryConfigStore.java index 8fc31a6c61..d066d859d0 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DistributedTelemetryConfigStore.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/DistributedTelemetryConfigStore.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableSet; import org.onlab.util.KryoNamespace; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; +import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig; import org.onosproject.openstacktelemetry.api.TelemetryConfigEvent; import org.onosproject.openstacktelemetry.api.TelemetryConfigProvider; import org.onosproject.openstacktelemetry.api.TelemetryConfigStore; diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/InfluxDbTelemetryManager.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/InfluxDbTelemetryManager.java index 962779a4b7..38dd2b8af9 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/InfluxDbTelemetryManager.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/InfluxDbTelemetryManager.java @@ -201,7 +201,7 @@ public class InfluxDbTelemetryManager implements InfluxDbTelemetryAdminService { InfluxDB producer = InfluxDBFactory.connect(influxDbServerBuilder.toString(), influxDbConfig.username(), influxDbConfig.password()); - producers.put(config.name(), producer); + producers.put(name, producer); createDB(producer, influxDbConfig.database()); } diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/KafkaTelemetryManager.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/KafkaTelemetryManager.java index 152bfde2a1..06936cadac 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/KafkaTelemetryManager.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/KafkaTelemetryManager.java @@ -54,8 +54,6 @@ public class KafkaTelemetryManager implements KafkaTelemetryAdminService { private final Logger log = LoggerFactory.getLogger(getClass()); - private static final String CODEC_PREFIX = "org.onosproject.openstacktelemetry.codec."; - private static final String BOOTSTRAP_SERVERS = "bootstrap.servers"; private static final String RETRIES = "retries"; private static final String ACKS = "acks"; @@ -102,11 +100,10 @@ public class KafkaTelemetryManager implements KafkaTelemetryAdminService { Set> futureSet = Sets.newHashSet(); producers.forEach((k, v) -> { TelemetryConfig config = telemetryConfigService.getConfig(k); - KafkaTelemetryConfig kafkaConfig = - fromTelemetryConfig(config); + KafkaTelemetryConfig kafkaConfig = fromTelemetryConfig(config); try { - Class codecClazz = Class.forName(CODEC_PREFIX + kafkaConfig.codec()); + Class codecClazz = Class.forName(kafkaConfig.codec()); TelemetryCodec codec = (TelemetryCodec) codecClazz.newInstance(); ByteBuffer buffer = codec.encode(flowInfos); @@ -148,7 +145,7 @@ public class KafkaTelemetryManager implements KafkaTelemetryAdminService { prop.put(KEY_SERIALIZER, kafkaConfig.keySerializer()); prop.put(VALUE_SERIALIZER, kafkaConfig.valueSerializer()); - producers.put(config.name(), new KafkaProducer<>(prop)); + producers.put(name, new KafkaProducer<>(prop)); } } diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/StatsFlowRuleManager.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/StatsFlowRuleManager.java index 3d9f577e84..30faac7665 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/StatsFlowRuleManager.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/StatsFlowRuleManager.java @@ -57,6 +57,9 @@ import org.onosproject.openstacknetworking.api.InstancePortService; import org.onosproject.openstacknetworking.api.OpenstackNetworkService; import org.onosproject.openstacknode.api.OpenstackNode; import org.onosproject.openstacknode.api.OpenstackNodeService; +import org.onosproject.openstacktelemetry.api.DefaultFlowInfo; +import org.onosproject.openstacktelemetry.api.DefaultStatsFlowRule; +import org.onosproject.openstacktelemetry.api.DefaultStatsInfo; import org.onosproject.openstacktelemetry.api.FlowInfo; import org.onosproject.openstacktelemetry.api.OpenstackTelemetryService; import org.onosproject.openstacktelemetry.api.StatsFlowRule; diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/TelemetryConfigManager.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/TelemetryConfigManager.java index 3ae2504b1b..9832ad3801 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/TelemetryConfigManager.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/TelemetryConfigManager.java @@ -23,6 +23,7 @@ import org.onosproject.cluster.NodeId; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.event.ListenerRegistry; +import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig; import org.onosproject.openstacktelemetry.api.TelemetryConfigAdminService; import org.onosproject.openstacktelemetry.api.TelemetryConfigEvent; import org.onosproject.openstacktelemetry.api.TelemetryConfigListener; @@ -74,6 +75,7 @@ public class TelemetryConfigManager private static final String ERR_NULL_CONFIG = "Telemetry config cannot be null"; private static final String NO_CONFIG = "Telemetry config not found"; + private static final String ERR_NULL_CONFIG_NAME = "Telemetry config name cannot be null"; private static final KryoNamespace SERIALIZER_TELEMETRY_CONFIG = KryoNamespace.newBuilder() @@ -174,6 +176,14 @@ public class TelemetryConfigManager log.info(String.format(MSG_TELEMETRY_CONFIG, config.name(), MSG_UPDATED)); } + @Override + public void removeTelemetryConfig(String name) { + checkNotNull(name, ERR_NULL_CONFIG_NAME); + + telemetryConfigStore.removeTelemetryConfig(name); + log.info(String.format(MSG_TELEMETRY_CONFIG, name, MSG_REMOVED)); + } + @Override public TelemetryConfig getConfig(String name) { return nullIsNotFound(telemetryConfigStore.telemetryConfig(name), NO_CONFIG); diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/XmlTelemetryConfigLoader.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/XmlTelemetryConfigLoader.java index 39a5df09ea..c9c6e9f90d 100644 --- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/XmlTelemetryConfigLoader.java +++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/impl/XmlTelemetryConfigLoader.java @@ -21,6 +21,7 @@ import com.google.common.collect.Maps; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.XMLConfiguration; +import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig; import org.onosproject.openstacktelemetry.api.config.TelemetryConfig; import java.io.IOException; @@ -45,8 +46,8 @@ import static org.onosproject.openstacktelemetry.api.config.TelemetryConfig.Conf *

*
  *     <configs>
- *         <config name=“...” [manufacturer="..." swVersion="..."]>
- *            [<property name=“key”>value</key>]
+ *         <config name="..." [manufacturer="..." swVersion="..."]>
+ *            [<property name="key">value</key>]
  *            ...
  *        </config>
  *        ...
@@ -203,10 +204,16 @@ public class XmlTelemetryConfigLoader {
         ImmutableMap.Builder properties = ImmutableMap.builder();
 
         // note that, we only allow the inheritance from single source
-        Map parentConfigs = Maps.newHashMap();
+        final Map parentConfigs = Maps.newHashMap();
         if (!parents.isEmpty()) {
             TelemetryConfig parent = parents.get(0);
-            parentConfigs = parent.properties();
+            parent.properties().forEach(parentConfigs::put);
+        }
+
+        for (HierarchicalConfiguration b : config.configurationsAt(PROPERTY)) {
+            if (parentConfigs.keySet().contains(b.getString(NAME))) {
+                parentConfigs.remove(b.getString(NAME));
+            }
         }
 
         properties.putAll(parentConfigs);
@@ -214,6 +221,7 @@ public class XmlTelemetryConfigLoader {
         for (HierarchicalConfiguration b : config.configurationsAt(PROPERTY)) {
             properties.put(b.getString(NAME), (String) b.getRootNode().getValue());
         }
+
         return properties.build();
     }
 }
diff --git a/apps/openstacktelemetry/app/src/main/resources/definitions/dummy.json b/apps/openstacktelemetry/app/src/main/resources/definitions/dummy.json
deleted file mode 100644
index 7a73a41bfd..0000000000
--- a/apps/openstacktelemetry/app/src/main/resources/definitions/dummy.json
+++ /dev/null
@@ -1,2 +0,0 @@
-{
-}
\ No newline at end of file
diff --git a/apps/openstacktelemetry/app/src/main/resources/org/onosproject/openstacktelemetry/impl/kafka-configs.xml b/apps/openstacktelemetry/app/src/main/resources/org/onosproject/openstacktelemetry/impl/kafka-configs.xml
index 7429ac2845..48623b6621 100644
--- a/apps/openstacktelemetry/app/src/main/resources/org/onosproject/openstacktelemetry/impl/kafka-configs.xml
+++ b/apps/openstacktelemetry/app/src/main/resources/org/onosproject/openstacktelemetry/impl/kafka-configs.xml
@@ -34,6 +34,8 @@
         
         sona.flow
         flowdata
-        TinaMessageByteBufferCodec
+        
+            org.onosproject.openstacktelemetry.codec.bytebuffer.TinaMessageByteBufferCodec
+        
     
 
\ No newline at end of file
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/TinaFlowInfoByteBufferCodecTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodecTest.java
similarity index 92%
rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/TinaFlowInfoByteBufferCodecTest.java
rename to apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodecTest.java
index 8f4af77b97..b1f48e4b49 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/TinaFlowInfoByteBufferCodecTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodecTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.openstacktelemetry.codec;
+package org.onosproject.openstacktelemetry.codec.bytebuffer;
 
 import com.google.common.testing.EqualsTester;
 import org.junit.Before;
@@ -24,10 +24,10 @@ import org.onlab.packet.MacAddress;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
 import org.onosproject.net.DeviceId;
+import org.onosproject.openstacktelemetry.api.DefaultFlowInfo;
+import org.onosproject.openstacktelemetry.api.DefaultStatsInfo;
 import org.onosproject.openstacktelemetry.api.FlowInfo;
 import org.onosproject.openstacktelemetry.api.StatsInfo;
-import org.onosproject.openstacktelemetry.impl.DefaultFlowInfo;
-import org.onosproject.openstacktelemetry.impl.DefaultStatsInfo;
 
 import java.nio.ByteBuffer;
 
@@ -52,8 +52,7 @@ public final class TinaFlowInfoByteBufferCodecTest {
     private static final MacAddress DST_MAC_ADDRESS = MacAddress.valueOf("FF:EE:DD:CC:BB:AA");
 
     private FlowInfo info;
-    private final TinaFlowInfoByteBufferCodec codec =
-            new TinaFlowInfoByteBufferCodec();
+    private final TinaFlowInfoByteBufferCodec codec = new TinaFlowInfoByteBufferCodec();
 
     /**
      * Initial setup for this unit test.
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/TinaStatsInfoByteBufferCodecTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodecTest.java
similarity index 90%
rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/TinaStatsInfoByteBufferCodecTest.java
rename to apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodecTest.java
index f32e5bbcdb..d217aea34a 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/TinaStatsInfoByteBufferCodecTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodecTest.java
@@ -13,13 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.openstacktelemetry.codec;
+package org.onosproject.openstacktelemetry.codec.bytebuffer;
 
 import com.google.common.testing.EqualsTester;
 import org.junit.Before;
 import org.junit.Test;
+import org.onosproject.openstacktelemetry.api.DefaultStatsInfo;
 import org.onosproject.openstacktelemetry.api.StatsInfo;
-import org.onosproject.openstacktelemetry.impl.DefaultStatsInfo;
 
 import java.nio.ByteBuffer;
 
@@ -39,8 +39,7 @@ public class TinaStatsInfoByteBufferCodecTest {
     private static final short DROP_PACKETS = 30000;
 
     private StatsInfo info;
-    private final TinaStatsInfoByteBufferCodec codec =
-                                            new TinaStatsInfoByteBufferCodec();
+    private final TinaStatsInfoByteBufferCodec codec = new TinaStatsInfoByteBufferCodec();
 
     /**
      * Initial setup for this unit test.
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultGrpcTelemetryConfigTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultGrpcTelemetryConfigTest.java
index c56247f8e0..89fc1d0533 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultGrpcTelemetryConfigTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultGrpcTelemetryConfigTest.java
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.onosproject.openstacktelemetry.api.config.GrpcTelemetryConfig;
 import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
-import org.onosproject.openstacktelemetry.impl.DefaultTelemetryConfig;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
 
 import java.util.Map;
 
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultInfluxDbTelemetryConfigTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultInfluxDbTelemetryConfigTest.java
index cd4a9737f3..9f8401536c 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultInfluxDbTelemetryConfigTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultInfluxDbTelemetryConfigTest.java
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.onosproject.openstacktelemetry.api.config.InfluxDbTelemetryConfig;
 import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
-import org.onosproject.openstacktelemetry.impl.DefaultTelemetryConfig;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
 
 import java.util.Map;
 
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultKafkaTelemetryConfigTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultKafkaTelemetryConfigTest.java
index ba9b34ba60..999bcf16db 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultKafkaTelemetryConfigTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultKafkaTelemetryConfigTest.java
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.onosproject.openstacktelemetry.api.config.KafkaTelemetryConfig;
 import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
-import org.onosproject.openstacktelemetry.impl.DefaultTelemetryConfig;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
 
 import java.util.Map;
 
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultPrometheusTelemetryConfigTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultPrometheusTelemetryConfigTest.java
index de94f8306e..4a89b74a74 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultPrometheusTelemetryConfigTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultPrometheusTelemetryConfigTest.java
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.onosproject.openstacktelemetry.api.config.PrometheusTelemetryConfig;
 import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
-import org.onosproject.openstacktelemetry.impl.DefaultTelemetryConfig;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
 
 import java.util.Map;
 
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultRestTelemetryConfigTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultRestTelemetryConfigTest.java
index c78bb63383..28b84650ec 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultRestTelemetryConfigTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/config/DefaultRestTelemetryConfigTest.java
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.onosproject.openstacktelemetry.api.config.RestTelemetryConfig;
 import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
-import org.onosproject.openstacktelemetry.impl.DefaultTelemetryConfig;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
 
 import java.util.Map;
 
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultInfluxRecordTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultInfluxRecordTest.java
index 866e34d76c..da693803f4 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultInfluxRecordTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DefaultInfluxRecordTest.java
@@ -25,6 +25,8 @@ import org.onlab.packet.MacAddress;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
 import org.onosproject.net.DeviceId;
+import org.onosproject.openstacktelemetry.api.DefaultFlowInfo;
+import org.onosproject.openstacktelemetry.api.DefaultStatsInfo;
 import org.onosproject.openstacktelemetry.api.FlowInfo;
 import org.onosproject.openstacktelemetry.api.InfluxRecord;
 import org.onosproject.openstacktelemetry.api.StatsInfo;
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DistributedTelemetryConfigStoreTest.java b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DistributedTelemetryConfigStoreTest.java
index 511fa6ddb5..85f6b413f9 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DistributedTelemetryConfigStoreTest.java
+++ b/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/impl/DistributedTelemetryConfigStoreTest.java
@@ -22,6 +22,7 @@ import org.junit.Test;
 import org.onosproject.TestApplicationId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
 import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
 import org.onosproject.openstacktelemetry.api.config.TelemetryConfig.ConfigType;
 import org.onosproject.store.service.TestStorageService;
diff --git a/apps/openstacktelemetry/web/BUILD b/apps/openstacktelemetry/web/BUILD
new file mode 100644
index 0000000000..a677d58fbb
--- /dev/null
+++ b/apps/openstacktelemetry/web/BUILD
@@ -0,0 +1,19 @@
+COMPILE_DEPS = CORE_DEPS + JACKSON + KRYO + REST + [
+    "//apps/openstacktelemetry/api:onos-apps-openstacktelemetry-api",
+]
+
+TEST_DEPS = TEST_ADAPTERS + TEST_REST + [
+    "//core/api:onos-api-tests",
+    "//core/common:onos-core-common-tests",
+    "//web/api:onos-rest-tests",
+]
+
+osgi_jar_with_tests(
+    api_description = "OpenStack Network Telemetry REST API",
+    api_package = "org.onosproject.openstacktelemetry.web",
+    api_title = "OpenStack Network Telemetry REST API",
+    api_version = "1.0",
+    test_deps = TEST_DEPS,
+    web_context = "/onos/openstacktelemetry",
+    deps = COMPILE_DEPS,
+)
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonCodec.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonCodec.java
similarity index 98%
rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonCodec.java
rename to apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonCodec.java
index be51b15453..a6d75ec1e6 100644
--- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonCodec.java
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonCodec.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.openstacktelemetry.codec;
+package org.onosproject.openstacktelemetry.codec.rest;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -27,7 +27,7 @@ import org.onosproject.codec.JsonCodec;
 import org.onosproject.net.DeviceId;
 import org.onosproject.openstacktelemetry.api.FlowInfo;
 import org.onosproject.openstacktelemetry.api.StatsInfo;
-import org.onosproject.openstacktelemetry.impl.DefaultFlowInfo;
+import org.onosproject.openstacktelemetry.api.DefaultFlowInfo;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onlab.packet.VlanId.NO_VID;
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/StatsFlowRuleJsonCodec.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/StatsFlowRuleJsonCodec.java
similarity index 80%
rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/StatsFlowRuleJsonCodec.java
rename to apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/StatsFlowRuleJsonCodec.java
index 384987b6a9..3d2b13fc50 100644
--- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/StatsFlowRuleJsonCodec.java
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/StatsFlowRuleJsonCodec.java
@@ -13,21 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.openstacktelemetry.codec;
+package org.onosproject.openstacktelemetry.codec.rest;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.IpPrefix;
 import org.onlab.packet.TpPort;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.codec.JsonCodec;
+import org.onosproject.openstacktelemetry.api.DefaultStatsFlowRule;
 import org.onosproject.openstacktelemetry.api.StatsFlowRule;
-import org.onosproject.openstacktelemetry.impl.DefaultStatsFlowRule;
 import org.slf4j.Logger;
 
-import org.onlab.packet.IpPrefix;
-
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.openstacktelemetry.util.OpenstackTelemetryUtil.getProtocolTypeFromString;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -37,6 +36,11 @@ public class StatsFlowRuleJsonCodec extends JsonCodec {
 
     private final Logger log = getLogger(getClass());
 
+    private static final String PROTOCOL_NAME_TCP = "tcp";
+    private static final String PROTOCOL_NAME_UDP = "udp";
+    private static final String PROTOCOL_NAME_ANY = "any";
+    private static final int ARBITRARY_PROTOCOL = 0x0;
+
     public static final String SRC_IP_PREFIX = "srcIpPrefix";
     public static final String DST_IP_PREFIX = "dstIpPrefix";
     public static final String IP_PROTOCOL   = "ipProtocol";
@@ -88,4 +92,21 @@ public class StatsFlowRuleJsonCodec extends JsonCodec {
         }
         return null;
     }
+
+    /**
+     * Obtains transport protocol type from the given string.
+     *
+     * @param str transport protocol name
+     * @return transport protocol type
+     */
+    private byte getProtocolTypeFromString(String str) {
+        switch (str.toLowerCase()) {
+            case PROTOCOL_NAME_TCP:
+                return IPv4.PROTOCOL_TCP;
+            case PROTOCOL_NAME_UDP:
+                return IPv4.PROTOCOL_UDP;
+            default:
+                return ARBITRARY_PROTOCOL;
+        }
+    }
 }
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/StatsInfoJsonCodec.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/StatsInfoJsonCodec.java
similarity index 96%
rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/StatsInfoJsonCodec.java
rename to apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/StatsInfoJsonCodec.java
index 905b2ff77f..de8a7ef5ad 100644
--- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/StatsInfoJsonCodec.java
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/StatsInfoJsonCodec.java
@@ -13,13 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.openstacktelemetry.codec;
+package org.onosproject.openstacktelemetry.codec.rest;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.codec.JsonCodec;
 import org.onosproject.openstacktelemetry.api.StatsInfo;
-import org.onosproject.openstacktelemetry.impl.DefaultStatsInfo;
+import org.onosproject.openstacktelemetry.api.DefaultStatsInfo;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
diff --git a/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigJsonCodec.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigJsonCodec.java
new file mode 100644
index 0000000000..8c0a6e3e9e
--- /dev/null
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigJsonCodec.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacktelemetry.codec.rest;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
+import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
+
+import java.util.Map;
+import java.util.stream.IntStream;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * Openstack telemetry config codec used for serializing and de-serializing JSON string.
+ */
+public final class TelemetryConfigJsonCodec extends JsonCodec {
+
+    private static final String NAME = "name";
+    private static final String TYPE = "type";
+    private static final String MANUFACTURER = "manufacturer";
+    private static final String SW_VERSION = "swVersion";
+    private static final String ENABLED = "enabled";
+    private static final String PROPS = "props";
+    private static final String KEY = "key";
+    private static final String VALUE = "value";
+
+    private static final String MISSING_MESSAGE = " is required in TelemetryConfig";
+
+    @Override
+    public ObjectNode encode(TelemetryConfig config, CodecContext context) {
+        checkNotNull(config, "TelemetryConfig cannot be null");
+
+        ObjectNode node = context.mapper().createObjectNode()
+                .put(NAME, config.name())
+                .put(TYPE, config.type().name())
+                .put(MANUFACTURER, config.manufacturer())
+                .put(SW_VERSION, config.swVersion())
+                .put(ENABLED, config.enabled());
+
+        Map props = config.properties();
+        ArrayNode propsJson = context.mapper().createArrayNode();
+        props.forEach((k, v) -> {
+            ObjectNode propNode = context.mapper().createObjectNode();
+            propNode.put(KEY, k);
+            propNode.put(VALUE, v);
+            propsJson.add(propNode);
+        });
+        node.set(PROPS, propsJson);
+        return node;
+    }
+
+    @Override
+    public TelemetryConfig decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse name
+        String name = nullIsIllegal(json.get(NAME),
+                NAME + MISSING_MESSAGE).asText();
+
+        // parse type
+        String type = nullIsIllegal(json.get(TYPE),
+                TYPE + MISSING_MESSAGE).asText();
+
+        TelemetryConfig.ConfigType configType = configType(type);
+
+        // parse manufacturer
+        String manufacturer = nullIsIllegal(json.get(MANUFACTURER).asText(),
+                MANUFACTURER + MISSING_MESSAGE);
+
+        // parse software version
+        String swVersion = nullIsIllegal(json.get(SW_VERSION),
+                SW_VERSION + MISSING_MESSAGE).asText();
+
+        // parse enabled flag
+        boolean enabled = nullIsIllegal(json.get(ENABLED),
+                ENABLED + MISSING_MESSAGE).asBoolean();
+
+        JsonNode propertiesJson = json.get(PROPS);
+        Map properties = Maps.newConcurrentMap();
+        if (propertiesJson != null) {
+            IntStream.range(0, propertiesJson.size()).forEach(i -> {
+                ObjectNode propertyJson = get(propertiesJson, i);
+                properties.put(propertyJson.get(KEY).asText(),
+                        propertyJson.get(VALUE).asText());
+            });
+        }
+
+        return new DefaultTelemetryConfig(name, configType,
+                ImmutableList.of(), manufacturer, swVersion, enabled, properties);
+    }
+
+    private TelemetryConfig.ConfigType configType(String type) {
+        switch (type.toUpperCase()) {
+            case "KAFKA" :
+                return TelemetryConfig.ConfigType.KAFKA;
+            case "GRPC" :
+                return TelemetryConfig.ConfigType.GRPC;
+            case "INFLUXDB" :
+                return TelemetryConfig.ConfigType.INFLUXDB;
+            case "PROMETHEUS" :
+                return TelemetryConfig.ConfigType.PROMETHEUS;
+            case "REST" :
+                return TelemetryConfig.ConfigType.REST;
+            default:
+                return TelemetryConfig.ConfigType.UNKNOWN;
+        }
+    }
+}
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/package-info.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/package-info.java
similarity index 92%
rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/package-info.java
rename to apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/package-info.java
index f7f6401ff7..3a699c1dd0 100644
--- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/package-info.java
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/codec/rest/package-info.java
@@ -17,4 +17,4 @@
 /**
  * Implementations of the codec broker and openstack telemetry entity codecs.
  */
-package org.onosproject.openstacktelemetry.codec;
\ No newline at end of file
+package org.onosproject.openstacktelemetry.codec.rest;
\ No newline at end of file
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegister.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegister.java
similarity index 80%
rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegister.java
rename to apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegister.java
index c8bfeb5d3e..6bd8636f93 100644
--- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegister.java
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegister.java
@@ -15,18 +15,20 @@
  */
 package org.onosproject.openstacktelemetry.web;
 
+import org.onosproject.codec.CodecService;
+import org.onosproject.openstacktelemetry.api.FlowInfo;
+import org.onosproject.openstacktelemetry.api.StatsFlowRule;
+import org.onosproject.openstacktelemetry.api.StatsInfo;
+import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
+import org.onosproject.openstacktelemetry.codec.rest.FlowInfoJsonCodec;
+import org.onosproject.openstacktelemetry.codec.rest.StatsFlowRuleJsonCodec;
+import org.onosproject.openstacktelemetry.codec.rest.StatsInfoJsonCodec;
+import org.onosproject.openstacktelemetry.codec.rest.TelemetryConfigJsonCodec;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.onosproject.codec.CodecService;
-import org.onosproject.openstacktelemetry.api.FlowInfo;
-import org.onosproject.openstacktelemetry.api.StatsFlowRule;
-import org.onosproject.openstacktelemetry.api.StatsInfo;
-import org.onosproject.openstacktelemetry.codec.FlowInfoJsonCodec;
-import org.onosproject.openstacktelemetry.codec.StatsFlowRuleJsonCodec;
-import org.onosproject.openstacktelemetry.codec.StatsInfoJsonCodec;
 
 import static org.slf4j.LoggerFactory.getLogger;
 
@@ -46,6 +48,7 @@ public class OpenstackTelemetryCodecRegister {
         codecService.registerCodec(StatsInfo.class, new StatsInfoJsonCodec());
         codecService.registerCodec(FlowInfo.class, new FlowInfoJsonCodec());
         codecService.registerCodec(StatsFlowRule.class, new StatsFlowRuleJsonCodec());
+        codecService.registerCodec(TelemetryConfig.class, new TelemetryConfigJsonCodec());
 
         log.info("Started");
     }
@@ -55,6 +58,7 @@ public class OpenstackTelemetryCodecRegister {
         codecService.unregisterCodec(StatsInfo.class);
         codecService.unregisterCodec(FlowInfo.class);
         codecService.unregisterCodec(StatsFlowRule.class);
+        codecService.unregisterCodec(TelemetryConfig.class);
 
         log.info("Stopped");
     }
diff --git a/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryConfigWebResource.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryConfigWebResource.java
new file mode 100644
index 0000000000..7484d04f6c
--- /dev/null
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryConfigWebResource.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacktelemetry.web;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Maps;
+import org.onosproject.openstacktelemetry.api.TelemetryConfigAdminService;
+import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.Map;
+
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+/**
+ * Handles REST API call of openstack telemetry configuration.
+ */
+@Path("config")
+public class OpenstackTelemetryConfigWebResource extends AbstractWebResource {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private static final String MESSAGE_CONFIG = "Received config %s request";
+    private static final String CONFIG = "config";
+    private static final String ADDRESS = "address";
+    private static final String QUERY = "QUERY";
+    private static final String UPDATE = "UPDATE";
+    private static final String DELETE = "DELETE";
+    private static final String CONFIG_NAME = "config name";
+    private static final String NOT_NULL_MESSAGE = " cannot be null";
+    private static final String CONFIG_NOT_FOUND = "Config is not found";
+
+    private final TelemetryConfigAdminService configService =
+                                        get(TelemetryConfigAdminService.class);
+
+    @Context
+    private UriInfo uriInfo;
+
+    /**
+     * Updates the telemetry configuration address from the JSON input stream.
+     *
+     * @param configName telemetry config name
+     * @param address telemetry config address
+     * @return 200 OK with the updated telemetry config, 400 BAD_REQUEST
+     * if the JSON is malformed, and 304 NOT_MODIFIED without the updated config
+     * due to incorrect configuration name so that we cannot find the existing config
+     */
+    @PUT
+    @Path("address/{name}/{address}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response updateConfigAddress(@PathParam("name") String configName,
+                                        @PathParam("address") String address) {
+        log.trace(String.format(MESSAGE_CONFIG, UPDATE));
+
+        try {
+            TelemetryConfig config = configService.getConfig(
+                    nullIsIllegal(configName, CONFIG_NAME + NOT_NULL_MESSAGE));
+
+            if (config == null) {
+                log.warn("There is no config found to modify for {}", configName);
+                return Response.notModified().build();
+            } else {
+                Map updatedProperties =
+                        Maps.newHashMap(config.properties());
+                updatedProperties.put(ADDRESS,
+                        nullIsIllegal(address, ADDRESS + NOT_NULL_MESSAGE));
+                TelemetryConfig updatedConfig =
+                        config.updateProperties(updatedProperties);
+
+                configService.updateTelemetryConfig(updatedConfig);
+                return Response.ok().build();
+            }
+
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Deletes the telemetry configuration by referring to configuration name.
+     *
+     * @param configName telemetry configuration name
+     * @return 204 NO_CONTENT, 400 BAD_REQUEST if the JSON is malformed,
+     * and 304 NOT_MODIFIED without removing config, due to incorrect
+     * configuration name so that we cannot find the existing config
+     */
+    @DELETE
+    @Path("{name}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response deleteTelemetryConfig(@PathParam("name") String configName) {
+        log.trace(String.format(MESSAGE_CONFIG, DELETE));
+
+        TelemetryConfig config = configService.getConfig(
+                nullIsIllegal(configName, CONFIG_NAME + NOT_NULL_MESSAGE));
+
+        if (config == null) {
+            log.warn("There is no config found to delete for {}", configName);
+            return Response.notModified().build();
+        } else {
+            configService.removeTelemetryConfig(configName);
+            return Response.noContent().build();
+        }
+    }
+
+    /**
+     * Get details of telemetry config.
+     * Returns detailed properties of the specified telemetry config.
+     *
+     * @param configName telemetry configName
+     * @return 200 OK with detailed properties of the specific telemetry config
+     * @onos.rsModel TelemetryConfig
+     */
+    @GET
+    @Path("{name}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getConfig(@PathParam("name") String configName) {
+        log.trace(String.format(MESSAGE_CONFIG, QUERY));
+
+        final TelemetryConfig config =
+                nullIsNotFound(configService.getConfig(configName), CONFIG_NOT_FOUND);
+        final ObjectNode root = codec(TelemetryConfig.class).encode(config, this);
+        return ok(root).build();
+    }
+
+    /**
+     * Enables the telemetry configuration with the given config name.
+     *
+     * @param configName telemetry configuration name
+     * @return 200 OK with the enabled telemetry config,
+     * 400 BAD_REQUEST if the JSON is malformed,
+     * and 304 NOT_MODIFIED without removing config, due to incorrect
+     * configuration name so that we cannot find the existing config
+     */
+    @PUT
+    @Path("enable/{name}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response enableConfig(@PathParam("name") String configName) {
+        log.trace(String.format(MESSAGE_CONFIG, UPDATE));
+
+        TelemetryConfig config = configService.getConfig(
+                nullIsIllegal(configName, CONFIG_NAME + NOT_NULL_MESSAGE));
+
+        if (config == null) {
+            log.warn("There is no config found to enable for {}", configName);
+            return Response.notModified().build();
+        } else {
+            TelemetryConfig updatedConfig = config.updateEnabled(true);
+            configService.updateTelemetryConfig(updatedConfig);
+            return Response.ok().build();
+        }
+    }
+
+    /**
+     * Disables the telemetry configuration with the given config name.
+     *
+     * @param configName telemetry configuration name
+     * @return 200 OK with the disabled telemetry config
+     * 400 BAD_REQUEST if the JSON is malformed,
+     * and 304 NOT_MODIFIED without removing config, due to incorrect
+     * configuration name so that we cannot find the existing config
+     */
+    @PUT
+    @Path("disable/{name}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response disableConfig(@PathParam("name") String configName) {
+        log.trace(String.format(MESSAGE_CONFIG, UPDATE));
+
+        TelemetryConfig config = configService.getConfig(
+                nullIsIllegal(configName, CONFIG_NAME + NOT_NULL_MESSAGE));
+
+        if (config == null) {
+            log.warn("There is no config found to disable for {}", configName);
+            return Response.notModified().build();
+        } else {
+            TelemetryConfig updatedConfig = config.updateEnabled(false);
+            configService.updateTelemetryConfig(updatedConfig);
+            return Response.ok().build();
+        }
+    }
+}
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebApplication.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebApplication.java
similarity index 88%
rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebApplication.java
rename to apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebApplication.java
index 9dc4e185bb..4deff1c773 100644
--- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebApplication.java
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebApplication.java
@@ -25,6 +25,7 @@ import java.util.Set;
 public class OpenstackTelemetryWebApplication extends AbstractWebApplication {
     @Override
     public Set> getClasses() {
-        return getClasses(OpenstackTelemetryWebResource.class);
+        return getClasses(OpenstackTelemetryWebResource.class,
+                OpenstackTelemetryConfigWebResource.class);
     }
 }
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebResource.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebResource.java
similarity index 94%
rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebResource.java
rename to apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebResource.java
index 34f8366032..40b5c93165 100644
--- a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebResource.java
+++ b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryWebResource.java
@@ -24,7 +24,7 @@ import org.onosproject.codec.JsonCodec;
 import org.onosproject.openstacktelemetry.api.FlowInfo;
 import org.onosproject.openstacktelemetry.api.StatsFlowRule;
 import org.onosproject.openstacktelemetry.api.StatsFlowRuleAdminService;
-import org.onosproject.openstacktelemetry.codec.FlowInfoJsonCodec;
+import org.onosproject.openstacktelemetry.codec.rest.FlowInfoJsonCodec;
 import org.onosproject.rest.AbstractWebResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -51,7 +51,6 @@ import static org.onlab.util.Tools.readTreeFromStream;
 /**
  * Handles REST API call of openstack telemetry.
  */
-
 @Path("telemetry")
 public class OpenstackTelemetryWebResource extends AbstractWebResource {
 
@@ -138,18 +137,13 @@ public class OpenstackTelemetryWebResource extends AbstractWebResource {
         Set flowInfoSet;
         flowInfoSet = statsFlowRuleService.getOverlayFlowInfos();
 
-        log.info("\n\n======================================================\n" +
-                 "FlowInfo Set: \n{}" +
-                 "\n\n======================================================\n",
-                 flowInfoSet);
-
         JsonCodec flowInfoCodec = new FlowInfoJsonCodec();
 
         ObjectNode nodeJson;
         int idx = 0;
         for (FlowInfo flowInfo: flowInfoSet) {
             nodeJson = flowInfoCodec.encode(flowInfo, this);
-            root.put("FlowInfo" + String.valueOf(idx++), nodeJson.toString());
+            root.put("FlowInfo" + idx++, nodeJson.toString());
         }
         return ok(root).build();
     }
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/package-info.java b/apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/package-info.java
similarity index 100%
rename from apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/web/package-info.java
rename to apps/openstacktelemetry/web/src/main/java/org/onosproject/openstacktelemetry/web/package-info.java
diff --git a/apps/openstacktelemetry/web/src/main/resources/definitions/TelemetryConfig.json b/apps/openstacktelemetry/web/src/main/resources/definitions/TelemetryConfig.json
new file mode 100644
index 0000000000..f4d1288f8c
--- /dev/null
+++ b/apps/openstacktelemetry/web/src/main/resources/definitions/TelemetryConfig.json
@@ -0,0 +1,53 @@
+{
+  "type": "object",
+  "required": [
+    "name",
+    "type",
+    "manufacturer",
+    "swVersion",
+    "enabled",
+    "properties"
+  ],
+  "properties": {
+    "name": {
+      "type": "string",
+      "example": "grpc config"
+    },
+    "type": {
+      "type": "string",
+      "example": "GRPC"
+    },
+    "manufacturer": {
+      "type": "string",
+      "example": "grpc.io"
+    },
+    "swVersion": {
+      "type": "string",
+      "example": "1.0"
+    },
+    "enabled": {
+      "type": "boolean",
+      "example": true
+    },
+    "props": {
+      "type": "array",
+      "items": {
+        "type": "object",
+        "required": [
+          "key",
+          "value"
+        ],
+        "properties": {
+          "key": {
+            "type": "string",
+            "example": "address"
+          },
+          "value": {
+            "type": "string",
+            "example": "127.0.0.1"
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/apps/openstacktelemetry/app/src/main/webapp/WEB-INF/web.xml b/apps/openstacktelemetry/web/src/main/webapp/WEB-INF/web.xml
similarity index 100%
rename from apps/openstacktelemetry/app/src/main/webapp/WEB-INF/web.xml
rename to apps/openstacktelemetry/web/src/main/webapp/WEB-INF/web.xml
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonCodecTest.java b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonCodecTest.java
similarity index 96%
rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonCodecTest.java
rename to apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonCodecTest.java
index ee84e59f34..4d3cb47229 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonCodecTest.java
+++ b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonCodecTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.openstacktelemetry.codec;
+package org.onosproject.openstacktelemetry.codec.rest;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -32,8 +32,8 @@ import org.onosproject.core.CoreService;
 import org.onosproject.net.DeviceId;
 import org.onosproject.openstacktelemetry.api.FlowInfo;
 import org.onosproject.openstacktelemetry.api.StatsInfo;
-import org.onosproject.openstacktelemetry.impl.DefaultFlowInfo;
-import org.onosproject.openstacktelemetry.impl.DefaultStatsInfo;
+import org.onosproject.openstacktelemetry.api.DefaultFlowInfo;
+import org.onosproject.openstacktelemetry.api.DefaultStatsInfo;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -44,7 +44,7 @@ import static org.easymock.EasyMock.replay;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.openstacktelemetry.codec.FlowInfoJsonMatcher.matchesFlowInfo;
+import static org.onosproject.openstacktelemetry.codec.rest.FlowInfoJsonMatcher.matchesFlowInfo;
 
 /**
  * Unit tests for FlowInfo codec.
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonMatcher.java b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonMatcher.java
similarity index 99%
rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonMatcher.java
rename to apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonMatcher.java
index 7574054b30..66ab1bad29 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/FlowInfoJsonMatcher.java
+++ b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/FlowInfoJsonMatcher.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.openstacktelemetry.codec;
+package org.onosproject.openstacktelemetry.codec.rest;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import org.hamcrest.Description;
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/StatsInfoJsonMatcher.java b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/StatsInfoJsonMatcher.java
similarity index 98%
rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/StatsInfoJsonMatcher.java
rename to apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/StatsInfoJsonMatcher.java
index ffebaf58da..4ad86fa7af 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/codec/StatsInfoJsonMatcher.java
+++ b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/StatsInfoJsonMatcher.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.openstacktelemetry.codec;
+package org.onosproject.openstacktelemetry.codec.rest;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import org.hamcrest.Description;
diff --git a/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigCodecTest.java b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigCodecTest.java
new file mode 100644
index 0000000000..626aa02cb0
--- /dev/null
+++ b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigCodecTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacktelemetry.codec.rest;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import org.hamcrest.MatcherAssert;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.codec.impl.CodecManager;
+import org.onosproject.core.CoreService;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
+import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.openstacktelemetry.codec.rest.TelemetryConfigJsonMatcher.matchesTelemetryConfig;
+
+/**
+ * Unit tests for TelemetryConfig codec.
+ */
+public class TelemetryConfigCodecTest {
+
+    MockCodecContext context;
+
+    JsonCodec telemetryConfigCodec;
+
+    final CoreService mockCoreService = createMock(CoreService.class);
+    private static final String REST_APP_ID = "org.onosproject.rest";
+
+    @Before
+    public void setUp() {
+        context = new MockCodecContext();
+        telemetryConfigCodec = new TelemetryConfigJsonCodec();
+
+        assertThat(telemetryConfigCodec, notNullValue());
+
+        expect(mockCoreService.registerApplication(REST_APP_ID))
+                .andReturn(APP_ID).anyTimes();
+        replay(mockCoreService);
+        context.registerService(CoreService.class, mockCoreService);
+    }
+
+    /**
+     * Tests the telemetry config encoding.
+     */
+    @Test
+    public void testTelemetryConfigEncode() {
+
+        String name = "grpc";
+        TelemetryConfig.ConfigType type = TelemetryConfig.ConfigType.GRPC;
+        String manufacturer = "grpc.io";
+        String swVersion = "1.0";
+        boolean enabled = true;
+
+        Map properties = Maps.newConcurrentMap();
+        properties.put("key1", "value1");
+        properties.put("key2", "value2");
+
+        TelemetryConfig config = new DefaultTelemetryConfig(name, type,
+                ImmutableList.of(), manufacturer, swVersion, enabled, properties);
+
+        ObjectNode configJson = telemetryConfigCodec.encode(config, context);
+        assertThat(configJson, matchesTelemetryConfig(config));
+    }
+
+    /**
+     * Tests the telemetry config decoding.
+     */
+    @Test
+    public void testTelemetryConfigDecode() throws IOException {
+        TelemetryConfig config = getTelemetryConfig("TelemetryConfig.json");
+
+        assertEquals(config.name(), "grpc-config");
+        assertEquals(config.type().name(), "GRPC");
+        assertEquals(config.manufacturer(), "grpc.io");
+        assertEquals(config.swVersion(), "1.0");
+        assertTrue(config.enabled());
+
+        config.properties().forEach((k, v) -> {
+            if (k.equals("address")) {
+                assertEquals(v, "127.0.0.1");
+            }
+            if (k.equals("port")) {
+                assertEquals(v, "9092");
+            }
+        });
+    }
+
+    /**
+     * Reads in a telemetry config from the given resource and decodes it.
+     *
+     * @param resourceName resource to use to read the JSON for the rule
+     * @return decoded telemetry config
+     * @throws IOException if processing the resource fails
+     */
+    private TelemetryConfig getTelemetryConfig(String resourceName) throws IOException {
+        InputStream jsonStream = TelemetryConfigCodecTest.class.getResourceAsStream(resourceName);
+        JsonNode json = context.mapper().readTree(jsonStream);
+        MatcherAssert.assertThat(json, notNullValue());
+        TelemetryConfig config = telemetryConfigCodec.decode((ObjectNode) json, context);
+        assertThat(config, notNullValue());
+        return config;
+    }
+
+    /**
+     * Mock codec context for use in codec unit tests.
+     */
+    private class MockCodecContext implements CodecContext {
+        private final ObjectMapper mapper = new ObjectMapper();
+        private final CodecManager manager = new CodecManager();
+        private final Map, Object> services = new HashMap<>();
+
+        /**
+         * Constructs a new mock codec context.
+         */
+        public MockCodecContext() {
+            manager.activate();
+        }
+
+        @Override
+        public ObjectMapper mapper() {
+            return mapper;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public  JsonCodec codec(Class entityClass) {
+            if (entityClass == TelemetryConfig.class) {
+                return (JsonCodec) telemetryConfigCodec;
+            }
+            return manager.getCodec(entityClass);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public  T getService(Class serviceClass) {
+            return (T) services.get(serviceClass);
+        }
+
+        // for registering mock services
+        public  void registerService(Class serviceClass, T impl) {
+            services.put(serviceClass, impl);
+        }
+    }
+}
diff --git a/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigJsonMatcher.java b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigJsonMatcher.java
new file mode 100644
index 0000000000..9bc50a20aa
--- /dev/null
+++ b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfigJsonMatcher.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacktelemetry.codec.rest;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
+
+/**
+ * Hamcrest matcher for TelemetryConfig.
+ */
+public final class TelemetryConfigJsonMatcher extends TypeSafeDiagnosingMatcher {
+
+    private final TelemetryConfig telemetryConfig;
+
+    private static final String NAME = "name";
+    private static final String TYPE = "type";
+    private static final String MANUFACTURER = "manufacturer";
+    private static final String SW_VERSION = "swVersion";
+    private static final String ENABLED = "enabled";
+    private static final String PROPS = "props";
+    private static final String KEY = "key";
+    private static final String VALUE = "value";
+
+    private TelemetryConfigJsonMatcher(TelemetryConfig telemetryConfig) {
+        this.telemetryConfig = telemetryConfig;
+    }
+
+    @Override
+    protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+
+        // check name
+        String jsonName = jsonNode.get(NAME).asText();
+        String name = telemetryConfig.name();
+        if (!jsonName.equals(name)) {
+            description.appendText("name was " + jsonName);
+            return false;
+        }
+
+        // check type
+        String jsonType = jsonNode.get(TYPE).asText();
+        String type = telemetryConfig.type().name();
+        if (!jsonType.equalsIgnoreCase(type)) {
+            description.appendText("type was " + jsonType);
+            return false;
+        }
+
+        // check manufacturer
+        String jsonManufacturer = jsonNode.get(MANUFACTURER).asText();
+        String manufacturer = telemetryConfig.manufacturer();
+        if (!jsonManufacturer.equals(manufacturer)) {
+            description.appendText("manufacturer was " + jsonManufacturer);
+            return false;
+        }
+
+        // check software version
+        String jsonSwVersion = jsonNode.get(SW_VERSION).asText();
+        String swVersion = telemetryConfig.swVersion();
+        if (!jsonSwVersion.equals(swVersion)) {
+            description.appendText("SW version was " + jsonSwVersion);
+            return false;
+        }
+
+        // check enabled
+        JsonNode jsonEnabled = jsonNode.get(ENABLED);
+        boolean enabled = telemetryConfig.enabled();
+        if (jsonEnabled == null || jsonEnabled.asBoolean() != enabled) {
+            description.appendText("Enabled was " + jsonEnabled);
+            return false;
+        }
+
+        // check properties
+        JsonNode jsonProperties = jsonNode.get(PROPS);
+        if (jsonProperties != null) {
+            if (jsonProperties.size() != telemetryConfig.properties().size()) {
+                description.appendText("properties size was " + jsonProperties.size());
+                return false;
+            }
+
+            for (String key : telemetryConfig.properties().keySet()) {
+                boolean keyFound = false;
+                boolean valueFound = false;
+                String value = telemetryConfig.properties().get(key);
+                for (int keyIndex = 0; keyIndex < jsonProperties.size(); keyIndex++) {
+                    ObjectNode jsonProperty = get(jsonProperties, keyIndex);
+                    JsonNode jsonKey = jsonProperty.get(KEY);
+                    JsonNode jsonValue = jsonProperty.get(VALUE);
+
+                    if (jsonKey != null && jsonValue != null) {
+                        if (jsonKey.asText().equals(key)) {
+                            keyFound = true;
+                        }
+
+                        if (jsonValue.asText().equals(value)) {
+                            valueFound = true;
+                        }
+
+                        if (keyFound && valueFound) {
+                            break;
+                        }
+                    }
+                }
+
+                if (!keyFound) {
+                    description.appendText("Property key not found " + key);
+                    return false;
+                }
+
+                if (!valueFound) {
+                    description.appendText("Property value not found " + value);
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText(telemetryConfig.toString());
+    }
+
+    /**
+     * Factory to allocate an flow info matcher.
+     *
+     * @param telemetryConfig telemetry config object we are looking for
+     * @return matcher
+     */
+    public static TelemetryConfigJsonMatcher
+                    matchesTelemetryConfig(TelemetryConfig telemetryConfig) {
+        return new TelemetryConfigJsonMatcher(telemetryConfig);
+    }
+
+    private static ObjectNode get(JsonNode parent, int childIndex) {
+        JsonNode node = parent.path(childIndex);
+        return node.isObject() && !node.isNull() ? (ObjectNode) node : null;
+    }
+}
diff --git a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegisterTest.java b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegisterTest.java
similarity index 84%
rename from apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegisterTest.java
rename to apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegisterTest.java
index 683e9c1965..6eee6164dc 100644
--- a/apps/openstacktelemetry/app/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegisterTest.java
+++ b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryCodecRegisterTest.java
@@ -24,9 +24,11 @@ import org.onosproject.codec.JsonCodec;
 import org.onosproject.openstacktelemetry.api.FlowInfo;
 import org.onosproject.openstacktelemetry.api.StatsFlowRule;
 import org.onosproject.openstacktelemetry.api.StatsInfo;
-import org.onosproject.openstacktelemetry.codec.FlowInfoJsonCodec;
-import org.onosproject.openstacktelemetry.codec.StatsFlowRuleJsonCodec;
-import org.onosproject.openstacktelemetry.codec.StatsInfoJsonCodec;
+import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
+import org.onosproject.openstacktelemetry.codec.rest.FlowInfoJsonCodec;
+import org.onosproject.openstacktelemetry.codec.rest.StatsFlowRuleJsonCodec;
+import org.onosproject.openstacktelemetry.codec.rest.StatsInfoJsonCodec;
+import org.onosproject.openstacktelemetry.codec.rest.TelemetryConfigJsonCodec;
 
 import java.util.Map;
 import java.util.Set;
@@ -58,12 +60,15 @@ public final class OpenstackTelemetryCodecRegisterTest {
                 codecService.getCodec(FlowInfo.class).getClass().getName());
         assertEquals(StatsFlowRuleJsonCodec.class.getName(),
                 codecService.getCodec(StatsFlowRule.class).getClass().getName());
+        assertEquals(TelemetryConfigJsonCodec.class.getName(),
+                codecService.getCodec(TelemetryConfig.class).getClass().getName());
 
         register.deactivate();
 
         assertNull(codecService.getCodec(StatsInfo.class));
         assertNull(codecService.getCodec(FlowInfo.class));
         assertNull(codecService.getCodec(StatsFlowRule.class));
+        assertNull(codecService.getCodec(TelemetryConfig.class));
     }
 
     private static class TestCodecService implements CodecService {
diff --git a/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryConfigWebResourceTest.java b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryConfigWebResourceTest.java
new file mode 100644
index 0000000000..ff027bc910
--- /dev/null
+++ b/apps/openstacktelemetry/web/src/test/java/org/onosproject/openstacktelemetry/web/OpenstackTelemetryConfigWebResourceTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacktelemetry.web;
+
+import com.google.common.collect.Maps;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onosproject.openstacktelemetry.api.DefaultTelemetryConfig;
+import org.onosproject.openstacktelemetry.api.TelemetryConfigAdminService;
+import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
+import org.onosproject.rest.resources.ResourceTest;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.easymock.EasyMock.anyString;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.onosproject.openstacktelemetry.api.config.TelemetryConfig.ConfigType.GRPC;
+
+/**
+ * Unit tests for openstack telemetry config REST API.
+ */
+public class OpenstackTelemetryConfigWebResourceTest extends ResourceTest {
+
+    private static final String NAME = "grpc";
+
+    private static final TelemetryConfig.ConfigType TYPE = GRPC;
+
+    private static final String MANUFACTURER = "grpc.io";
+
+    private static final String SW_VERSION = "1.0";
+
+    private static final Map PROP = Maps.newConcurrentMap();
+
+    private static final String PROP_KEY_1 = "key11";
+    private static final String PROP_KEY_2 = "key12";
+    private static final String PROP_VALUE_1 = "value11";
+    private static final String PROP_VALUE_2 = "value12";
+
+    private static final boolean ENABLED = true;
+
+    private final TelemetryConfigAdminService mockConfigAdminService =
+            createMock(TelemetryConfigAdminService.class);
+    private static final String PATH = "config";
+
+    /**
+     * Constructs an openstack telemetry config resource test instance.
+     */
+    public OpenstackTelemetryConfigWebResourceTest() {
+        super(ResourceConfig.forApplicationClass(OpenstackTelemetryWebApplication.class));
+    }
+
+    private TelemetryConfig telemetryConfig;
+
+    /**
+     * Sets up the global values for all the tests.
+     */
+    @Before
+    public void setUpTest() {
+        ServiceDirectory testDirectory =
+                new TestServiceDirectory()
+                        .add(TelemetryConfigAdminService.class,
+                                mockConfigAdminService);
+        setServiceDirectory(testDirectory);
+
+        PROP.put(PROP_KEY_1, PROP_VALUE_1);
+        PROP.put(PROP_KEY_2, PROP_VALUE_2);
+
+        telemetryConfig = new DefaultTelemetryConfig(NAME, TYPE, null,
+                MANUFACTURER, SW_VERSION, ENABLED, PROP);
+    }
+
+    /**
+     * Tests the results of the REST API PUT method by modifying config address.
+     */
+    @Test
+    public void testUpdateConfigAddressWithModifyOperation() {
+        expect(mockConfigAdminService.getConfig(anyString()))
+                .andReturn(telemetryConfig).once();
+        mockConfigAdminService.updateTelemetryConfig(telemetryConfig);
+        replay(mockConfigAdminService);
+
+        final WebTarget wt = target();
+        Response response = wt.path(PATH + "/address/test1/address1")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(""));
+        final int status = response.getStatus();
+
+        assertEquals(200, status);
+
+        verify(mockConfigAdminService);
+    }
+
+    /**
+     * Tests the results of the REST API PUT method without modifying config address.
+     */
+    @Test
+    public void testUpdateConfigAddressWithoutOperation() {
+        expect(mockConfigAdminService.getConfig(anyString())).andReturn(null).once();
+        replay(mockConfigAdminService);
+
+        final WebTarget wt = target();
+        Response response = wt.path(PATH + "/address/test1/address1")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(""));
+        final int status = response.getStatus();
+
+        assertEquals(304, status);
+
+        verify(mockConfigAdminService);
+    }
+
+    /**
+     * Tests the results of the REST API DELETE method by removing config.
+     */
+    @Test
+    public void testDeleteConfigWithModifyOperation() {
+        expect(mockConfigAdminService.getConfig(anyString()))
+                .andReturn(telemetryConfig).once();
+        mockConfigAdminService.removeTelemetryConfig(anyString());
+        replay(mockConfigAdminService);
+
+        final WebTarget wt = target();
+        Response response = wt.path(PATH + "/test1")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .delete();
+        final int status = response.getStatus();
+
+        assertEquals(204, status);
+
+        verify(mockConfigAdminService);
+    }
+
+    /**
+     * Tests the results of the REST API DELETE method without removing config.
+     */
+    @Test
+    public void testDeleteConfigWithoutModifyOperation() {
+        expect(mockConfigAdminService.getConfig(anyString())).andReturn(null).once();
+        replay(mockConfigAdminService);
+
+        final WebTarget wt = target();
+        Response response = wt.path(PATH + "/test1")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .delete();
+        final int status = response.getStatus();
+
+        assertEquals(304, status);
+
+        verify(mockConfigAdminService);
+    }
+
+    /**
+     * Tests the results of REST API PUT method with enabling the config.
+     */
+    @Test
+    public void testEnableConfig() {
+        expect(mockConfigAdminService.getConfig(anyString()))
+                .andReturn(telemetryConfig).once();
+        mockConfigAdminService.updateTelemetryConfig(telemetryConfig);
+        replay(mockConfigAdminService);
+
+        final WebTarget wt = target();
+        Response response = wt.path(PATH + "/enable/test1")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(""));
+        final int status = response.getStatus();
+
+        assertEquals(200, status);
+
+        verify(mockConfigAdminService);
+    }
+
+    /**
+     * Tests the results of REST API PUT method with disabling the config.
+     */
+    @Test
+    public void testDisableConfig() {
+        expect(mockConfigAdminService.getConfig(anyString()))
+                .andReturn(telemetryConfig).once();
+        mockConfigAdminService.updateTelemetryConfig(telemetryConfig);
+        replay(mockConfigAdminService);
+
+        final WebTarget wt = target();
+        Response response = wt.path(PATH + "/disable/test1")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(""));
+        final int status = response.getStatus();
+
+        assertEquals(200, status);
+
+        verify(mockConfigAdminService);
+    }
+}
diff --git a/apps/openstacktelemetry/web/src/test/resources/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfig.json b/apps/openstacktelemetry/web/src/test/resources/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfig.json
new file mode 100644
index 0000000000..681cad3592
--- /dev/null
+++ b/apps/openstacktelemetry/web/src/test/resources/org/onosproject/openstacktelemetry/codec/rest/TelemetryConfig.json
@@ -0,0 +1,17 @@
+{
+  "name": "grpc-config",
+  "type": "GRPC",
+  "manufacturer": "grpc.io",
+  "swVersion": "1.0",
+  "enabled": true,
+  "props": [
+    {
+      "key": "address",
+      "value": "127.0.0.1"
+    },
+    {
+      "key": "port",
+      "value": "9092"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/apps/openstacktelemetry/web/src/test/resources/org/onosproject/openstacktelemetry/web/openstack-telemetry-config-address.json b/apps/openstacktelemetry/web/src/test/resources/org/onosproject/openstacktelemetry/web/openstack-telemetry-config-address.json
new file mode 100644
index 0000000000..a4132c51c2
--- /dev/null
+++ b/apps/openstacktelemetry/web/src/test/resources/org/onosproject/openstacktelemetry/web/openstack-telemetry-config-address.json
@@ -0,0 +1,5 @@
+{
+  "config": {
+    "address": "10.10.10.10"
+  }
+}
\ No newline at end of file