P4-related cherry-picks for 1.12

Squashed. Includes the following commits from master:

8b19a07297 Fixed onos.py
74174bf177 Fix 'unable to translate flow rule' in p4-tutorial icmpdropper
4555c5f308 Minor refactoring of BMv2 mininet scripts
07b2b70f53 Refactored PI-ECMP app to use action profiles of basic.p4
6ffd3772b7 ONOS-7050 First stab at PI translation store
2d4271fc20 ONOS-7050 Refactored PI translation service and store
3874b44821 ONOS-7050 Refactored P4Runtime FRP to use distributed stores
41efe435be ONOS-7050 Refactored P4Runtime GP to use distributed stores
806f7b7418 ONOS-6810 Implement Mastership handling in general DeviceProvider
c7922a4b40 ONOS-7267 Fix pipeconf UI

Change-Id: I279b6477f48ebec768b494799feb12faadbd559c
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
index 27a604c..b62007f 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
@@ -18,12 +18,13 @@
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.pi.service.PiTranslatable;
 
 /**
  * Represents a generalized match & action pair to be applied to an
  * infrastructure device.
  */
-public interface FlowRule {
+public interface FlowRule extends PiTranslatable {
 
     IndexTableId DEFAULT_TABLE = IndexTableId.of(0);
     int MAX_TIMEOUT = 60;
diff --git a/core/api/src/main/java/org/onosproject/net/group/Group.java b/core/api/src/main/java/org/onosproject/net/group/Group.java
index 3e2494c..39c6a3d 100644
--- a/core/api/src/main/java/org/onosproject/net/group/Group.java
+++ b/core/api/src/main/java/org/onosproject/net/group/Group.java
@@ -16,11 +16,12 @@
 package org.onosproject.net.group;
 
 import org.onosproject.core.GroupId;
+import org.onosproject.net.pi.service.PiTranslatable;
 
 /**
  * ONOS representation of group that is stored in the system.
  */
-public interface Group extends GroupDescription {
+public interface Group extends GroupDescription, PiTranslatable {
     /**
      * State of the group object in ONOS.
      */
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroup.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroup.java
index 1d9a94b..9084bea 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroup.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroup.java
@@ -34,7 +34,7 @@
  * Instance of an action group of a protocol-independent pipeline.
  */
 @Beta
-public final class PiActionGroup {
+public final class PiActionGroup implements PiEntity {
 
     private final PiActionGroupId id;
     private final PiActionGroupType type;
@@ -125,6 +125,11 @@
         return new Builder();
     }
 
+    @Override
+    public PiEntityType piEntityType() {
+        return PiEntityType.GROUP;
+    }
+
     /**
      * Builder of action groups.
      */
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroupHandle.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroupHandle.java
new file mode 100644
index 0000000..25a035b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroupHandle.java
@@ -0,0 +1,77 @@
+/*
+ * 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.net.pi.runtime;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Global identifier of a PI action group applied to a device, uniquely defined
+ * by a device ID, action profile ID and group ID.
+ */
+@Beta
+public final class PiActionGroupHandle extends PiHandle<PiActionGroup> {
+
+    private PiActionGroupHandle(DeviceId deviceId, PiActionGroup group) {
+        super(deviceId, group);
+    }
+
+    /**
+     * Creates a new handle for the given device ID and PI action group.
+     *
+     * @param deviceId device ID
+     * @param group PI action group
+     * @return PI action group handle
+     */
+    public static PiActionGroupHandle of(DeviceId deviceId,
+                                         PiActionGroup group) {
+        return new PiActionGroupHandle(deviceId, group);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(deviceId(),
+                                piEntity().actionProfileId(),
+                                piEntity().id());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiActionGroupHandle that = (PiActionGroupHandle) o;
+        return Objects.equal(deviceId(), that.deviceId()) &&
+                Objects.equal(piEntity().actionProfileId(),
+                              that.piEntity().actionProfileId()) &&
+                Objects.equal(piEntity().id(), piEntity().id());
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("deviceId", deviceId())
+                .add("actionProfileId", piEntity().actionProfileId())
+                .add("groupId", piEntity().id())
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntity.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntity.java
new file mode 100644
index 0000000..c3d5a01
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntity.java
@@ -0,0 +1,34 @@
+/*
+ * 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.net.pi.runtime;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Abstraction of an entity of a protocol-independent that can be read or write
+ * at runtime.
+ */
+@Beta
+public interface PiEntity {
+
+    /**
+     * Returns the type of this entity.
+     *
+     * @return entity type
+     */
+    PiEntityType piEntityType();
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntityType.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntityType.java
new file mode 100644
index 0000000..e01e520
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntityType.java
@@ -0,0 +1,35 @@
+/*
+ * 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.net.pi.runtime;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Type of runtime entity of a protocol-independent pipeline.
+ */
+@Beta
+public enum PiEntityType {
+    /**
+     * Table entry.
+     */
+    TABLE_ENTRY,
+
+    /**
+     * Action profile group.
+     */
+    GROUP
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiHandle.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiHandle.java
new file mode 100644
index 0000000..e8e70d1
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiHandle.java
@@ -0,0 +1,74 @@
+/*
+ * 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.net.pi.runtime;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.DeviceId;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Global identifier of a PI entity applied to a device, unique in the scope of
+ * the whole network.
+ */
+@Beta
+public abstract class PiHandle<E extends PiEntity> {
+
+    private final DeviceId deviceId;
+    private final E piEntity;
+
+    protected PiHandle(DeviceId deviceId, E piEntity) {
+        this.deviceId = checkNotNull(deviceId);
+        this.piEntity = checkNotNull(piEntity);
+    }
+
+    /**
+     * Returns the device ID of this handle.
+     *
+     * @return device ID
+     */
+    public final DeviceId deviceId() {
+        return deviceId;
+    }
+
+    /**
+     * Returns the type of entity identified by this handle.
+     *
+     * @return PI entity type
+     */
+    public final PiEntityType entityType() {
+        return piEntity.piEntityType();
+    }
+
+    /**
+     * The entity to which this handle is associated.
+     *
+     * @return PI entity
+     */
+    public final E piEntity() {
+        return piEntity;
+    }
+
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public abstract boolean equals(Object obj);
+
+    @Override
+    public abstract String toString();
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntry.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntry.java
index cd7e493..5770c6b 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntry.java
@@ -30,7 +30,7 @@
  * Instance of a table entry in a protocol-independent pipeline.
  */
 @Beta
-public final class PiTableEntry {
+public final class PiTableEntry implements PiEntity {
 
     public static final PiTableEntry EMTPY = new PiTableEntry();
 
@@ -160,6 +160,11 @@
         return new Builder();
     }
 
+    @Override
+    public PiEntityType piEntityType() {
+        return PiEntityType.TABLE_ENTRY;
+    }
+
     public static final class Builder {
 
         private PiTableId tableId;
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntryHandle.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntryHandle.java
new file mode 100644
index 0000000..7eeb7f6
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntryHandle.java
@@ -0,0 +1,77 @@
+/*
+ * 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.net.pi.runtime;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Global identifier of a PI table entry applied on a device, uniquely defined
+ * by a device ID, table ID and match key.
+ */
+@Beta
+public final class PiTableEntryHandle extends PiHandle<PiTableEntry> {
+
+    private PiTableEntryHandle(DeviceId deviceId, PiTableEntry entry) {
+        super(deviceId, entry);
+    }
+
+    /**
+     * Creates a new handle for the given PI table entry and device ID.
+     *
+     * @param deviceId device ID
+     * @param entry    PI table entry
+     * @return PI table entry handle
+     */
+    public static PiTableEntryHandle of(DeviceId deviceId, PiTableEntry entry) {
+        return new PiTableEntryHandle(deviceId, entry);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(deviceId(),
+                                piEntity().table(),
+                                piEntity().matchKey());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final PiTableEntryHandle other = (PiTableEntryHandle) obj;
+        return Objects.equal(this.deviceId(), other.deviceId())
+                && Objects.equal(this.piEntity().table(),
+                                 other.piEntity().table())
+                && Objects.equal(this.piEntity().matchKey(),
+                                 other.piEntity().matchKey());
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("deviceId", deviceId())
+                .add("tableId", piEntity().table())
+                .add("matchKey", piEntity().matchKey())
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslationStore.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslationStore.java
new file mode 100644
index 0000000..a80de10
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslationStore.java
@@ -0,0 +1,30 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.pi.runtime.PiTableEntry;
+
+/**
+ * A PI translation store that keeps track of which flow rules have been
+ * translated to which PI table entries.
+ */
+@Beta
+public interface PiFlowRuleTranslationStore
+        extends PiTranslationStore<FlowRule, PiTableEntry> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslator.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslator.java
new file mode 100644
index 0000000..cc82f73
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslator.java
@@ -0,0 +1,29 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.pi.runtime.PiTableEntry;
+
+/**
+ * A translator of flow rules to PI table entries.
+ */
+@Beta
+public interface PiFlowRuleTranslator
+        extends PiTranslator<FlowRule, PiTableEntry> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslationStore.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslationStore.java
new file mode 100644
index 0000000..4fe526a
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslationStore.java
@@ -0,0 +1,30 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+
+/**
+ * A PI translation store that keeps track of which groups have been
+ * translated to which PI action groups.
+ */
+@Beta
+public interface PiGroupTranslationStore
+        extends PiTranslationStore<Group, PiActionGroup> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslator.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslator.java
new file mode 100644
index 0000000..d5eb5af
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslator.java
@@ -0,0 +1,29 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+
+/**
+ * A translator of groups to PI action groups.
+ */
+@Beta
+public interface PiGroupTranslator
+        extends PiTranslator<Group, PiActionGroup> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatable.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatable.java
new file mode 100644
index 0000000..316c3ed
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatable.java
@@ -0,0 +1,27 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Abstraction of protocol-dependent (PD) entity that can be translated to an
+ * equivalent protocol-independent (PI) one.
+ */
+@Beta
+public interface PiTranslatable {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatedEntity.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatedEntity.java
new file mode 100644
index 0000000..4ca094b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatedEntity.java
@@ -0,0 +1,85 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiEntityType;
+import org.onosproject.net.pi.runtime.PiHandle;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of the result of a PD-to-PI translation associated to a PI
+ * entity handle.
+ */
+@Beta
+public final class PiTranslatedEntity<T extends PiTranslatable, E extends PiEntity> {
+
+    private final T original;
+    private final E translated;
+    private final PiHandle<E> handle;
+
+    /**
+     * Creates a new translated entity.
+     *
+     * @param original PD entity
+     * @param translated PI entity
+     * @param handle PI entity handle
+     */
+    public PiTranslatedEntity(T original, E translated, PiHandle<E> handle) {
+        this.original = checkNotNull(original);
+        this.translated = checkNotNull(translated);
+        this.handle = checkNotNull(handle);
+    }
+
+    /**
+     * Returns the type of the translated entity.
+     *
+     * @return type of the translated entity
+     */
+    public final PiEntityType entityType() {
+        return translated.piEntityType();
+    }
+
+    /**
+     * Returns the original PD entity.
+     *
+     * @return instance of PI translatable entity
+     */
+    public final T original() {
+        return original;
+    }
+
+    /**
+     * Returns the translated PI entity.
+     *
+     * @return PI entity
+     */
+    public final E translated() {
+        return translated;
+    }
+
+    /**
+     * Returns the PI entity handle.
+     *
+     * @return PI entity handle
+     */
+    public final PiHandle<E> handle() {
+        return handle;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationEvent.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationEvent.java
new file mode 100644
index 0000000..9e2411d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationEvent.java
@@ -0,0 +1,57 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.pi.runtime.PiEntity;
+
+/**
+ * Signals an event related to the translation of a protocol-dependent (PD)
+ * entity to a protocol-independent (PI) one.
+ */
+@Beta
+public final class PiTranslationEvent<T extends PiTranslatable, E extends PiEntity>
+        extends AbstractEvent<PiTranslationEvent.Type, PiTranslatedEntity<T, E>> {
+
+    /**
+     * Type of event.
+     */
+    public enum Type {
+        /**
+         * Signals that A PD entity has been translated to a PI one, and the
+         * mapping between the two entities has been learned by the system.
+         */
+        LEARNED,
+
+        /**
+         * Signals that a previously learned mapping between a PD entity and its
+         * PI counterpart has been removed.
+         */
+        FORGOT,
+    }
+
+    /**
+     * Creates a new translation event.
+     *
+     * @param type    type of event
+     * @param subject subject of event
+     */
+    public PiTranslationEvent(Type type, PiTranslatedEntity<T, E> subject) {
+        super(type, subject);
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationException.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationException.java
new file mode 100644
index 0000000..d8a6c63
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Signals that an error was encountered while translating an entity.
+ */
+@Beta
+public final class PiTranslationException extends Exception {
+
+    /**
+     * Creates a new exception with the given message.
+     *
+     * @param message a message
+     */
+    public PiTranslationException(String message) {
+        super(message);
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java
index 210b7e0..c7a95c3 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java
@@ -17,54 +17,25 @@
 package org.onosproject.net.pi.service;
 
 import com.google.common.annotations.Beta;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.pi.model.PiPipeconf;
-import org.onosproject.net.pi.runtime.PiActionGroup;
-import org.onosproject.net.pi.runtime.PiTableEntry;
 
 /**
- * A service to translate protocol-dependent entities to protocol-independent ones.
+ * A service to translate protocol-dependent (PD) entities to
+ * protocol-independent (PI) ones.
  */
 @Beta
 public interface PiTranslationService {
 
     /**
-     * Returns a PI table entry equivalent to the given flow rule for the given protocol-independent pipeline
-     * configuration.
+     * Returns a flow rule translator.
      *
-     * @param rule     a flow rule
-     * @param pipeconf a pipeline configuration
-     * @return a table entry
-     * @throws PiTranslationException if the flow rule cannot be translated
+     * @return flow rule translator
      */
-    PiTableEntry translateFlowRule(FlowRule rule, PiPipeconf pipeconf)
-            throws PiTranslationException;
+    PiFlowRuleTranslator flowRuleTranslator();
 
     /**
-     * Returns a PI action group equivalent to the given group for the given protocol-independent pipeline
-     * configuration.
+     * Returns a group translator.
      *
-     * @param group    a group
-     * @param pipeconf a pipeline configuration
-     * @return a PI action group
-     * @throws PiTranslationException if the group cannot be translated
+     * @return group translator
      */
-    PiActionGroup translateGroup(Group group, PiPipeconf pipeconf)
-            throws PiTranslationException;
-
-    /**
-     * Signals that an error was encountered while translating an entity.
-     */
-    class PiTranslationException extends Exception {
-
-        /**
-         * Creates a new exception with the given message.
-         *
-         * @param message a message
-         */
-        public PiTranslationException(String message) {
-            super(message);
-        }
-    }
+    PiGroupTranslator groupTranslator();
 }
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStore.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStore.java
new file mode 100644
index 0000000..6274deb
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStore.java
@@ -0,0 +1,60 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiHandle;
+import org.onosproject.store.Store;
+
+/**
+ * PI translation store abstraction that maintains a mapping between a PI entity
+ * handle and a translated entity.
+ *
+ * @param <T> PD entity class (translatable to PI)
+ * @param <E> PI entity class
+ */
+@Beta
+public interface PiTranslationStore<T extends PiTranslatable, E extends PiEntity>
+        extends Store<PiTranslationEvent<T, E>, PiTranslationStoreDelegate<T, E>> {
+
+    /**
+     * Adds or update a mapping between the given PI entity handle and
+     * translated entity.
+     *
+     * @param handle PI entity handle
+     * @param entity PI translated entity
+     */
+    void addOrUpdate(PiHandle<E> handle, PiTranslatedEntity<T, E> entity);
+
+    /**
+     * Returns a PI translated entity for the given handle. Returns null if this
+     * store does not contain a mapping between the two for the given pipeconf
+     * ID.
+     *
+     * @param handle PI entity handle
+     * @return PI translated entity
+     */
+    PiTranslatedEntity<T, E> get(PiHandle<E> handle);
+
+    /**
+     * Removes a previously added mapping for the given PI entity handle.
+     *
+     * @param handle PI entity handle
+     */
+    void remove(PiHandle<E> handle);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStoreDelegate.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStoreDelegate.java
new file mode 100644
index 0000000..2a8d16f
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStoreDelegate.java
@@ -0,0 +1,33 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * PI translation store delegate abstraction.
+ *
+ * @param <T> PD entity class (translatable to PI)
+ * @param <E> PI entity class
+ */
+@Beta
+public interface PiTranslationStoreDelegate
+        <T extends PiTranslatable, E extends PiEntity>
+        extends StoreDelegate<PiTranslationEvent<T, E>> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslator.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslator.java
new file mode 100644
index 0000000..202636a
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslator.java
@@ -0,0 +1,75 @@
+/*
+ * 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.net.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiHandle;
+
+import java.util.Optional;
+
+/**
+ * A translator of PI entities to equivalent PD ones which offer means to learn
+ * translated entities for later use.
+ *
+ * @param <T> PD entity class (translatable to PI)
+ * @param <E> PI entity class
+ */
+@Beta
+public interface PiTranslator<T extends PiTranslatable, E extends PiEntity> {
+
+    /**
+     * Translate the given PD entity (original) and returns a PI entity that is
+     * equivalent to he PD one for the given pipeconf.
+     *
+     * @param original PD entity
+     * @param pipeconf pipeconf
+     * @return PI entity
+     * @throws PiTranslationException if a translation is not possible (see
+     *                                message for an explanation)
+     */
+    E translate(T original, PiPipeconf pipeconf)
+            throws PiTranslationException;
+
+    /**
+     * Stores a mapping between the given translated entity and handle.
+     *
+     * @param handle PI entity handle
+     * @param entity PI translated entity
+     */
+    void learn(PiHandle<E> handle, PiTranslatedEntity<T, E> entity);
+
+    /**
+     * Returns a PI translated entity that was previously associated with the
+     * given  handle, if present. If not present, it means a mapping between the
+     * two has not been learned by the system (via {@link #learn(PiHandle,
+     * PiTranslatedEntity)}) or that it has been removed (via {@link
+     * #forget(PiHandle)}). the
+     *
+     * @param handle PI entity handle
+     * @return optional PI translated entity
+     */
+    Optional<PiTranslatedEntity<T, E>> lookup(PiHandle<E> handle);
+
+    /**
+     * Removes any mapping for the given PI entity handle.
+     *
+     * @param handle PI entity handle.
+     */
+    void forget(PiHandle<E> handle);
+}
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractPiTranslatorImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractPiTranslatorImpl.java
new file mode 100644
index 0000000..5d7178c
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractPiTranslatorImpl.java
@@ -0,0 +1,58 @@
+/*
+ * 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.net.pi.impl;
+
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiHandle;
+import org.onosproject.net.pi.service.PiTranslatable;
+import org.onosproject.net.pi.service.PiTranslatedEntity;
+import org.onosproject.net.pi.service.PiTranslationStore;
+import org.onosproject.net.pi.service.PiTranslator;
+
+import java.util.Optional;
+
+/**
+ * Abstract implementation of a PI translator backed by a PI translation store.
+ *
+ * @param <T> PD entity class
+ * @param <E> PI entity class
+ */
+public abstract class AbstractPiTranslatorImpl
+        <T extends PiTranslatable, E extends PiEntity>
+        implements PiTranslator<T, E> {
+
+    private final PiTranslationStore<T, E> store;
+
+    AbstractPiTranslatorImpl(PiTranslationStore<T, E> store) {
+        this.store = store;
+    }
+
+    @Override
+    public void learn(PiHandle<E> handle, PiTranslatedEntity<T, E> entity) {
+        store.addOrUpdate(handle, entity);
+    }
+
+    @Override
+    public Optional<PiTranslatedEntity<T, E>> lookup(PiHandle<E> handle) {
+        return Optional.ofNullable(store.get(handle));
+    }
+
+    @Override
+    public void forget(PiHandle<E> handle) {
+        store.remove(handle);
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java b/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java
index 22d53fd..7f43e22 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java
@@ -86,13 +86,13 @@
 import org.onosproject.net.pi.runtime.PiFieldMatch;
 import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
 import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
+import org.onosproject.net.pi.service.PiTranslationException;
 
 import java.util.Map;
 
 import static java.lang.String.format;
 import static org.onlab.util.ImmutableByteSequence.ByteSequenceTrimException;
 import static org.onosproject.net.pi.impl.CriterionTranslator.CriterionTranslatorException;
-import static org.onosproject.net.pi.service.PiTranslationService.PiTranslationException;
 
 /**
  * Helper class to translate criterion instances to PI field matches.
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
similarity index 98%
rename from core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java
rename to core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
index d856fd3..f04e7b0 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
@@ -46,6 +46,7 @@
 import org.onosproject.net.pi.runtime.PiTableAction;
 import org.onosproject.net.pi.runtime.PiTableEntry;
 import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
+import org.onosproject.net.pi.service.PiTranslationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,17 +63,16 @@
 import static org.onosproject.net.pi.impl.CriterionTranslatorHelper.translateCriterion;
 import static org.onosproject.net.pi.impl.PiUtils.getInterpreterOrNull;
 import static org.onosproject.net.pi.impl.PiUtils.translateTableId;
-import static org.onosproject.net.pi.service.PiTranslationService.PiTranslationException;
 
 /**
  * Implementation of flow rule translation logic.
  */
-final class PiFlowRuleTranslator {
+final class PiFlowRuleTranslatorImpl {
 
     public static final int MAX_PI_PRIORITY = (int) Math.pow(2, 24);
-    private static final Logger log = LoggerFactory.getLogger(PiFlowRuleTranslator.class);
+    private static final Logger log = LoggerFactory.getLogger(PiFlowRuleTranslatorImpl.class);
 
-    private PiFlowRuleTranslator() {
+    private PiFlowRuleTranslatorImpl() {
         // Hide constructor.
     }
 
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java
similarity index 95%
rename from core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java
rename to core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java
index 255ccb9..eeabebc 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java
@@ -29,21 +29,21 @@
 import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
 import org.onosproject.net.pi.runtime.PiGroupKey;
 import org.onosproject.net.pi.runtime.PiTableAction;
-import org.onosproject.net.pi.service.PiTranslationService.PiTranslationException;
+import org.onosproject.net.pi.service.PiTranslationException;
 
 import java.nio.ByteBuffer;
 
 import static java.lang.String.format;
-import static org.onosproject.net.pi.impl.PiFlowRuleTranslator.translateTreatment;
+import static org.onosproject.net.pi.impl.PiFlowRuleTranslatorImpl.translateTreatment;
 import static org.onosproject.net.pi.impl.PiUtils.getInterpreterOrNull;
 import static org.onosproject.net.pi.runtime.PiTableAction.Type.ACTION;
 
 /**
  * Implementation of group translation logic.
  */
-final class PiGroupTranslator {
+final class PiGroupTranslatorImpl {
 
-    private PiGroupTranslator() {
+    private PiGroupTranslatorImpl() {
         // Hides constructor.
     }
 
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
index d60e9b3..212cf1c 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
@@ -28,6 +28,9 @@
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.util.ItemNotFoundException;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.config.ConfigFactory;
 import org.onosproject.net.config.NetworkConfigEvent;
@@ -79,6 +82,9 @@
     protected NetworkConfigRegistry cfgService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LeadershipService leadershipService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DriverService driverService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -87,6 +93,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected PiPipeconfMappingStore pipeconfMappingStore;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ClusterService clusterService;
+
     // Registered pipeconf are replicated through the app subsystem and registered on app activated events.
     protected ConcurrentHashMap<PiPipeconfId, PiPipeconf> piPipeconfs = new ConcurrentHashMap<>();
 
@@ -200,21 +209,28 @@
                     // due to 1:1:1 pipeconf:driver:provider maybe find better way
                     DriverProvider provider = new PiPipeconfDriverProviderInternal(completeDriver);
 
-                    //we register to the dirver susbystem the driver provider containing the merged driver
+                    //we register to the driver susbystem the driver provider containing the merged driver
                     driverAdminService.registerProvider(provider);
                 }
 
                 // Changing the configuration for the device to enforce the full driver with pipipeconf
-                // and base behaviours
-                ObjectNode newCfg = (ObjectNode) basicDeviceConfig.node();
-                newCfg = newCfg.put(DRIVER, completeDriverName);
-                ObjectMapper mapper = new ObjectMapper();
-                JsonNode newCfgNode = mapper.convertValue(newCfg, JsonNode.class);
-                cfgService.applyConfig(deviceId, BasicDeviceConfig.class, newCfgNode);
-                // Completable future is needed for when this method will also apply the pipeline to the device.
-                // FIXME (maybe): the pipeline is currently applied by the general device provider. But we store here
-                // the association between device and pipeconf.
-                pipeconfMappingStore.createOrUpdateBinding(deviceId, pipeconfId);
+                // and base behaviours, updating binding only first time something changes
+                NodeId leaderNodeId = leadershipService.getLeader("deploy-" +
+                        deviceId.toString() + "-pipeconf");
+                NodeId localNodeId = clusterService.getLocalNode().id();
+
+                if (!basicDeviceConfig.driver().equals(completeDriverName) && localNodeId.equals(leaderNodeId)) {
+                    ObjectNode newCfg = (ObjectNode) basicDeviceConfig.node();
+                    newCfg = newCfg.put(DRIVER, completeDriverName);
+                    ObjectMapper mapper = new ObjectMapper();
+                    JsonNode newCfgNode = mapper.convertValue(newCfg, JsonNode.class);
+                    log.debug("New driver {} for device {}", completeDriverName, deviceId);
+                    cfgService.applyConfig(deviceId, BasicDeviceConfig.class, newCfgNode);
+                    // Completable future is needed for when this method will also apply the pipeline to the device.
+                    // FIXME (maybe): the pipeline is currently applied by the general device provider.
+                    // But we store here the association between device and pipeconf.
+                    pipeconfMappingStore.createOrUpdateBinding(deviceId, pipeconfId);
+                }
                 operationResult.complete(true);
             }
         });
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java
index 3cb0a09..9780fac 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java
@@ -30,12 +30,17 @@
 import org.onosproject.net.pi.model.PiPipeconf;
 import org.onosproject.net.pi.runtime.PiActionGroup;
 import org.onosproject.net.pi.runtime.PiTableEntry;
+import org.onosproject.net.pi.service.PiFlowRuleTranslationStore;
+import org.onosproject.net.pi.service.PiFlowRuleTranslator;
+import org.onosproject.net.pi.service.PiGroupTranslationStore;
+import org.onosproject.net.pi.service.PiGroupTranslator;
+import org.onosproject.net.pi.service.PiTranslationException;
 import org.onosproject.net.pi.service.PiTranslationService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Implementation of the protocol-independent translation service.
+ * Implementation of the PI translation service.
  */
 @Component(immediate = true)
 @Service
@@ -48,24 +53,37 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private PiFlowRuleTranslationStore flowRuleTranslationStore;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private PiGroupTranslationStore groupTranslationStore;
+
+    private PiFlowRuleTranslator flowRuleTranslator;
+    private PiGroupTranslator groupTranslator;
+
     @Activate
     public void activate() {
+        flowRuleTranslator = new InternalFlowRuleTranslator(flowRuleTranslationStore);
+        groupTranslator = new InternalGroupTranslator(groupTranslationStore);
         log.info("Started");
     }
 
     @Deactivate
     public void deactivate() {
+        flowRuleTranslator = null;
+        groupTranslator = null;
         log.info("Stopped");
     }
 
     @Override
-    public PiTableEntry translateFlowRule(FlowRule rule, PiPipeconf pipeconf) throws PiTranslationException {
-        return PiFlowRuleTranslator.translate(rule, pipeconf, getDevice(rule.deviceId()));
+    public PiFlowRuleTranslator flowRuleTranslator() {
+        return flowRuleTranslator;
     }
 
     @Override
-    public PiActionGroup translateGroup(Group group, PiPipeconf pipeconf) throws PiTranslationException {
-        return PiGroupTranslator.translate(group, pipeconf, getDevice(group.deviceId()));
+    public PiGroupTranslator groupTranslator() {
+        return groupTranslator;
     }
 
     private Device getDevice(DeviceId deviceId) throws PiTranslationException {
@@ -75,5 +93,37 @@
         }
         return device;
     }
+
+    private final class InternalFlowRuleTranslator
+            extends AbstractPiTranslatorImpl<FlowRule, PiTableEntry>
+            implements PiFlowRuleTranslator {
+
+        private InternalFlowRuleTranslator(PiFlowRuleTranslationStore store) {
+            super(store);
+        }
+
+        @Override
+        public PiTableEntry translate(FlowRule original, PiPipeconf pipeconf)
+                throws PiTranslationException {
+            return PiFlowRuleTranslatorImpl
+                    .translate(original, pipeconf, getDevice(original.deviceId()));
+        }
+    }
+
+    private final class InternalGroupTranslator
+            extends AbstractPiTranslatorImpl<Group, PiActionGroup>
+            implements PiGroupTranslator {
+
+        private InternalGroupTranslator(PiGroupTranslationStore store) {
+            super(store);
+        }
+
+        @Override
+        public PiActionGroup translate(Group original, PiPipeconf pipeconf)
+                throws PiTranslationException {
+            return PiGroupTranslatorImpl
+                    .translate(original, pipeconf, getDevice(original.deviceId()));
+        }
+    }
 }
 
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java
index 6e93d67..78bca5f 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java
@@ -22,7 +22,7 @@
 import org.onosproject.net.pi.model.PiPipeconf;
 import org.onosproject.net.pi.model.PiPipelineInterpreter;
 import org.onosproject.net.pi.model.PiTableId;
-import org.onosproject.net.pi.service.PiTranslationService;
+import org.onosproject.net.pi.service.PiTranslationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -60,23 +60,23 @@
     }
 
     static PiTableId translateTableId(TableId tableId, PiPipelineInterpreter interpreter)
-            throws PiTranslationService.PiTranslationException {
+            throws PiTranslationException {
         switch (tableId.type()) {
             case PIPELINE_INDEPENDENT:
                 return (PiTableId) tableId;
             case INDEX:
                 IndexTableId indexId = (IndexTableId) tableId;
                 if (interpreter == null) {
-                    throw new PiTranslationService.PiTranslationException(format(
+                    throw new PiTranslationException(format(
                             "Unable to map table ID '%d' from index to PI: missing interpreter", indexId.id()));
                 } else if (!interpreter.mapFlowRuleTableId(indexId.id()).isPresent()) {
-                    throw new PiTranslationService.PiTranslationException(format(
+                    throw new PiTranslationException(format(
                             "Unable to map table ID '%d' from index to PI: missing ID in interpreter", indexId.id()));
                 } else {
                     return interpreter.mapFlowRuleTableId(indexId.id()).get();
                 }
             default:
-                throw new PiTranslationService.PiTranslationException(format(
+                throw new PiTranslationException(format(
                         "Unrecognized table ID type %s", tableId.type().name()));
         }
     }
diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java b/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
index d13def7..9a80e9f 100644
--- a/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
+++ b/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
@@ -67,7 +67,7 @@
 import static org.onlab.util.ImmutableByteSequence.copyFrom;
 import static org.onlab.util.ImmutableByteSequence.fit;
 import static org.onosproject.net.group.GroupDescription.Type.SELECT;
-import static org.onosproject.net.pi.impl.PiFlowRuleTranslator.MAX_PI_PRIORITY;
+import static org.onosproject.net.pi.impl.PiFlowRuleTranslatorImpl.MAX_PI_PRIORITY;
 import static org.onosproject.pipelines.basic.BasicConstants.ACT_PRF_WCMP_SELECTOR_ID;
 import static org.onosproject.pipelines.basic.BasicConstants.ACT_PRM_PORT_ID;
 import static org.onosproject.pipelines.basic.BasicConstants.ACT_SET_EGRESS_PORT_ID;
@@ -80,7 +80,7 @@
 import static org.onosproject.pipelines.basic.BasicConstants.TBL_WCMP_TABLE_ID;
 
 /**
- * Tests for {@link PiFlowRuleTranslator}.
+ * Tests for {@link PiFlowRuleTranslatorImpl}.
  */
 @SuppressWarnings("ConstantConditions")
 public class PiTranslatorServiceTest {
@@ -161,8 +161,8 @@
                 .withPriority(priority)
                 .build();
 
-        PiTableEntry entry1 = PiFlowRuleTranslator.translate(rule1, pipeconf, null);
-        PiTableEntry entry2 = PiFlowRuleTranslator.translate(rule1, pipeconf, null);
+        PiTableEntry entry1 = PiFlowRuleTranslatorImpl.translate(rule1, pipeconf, null);
+        PiTableEntry entry2 = PiFlowRuleTranslatorImpl.translate(rule1, pipeconf, null);
 
         // check equality, i.e. same rules must produce same entries
         new EqualsTester()
@@ -236,8 +236,8 @@
     @Test
     public void testTranslateGroups() throws Exception {
 
-        PiActionGroup piGroup1 = PiGroupTranslator.translate(GROUP, pipeconf, null);
-        PiActionGroup piGroup2 = PiGroupTranslator.translate(GROUP, pipeconf, null);
+        PiActionGroup piGroup1 = PiGroupTranslatorImpl.translate(GROUP, pipeconf, null);
+        PiActionGroup piGroup2 = PiGroupTranslatorImpl.translate(GROUP, pipeconf, null);
 
         new EqualsTester()
                 .addEqualityGroup(piGroup1, piGroup2)
diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java
new file mode 100644
index 0000000..9df6a86
--- /dev/null
+++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java
@@ -0,0 +1,143 @@
+/*
+ * 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.store.pi.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiHandle;
+import org.onosproject.net.pi.service.PiTranslatable;
+import org.onosproject.net.pi.service.PiTranslatedEntity;
+import org.onosproject.net.pi.service.PiTranslationEvent;
+import org.onosproject.net.pi.service.PiTranslationStore;
+import org.onosproject.net.pi.service.PiTranslationStoreDelegate;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapEvent;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.slf4j.Logger;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Distributed implementation of PiTranslationStore.
+ */
+@Component(immediate = true)
+public abstract class AbstractDistributedPiTranslationStore
+        <T extends PiTranslatable, E extends PiEntity>
+        extends AbstractStore<PiTranslationEvent<T, E>, PiTranslationStoreDelegate<T, E>>
+        implements PiTranslationStore<T, E> {
+
+    private static final String MAP_NAME_TEMPLATE = "onos-pi-translated-%s-map";
+
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected StorageService storageService;
+
+    private EventuallyConsistentMap<PiHandle<E>, PiTranslatedEntity<T, E>>
+            translatedEntities;
+
+    private final EventuallyConsistentMapListener
+            <PiHandle<E>, PiTranslatedEntity<T, E>> entityMapListener =
+            new InternalEntityMapListener();
+
+    /**
+     * Returns a string that identifies the map maintained by this store among
+     * others that uses this abstract class.
+     *
+     * @return string
+     */
+    protected abstract String mapSimpleName();
+
+    @Activate
+    public void activate() {
+        final String fullMapName = format(MAP_NAME_TEMPLATE, mapSimpleName());
+        translatedEntities = storageService
+                .<PiHandle<E>, PiTranslatedEntity<T, E>>eventuallyConsistentMapBuilder()
+                .withName(fullMapName)
+                .withSerializer(KryoNamespaces.API)
+                .withTimestampProvider((k, v) -> new WallClockTimestamp())
+                .build();
+        translatedEntities.addListener(entityMapListener);
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        translatedEntities.removeListener(entityMapListener);
+        translatedEntities = null;
+        log.info("Stopped");
+    }
+
+    @Override
+    public void addOrUpdate(PiHandle<E> handle, PiTranslatedEntity<T, E> entity) {
+        checkNotNull(handle);
+        checkNotNull(entity);
+        checkArgument(handle.entityType().equals(entity.entityType()),
+                      "Entity type must be the same for handle and translated entity");
+        translatedEntities.put(handle, entity);
+    }
+
+    @Override
+    public void remove(PiHandle<E> handle) {
+        checkNotNull(handle);
+        translatedEntities.remove(handle);
+    }
+
+    @Override
+    public PiTranslatedEntity<T, E> get(PiHandle<E> handle) {
+        checkNotNull(handle);
+        return translatedEntities.get(handle);
+    }
+
+    public Iterable<PiTranslatedEntity<T, E>> getAll() {
+        return translatedEntities.values();
+    }
+
+    private class InternalEntityMapListener
+            implements EventuallyConsistentMapListener
+                               <PiHandle<E>, PiTranslatedEntity<T, E>> {
+
+        @Override
+        public void event(EventuallyConsistentMapEvent<PiHandle<E>,
+                PiTranslatedEntity<T, E>> event) {
+            final PiTranslationEvent.Type type;
+            switch (event.type()) {
+                case PUT:
+                    type = PiTranslationEvent.Type.LEARNED;
+                    break;
+                case REMOVE:
+                    type = PiTranslationEvent.Type.FORGOT;
+                    break;
+                default:
+                    throw new IllegalArgumentException(
+                            "Unknown event type " + event.type().name());
+            }
+            notifyDelegate(new PiTranslationEvent<>(type, event.value()));
+        }
+    }
+}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java
new file mode 100644
index 0000000..c123ec5
--- /dev/null
+++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java
@@ -0,0 +1,40 @@
+/*
+ * 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.store.pi.impl;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.pi.runtime.PiTableEntry;
+import org.onosproject.net.pi.service.PiFlowRuleTranslationStore;
+
+/**
+ * Distributed implementation of a PI translation store for flow rules.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedPiFlowRuleTranslationStore
+        extends AbstractDistributedPiTranslationStore<FlowRule, PiTableEntry>
+        implements PiFlowRuleTranslationStore {
+
+    private static final String MAP_SIMPLE_NAME = "flowrule";
+
+    @Override
+    protected String mapSimpleName() {
+        return MAP_SIMPLE_NAME;
+    }
+}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java
new file mode 100644
index 0000000..fa62ef1
--- /dev/null
+++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java
@@ -0,0 +1,40 @@
+/*
+ * 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.store.pi.impl;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.service.PiGroupTranslationStore;
+
+/**
+ * Distributed implementation of a PI translation store for groups.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedPiGroupTranslationStore
+        extends AbstractDistributedPiTranslationStore<Group, PiActionGroup>
+        implements PiGroupTranslationStore {
+
+    private static final String MAP_SIMPLE_NAME = "group";
+
+    @Override
+    protected String mapSimpleName() {
+        return MAP_SIMPLE_NAME;
+    }
+}
diff --git a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java
index 83b997d..9a31b0c 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java
@@ -119,4 +119,4 @@
         store.deviceToPipeconf.clear();
     }
 
-}
\ No newline at end of file
+}
diff --git a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java
new file mode 100644
index 0000000..2ba52a2
--- /dev/null
+++ b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.store.pi.impl;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang3.RandomUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiEntityType;
+import org.onosproject.net.pi.runtime.PiHandle;
+import org.onosproject.net.pi.service.PiTranslatable;
+import org.onosproject.net.pi.service.PiTranslatedEntity;
+import org.onosproject.store.service.TestStorageService;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test for {@link AbstractDistributedPiTranslationStore}.
+ */
+public class DistributedPiTranslationStoreTest {
+
+    private AbstractDistributedPiTranslationStore<PiTranslatable, PiEntity> store;
+
+    private static final int HANDLE_HASH = RandomUtils.nextInt();
+    private static final PiTranslatable PI_TRANSLATABLE =
+            new PiTranslatable() {
+            };
+    private static final PiEntity PI_ENTITY = () -> PiEntityType.TABLE_ENTRY;
+    private static final PiHandle<PiEntity> PI_HANDLE =
+            new PiHandle<PiEntity>(DeviceId.NONE, PI_ENTITY) {
+                @Override
+                public int hashCode() {
+                    return HANDLE_HASH;
+                }
+
+                @Override
+                public boolean equals(Object other) {
+                    return other instanceof PiHandle && other.hashCode() == hashCode();
+                }
+
+                @Override
+                public String toString() {
+                    return String.valueOf(HANDLE_HASH);
+                }
+            };
+    private static final PiTranslatedEntity<PiTranslatable, PiEntity> TRANSLATED_ENTITY =
+            new PiTranslatedEntity<>(PI_TRANSLATABLE, PI_ENTITY, PI_HANDLE);
+
+    /**
+     * Sets up the store and the storage service test harness.
+     */
+    @Before
+    public void setUp() {
+        store = new AbstractDistributedPiTranslationStore<PiTranslatable, PiEntity>() {
+            @Override
+            protected String mapSimpleName() {
+                return "test";
+            }
+        };
+        store.storageService = new TestStorageService();
+        store.setDelegate(event -> {
+        });
+        store.activate();
+    }
+
+    /**
+     * Tests equality of key and value used in other tests.
+     */
+    @Test
+    public void testEquality() {
+        assertEquals(PI_HANDLE, PI_HANDLE);
+        assertEquals(TRANSLATED_ENTITY, TRANSLATED_ENTITY);
+    }
+
+    /**
+     * Test for activate.
+     */
+    @Test
+    public void activate() {
+        assertNotNull(store.storageService);
+        assertTrue("Store must have delegate",
+                   store.hasDelegate());
+        assertTrue("No value should be in the map",
+                   Lists.newArrayList(store.getAll()).isEmpty());
+    }
+
+    /**
+     * Test for deactivate.
+     */
+    @Test(expected = NullPointerException.class)
+    public void deactivate() {
+        store.deactivate();
+        store.getAll();
+    }
+
+    /**
+     * Test of value add or update.
+     */
+    @Test
+    public void addOrUpdate() {
+        store.addOrUpdate(PI_HANDLE, TRANSLATED_ENTITY);
+        assertTrue("Value should be in the map",
+                   store.get(PI_HANDLE) != null);
+        assertTrue("Exactly 1 value should be in the map",
+                   Lists.newArrayList(store.getAll()).size() == 1);
+
+        // Add again, expect 1 value.
+        store.addOrUpdate(PI_HANDLE, TRANSLATED_ENTITY);
+        assertTrue("Exactly 1 value should be in the map",
+                   Lists.newArrayList(store.getAll()).size() == 1);
+    }
+
+    /**
+     * Test of value lookup.
+     */
+    @Test
+    public void lookup() throws Exception {
+        clear();
+        addOrUpdate();
+        assertEquals("Wrong value in the map",
+                     store.get(PI_HANDLE), TRANSLATED_ENTITY);
+    }
+
+    /**
+     * Test of value removal.
+     */
+    @Test
+    public void clear() {
+        store.remove(PI_HANDLE);
+        assertTrue("Value should NOT be in the map",
+                   store.get(PI_HANDLE) == null);
+        assertTrue("No value should be in the map",
+                   Lists.newArrayList(store.getAll()).isEmpty());
+    }
+}
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index cc3c05d..6a03032 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -220,6 +220,7 @@
 import org.onosproject.net.pi.model.PiTableType;
 import org.onosproject.net.pi.runtime.PiAction;
 import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupHandle;
 import org.onosproject.net.pi.runtime.PiActionGroupId;
 import org.onosproject.net.pi.runtime.PiActionGroupMember;
 import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
@@ -227,9 +228,12 @@
 import org.onosproject.net.pi.runtime.PiControlMetadata;
 import org.onosproject.net.pi.runtime.PiCounterCellData;
 import org.onosproject.net.pi.runtime.PiCounterCellId;
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiEntityType;
 import org.onosproject.net.pi.runtime.PiExactFieldMatch;
 import org.onosproject.net.pi.runtime.PiFieldMatch;
 import org.onosproject.net.pi.runtime.PiGroupKey;
+import org.onosproject.net.pi.runtime.PiHandle;
 import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
 import org.onosproject.net.pi.runtime.PiMatchKey;
 import org.onosproject.net.pi.runtime.PiPacketOperation;
@@ -239,6 +243,9 @@
 import org.onosproject.net.pi.runtime.PiTableEntry;
 import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
 import org.onosproject.net.pi.runtime.PiValidFieldMatch;
+import org.onosproject.net.pi.runtime.PiTableEntryHandle;
+import org.onosproject.net.pi.service.PiTranslatable;
+import org.onosproject.net.pi.service.PiTranslatedEntity;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.net.region.DefaultRegion;
 import org.onosproject.net.region.Region;
@@ -630,6 +637,7 @@
                     // PI Runtime
                     PiAction.class,
                     PiActionGroup.class,
+                    PiActionGroupHandle.class,
                     PiActionGroupId.class,
                     PiActionGroupMember.class,
                     PiActionGroupMemberId.class,
@@ -637,9 +645,12 @@
                     PiControlMetadata.class,
                     PiCounterCellData.class,
                     PiCounterCellId.class,
+                    PiEntity.class,
+                    PiEntityType.class,
                     PiExactFieldMatch.class,
                     PiFieldMatch.class,
                     PiGroupKey.class,
+                    PiHandle.class,
                     PiLpmFieldMatch.class,
                     PiMatchKey.class,
                     PiPacketOperation.class,
@@ -649,6 +660,10 @@
                     PiTableEntry.class,
                     PiTernaryFieldMatch.class,
                     PiValidFieldMatch.class,
+                    // PI service
+                    PiTableEntryHandle.class,
+                    PiTranslatedEntity.class,
+                    PiTranslatable.class,
                     // Other
                     PiCriterion.class,
                     PiInstruction.class