[ONOS-7262] Cfm improvements to allow RMeps and Mds and Mas to be added and deleted

Change-Id: Ibffb13d046bfb29dbe88de7b558c95fbf9db046d
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceAssociation.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceAssociation.java
index 5d827f6..38c3d6f 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceAssociation.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceAssociation.java
@@ -213,6 +213,12 @@
         }
 
         @Override
+        public MaBuilder removeFromRemoteMepIdList(MepId remoteMep) {
+            this.remoteMepIdList.remove(remoteMep);
+            return this;
+        }
+
+        @Override
         public MaBuilder ccmInterval(CcmInterval ccmInterval) {
             this.ccmInterval = ccmInterval;
             return this;
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociation.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociation.java
index f6e1f3c..37c1a84 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociation.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociation.java
@@ -113,6 +113,8 @@
 
         MaBuilder addToRemoteMepIdList(MepId remoteMep);
 
+        MaBuilder removeFromRemoteMepIdList(MepId remoteMep);
+
         MaBuilder addToComponentList(Component component);
 
         MaBuilder maNumericId(short maNumericId);
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepKeyId.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepKeyId.java
new file mode 100644
index 0000000..afb337b
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepKeyId.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2017-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.incubator.net.l2monitoring.cfm.identifier;
+
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+
+/**
+ * Immutable class to represent a unique identifier of a Mep.
+ */
+public class MepKeyId {
+    private MdId mdId;
+    private MaIdShort maId;
+    private MepId mepId;
+
+    public MepKeyId(MdId mdId, MaIdShort maId, MepId mepId) {
+        this.mdId = mdId;
+        this.maId = maId;
+        this.mepId = mepId;
+        if (mdId == null || maId == null || mepId == null) {
+            throw new IllegalArgumentException("Arguments to MepKeyId constructor cannot be null");
+        }
+    }
+
+    public MepKeyId(Mep mep) {
+        this.mdId = mep.mdId();
+        this.maId = mep.maId();
+        this.mepId = mep.mepId();
+    }
+
+    public MdId mdId() {
+        return mdId;
+    }
+
+    public MaIdShort maId() {
+        return maId;
+    }
+
+    public MepId mepId() {
+        return mepId;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        MepKeyId mepKeyId = (MepKeyId) o;
+
+        if (mdId != null ? !mdId.equals(mepKeyId.mdId) : mepKeyId.mdId != null) {
+            return false;
+        }
+        if (maId != null ? !maId.equals(mepKeyId.maId) : mepKeyId.maId != null) {
+            return false;
+        }
+        return mepId != null ? mepId.equals(mepKeyId.mepId) : mepKeyId.mepId == null;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mdId != null ? mdId.hashCode() : 0;
+        result = 31 * result + (maId != null ? maId.hashCode() : 0);
+        result = 31 * result + (mepId != null ? mepId.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return mdId.mdName() + "/" + maId.maName() + "/" + mepId();
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMdService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMdService.java
index 9c9aa46..b495eb9 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMdService.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMdService.java
@@ -18,6 +18,7 @@
 import java.util.Collection;
 import java.util.Optional;
 
+import org.onosproject.event.ListenerService;
 import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
 import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
 import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
@@ -26,7 +27,7 @@
 /**
  * For the management of Maintenance Domains and Maintenance Associations.
  */
-public interface CfmMdService {
+public interface CfmMdService extends ListenerService<MdEvent, MdListener> {
 
     /**
      * Get a list of all of the Maintenance Domains on the system.
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepEvent.java
index 26abc45..cb96b52 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepEvent.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepEvent.java
@@ -16,12 +16,12 @@
 package org.onosproject.incubator.net.l2monitoring.cfm.service;
 
 import org.onosproject.event.AbstractEvent;
-import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
 
 /**
  * Event related to the maintenance of CFM MEPs.
  */
-public class CfmMepEvent extends AbstractEvent<CfmMepEvent.Type, Mep> {
+public class CfmMepEvent extends AbstractEvent<CfmMepEvent.Type, MepKeyId> {
 
     /**
      * Type of Mep events.
@@ -52,10 +52,9 @@
      * Creates an event of a given type and for the specified Mep and the current time.
      *
      * @param type Mep event type
-     * @param mep event Mep subject
+     * @param mepKeyId event Mep subject
      */
-    protected CfmMepEvent(Type type, Mep mep) {
-        super(type, mep);
-        // TODO Auto-generated constructor stub
+    public CfmMepEvent(Type type, MepKeyId mepKeyId) {
+        super(type, mepKeyId);
     }
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepProgrammable.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepProgrammable.java
index b92777b..1b902cb 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepProgrammable.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepProgrammable.java
@@ -15,14 +15,95 @@
  */
 package org.onosproject.incubator.net.l2monitoring.cfm.service;
 
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
 import org.onosproject.net.driver.HandlerBehaviour;
 
+import java.util.Optional;
+
 /**
  * Behaviour that allows Layer 2 Monitoring as defined in IEEE 802.1Q be implemented by devices.
  *
  * Has all of the same methods as
- * {@link org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService} so reuse that
+ * {@link CfmMepServiceBase} so reuse that
  */
-public interface CfmMepProgrammable extends HandlerBehaviour, CfmMepService {
+public interface CfmMepProgrammable extends HandlerBehaviour, CfmMepServiceBase {
+
+
+    /**
+     * Allows an MD and children MAs to be created on a device.
+     * A convenience method that allows an MD to be created on a device
+     * This is a preparation mechanism. If this was not called the MD would be created
+     * at the time of provisioning a MEP anyway
+     * @param mdId The ID of the MD to create - the details will be got from the CfmMdService
+     * @return true when created. false if it already existed
+     * @throws CfmConfigException If the MD already exists
+     */
+    boolean createMdOnDevice(MdId mdId) throws CfmConfigException;
+
+    /**
+     * Allows an MA to be created on an existing MD on a device.
+     * A convenience method that allows an MA to be created
+     * This is a preparation mechanism. If this was not called the MA would be created
+     * at the time of provisioning a MEP anyway. Also MAs can be created when they
+     * are contained in an MD using the createMdOnDevice method
+     * @param mdId The identifier of the MD to create the MA in
+     * @param maId The identifier of the MA to create - the details will be retrieved from the CfmMdService
+     * @return true when created. false if it already existed
+     * @throws CfmConfigException If the MD already exists
+     */
+    boolean createMaOnDevice(MdId mdId, MaIdShort maId) throws CfmConfigException;
+
+    /**
+     * Allows a MD and its MAs to be deleted from a device.
+     * A convenience method that allows an MD that has been provisioned on a
+     * device to be removed.
+     * All Meps must be removed first unless they are Meps unknown to ONOS.
+     * This is a cleanup mechanism. Deleting Meps in the normal way does not celan
+     * up MDs and MAs
+     * @param mdId The identifier of the MD
+     * @param oldMd The MaintenanceDomain that is being deleted
+     * @return true when deleted. false if it did not exist
+     * @throws CfmConfigException If the MD has any MAs that have MEPs then this will fail
+     */
+    boolean deleteMdOnDevice(MdId mdId, Optional<MaintenanceDomain> oldMd) throws CfmConfigException;
+
+    /**
+     * Allows an MA to be deleted from an MD on a device.
+     * A convenience method that allows an MA that has been provisioned on a
+     * device to be removed.
+     * All Meps must be removed first unless they are Meps unknown to ONOS.
+     * This is a cleanup mechanism. Deleting Meps in the normal way does not celan
+     * up MDs and MAs
+     * @param mdId The identifier of the MD
+     * @param maId The identifier of the MA
+     * @param oldMd The MaintenanceDomain from which the MA is being deleted
+     * @return true when deleted. false if it did not exist
+     * @throws CfmConfigException If the MA has any MEPs then this will fail
+     */
+    boolean deleteMaOnDevice(MdId mdId, MaIdShort maId,
+                             Optional<MaintenanceDomain> oldMd) throws CfmConfigException;
+
+    /**
+     * Creates a Remote Mep entry on an MA.
+     * @param mdId The identifier of the MD
+     * @param maId The identifier of the MA
+     * @param remoteMep The remote Mep Id to remove from the MA
+     * @return true when deleted. false if it did not exist
+     * @throws CfmConfigException If the MA does not exist this will fail
+     */
+    boolean createMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException;
+
+    /**
+     * Deletes a Remote Mep entry on an MA.
+     * @param mdId The identifier of the MD
+     * @param maId The identifier of the MA
+     * @param remoteMep The remote Mep Id to remove from the MA
+     * @return true when deleted. false if it did not exist
+     * @throws CfmConfigException If the MA does not exist this will fail
+     */
+    boolean deleteMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException;
 
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepService.java
index c0c2f92..c774c65 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepService.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepService.java
@@ -17,13 +17,12 @@
 
 import java.util.Collection;
 
+import org.onosproject.event.ListenerService;
 import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
 import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
-import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
-import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
 import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
 import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
-import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.net.DeviceId;
 
 /**
  * For the management of Maintenance Association Endpoints.
@@ -31,7 +30,8 @@
  * These are dependent on the Maintenance Domain service which maintains the
  * Maintenance Domain and Maintenance Associations
  */
-public interface CfmMepService {
+public interface CfmMepService
+        extends ListenerService<CfmMepEvent, CfmMepListener>, CfmMepServiceBase {
     /**
      * Retrieve all {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry}(s) belonging to an MA.
      * @param mdName A Maintenance Domain
@@ -43,67 +43,13 @@
             throws CfmConfigException;
 
     /**
-     * Retrieve a named {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry} belonging to an MA.
-     * @param mdName A Maintenance Domain
-     * @param maName A Maintetance Association in the MD
-     * @param mepId A Mep Id
-     * @return A MEP Entry or null if none found
-     * @throws CfmConfigException If there a problem with the MD, MA or MEP
-     */
-    MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId)
-            throws CfmConfigException;
-
-    /**
-     * Delete a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} belonging to an MA.
-     * @param mdName A Maintenance Domain
-     * @param maName A Maintetance Association in the MD
-     * @param mepId A Mep Id
-     * @return true if the MEP was deleted successfully. false if it was not found
+     * Retrieve all {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep}(s) belonging to an MA.
+     * Note: This just returns the configuration part of the Mep, not the MepEntry
+     * which contains config and state
+     * @param deviceId A device id
+     * @return A collection of MEP Entries
      * @throws CfmConfigException If there a problem with the MD or MA
      */
-    boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId)
+    Collection<Mep> getAllMepsByDevice(DeviceId deviceId)
             throws CfmConfigException;
-
-    /**
-     * Create a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} on an MA.
-     * @param mdName A Maintenance Domain
-     * @param maName A Maintetance Association in the MD
-     * @param mep A Mep object
-     * @return False if it was created successfully. True if the object already exists.
-     * @throws CfmConfigException If there a problem with the MD, MA or MEP
-     */
-    boolean createMep(MdId mdName, MaIdShort maName, Mep mep)
-            throws CfmConfigException;
-
-    /**
-     * Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep.
-     * @param mdName A Maintenance Domain
-     * @param maName A Maintetance Association in the MD
-     * @param mepId A Mep Id
-     * @param lbCreate The Loopback session details
-     * @throws CfmConfigException If there a problem with the MD, MA or MEP
-     */
-    void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId,
-            MepLbCreate lbCreate) throws CfmConfigException;
-
-    /**
-     * Abort a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep.
-     * @param mdName A Maintenance Domain
-     * @param maName A Maintetance Association in the MD
-     * @param mepId A Mep Id
-     * @throws CfmConfigException If there a problem with the MD, MA or MEP
-     */
-    void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId)
-            throws CfmConfigException;
-
-    /**
-     * Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtEntry Linktrace} session on the named Mep.
-     * @param mdName A Maintenance Domain
-     * @param maName A Maintetance Association in the MD
-     * @param mepId A Mep Id
-     * @param ltCreate The Linktrace session details
-     * @throws CfmConfigException If there a problem with the MD, MA or MEP
-     */
-    void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
-            MepLtCreate ltCreate) throws CfmConfigException;
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepServiceBase.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepServiceBase.java
new file mode 100644
index 0000000..71e5611
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepServiceBase.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017-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.incubator.net.l2monitoring.cfm.service;
+
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+
+import java.util.Optional;
+
+public interface CfmMepServiceBase {
+    /**
+     * Retrieve a named {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry} belonging to an MA.
+     * @param mdName A Maintenance Domain
+     * @param maName A Maintetance Association in the MD
+     * @param mepId A Mep Id
+     * @return A MEP Entry or null if none found
+     * @throws CfmConfigException If there a problem with the MD, MA or MEP
+     */
+    MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException;
+
+    /**
+     * Delete a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} belonging to an MA.
+     * @param mdName A Maintenance Domain
+     * @param maName A Maintetance Association in the MD
+     * @param mepId A Mep Id
+     * @param oldMd The MaintenanceDomain from which the MEP is being deleted
+     * @return true if the MEP was deleted successfully. false if it was not found
+     * @throws CfmConfigException If there a problem with the MD or MA
+     */
+    boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId, Optional<MaintenanceDomain> oldMd)
+            throws CfmConfigException;
+
+    /**
+     * Create a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} on an MA.
+     * @param mdName A Maintenance Domain
+     * @param maName A Maintetance Association in the MD
+     * @param mep A Mep object
+     * @return True if it was created successfully. False if the object already exists.
+     * @throws CfmConfigException If there a problem with the MD, MA or MEP
+     */
+    boolean createMep(MdId mdName, MaIdShort maName, Mep mep)
+            throws CfmConfigException;
+
+    /**
+     * Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep.
+     * @param mdName A Maintenance Domain
+     * @param maName A Maintetance Association in the MD
+     * @param mepId A Mep Id
+     * @param lbCreate The Loopback session details
+     * @throws CfmConfigException If there a problem with the MD, MA or MEP
+     */
+    void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId,
+                          MepLbCreate lbCreate) throws CfmConfigException;
+
+    /**
+     * Abort a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep.
+     * @param mdName A Maintenance Domain
+     * @param maName A Maintetance Association in the MD
+     * @param mepId A Mep Id
+     * @throws CfmConfigException If there a problem with the MD, MA or MEP
+     */
+    void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException;
+
+    /**
+     * Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtEntry Linktrace} session on the named Mep.
+     * @param mdName A Maintenance Domain
+     * @param maName A Maintetance Association in the MD
+     * @param mepId A Mep Id
+     * @param ltCreate The Linktrace session details
+     * @throws CfmConfigException If there a problem with the MD, MA or MEP
+     */
+    void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
+                           MepLtCreate ltCreate) throws CfmConfigException;
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdEvent.java
index e3090f7..49023d4 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdEvent.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdEvent.java
@@ -15,24 +15,78 @@
  */
 package org.onosproject.incubator.net.l2monitoring.cfm.service;
 
+import com.google.common.base.MoreObjects;
+import org.onlab.util.Tools;
 import org.onosproject.event.AbstractEvent;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
 import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
 
+import java.util.Optional;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
 /**
  * Event related to the maintenance of CFM MDs.
  */
 public class MdEvent extends AbstractEvent<MdEvent.Type, MdId> {
 
+    private MaIdShort maId;
+    private MaintenanceDomain oldMd;
     /**
      * MD Event types supported.
      */
     public enum Type {
         MD_ADDED,
         MD_REMOVED,
-        MD_UPDATED
+        MD_UPDATED,
+        MA_ADDED,
+        MA_REMOVED
     }
 
     public MdEvent(Type type, MdId mdId) {
         super(type, mdId);
     }
+
+    /**
+     * Constructor that allows the MD to be held in the event.
+     * This is useful if the MD had been deleted - it will be the only way of
+     * retrieving some of its attributes
+     * @param type The type of the event
+     * @param mdId The ID of the MD
+     * @param md The whole MD
+     * @throws CfmConfigException if there's a problem copying MD
+     */
+    public MdEvent(Type type, MdId mdId, MaintenanceDomain md) throws CfmConfigException {
+        super(type, mdId);
+        this.oldMd = DefaultMaintenanceDomain.builder(md).build();
+    }
+
+    public MdEvent(Type type, MdId mdId, MaintenanceDomain md, MaIdShort maId)
+            throws CfmConfigException {
+        super(type, mdId);
+        this.maId = maId;
+        this.oldMd = DefaultMaintenanceDomain.builder(md).build();
+    }
+
+    public Optional<MaIdShort> maId() {
+        return maId == null ? Optional.empty() : Optional.of(maId);
+    }
+
+    public Optional<MaintenanceDomain> md() {
+        return oldMd == null ? Optional.empty() : Optional.of(oldMd);
+    }
+
+    @Override
+    public String toString() {
+        MoreObjects.ToStringHelper helper = toStringHelper(this)
+                .add("time", Tools.defaultOffsetDataTime(time()))
+                .add("type", type())
+                .add("subject", subject());
+        if (maId != null) {
+            helper = helper.add("subject2", maId);
+        }
+        return helper.toString();
+    }
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStore.java
new file mode 100644
index 0000000..ed4bb35
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStore.java
@@ -0,0 +1,84 @@
+/*
+ * 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.incubator.net.l2monitoring.cfm.service;
+
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.Store;
+
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep Maintenance Association Endpoint's} storage interface.
+ * Note: because the Mep is immutable if anything needs to be
+ * changed in it, then it must be replaced in the store.
+ */
+public interface MepStore extends Store<CfmMepEvent, MepStoreDelegate> {
+    /**
+     * Get a list of all of the Meps on the system.
+     * @return A collection Meps from the Mep Store.
+     */
+    Collection<Mep> getAllMeps();
+
+    /**
+     * Get all Meps by MD.
+     * @param mdName An identifier for the Maintenance Domain
+     * @return MEPs from the MEP Store. Empty if not found.
+     */
+    Collection<Mep> getMepsByMd(MdId mdName);
+
+    /**
+     * Get all Meps by MD, MA.
+     * @param mdName An identifier for the Maintenance Domain
+     * @param maName An identifier for the Maintenance Association
+     * @return MEPs from the MEP Store. Empty if not found.
+     */
+    Collection<Mep> getMepsByMdMa(MdId mdName, MaIdShort maName);
+
+    /**
+     * Get all Meps by DeviceId.
+     * @param deviceId An identifier for the Device
+     * @return MEPs from the MEP Store. Empty if not found.
+     */
+    Collection<Mep> getMepsByDeviceId(DeviceId deviceId);
+
+    /**
+     * Get a specific Mep by its Mep key id.
+     * @param mepKeyId An unique identifier for the MEP
+     * @return A MEP from the MEP Store. Empty if not found.
+     */
+    Optional<Mep> getMep(MepKeyId mepKeyId);
+
+    /**
+     * Delete a specific Mep by its identifier.
+     * @param mepKeyId An unique identifier for the MEP
+     * @return True if the Mep was found and deleted
+     */
+    boolean deleteMep(MepKeyId mepKeyId);
+
+    /**
+     * Create or replace a Mep.
+     * @param mepKeyId An unique identifier for the MEP
+     * @param mep The new MEP
+     * @return true if an Mep of this name already existed
+     */
+    boolean createUpdateMep(MepKeyId mepKeyId, Mep mep);
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStoreDelegate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStoreDelegate.java
new file mode 100644
index 0000000..6d5dfd3
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * 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.incubator.net.l2monitoring.cfm.service;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Delegate for MEP Store.
+ */
+public interface MepStoreDelegate extends StoreDelegate<CfmMepEvent> {
+}