Detangling incubator: virtual nets, tunnels, resource labels, oh my

- virtual networking moved to /apps/virtual; with CLI & REST API
- tunnels and labels moved to /apps/tunnel; with CLI & REST API; UI disabled for now
- protobuf/models moved to /core/protobuf/models
- defunct grpc/rpc registry stuff left under /graveyard
- compile dependencies on /incubator moved to respective modules for compilation
- run-time dependencies will need to be re-tested for dependent apps

- /graveyard will be removed in not-too-distant future

Change-Id: I0a0b995c635487edcf95a352f50dd162186b0b39
diff --git a/core/api/src/main/java/org/onosproject/alarm/Alarm.java b/core/api/src/main/java/org/onosproject/alarm/Alarm.java
new file mode 100644
index 0000000..1460cc7
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/Alarm.java
@@ -0,0 +1,222 @@
+/*
+ * 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.alarm;
+
+import org.onosproject.net.DeviceId;
+
+/**
+ * Representation of an Alarm. At a given instant there can be only one alarm
+ * with the same deviceId + description + source combination.
+ */
+public interface Alarm {
+
+    /**
+     * Returns the unique alarm id within this ONOS instance.
+     *
+     * @return alarm identifier
+     */
+    AlarmId id();
+
+    /**
+     * The device to which this alarm is related.
+     *
+     * @return a device id
+     */
+    DeviceId deviceId();
+
+    /**
+     * Returns a description of alarm.
+     * <p>
+     * It may encapsulate Event Type as described by ITU Recommendation X.736
+     * ITU, Quoting https://tools.ietf.org/html/rfc3877 these include: other,
+     * communicationsAlarm, qualityOfServiceAlarm, processingErrorAlarm,
+     * equipmentAlarm, environmentalAlarm, integrityViolation,
+     * operationalViolation, physicalViolation,
+     * securityServiceOrMechanismViolation, timeDomainViolation
+     * <p>
+     * It may encapsulate Probable Cause as described by ITU Recommendation
+     * X.736 ITU, Quoting
+     * https://www.iana.org/assignments/ianaitualarmtc-mib/ianaitualarmtc-mib
+     * these include : aIS, callSetUpFailure, degradedSignal,
+     * farEndReceiverFailure, framingError, and hundreds more constants.
+     * <p>
+     * It may encapsulate a vendor-specific description of the underlying fault.
+     *
+     * @return description of alarm
+     */
+    String description();
+
+    /**
+     * Returns an entity within the context of this alarm's device. It may be
+     * null if deviceId sufficiently identifies the location. As an example, the
+     * source may indicate a port number
+     *
+     * @return source of alarm within the alarm's referenced Device.
+     */
+    AlarmEntityId source();
+
+    /**
+     * Returns the time when raised.
+     *
+     * @return time when raised, in milliseconds since start of epoch
+     */
+    long timeRaised();
+
+    /**
+     * Returns time at which the alarm was updated most recently, due to some
+     * change in the device, or ONOS. If the alarm has been cleared, this is the
+     * time at which the alarm was cleared.
+     *
+     * @return time when last updated, in milliseconds since start of epoch
+     */
+    long timeUpdated();
+
+    /**
+     * Returns the time when cleared. Null indicated no clear time, i.e. the
+     * alarm is still active.
+     *
+     * @return time when cleared, in milliseconds since start of epoch or null
+     * if uncleared.
+     */
+    Long timeCleared();
+
+    /**
+     * Returns the severity. Note, that cleared alarms may have EITHER
+     * SeverityLevel = CLEARED, or may be not present; both scenarios should be
+     * handled.
+     *
+     * @return severity of the alarm
+     */
+    SeverityLevel severity();
+
+    /**
+     * Returns true if alarm is service affecting Note: Whilst X.733 combines
+     * service-affecting state with severity (where severities of critical and
+     * major are deemed service-affecting) ONOS keeps these attributes separate.
+     *
+     * @return whether service affecting (true indicates it is)
+     */
+    boolean serviceAffecting();
+
+    /**
+     * Returns a flag to indicate if this alarm has been acknowledged. All
+     * alarms are unacknowledged until and unless an ONOS user takes action to
+     * indicate so.
+     *
+     * @return whether alarm is currently acknowledged (true indicates it is)
+     */
+    boolean acknowledged();
+
+    /**
+     * Returns a flag to indicate if this alarm has been cleared. All
+     * alarms are not cleared until and unless an ONOS user or app takes action to
+     * indicate so.
+     *
+     * @return whether alarm is currently cleared (true indicates it is)
+     */
+    default boolean cleared() {
+        return false;
+    }
+
+    /**
+     * Returns a flag to indicate if this alarm is manually-cleared by a user action within ONOS. Some stateless events
+     * e.g. backup-failure or upgrade-failure, may be mapped by ONOS to alarms, and these may be deemed manually-
+     * clearable. The more typical case is that an alarm represents a persistent fault on or related to a device and
+     * such alarms are never manually clearable, i.e. a configuration or operational state must occur for the alarm to
+     * clear.
+     *
+     * @return whether it may be cleared by a user action (true indicates it is)
+     */
+    boolean manuallyClearable();
+
+    /**
+     * Returns the user to whom this alarm is assigned; this is for future use
+     * and always returns null in this release. It is anticipated that in future ONOS
+     * releases, the existing JAAS user/key/role configuration will be extended
+     * to include a mechanism whereby some groups of users may allocate alarms
+     * to other users for bookkeeping and administrative purposes, and that ONOS
+     * will additionally provide a REST based mechanism, to retrieve from JAAS,
+     * the set of users to whom alarm assignment is possible for the current
+     * user.
+     *
+     * @return the assigned user; always null in this release.
+     */
+    String assignedUser();
+
+    /**
+     * Represents the severity level on an alarm, as per ITU-T X.733
+     * specifications.
+     * <p>
+     * The precedence is as follows for : Critical &gt; Major &gt; Minor &gt; Warning.
+     */
+    enum SeverityLevel {
+
+        /**
+         * From X.733: This indicates the clearing of one or more previously
+         * reported alarms. This alarm clears all alarms for this managed object
+         * that have the same Alarm type, Probable cause and Specific problems
+         * (if given). Multiple associated notifications may be cleared by using
+         * the Correlated notifications parameter (defined below). This
+         * Recommendation | International Standard does not require that the
+         * clearing of previously reported alarms be reported. Therefore, a
+         * managing system cannot assume that the absence of an alarm with the
+         * Cleared severity level means that the condition that caused the
+         * generation of previous alarms is still present. Managed object
+         * definers shall state if, and under which conditions, the Cleared
+         * severity level is used.
+         */
+        CLEARED,
+        /**
+         * From X.733: This indicates that the severity level cannot be
+         * determined.
+         */
+        INDETERMINATE,
+        /**
+         * From X.733: This indicates that a service affecting condition has
+         * occurred and an immediate corrective action is required. Such a
+         * severity can be reported, for example, when a managed object becomes
+         * totally out of service and its capability must be restored.
+         */
+        CRITICAL,
+        /**
+         * X.733 definition: This indicates that a service affecting condition
+         * has developed and an urgent corrective action is required. Such a
+         * severity can be reported, for example, when there is a severe
+         * degradation in the capability of the managed object and its full
+         * capability must be restored.
+         */
+        MAJOR,
+        /**
+         * From X.733: This indicates the existence of a non-service affecting
+         * fault condition and that corrective action should be taken in order
+         * to prevent a more serious (for example, service affecting) fault.
+         * Such a severity can be reported, for example, when the detected alarm
+         * condition is not currently degrading the capacity of the managed
+         * object.
+         */
+        MINOR,
+        /**
+         * From X.733: This indicates the detection of a potential or impending
+         * service affecting fault, before any significant effects have been
+         * felt. Action should be taken to further diagnose (if necessary) and
+         * correct the problem in order to prevent it from becoming a more
+         * serious service affecting fault.
+         */
+        WARNING
+
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmConsumer.java b/core/api/src/main/java/org/onosproject/alarm/AlarmConsumer.java
new file mode 100644
index 0000000..d791c07
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmConsumer.java
@@ -0,0 +1,38 @@
+/*
+ * 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.alarm;
+
+import org.onosproject.net.driver.HandlerBehaviour;
+
+import java.util.List;
+
+/**
+ * Abstraction of a device behaviour capable of retrieving/consuming list of
+ * pending alarms from the device.
+ */
+public interface AlarmConsumer extends HandlerBehaviour {
+
+    /**
+     * Returns the list of active alarms consumed from the device.
+     * This means that subsequent retrieval of alarms will not contain
+     * any duplicates.
+     *
+     * @return list of alarms consumed from the device
+     */
+    List<Alarm> consumeAlarms();
+
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmEntityId.java b/core/api/src/main/java/org/onosproject/alarm/AlarmEntityId.java
new file mode 100644
index 0000000..9debd0a
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmEntityId.java
@@ -0,0 +1,51 @@
+/*
+ * 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.alarm;
+
+import com.google.common.collect.ImmutableSet;
+import org.onlab.util.Identifier;
+
+import java.net.URI;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Immutable representation of a alarm source. It is meaningful within the
+ * context of a device.
+ */
+public final class AlarmEntityId extends Identifier<URI> {
+
+    public static final AlarmEntityId NONE = new AlarmEntityId(URI.create("none:none"));
+    public static final Set<String> SCHEMES = ImmutableSet.of("none", "port", "och", "other");
+
+    private AlarmEntityId(final URI uri) {
+        super(uri);
+    }
+
+    protected AlarmEntityId() {
+        super(NONE.identifier);
+    }
+
+    public static AlarmEntityId alarmEntityId(final String string) {
+        return alarmEntityId(URI.create(string));
+    }
+
+    public static AlarmEntityId alarmEntityId(final URI uri) {
+        checkArgument(SCHEMES.contains(uri.getScheme()), "Unexpected scheme");
+        return new AlarmEntityId(uri);
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmEvent.java b/core/api/src/main/java/org/onosproject/alarm/AlarmEvent.java
new file mode 100644
index 0000000..376d110
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmEvent.java
@@ -0,0 +1,55 @@
+/*
+ * 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.alarm;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Entity that represents Alarm events. Note: although the event will itself have a time,
+ * consumers may be more interested in the times embedded in the alarms themselves.
+ */
+public class AlarmEvent extends AbstractEvent<AlarmEvent.Type, Alarm> {
+
+    /**
+     * Type of alarm event.
+     */
+    public enum Type {
+
+        /**
+         * Individual alarm updated.
+         */
+        CREATED,
+        /**
+         * Individual alarm updated.
+         */
+        UPDATED,
+        /**
+         * Alarm set updated for a given device.
+         */
+        REMOVED,
+    }
+
+    /**
+     * Creates an event due to one alarm.
+     *
+     * @param type alarm type
+     * @param alarm the alarm related to the event.
+     */
+    public AlarmEvent(AlarmEvent.Type type, Alarm alarm) {
+        super(type, alarm);
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmId.java b/core/api/src/main/java/org/onosproject/alarm/AlarmId.java
new file mode 100644
index 0000000..39cd5b6
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmId.java
@@ -0,0 +1,80 @@
+/*
+ * 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.alarm;
+
+import com.google.common.annotations.Beta;
+import org.onlab.util.Identifier;
+import org.onosproject.net.DeviceId;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Alarm identifier suitable as an external key.
+ * <p>
+ * This class is immutable.</p>
+ */
+@Beta
+public final class AlarmId extends Identifier<String> {
+
+    /**
+     * Instantiates a new Alarm id.
+     *
+     * @param id               the device id
+     * @param uniqueIdentifier the unique identifier of the Alarm on that device
+     */
+    private AlarmId(DeviceId id, String uniqueIdentifier) {
+        super(id.toString() + ":" + uniqueIdentifier);
+        checkNotNull(id, "device id must not be null");
+        checkNotNull(uniqueIdentifier, "unique identifier must not be null");
+        checkArgument(!uniqueIdentifier.isEmpty(), "unique identifier must not be empty");
+    }
+
+    /**
+     * Instantiates a new Alarm id, primarily meant for lookup.
+     *
+     * @param globallyUniqueIdentifier the globally unique identifier of the Alarm,
+     *                                 device Id + local unique identifier on the device
+     */
+    private AlarmId(String globallyUniqueIdentifier) {
+        super(globallyUniqueIdentifier);
+        checkArgument(!globallyUniqueIdentifier.isEmpty(), "unique identifier must not be empty");
+    }
+
+    /**
+     * Creates an alarm identifier from the specified device id and
+     * unique identifier provided representation.
+     *
+     * @param id               device id
+     * @param uniqueIdentifier per device unique identifier of the alarm
+     * @return alarm identifier
+     */
+    public static AlarmId alarmId(DeviceId id, String uniqueIdentifier) {
+        return new AlarmId(id, uniqueIdentifier);
+    }
+
+    /**
+     * Creates an alarm identifier from the specified globally unique identifier.
+     *
+     * @param globallyUniqueIdentifier the globally unique identifier of the Alarm,
+     *                                 device Id + local unique identifier on the device
+     * @return alarm identifier
+     */
+    public static AlarmId alarmId(String globallyUniqueIdentifier) {
+        return new AlarmId(globallyUniqueIdentifier);
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmListener.java b/core/api/src/main/java/org/onosproject/alarm/AlarmListener.java
new file mode 100644
index 0000000..4977f66
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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.alarm;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving alarm related events.
+ */
+public interface AlarmListener extends EventListener<AlarmEvent> {
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmProvider.java b/core/api/src/main/java/org/onosproject/alarm/AlarmProvider.java
new file mode 100644
index 0000000..14c20b3
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmProvider.java
@@ -0,0 +1,36 @@
+/*
+ * 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.alarm;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Abstraction of an entity capable of supplying alarms collected from
+ * network devices.
+ */
+public interface AlarmProvider extends Provider {
+
+    /**
+     * Triggers an asynchronous discovery of the alarms on the specified device,
+     * intended to refresh internal alarm model for the device. An indirect
+     * result of this should be a event sent later with discovery result
+     * ie a set of alarms.
+     *
+     * @param deviceId ID of device to be probed
+     */
+    void triggerProbe(DeviceId deviceId);
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmProviderRegistry.java b/core/api/src/main/java/org/onosproject/alarm/AlarmProviderRegistry.java
new file mode 100644
index 0000000..32e812d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * 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.alarm;
+
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction of a alarm provider registry.
+ */
+public interface AlarmProviderRegistry extends ProviderRegistry<AlarmProvider, AlarmProviderService> {
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmProviderService.java b/core/api/src/main/java/org/onosproject/alarm/AlarmProviderService.java
new file mode 100644
index 0000000..674c0b1
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmProviderService.java
@@ -0,0 +1,38 @@
+/*
+ * 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.alarm;
+
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderService;
+
+import java.util.Collection;
+
+/**
+ * The interface Alarm provider service.
+ */
+
+public interface AlarmProviderService extends ProviderService<AlarmProvider> {
+
+    /**
+     * Sends active alarm list for a device.
+     *
+     * @param deviceId identity of the device
+     * @param alarms   list of device alarms
+     */
+    void updateAlarmList(DeviceId deviceId, Collection<Alarm> alarms);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmService.java b/core/api/src/main/java/org/onosproject/alarm/AlarmService.java
new file mode 100644
index 0000000..7be4d80
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmService.java
@@ -0,0 +1,144 @@
+/*
+ * 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.alarm;
+
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Service for interacting with the alarm handling of devices. Unless stated otherwise, getter methods
+ * return active AND recently-cleared alarms.
+ */
+public interface AlarmService extends ListenerService<AlarmEvent, AlarmListener> {
+
+    /**
+     * Update book-keeping (ie administrative) fields for the alarm matching the specified identifier.
+     *
+     * @param id             alarm identifier
+     * @param clear          true if the alarm has to be cleared
+     * @param isAcknowledged new acknowledged state
+     * @param assignedUser   new assigned user, null clear
+     * @return updated alarm (including any recent device-derived changes)
+     */
+    Alarm updateBookkeepingFields(AlarmId id, boolean clear, boolean isAcknowledged, String assignedUser);
+
+    /**
+     * Remove an alarm from ONOS.
+     *
+     * @param id alarm
+     */
+    void remove(AlarmId id);
+
+    /**
+     * Returns summary of alarms on a given device.
+     *
+     * @param deviceId the device
+     * @return map of severity (if applicable) vs alarm counts; empty map if either the device has no alarms or
+     * identified device is not managed.
+     */
+    Map<Alarm.SeverityLevel, Long> getAlarmCounts(DeviceId deviceId);
+
+    /**
+     * Returns summary of alarms on all devices.
+     *
+     * @return map of severity (if applicable) vs alarm counts; empty map if no alarms.
+     */
+    Map<Alarm.SeverityLevel, Long> getAlarmCounts();
+
+    /**
+     * Returns the alarm with the specified identifier.
+     *
+     * @param alarmId alarm identifier
+     * @return alarm matching id; null if no alarm matches the identifier.
+     */
+    Alarm getAlarm(AlarmId alarmId);
+
+    /**
+     * Returns all of the alarms.
+     *
+     * @return set of alarms; empty set if no alarms
+     */
+    Set<Alarm> getAlarms();
+
+    /**
+     * Returns all of the ACTIVE alarms. Recently cleared alarms excluded.
+     *
+     * @return set of alarms; empty set if no alarms
+     */
+    Set<Alarm> getActiveAlarms();
+
+    /**
+     * Returns the alarms with the specified severity.
+     *
+     * @param severity the alarm severity
+     * @return set of alarms with a particular severity; empty set if no alarms
+     */
+    Set<Alarm> getAlarms(Alarm.SeverityLevel severity);
+
+    /**
+     * Returns the alarm matching a given device, regardless of source within that device.
+     *
+     * @param deviceId the device to use when searching alarms.
+     * @return set of alarms; empty set if no alarms
+     */
+    Set<Alarm> getAlarms(DeviceId deviceId);
+
+    /**
+     * Returns all of the ACTIVE alarms for a specific device. Recently cleared alarms excluded.
+     *
+     * @param deviceId the device to use when searching alarms.
+     * @return set of alarms; empty set if no alarms
+     */
+    default Set<Alarm> getActiveAlarms(DeviceId deviceId) {
+        return getActiveAlarms().stream()
+                .filter(a -> deviceId.equals(a.deviceId()))
+                .collect(Collectors.toSet());
+    }
+
+    /**
+     * Returns the alarm for a given device and source.
+     *
+     * @param deviceId the device
+     * @param source   the source within the device
+     * @return set of alarms; empty set if no alarms
+     */
+    Set<Alarm> getAlarms(DeviceId deviceId, AlarmEntityId source);
+
+    /**
+     * Returns the alarm affecting a given link.
+     *
+     * @param src one end of the link
+     * @param dst one end of the link
+     * @return set of alarms; empty set if no alarms
+     */
+    Set<Alarm> getAlarmsForLink(ConnectPoint src, ConnectPoint dst);
+
+    /**
+     * Returns the alarm affecting a given flow.
+     *
+     * @param deviceId the device
+     * @param flowId   the flow
+     * @return set of alarms; empty set if no alarms
+     */
+    Set<Alarm> getAlarmsForFlow(DeviceId deviceId, long flowId);
+
+    // TODO Support retrieving alarms affecting other entity types may be added in future release
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/AlarmTranslator.java b/core/api/src/main/java/org/onosproject/alarm/AlarmTranslator.java
new file mode 100644
index 0000000..ad29535
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/AlarmTranslator.java
@@ -0,0 +1,38 @@
+/*
+ * 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.alarm;
+
+import org.onosproject.net.DeviceId;
+
+import java.io.InputStream;
+import java.util.Collection;
+
+/**
+ * Abstraction of ability to translate device messages into alarms.
+ */
+public interface AlarmTranslator {
+
+    /**
+     * Translates message from device into an alarm with appropriate
+     * information.
+     *
+     * @param deviceId device
+     * @param message message from device to translate to alarm
+     * @return Alarm with information determined by given message
+     */
+    Collection<Alarm> translateToAlarm(DeviceId deviceId, InputStream message);
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/DefaultAlarm.java b/core/api/src/main/java/org/onosproject/alarm/DefaultAlarm.java
new file mode 100644
index 0000000..278be4b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/DefaultAlarm.java
@@ -0,0 +1,401 @@
+/*
+ * 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.alarm;
+
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of an alarm.
+ */
+public final class DefaultAlarm implements Alarm {
+
+    private final AlarmId id;
+
+    private final DeviceId deviceId;
+    private final String description;
+    private final AlarmEntityId source;
+    private final long timeRaised;
+    private final boolean isServiceAffecting;
+    private final boolean isAcknowledged;
+    private final boolean isManuallyClearable;
+    private final String assignedUser;
+
+    private final SeverityLevel severity;
+    private final long timeUpdated;
+    private final Long timeCleared;
+
+
+    //Only for Kryo
+    DefaultAlarm() {
+        id = null;
+        deviceId = null;
+        description = null;
+        source = null;
+        timeRaised = -1;
+        timeUpdated = -1;
+        timeCleared = null;
+        severity = null;
+        isServiceAffecting = false;
+        isAcknowledged = false;
+        isManuallyClearable = false;
+        assignedUser = null;
+    }
+
+    /**
+     * Instantiates a new Default alarm.
+     *
+     * @param id                  the id
+     * @param deviceId            the device id
+     * @param description         the description
+     * @param source              the source, null indicates none.
+     * @param timeRaised          the time raised.
+     * @param timeUpdated         the time last updated.
+     * @param timeCleared         the time cleared, null indicates uncleared.
+     * @param severity            the severity
+     * @param isServiceAffecting  the service affecting
+     * @param isAcknowledged      the acknowledged
+     * @param isManuallyClearable the manually clearable
+     * @param assignedUser        the assigned user, `null` indicates none.
+     */
+    private DefaultAlarm(final AlarmId id,
+                         final DeviceId deviceId,
+                         final String description,
+                         final AlarmEntityId source,
+                         final long timeRaised,
+                         final long timeUpdated,
+                         final Long timeCleared,
+                         final SeverityLevel severity,
+                         final boolean isServiceAffecting,
+                         final boolean isAcknowledged,
+                         final boolean isManuallyClearable,
+                         final String assignedUser) {
+        this.id = id;
+        this.deviceId = deviceId;
+        this.description = description;
+        this.source = source;
+        this.timeRaised = timeRaised;
+        this.timeUpdated = timeUpdated;
+        this.timeCleared = timeCleared;
+        this.severity = severity;
+        this.isServiceAffecting = isServiceAffecting;
+        this.isAcknowledged = isAcknowledged;
+        this.isManuallyClearable = isManuallyClearable;
+        this.assignedUser = assignedUser;
+    }
+
+    @Override
+    public AlarmId id() {
+        return id;
+    }
+
+    @Override
+    public DeviceId deviceId() {
+        return deviceId;
+    }
+
+    @Override
+    public String description() {
+        return description;
+    }
+
+    @Override
+    public AlarmEntityId source() {
+        return source;
+    }
+
+    @Override
+    public long timeRaised() {
+        return timeRaised;
+    }
+
+    @Override
+    public long timeUpdated() {
+        return timeUpdated;
+    }
+
+    @Override
+    public Long timeCleared() {
+        return timeCleared;
+    }
+
+    @Override
+    public SeverityLevel severity() {
+        return severity;
+    }
+
+    @Override
+    public boolean serviceAffecting() {
+        return isServiceAffecting;
+    }
+
+    @Override
+    public boolean acknowledged() {
+        return isAcknowledged;
+    }
+
+    @Override
+    public boolean cleared() {
+        return severity.equals(SeverityLevel.CLEARED);
+    }
+
+    @Override
+    public boolean manuallyClearable() {
+        return isManuallyClearable;
+    }
+
+    @Override
+    public String assignedUser() {
+        return assignedUser;
+    }
+
+    @Override
+    public int hashCode() {
+        // id or timeRaised or timeUpdated may differ
+        return Objects.hash(deviceId, description,
+                            source, timeCleared, severity,
+                            isServiceAffecting, isAcknowledged,
+                            isManuallyClearable, assignedUser);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        // Make sure equals() is tune with hashCode() so works ok in a hashSet !
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final DefaultAlarm other = (DefaultAlarm) obj;
+
+        // id or timeRaised or timeUpdated may differ
+        if (!Objects.equals(this.deviceId, other.deviceId)) {
+            return false;
+        }
+        if (!Objects.equals(this.description, other.description)) {
+            return false;
+        }
+        if (!Objects.equals(this.source, other.source)) {
+            return false;
+        }
+
+        if (!Objects.equals(this.timeCleared, other.timeCleared)) {
+            return false;
+        }
+        if (this.severity != other.severity) {
+            return false;
+        }
+        if (this.isServiceAffecting != other.isServiceAffecting) {
+            return false;
+        }
+        if (this.isAcknowledged != other.isAcknowledged) {
+            return false;
+        }
+        if (this.isManuallyClearable != other.isManuallyClearable) {
+            return false;
+        }
+        if (!Objects.equals(this.assignedUser, other.assignedUser)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("id", id)
+                .add("deviceId", deviceId)
+                .add("description", description)
+                .add("source", source)
+                .add("timeRaised", timeRaised)
+                .add("timeUpdated", timeUpdated)
+                .add("timeCleared", timeCleared)
+                .add("severity", severity)
+                .add("serviceAffecting", isServiceAffecting)
+                .add("acknowledged", isAcknowledged)
+                .add("manuallyClearable", isManuallyClearable)
+                .add("assignedUser", assignedUser)
+                .toString();
+    }
+
+    /**
+     * Builder for the DefaultAlarm object.
+     */
+    public static class Builder {
+
+        // Manadatory fields when constructing alarm ...
+        private AlarmId id;
+        private final DeviceId deviceId;
+        private final String description;
+        private SeverityLevel severity;
+        private final long timeRaised;
+
+        // Optional fields ..
+        private AlarmEntityId source = AlarmEntityId.NONE;
+        private long timeUpdated;
+        private Long timeCleared = null;
+        private boolean isServiceAffecting = false;
+        private boolean isAcknowledged = false;
+        private boolean isManuallyClearable = false;
+        private String assignedUser = null;
+
+        /**
+         * Constructs a Builder to create a Default Alarm based on another alarm.
+         *
+         * @param alarm the other alarm
+         */
+        public Builder(final Alarm alarm) {
+            this(alarm.id(), alarm.deviceId(), alarm.description(), alarm.severity(), alarm.timeRaised());
+            this.source = alarm.source();
+            this.timeUpdated = alarm.timeUpdated();
+            this.timeCleared = alarm.timeCleared();
+            this.isServiceAffecting = alarm.serviceAffecting();
+            this.isAcknowledged = alarm.acknowledged();
+            this.isManuallyClearable = alarm.manuallyClearable();
+            this.assignedUser = alarm.assignedUser();
+
+        }
+
+        /**
+         * Constructs a Builder to create a Default Alarm.
+         *
+         * @param id          the AlarmId
+         * @param deviceId    the device ID
+         * @param description the Alarm description
+         * @param severity    the severity
+         * @param timeRaised  when the alarm was raised
+         */
+        public Builder(final AlarmId id, final DeviceId deviceId,
+                       final String description, final SeverityLevel severity, final long timeRaised) {
+            super();
+            this.id = id;
+            this.deviceId = deviceId;
+            this.description = description;
+            this.severity = severity;
+            this.timeRaised = timeRaised;
+            // Unless specified time-updated is same as raised.
+            this.timeUpdated = timeRaised;
+        }
+
+        /**
+         * Sets the new alarm source.
+         *
+         * @param source the source
+         * @return self for chaining
+         */
+        public Builder forSource(final AlarmEntityId source) {
+            this.source = source;
+            return this;
+        }
+
+        /**
+         * Sets the new alarm time updated.
+         *
+         * @param timeUpdated the time
+         * @return self for chaining
+         */
+        public Builder withTimeUpdated(final long timeUpdated) {
+            this.timeUpdated = timeUpdated;
+            return this;
+        }
+
+        /**
+         * Sets the new alarm time cleared.
+         *
+         * @param timeCleared the time
+         * @return self for chaining
+         */
+        public Builder withTimeCleared(final Long timeCleared) {
+            this.timeCleared = timeCleared;
+            return this;
+        }
+
+        /**
+         * Clears the alarm that is being created.
+         *
+         * @return self for chaining
+         */
+        public Builder clear() {
+            this.severity = SeverityLevel.CLEARED;
+            final long now = System.currentTimeMillis();
+            return withTimeCleared(now).withTimeUpdated(now);
+        }
+
+        /**
+         * Sets the new alarm service affecting flag.
+         *
+         * @param isServiceAffecting the service affecting flag
+         * @return self for chaining
+         */
+        public Builder withServiceAffecting(final boolean isServiceAffecting) {
+            this.isServiceAffecting = isServiceAffecting;
+            return this;
+        }
+
+        /**
+         * Sets the new alarm acknowledged flag.
+         *
+         * @param isAcknowledged the acknowledged flag
+         * @return self for chaining
+         */
+        public Builder withAcknowledged(final boolean isAcknowledged) {
+            this.isAcknowledged = isAcknowledged;
+            return this;
+        }
+
+        /**
+         * Sets the new alarm the manually clearable flag.
+         *
+         * @param isManuallyClearable the manually clearable flag
+         * @return self for chaining
+         */
+        public Builder withManuallyClearable(final boolean isManuallyClearable) {
+            this.isManuallyClearable = isManuallyClearable;
+            return this;
+        }
+
+        /**
+         * Sets the new alarm assigned user.
+         *
+         * @param assignedUser the user
+         * @return self for chaining
+         */
+        public Builder withAssignedUser(final String assignedUser) {
+            this.assignedUser = assignedUser;
+            return this;
+        }
+
+        /**
+         * Builds the alarm.
+         *
+         * @return self for chaining
+         */
+        public DefaultAlarm build() {
+            checkNotNull(id, "Must specify an alarm id");
+            checkNotNull(deviceId, "Must specify a device");
+            checkNotNull(description, "Must specify a description");
+            checkNotNull(severity, "Must specify a severity");
+
+            return new DefaultAlarm(id, deviceId, description, source, timeRaised, timeUpdated, timeCleared,
+                                    severity, isServiceAffecting, isAcknowledged, isManuallyClearable, assignedUser);
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/DeviceAlarmConfig.java b/core/api/src/main/java/org/onosproject/alarm/DeviceAlarmConfig.java
new file mode 100644
index 0000000..8d6146f
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/DeviceAlarmConfig.java
@@ -0,0 +1,52 @@
+/*
+ * 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.alarm;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Abstraction of a device behaviour capable of translating a list of
+ * alarms from a device. Also provides a method to configure the address where to
+ * send the alarms/traps/notifications.
+ */
+public interface DeviceAlarmConfig extends HandlerBehaviour {
+
+    /**
+     * Configures the device to send alarms to a particular Ip and port combination.
+     *
+     * @param address  address to wich the device should send alarms
+     * @param port     port on which the controller is listening
+     * @param protocol tcp or udp
+     * @return boolean true if the device was properly configured
+     */
+    boolean configureDevice(IpAddress address, int port, String protocol);
+
+    /**
+     * Returns the list of translated alarms from device-specific representation
+     * to ONOS alarms.
+     *
+     * @param unparsedAlarms alarms arrived from the device depending on protocol
+     * @param <T> type of object given from the device
+     * @return list of alarms consumed from the device
+     */
+    <T> Set<Alarm> translateAlarms(List<T> unparsedAlarms);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/XmlEventParser.java b/core/api/src/main/java/org/onosproject/alarm/XmlEventParser.java
new file mode 100644
index 0000000..0154cb9
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/XmlEventParser.java
@@ -0,0 +1,105 @@
+/*
+ * 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.alarm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.DateTimeException;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Parser for Netconf notifications.
+ */
+public final class XmlEventParser {
+    public static final Logger log = LoggerFactory
+            .getLogger(XmlEventParser.class);
+
+    private static final String DISALLOW_DTD_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
+    private static final String DISALLOW_EXTERNAL_DTD =
+            "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+    private static final String EVENTTIME_TAGNAME = "eventTime";
+
+    private XmlEventParser() {
+    }
+
+    /**
+     * Creates a document from the input stream message and returns the result.
+     *
+     * @param message input stream message
+     * @return the document result
+     * @throws SAXException Throws SAX Exception
+     * @throws IOException Throws IO Exception
+     * @throws ParserConfigurationException Throws ParserConfigurationException
+     */
+    public static Document createDocFromMessage(InputStream message)
+            throws SAXException, IOException, ParserConfigurationException {
+        DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
+        //Disabling DTDs in order to avoid XXE xml-based attacks.
+        disableFeature(dbfactory, DISALLOW_DTD_FEATURE);
+        disableFeature(dbfactory, DISALLOW_EXTERNAL_DTD);
+        dbfactory.setXIncludeAware(false);
+        dbfactory.setExpandEntityReferences(false);
+        DocumentBuilder builder = dbfactory.newDocumentBuilder();
+        return builder.parse(new InputSource(message));
+    }
+
+    private static void disableFeature(DocumentBuilderFactory dbfactory, String feature) {
+        try {
+            dbfactory.setFeature(feature, true);
+        } catch (ParserConfigurationException e) {
+            // This should catch a failed setFeature feature
+            log.info("ParserConfigurationException was thrown. The feature '" +
+                    feature + "' is probably not supported by your XML processor.");
+        }
+    }
+
+    public static long getEventTime(String dateTime)
+        throws UnsupportedOperationException, IllegalArgumentException {
+        try {
+            OffsetDateTime date = OffsetDateTime.parse(dateTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+            return date.toInstant().toEpochMilli();
+        } catch (DateTimeException e) {
+            log.error("Cannot parse exception {} {}", dateTime, e);
+        }
+        return System.currentTimeMillis();
+    }
+
+    public static long getEventTime(Document doc)
+        throws UnsupportedOperationException, IllegalArgumentException {
+        String dateTime = getEventTimeNode(doc).getTextContent();
+        return getEventTime(dateTime);
+    }
+
+    public static Node getDescriptionNode(Document doc) {
+        return getEventTimeNode(doc).getNextSibling();
+    }
+
+    private static Node getEventTimeNode(Document doc) {
+        return doc.getElementsByTagName(EVENTTIME_TAGNAME).item(0);
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/alarm/package-info.java b/core/api/src/main/java/org/onosproject/alarm/package-info.java
new file mode 100644
index 0000000..4003645
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/alarm/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.
+ */
+/**
+ * Abstractions for interacting with alarms. An alarm is a persistent indication
+ * of a fault that clears only when the triggering condition has been resolved.
+ */
+package org.onosproject.alarm;
diff --git a/core/api/src/main/java/org/onosproject/net/TenantId.java b/core/api/src/main/java/org/onosproject/net/TenantId.java
new file mode 100644
index 0000000..1b8fadb
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/TenantId.java
@@ -0,0 +1,52 @@
+/*
+ * 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.net;
+
+import org.onlab.util.Identifier;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Representation of network tenant.
+ */
+public final class TenantId extends Identifier<String> {
+
+    /**
+     * Represents no tenant, or an unspecified tenant.
+     */
+    public static final TenantId NONE = new TenantId();
+
+    // Public construction is prohibited
+    private TenantId(String id) {
+        super(id);
+        checkArgument(id != null && id.length() > 0, "Tenant ID cannot be null or empty");
+    }
+
+    // Default constructor for serialization
+    protected TenantId() {
+        super("");
+    }
+
+    /**
+     * Creates a tenant id using the supplied backing id.
+     *
+     * @param id network id
+     * @return network identifier
+     */
+    public static TenantId tenantId(String id) {
+        return new TenantId(id);
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/PortDescriptionsConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/PortDescriptionsConfig.java
new file mode 100644
index 0000000..484660e
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/PortDescriptionsConfig.java
@@ -0,0 +1,146 @@
+/*
+ * 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.net.config.basics;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.device.DefaultPortDescription;
+import org.onosproject.net.device.PortDescription;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Configuration for Ports. Creates a list of PortDescription based on the given Json.
+ */
+@Beta
+public class PortDescriptionsConfig extends Config<DeviceId> {
+    private static Logger log = LoggerFactory.getLogger(PortDescriptionsConfig.class);
+
+    private static final String NUMBER = "number";
+    private static final String NAME = "name";
+    private static final String ENABLED = "enabled";
+    private static final String REMOVED = "removed";
+    private static final String TYPE = "type";
+    private static final String SPEED = "speed";
+    private static final String ANNOTATIONS = "annotations";
+
+    private static final String CONFIG_VALUE_ERROR = "Error parsing config value";
+
+    @Override
+    public boolean isValid() {
+        for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext();) {
+            JsonNode nodePort = it.next().getValue();
+            if (!hasOnlyFields((ObjectNode) nodePort, NUMBER, NAME, ENABLED, REMOVED, TYPE,
+                    SPEED, ANNOTATIONS)) {
+                return false;
+            }
+            ObjectNode obj = (ObjectNode) nodePort;
+
+            if (!(isNumber(obj, NUMBER, FieldPresence.MANDATORY) &&
+                    isString(obj, NAME, FieldPresence.OPTIONAL) &&
+                    isBoolean(obj, ENABLED, FieldPresence.OPTIONAL) &&
+                    isBoolean(obj, REMOVED, FieldPresence.OPTIONAL) &&
+                    isString(obj, TYPE, FieldPresence.OPTIONAL) &&
+                    isIntegralNumber(obj, SPEED, FieldPresence.OPTIONAL))) {
+                return false;
+            }
+
+            if (node.has(ANNOTATIONS) && !node.get(ANNOTATIONS).isObject()) {
+                log.error("Annotations must be an inner json node");
+                return false;
+            }
+
+        }
+        return true;
+    }
+
+    /**
+     * Retrieves all port descriptions.
+     *
+     * @return set of port descriptions
+     */
+    public List<PortDescription> portDescriptions() {
+
+        try {
+            ImmutableList.Builder<PortDescription> portDescriptions = ImmutableList.builder();
+            for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext();) {
+                JsonNode portNode = it.next().getValue();
+                long number = portNode.path(NUMBER).asLong();
+
+                String name = portNode.path(NAME).asText(null);
+
+                PortNumber portNumber = createPortNumber(number, name);
+
+                DefaultPortDescription.Builder builder = DefaultPortDescription.builder()
+                        .withPortNumber(portNumber);
+                if (portNode.has(ENABLED)) {
+                    builder.isEnabled(portNode.path(ENABLED).asBoolean());
+                }
+
+                if (portNode.has(REMOVED)) {
+                    builder.isRemoved(portNode.path(REMOVED).asBoolean());
+                }
+
+                if (portNode.has(TYPE)) {
+                    builder.type(Port.Type.valueOf(portNode.path(TYPE).asText().toUpperCase()));
+                }
+
+                if (portNode.has(SPEED)) {
+                    builder.portSpeed(portNode.path(SPEED).asLong());
+                }
+
+                if (portNode.has(ANNOTATIONS)) {
+                    DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder();
+                    Iterator<Map.Entry<String, JsonNode>> annotationsIt = portNode.get(ANNOTATIONS).fields();
+                    while (annotationsIt.hasNext()) {
+                        Map.Entry<String, JsonNode> entry = annotationsIt.next();
+                        annotationsBuilder.set(entry.getKey(), entry.getValue().asText());
+                    }
+                    builder.annotations(annotationsBuilder.build());
+                }
+
+                portDescriptions.add(builder.build());
+            }
+
+            return portDescriptions.build();
+
+        } catch (IllegalArgumentException e) {
+            log.error(CONFIG_VALUE_ERROR, e);
+            return ImmutableList.of();
+        }
+    }
+
+    private PortNumber createPortNumber(long number, String name) {
+        if (name == null) {
+            return PortNumber.portNumber(number);
+        }
+        return PortNumber.portNumber(number, name);
+    }
+
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/statistic/PortStatisticsService.java b/core/api/src/main/java/org/onosproject/net/statistic/PortStatisticsService.java
new file mode 100644
index 0000000..4ed782b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/statistic/PortStatisticsService.java
@@ -0,0 +1,55 @@
+/*
+ * 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.net.statistic;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Service for obtaining statistic information about device ports.
+ */
+@Beta
+public interface PortStatisticsService {
+
+    /** Specifies the type of metric. */
+    enum MetricType {
+        /** Load is to be given in bytes/second. */
+        BYTES,
+
+        /** Load is to be given in packets/second. */
+        PACKETS
+    }
+
+    /**
+     * Obtain the egress load for the given port in terms of bytes per second.
+     *
+     * @param connectPoint the port to query
+     * @return egress traffic load
+     */
+    Load load(ConnectPoint connectPoint);
+
+    /**
+     * Obtain the egress load for the given port in terms of the specified metric.
+     *
+     * @param connectPoint the port to query
+     * @param metricType   metric type
+     * @return egress traffic load
+     */
+    default Load load(ConnectPoint connectPoint, MetricType metricType) {
+        return load(connectPoint);
+    }
+
+}