REST API for pseudowire addition / deletion.

Refactored pseudowire code to use REST in order
to add or delete pseudowires individually. Previous implementation
used the network configuration, which is now completely
removed from the code. Further, I re-organized the code
and create a utility class that holds all the necessary
functionality for verifying pseudowires.

Further, I removed all mastership checks in the pw code
since now a specific pseudowire creation is sent to a single
instance, which will handle the call.

Change-Id: I1eb5e7cc7730ad792ea84dd389475768153e2b68
diff --git a/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index d951b53..b9912ac 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -15,8 +15,6 @@
  */
 package org.onosproject.segmentrouting;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
@@ -94,7 +92,6 @@
 import org.onosproject.routeservice.RouteService;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
 import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.PwaasConfig;
 import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
 import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
 import org.onosproject.segmentrouting.config.XConnectConfig;
@@ -104,9 +101,13 @@
 import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
 import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelHandler;
 import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
+import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
+
 import org.onosproject.segmentrouting.pwaas.L2Tunnel;
 import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
 import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
+import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
+
 import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
 import org.onosproject.segmentrouting.storekey.McastStoreKey;
 import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
@@ -142,6 +143,7 @@
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_REGISTERED;
 import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UNREGISTERED;
+import static org.onosproject.segmentrouting.pwaas.PwaasUtil.configurationValidity;
 
 /**
  * Segment routing manager.
@@ -234,7 +236,7 @@
     private RouteHandler routeHandler = null;
     LinkHandler linkHandler = null;
     private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
-    private L2TunnelHandler l2TunnelHandler = null;
+    private DefaultL2TunnelHandler l2TunnelHandler = null;
     private InternalEventHandler eventHandler = new InternalEventHandler();
     private final InternalHostListener hostListener = new InternalHostListener();
     private final InternalConfigListener cfgListener = new InternalConfigListener(this);
@@ -314,16 +316,6 @@
                 }
             };
 
-    private final ConfigFactory<ApplicationId, PwaasConfig> pwaasConfigFactory =
-            new ConfigFactory<ApplicationId, PwaasConfig>(
-                    SubjectFactories.APP_SUBJECT_FACTORY,
-                    PwaasConfig.class, "pwaas") {
-                @Override
-                public PwaasConfig createConfig() {
-                    return new PwaasConfig();
-                }
-            };
-
     private static final Object THREAD_SCHED_LOCK = new Object();
     private static int numOfEventsQueued = 0;
     private static int numOfEventsExecuted = 0;
@@ -430,7 +422,6 @@
         cfgService.registerConfigFactory(appConfigFactory);
         cfgService.registerConfigFactory(xConnectConfigFactory);
         cfgService.registerConfigFactory(mcastConfigFactory);
-        cfgService.registerConfigFactory(pwaasConfigFactory);
         log.info("Configuring network before adding listeners");
         cfgListener.configureNetwork();
 
@@ -474,7 +465,6 @@
         cfgService.unregisterConfigFactory(appConfigFactory);
         cfgService.unregisterConfigFactory(xConnectConfigFactory);
         cfgService.unregisterConfigFactory(mcastConfigFactory);
-        cfgService.unregisterConfigFactory(pwaasConfigFactory);
         compCfgService.unregisterProperties(getClass(), false);
 
         hostService.removeListener(hostListener);
@@ -567,55 +557,90 @@
     }
 
     @Override
-    public L2TunnelHandler.Result addPseudowire(String tunnelId, String pwLabel, String cP1,
-                                                 String cP1InnerVlan, String cP1OuterVlan, String cP2,
-                                                 String cP2InnerVlan, String cP2OuterVlan,
-                                                 String mode, String sdTag) {
-        // Try to inject an empty Pwaas config if it is not found for the first time
-        PwaasConfig config = cfgService.getConfig(appId(), PwaasConfig.class);
-        if (config == null) {
-            log.debug("Pwaas config not found. Try to create an empty one.");
-            cfgService.applyConfig(appId(), PwaasConfig.class, new ObjectMapper().createObjectNode());
-            config = cfgService.getConfig(appId(), PwaasConfig.class);
+    public L2TunnelHandler.Result addPseudowire(L2TunnelDescription l2TunnelDescription) {
+
+        List<L2Tunnel> tunnels = getL2Tunnels();
+        List<L2TunnelPolicy> policies = getL2Policies();
+
+        // combine polices and tunnels to pseudowires
+        List<L2TunnelDescription> pseudowires = tunnels.stream()
+                .map(l2Tunnel -> {
+                    L2TunnelPolicy policy = null;
+                    for (L2TunnelPolicy l2Policy : policies) {
+                        if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
+                            policy = l2Policy;
+                            break;
+                        }
+                    }
+
+                    return new DefaultL2TunnelDescription(l2Tunnel, policy);
+                })
+                .collect(Collectors.toList());
+
+
+        // creating a new list with the new pseudowire
+        Set<L2TunnelDescription> newPseudowires = new HashSet<>(pseudowires);
+
+        // corner case where we try to add the exact same pseudowire
+        if (newPseudowires.contains(l2TunnelDescription)) {
+            log.info("Pseudowire with {} already exists!", l2TunnelDescription);
+            return L2TunnelHandler.Result.SUCCESS;
         }
 
-        ObjectNode object = config.addPseudowire(tunnelId, pwLabel,
-                                                 cP1, cP1InnerVlan, cP1OuterVlan,
-                                                 cP2, cP2InnerVlan, cP2OuterVlan,
-                                                 mode, sdTag);
-        if (object == null) {
-            log.warn("Could not add pseudowire to the configuration!");
+        // add the new pseudowire to the Set
+        newPseudowires.add(l2TunnelDescription);
+
+        // validate the new set of pseudowires
+        boolean res = configurationValidity(newPseudowires);
+        if (res) {
+
+            // deploy a set with ONLY the new pseudowire
+            newPseudowires = new HashSet<>();
+            newPseudowires.add(l2TunnelDescription);
+            l2TunnelHandler.deploy(newPseudowires);
+
+            log.info("Pseudowire with {} deployment started, check log for any errors in this process!",
+                     l2TunnelDescription.l2Tunnel().tunnelId());
+            return L2TunnelHandler.Result.SUCCESS;
+        } else {
+
+            log.error("Pseudowire with {} can not be added!", l2TunnelDescription.l2Tunnel().tunnelId());
             return L2TunnelHandler.Result.ADDITION_ERROR;
         }
-
-        // inform everyone about the valid change in the pw configuration
-        cfgService.applyConfig(appId(), PwaasConfig.class, object);
-        return L2TunnelHandler.Result.SUCCESS;
     }
 
     @Override
-    public L2TunnelHandler.Result removePseudowire(String pwId) {
+    public L2TunnelHandler.Result removePseudowire(Integer pwId) {
 
-        PwaasConfig config = cfgService.getConfig(appId(), PwaasConfig.class);
-        if (config == null) {
-            log.warn("Configuration for Pwaas class could not be found!");
-            return L2TunnelHandler.Result.CONFIG_NOT_FOUND;
-        }
+        List<L2Tunnel> tunnels = getL2Tunnels();
+        List<L2TunnelPolicy> policies = getL2Policies();
 
-        ObjectNode object = config.removePseudowire(pwId);
-        if (object == null) {
-            log.warn("Could not delete pseudowire from configuration!");
+        // get the pseudowire, if it exists
+        List<L2TunnelDescription> pseudowires = tunnels.stream().map(l2Tunnel -> {
+            L2TunnelPolicy policy = null;
+            for (L2TunnelPolicy l2Policy : policies) {
+                if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
+                    policy = l2Policy;
+                    break;
+                }
+            }
+
+            return new DefaultL2TunnelDescription(l2Tunnel, policy);
+        }).filter(l2desc ->
+            l2desc.l2Tunnel().tunnelId() == pwId
+        ).collect(Collectors.toList());
+
+        if (pseudowires.size() == 0) {
+            log.error("Pseudowire with id {} does not exist", pwId);
             return L2TunnelHandler.Result.REMOVAL_ERROR;
+        } else {
+
+            l2TunnelHandler.tearDown(new HashSet<>(pseudowires));
+
+            log.info("Removal of pseudowire with {} started, check log for any errors in this process!",
+                     pwId);
+            return L2TunnelHandler.Result.SUCCESS;
         }
-
-        // sanity check, this should never fail since we removed a pw
-        // and we always check when we update the configuration
-        config.isValid();
-
-        // inform everyone
-        cfgService.applyConfig(appId(), PwaasConfig.class, object);
-
-        return L2TunnelHandler.Result.SUCCESS;
     }
 
     @Override
@@ -1411,21 +1436,6 @@
                     default:
                         break;
                 }
-            } else if (event.configClass().equals(PwaasConfig.class)) {
-                checkState(l2TunnelHandler != null, "DefaultL2TunnelHandler is not initialized");
-                switch (event.type()) {
-                    case CONFIG_ADDED:
-                        l2TunnelHandler.processPwaasConfigAdded(event);
-                        break;
-                    case CONFIG_UPDATED:
-                        l2TunnelHandler.processPwaasConfigUpdated(event);
-                        break;
-                    case CONFIG_REMOVED:
-                        l2TunnelHandler.processPwaasConfigRemoved(event);
-                        break;
-                    default:
-                        break;
-                }
             }
         }
 
@@ -1440,8 +1450,7 @@
             if (!event.configClass().equals(SegmentRoutingDeviceConfig.class) &&
                     !event.configClass().equals(SegmentRoutingAppConfig.class) &&
                     !event.configClass().equals(InterfaceConfig.class) &&
-                    !event.configClass().equals(XConnectConfig.class) &&
-                    !event.configClass().equals(PwaasConfig.class)) {
+                    !event.configClass().equals(XConnectConfig.class)) {
                 log.debug("Ignore event {} due to class mismatch", event);
                 return false;
             }
diff --git a/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java b/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
index 6f115e4..fa7b7d6 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
@@ -25,6 +25,7 @@
 import org.onosproject.segmentrouting.pwaas.L2Tunnel;
 import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
 import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
+import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
 import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
 
 import com.google.common.collect.ImmutableMap;
@@ -101,33 +102,20 @@
     List<L2TunnelPolicy> getL2Policies();
 
     /**
-     * Removes pw. Essentially updates configuration for PwaasConfig
-     * and sends event for removal. The rest are handled by DefaultL2TunnelHandler
+     * Removes pseudowire. Used ONLY by the REST api.
      *
-     * @param pwId The pseudowire id
+     * @param pwId The id of the pseudowire.
      * @return SUCCESS if operation successful or a descriptive error otherwise.
      */
-    L2TunnelHandler.Result removePseudowire(String pwId);
+    L2TunnelHandler.Result removePseudowire(Integer pwId);
 
     /**
      * Adds a Pseudowire to the configuration.
      *
-     * @param tunnelId The pseudowire id
-     * @param pwLabel Pw label
-     * @param cP1 Connection Point 1 of pw
-     * @param cP1InnerVlan Outer vlan of cp2
-     * @param cP1OuterVlan Outer vlan of cp1
-     * @param cP2 Connection Point 2 of pw
-     * @param cP2InnerVlan Inner vlan of cp2
-     * @param cP2OuterVlan Outer vlan of cp1
-     * @param mode Mode of pw
-     * @param sdTag Service Delimiting tag of pw
+     * @param tunnel The pseudowire tunnel.
      * @return SUCCESS if operation is successful or a descriptive error otherwise.
      */
-    L2TunnelHandler.Result addPseudowire(String tunnelId, String pwLabel, String cP1,
-                                          String cP1InnerVlan, String cP1OuterVlan, String cP2,
-                                          String cP2InnerVlan, String cP2OuterVlan,
-                                          String mode, String sdTag);
+    L2TunnelHandler.Result addPseudowire(L2TunnelDescription tunnel);
 
     /**
      * Creates a policy.
diff --git a/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java b/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java
index d916823..ab80aff 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java
@@ -19,8 +19,17 @@
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
 import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
 import org.onosproject.segmentrouting.SegmentRoutingService;
+import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
+import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
+import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
+import org.onosproject.segmentrouting.pwaas.L2Tunnel;
+import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
 import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
+import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
+
+import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
 
 
 /**
@@ -86,16 +95,36 @@
         SegmentRoutingService srService =
                 AbstractShellCommand.get(SegmentRoutingService.class);
 
-        L2TunnelHandler.Result res = srService.addPseudowire(pwId, pwLabel,
-                                                             cP1, cP1InnerVlan, cP1OuterVlan,
-                                                             cP2, cP2InnerVlan, cP2OuterVlan,
-                                                             mode, sDTag);
+        L2Tunnel tun;
+        L2TunnelPolicy policy;
+
+        try {
+            tun = new DefaultL2Tunnel(parseMode(mode), parseVlan(sDTag), parsePwId(pwId), parsePWLabel(pwLabel));
+        } catch (Exception e) {
+            print("Exception while parsing L2Tunnel : {}", e);
+            return;
+        }
+
+        try {
+            policy = new DefaultL2TunnelPolicy(parsePwId(pwId),
+                                               ConnectPoint.deviceConnectPoint(cP1), parseVlan(cP1InnerVlan),
+                                               parseVlan(cP1OuterVlan), ConnectPoint.deviceConnectPoint(cP2),
+                                               parseVlan(cP2InnerVlan), parseVlan(cP2OuterVlan));
+
+        } catch (Exception e) {
+            print("Exception while parsing L2TunnelPolicy : {}", e);
+            return;
+        }
+
+        L2TunnelDescription pw = new DefaultL2TunnelDescription(tun, policy);
+        L2TunnelHandler.Result res = srService.addPseudowire(pw);
+
         switch (res) {
             case ADDITION_ERROR:
-                print("Pseudowire could not be added, error in configuration, please check logs for more details!");
+                print("Pseudowire could not be added, please check logs for more details!");
                 break;
-            case CONFIG_NOT_FOUND:
-                print("Configuration for pwaas was not found! Initialize the configuration first through netcfg.");
+            case SUCCESS:
+                print("Pseudowire was added succesfully!");
                 break;
             default:
                 break;
diff --git a/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java b/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java
index 098bbf9..0f027b2 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java
@@ -23,6 +23,8 @@
 import org.onosproject.segmentrouting.SegmentRoutingService;
 import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
 
+import static org.onosproject.segmentrouting.pwaas.PwaasUtil.parsePwId;
+
 
 /**
  * Command to remove a pseudowire.
@@ -44,8 +46,15 @@
 
         // remove the pseudowire
         SegmentRoutingManager mngr = (SegmentRoutingManager) srService;
-        L2TunnelHandler.Result res = mngr.removePseudowire(pwId);
+        int pwIntId;
+        try {
+            pwIntId = parsePwId(pwId);
+        } catch (Exception e) {
+            print("Exception while parsing pseudowire id : {}", e);
+            return;
+        }
 
+        L2TunnelHandler.Result res = mngr.removePseudowire(pwIntId);
         switch (res) {
             case REMOVAL_ERROR:
                 error("Error in deletion, pseudowire not found!");
diff --git a/app/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java b/app/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java
deleted file mode 100644
index 31cad7e..0000000
--- a/app/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
- * Copyright 2016-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.segmentrouting.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableSet;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Mode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * App configuration object for Pwaas.
- */
-public class PwaasConfig extends Config<ApplicationId> {
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    public DeviceService deviceService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    public InterfaceService intfService;
-
-    private static Logger log = LoggerFactory
-            .getLogger(PwaasConfig.class);
-
-    private static final String SRC_CP = "cP1";
-    private static final String DST_CP = "cP2";
-    private static final String SRC_OUTER_TAG = "cP1OuterTag";
-    private static final String DST_OUTER_TAG = "cP2OuterTag";
-    private static final String SRC_INNER_TAG = "cP1InnerTag";
-    private static final String DST_INNER_TAG = "cP2InnerTag";
-    private static final String MODE = "mode";
-    private static final String SD_TAG = "sdTag";
-    private static final String PW_LABEL = "pwLabel";
-
-    public PwaasConfig(DeviceService devS, InterfaceService intfS) {
-
-        super();
-
-        deviceService = devS;
-        intfService = intfS;
-    }
-
-    public PwaasConfig() {
-
-        super();
-
-        deviceService = AbstractShellCommand.get(DeviceService.class);
-        intfService = AbstractShellCommand.get(InterfaceService.class);
-    }
-    /**
-     * Error message for missing parameters.
-     */
-    private static final String MISSING_PARAMS = "Missing parameters in pseudo wire description";
-
-    /**
-     * Error message for invalid l2 mode.
-     */
-    private static final String INVALID_L2_MODE = "Invalid pseudo wire mode";
-
-    /**
-     * Error message for invalid VLAN.
-     */
-    private static final String INVALID_VLAN = "Vlan should be either int or */-";
-
-    /**
-     * Error message for invalid PW label.
-     */
-    private static final String INVALID_PW_LABEL = "Pseudowire label should be an integer";
-
-    /**
-     * Verify if the pwaas configuration block is valid.
-     *
-     * Here we try to ensure that the provided pseudowires will get instantiated
-     * correctly in the network. We also check for any collisions with already used
-     * interfaces and also between different pseudowires. Most of the restrictions stem
-     * from the fact that all vlan matching is done in table 10 of ofdpa.
-     *
-     * @return true, if the configuration block is valid.
-     *         False otherwise.
-     */
-    @Override
-    public boolean isValid() {
-
-        Set<L2TunnelDescription> pseudowires;
-        try {
-            pseudowires = getPwIds().stream()
-                    .map(this::getPwDescription)
-                    .collect(Collectors.toSet());
-
-            // check semantics now and return
-            return configurationValidity(pseudowires);
-
-        } catch (IllegalArgumentException e) {
-            log.warn("{}", e.getMessage());
-            return false;
-        }
-    }
-
-    /**
-     * Helper method to verify if the tunnel is whether or not
-     * supported.
-     *
-     * @param l2Tunnel the tunnel to verify
-     * @return the result of the verification
-     */
-    private void verifyTunnel(L2Tunnel l2Tunnel) {
-
-        // Service delimiting tag not supported yet.
-        if (!l2Tunnel.sdTag().equals(VlanId.NONE)) {
-            throw new IllegalArgumentException(String.format("Service delimiting tag not supported yet for " +
-                                                             "pseudowire %d.", l2Tunnel.tunnelId()));
-        }
-
-        // Tag mode not supported yet.
-        if (l2Tunnel.pwMode() == L2Mode.TAGGED) {
-            throw new IllegalArgumentException(String.format("Tagged mode not supported yet for pseudowire %d.",
-                                                                            l2Tunnel.tunnelId()));
-        }
-
-        // Raw mode without service delimiting tag
-        // is the only mode supported for now.
-    }
-
-    /**
-     * Helper method to verify if the policy is whether or not
-     * supported and if policy will be successfully instantiated in the
-     * network.
-     *
-     * @param ingressInner the ingress inner tag
-     * @param ingressOuter the ingress outer tag
-     * @param egressInner the egress inner tag
-     * @param egressOuter the egress outer tag
-     * @return the result of verification
-     */
-    private void verifyPolicy(ConnectPoint cP1,
-                              ConnectPoint cP2,
-                              VlanId ingressInner,
-                              VlanId ingressOuter,
-                              VlanId egressInner,
-                              VlanId egressOuter,
-                              Long tunnelId) {
-
-        if (cP1.deviceId().equals(cP2.deviceId())) {
-            throw new IllegalArgumentException(String.format("Pseudowire connection points can not reside in the " +
-                                                             "same node, in pseudowire %d.", tunnelId));
-        }
-
-        // We can have multiple tags, all of them can be NONE,
-        // indicating untagged traffic, however, the outer tag can
-        // not have value if the inner tag is None
-        if (ingressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) {
-            throw new IllegalArgumentException(String.format("Inner tag should not be empty when " +
-                                                             "outer tag is set for pseudowire %d for cP1.",
-                                                              tunnelId));
-        }
-
-        if (egressInner.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Inner tag should not be empty when" +
-                                                                            " outer tag is set for pseudowire %d " +
-                                                                            "for cP2.", tunnelId)));
-        }
-
-        if (ingressInner.equals(VlanId.ANY) ||
-                ingressOuter.equals(VlanId.ANY) ||
-                egressInner.equals(VlanId.ANY) ||
-                egressOuter.equals(VlanId.ANY)) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Wildcard VLAN matching not yet " +
-                                                                            "supported for pseudowire %d.",
-                                                                            tunnelId)));
-        }
-
-        if (((!ingressOuter.equals(VlanId.NONE) && !ingressInner.equals(VlanId.NONE)) &&
-                (egressOuter.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE)))
-                || ((ingressOuter.equals(VlanId.NONE) && ingressInner.equals(VlanId.NONE)) &&
-                (!egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)))) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Support for double tag <-> untag is not" +
-                                                                                    "supported for pseudowire %d.",
-                                                                            tunnelId)));
-        }
-        if ((!ingressInner.equals(VlanId.NONE) &&
-                ingressOuter.equals(VlanId.NONE) &&
-                !egressOuter.equals(VlanId.NONE))
-           || (egressOuter.equals(VlanId.NONE) &&
-                !egressInner.equals(VlanId.NONE) &&
-                !ingressOuter.equals(VlanId.NONE))) {
-                throw new IllegalArgumentException(String.valueOf(String.format("Support for double-tag<->" +
-                                                                                "single-tag is not supported" +
-                                                                                " for pseudowire %d.", tunnelId)));
-        }
-
-        if ((ingressInner.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE))
-                || (!ingressInner.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) {
-            throw new IllegalArgumentException(String.valueOf(String.format("single-tag <-> untag is not supported" +
-                                                                            " for pseudowire %d.", tunnelId)));
-        }
-
-
-        if (!ingressInner.equals(egressInner) && !ingressOuter.equals(egressOuter)) {
-            throw new IllegalArgumentException(String.valueOf(String.format("We do not support changing both tags " +
-                                                                             "in double tagged pws, only the outer," +
-                                                                             " for pseudowire %d.", tunnelId)));
-        }
-
-        // check if cp1 and port of cp1 exist
-        if (deviceService.getDevice(cP1.deviceId()) == null) {
-            throw new IllegalArgumentException(String.valueOf(String.format("cP1 device %s does not exist for" +
-                                                                            " pseudowire %d.", cP1.deviceId(),
-                                                                            tunnelId)));
-        }
-
-        if (deviceService.getPort(cP1) == null) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP1 device %s does not" +
-                                                                            " exist for pseudowire %d.", cP1.port(),
-                                                                            cP1.deviceId(), tunnelId)));
-        }
-
-        // check if cp2 and port of cp2 exist
-        if (deviceService.getDevice(cP2.deviceId()) == null) {
-            throw new IllegalArgumentException(String.valueOf(String.format("cP2 device %s does not exist for" +
-                                                                            " pseudowire %d.", cP2.deviceId(),
-                                                                            tunnelId)));
-        }
-
-        if (deviceService.getPort(cP2) == null) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP2 device %s does " +
-                                                                            "not exist for pseudowire %d.",
-                                                                            cP2.port(), cP2.deviceId(), tunnelId)));
-        }
-    }
-
-    /**
-     * Verifies that the pseudowires will not conflict with each other.
-     *
-     * Further, check if vlans for connect points are already used.
-     *
-     * @param tunnel Tunnel for pw
-     * @param policy Policy for pw
-     * @param labelSet Label set used so far with this configuration
-     * @param vlanSet Vlan set used with this configuration
-     * @param tunnelSet Tunnel set used with this configuration
-     */
-    private void verifyGlobalValidity(L2Tunnel tunnel,
-                                      L2TunnelPolicy policy,
-                                      Set<MplsLabel> labelSet,
-                                      Map<ConnectPoint, Set<VlanId>> vlanSet,
-                                      Set<Long> tunnelSet) {
-
-        if (tunnelSet.contains(tunnel.tunnelId())) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Tunnel Id %d already used by" +
-                                                                           " another pseudowire, in " +
-                                                                           "pseudowire %d!", tunnel.tunnelId(),
-                                                                            tunnel.tunnelId())));
-        }
-        tunnelSet.add(tunnel.tunnelId());
-
-        // check if tunnel id is used again
-        ConnectPoint cP1 = policy.cP1();
-        ConnectPoint cP2 = policy.cP2();
-
-        // insert cps to hashmap if this is the first time seen
-        if (!vlanSet.containsKey(cP1)) {
-            vlanSet.put(cP1, new HashSet<VlanId>());
-        }
-        if (!vlanSet.containsKey(cP2)) {
-            vlanSet.put(cP2, new HashSet<VlanId>());
-        }
-
-        // if single tagged or untagged vlan is the inner
-        // if double tagged vlan is the outer
-        VlanId vlanToCheckCP1;
-        if (policy.cP1OuterTag().equals(VlanId.NONE)) {
-            vlanToCheckCP1 = policy.cP1InnerTag();
-        } else {
-            vlanToCheckCP1 = policy.cP1OuterTag();
-        }
-
-        VlanId vlanToCheckCP2;
-        if (policy.cP2OuterTag().equals(VlanId.NONE)) {
-            vlanToCheckCP2 = policy.cP2InnerTag();
-        } else {
-            vlanToCheckCP2 = policy.cP2OuterTag();
-        }
-
-        if (labelSet.contains(tunnel.pwLabel())) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Label %s already used by another" +
-                                                                            " pseudowire, in pseudowire %d!",
-                                                                            tunnel.pwLabel(), tunnel.tunnelId())));
-        }
-        labelSet.add(tunnel.pwLabel());
-
-        if (vlanSet.get(cP1).contains(vlanToCheckCP1)) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already used " +
-                                                                            "by another pseudowire, in pseudowire" +
-                                                                            " %d!", vlanToCheckCP1,  cP1,
-                                                                            tunnel.tunnelId())));
-        }
-        vlanSet.get(cP1).add(vlanToCheckCP1);
-
-        if (vlanSet.get(cP2).contains(vlanToCheckCP2)) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already used" +
-                                                                            " by another pseudowire, in" +
-                                                                            " pseudowire %d!", vlanToCheckCP2, cP2,
-                                                                            tunnel.tunnelId())));
-        }
-        vlanSet.get(cP2).add(vlanToCheckCP2);
-
-        // check that vlans for the connect points are not used
-        intfService.getInterfacesByPort(cP1).stream()
-                .forEach(intf -> {
-
-                    // check if tagged pw affects tagged interface
-                    if (intf.vlanTagged().contains(vlanToCheckCP1)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already" +
-                                                                                        " used for this interface, in" +
-                                                                                        " pseudowire %d!",
-                                                                                        vlanToCheckCP1, cP1,
-                                                                                        tunnel.tunnelId())));
-                    }
-
-                    // if vlanNative != null this interface is configured with untagged traffic also
-                    // check if it collides with untagged interface
-                    if ((intf.vlanNative() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP1 " +
-                                                                                         "%s already used for this " +
-                                                                                         "interface, in pseudowire " +
-                                                                                         "%d!", cP1,
-                                                                                         tunnel.tunnelId())));
-                    }
-
-                    // if vlanUntagged != null this interface is configured only with untagged traffic
-                    // check if it collides with untagged interface
-                    if ((intf.vlanUntagged() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for " +
-                                                                                         "cP1 %s already" +
-                                                                                         " used for this interface," +
-                                                                                         " in pseudowire %d!",
-                                                                                         cP1, tunnel.tunnelId())));
-                    }
-                });
-
-        intfService.getInterfacesByPort(cP2).stream()
-                .forEach(intf -> {
-                    if (intf.vlanTagged().contains(vlanToCheckCP2)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already" +
-                                                                                        " used for  this interface, " +
-                                                                                        "in pseudowire %d!",
-                                                                                        vlanToCheckCP2, cP2,
-                                                                                        tunnel.tunnelId())));
-                    }
-
-                    // if vlanNative != null this interface is configured with untagged traffic also
-                    // check if it collides with untagged interface
-                    if ((intf.vlanNative() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s " +
-                                                                                        "already used for this" +
-                                                                                        " interface, " +
-                                                                                        "in pseudowire %d!",
-                                                                                        cP2, tunnel.tunnelId())));
-                    }
-
-                    // if vlanUntagged != null this interface is configured only with untagged traffic
-                    // check if it collides with untagged interface
-                    if ((intf.vlanUntagged() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s" +
-                                                                                        " already" +
-                                                                                        " used for this interface, " +
-                                                                                        "in pseudowire %d!",
-                                                                                        cP2, tunnel.tunnelId())));
-                    }
-                });
-
-    }
-
-    /**
-     * Helper method to verify the integrity of the pseudo wire.
-     *
-     * @param l2TunnelDescription the pseudo wire description
-     * @return the result of the check
-     */
-    private void verifyPseudoWire(L2TunnelDescription l2TunnelDescription,
-                                  Set<MplsLabel> labelSet,
-                                  Map<ConnectPoint, Set<VlanId>> vlanset,
-                                  Set<Long> tunnelSet) {
-
-        L2Tunnel l2Tunnel = l2TunnelDescription.l2Tunnel();
-        L2TunnelPolicy l2TunnelPolicy = l2TunnelDescription.l2TunnelPolicy();
-
-        verifyTunnel(l2Tunnel);
-
-        verifyPolicy(
-                l2TunnelPolicy.cP1(),
-                l2TunnelPolicy.cP2(),
-                l2TunnelPolicy.cP1InnerTag(),
-                l2TunnelPolicy.cP1OuterTag(),
-                l2TunnelPolicy.cP2InnerTag(),
-                l2TunnelPolicy.cP2OuterTag(),
-                l2Tunnel.tunnelId()
-        );
-
-        verifyGlobalValidity(l2Tunnel,
-                             l2TunnelPolicy,
-                             labelSet,
-                             vlanset,
-                             tunnelSet);
-
-    }
-
-    /**
-     * Checks if the configured pseudowires will create problems in the network.
-     * If yes, then no pseudowires is deployed from this configuration.
-     *
-     * @param pseudowires Set of pseudowries to validate
-     * @return returns true if everything goes well.
-     */
-    public boolean configurationValidity(Set<L2TunnelDescription> pseudowires) {
-
-        // structures to keep pw information
-        // in order to see if instantiating them will create
-        // problems
-        Set<Long> tunIds = new HashSet<>();
-        Set<MplsLabel> labelsUsed = new HashSet<>();
-        Map<ConnectPoint, Set<VlanId>> vlanIds = new HashMap<>();
-
-        // check that pseudowires can be instantiated in the network
-        // we try to guarantee that all the pws will work before
-        // instantiating any of them
-        for (L2TunnelDescription pw : pseudowires) {
-            verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds);
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns all pseudo wire keys.
-     *
-     * @return all keys (tunnels id)
-     * @throws IllegalArgumentException if wrong format
-     */
-    public Set<Long> getPwIds() {
-        ImmutableSet.Builder<Long> builder = ImmutableSet.builder();
-        object.fields().forEachRemaining(entry -> {
-            Long tunnelId = Long.parseLong(entry.getKey());
-            builder.add(tunnelId);
-        });
-        return builder.build();
-    }
-
-    /**
-     * Parses a vlan as a string. Returns the VlanId if
-     * provided String can be parsed as an integer or is '' / '*'
-     *
-     * @param vlan string as read from configuration
-     * @return VlanId
-     * @throws IllegalArgumentException if wrong format of vlan
-     */
-    public VlanId parseVlan(String vlan) {
-
-        if (vlan.equals("*") || vlan.equals("Any")) {
-            return VlanId.vlanId("Any");
-        } else if (vlan.equals("") || vlan.equals("None")) {
-            return VlanId.vlanId("None");
-        } else {
-            try {
-                VlanId newVlan = VlanId.vlanId(vlan);
-                return newVlan;
-            } catch (IllegalArgumentException e) {
-                throw new IllegalArgumentException(INVALID_VLAN);
-            }
-        }
-    }
-
-    /**
-     *
-     * @param mode RAW or TAGGED
-     * @return the L2Mode if input is correct
-     * @throws  IllegalArgumentException if not supported mode
-     */
-    public L2Mode parseMode(String mode) {
-
-        if (!mode.equals("RAW") && !mode.equals("TAGGED")) {
-            throw  new IllegalArgumentException(INVALID_L2_MODE);
-        }
-
-        return L2Mode.valueOf(mode);
-    }
-
-    /**
-     *
-     * @param label the mpls label of the pseudowire
-     * @return the MplsLabel
-     * @throws IllegalArgumentException if label is invalid
-     */
-    public MplsLabel parsePWLabel(String label) {
-
-        try {
-            MplsLabel pwLabel = MplsLabel.mplsLabel(label);
-            return pwLabel;
-        } catch (Exception e) {
-            throw new IllegalArgumentException(INVALID_PW_LABEL);
-        }
-    }
-
-    /**
-     * Returns pw description of given pseudo wire id.
-     *
-     * @param tunnelId pseudo wire key
-     * @return set of l2 tunnel descriptions
-     * @throws IllegalArgumentException if wrong format
-     */
-    public L2TunnelDescription getPwDescription(Long tunnelId) {
-        JsonNode pwDescription = object.get(tunnelId.toString());
-        if (!hasFields((ObjectNode) pwDescription,
-                      SRC_CP, SRC_INNER_TAG, SRC_OUTER_TAG,
-                      DST_CP, DST_INNER_TAG, DST_OUTER_TAG,
-                      MODE, SD_TAG, PW_LABEL)) {
-            throw new IllegalArgumentException(MISSING_PARAMS);
-        }
-        String tempString;
-
-        tempString = pwDescription.get(SRC_CP).asText();
-        ConnectPoint srcCp = ConnectPoint.deviceConnectPoint(tempString);
-
-        tempString = pwDescription.get(DST_CP).asText();
-        ConnectPoint dstCp = ConnectPoint.deviceConnectPoint(tempString);
-
-        tempString = pwDescription.get(SRC_INNER_TAG).asText();
-        VlanId srcInnerTag = parseVlan(tempString);
-
-        tempString = pwDescription.get(SRC_OUTER_TAG).asText();
-        VlanId srcOuterTag = parseVlan(tempString);
-
-        tempString = pwDescription.get(DST_INNER_TAG).asText();
-        VlanId dstInnerTag = parseVlan(tempString);
-
-        tempString = pwDescription.get(DST_OUTER_TAG).asText();
-        VlanId dstOuterTag = parseVlan(tempString);
-
-        tempString = pwDescription.get(MODE).asText();
-        L2Mode l2Mode = parseMode(tempString);
-
-        tempString = pwDescription.get(SD_TAG).asText();
-        VlanId sdTag = parseVlan(tempString);
-
-        tempString = pwDescription.get(PW_LABEL).asText();
-        MplsLabel pwLabel = parsePWLabel(tempString);
-
-        L2Tunnel l2Tunnel = new DefaultL2Tunnel(
-                l2Mode,
-                sdTag,
-                tunnelId,
-                pwLabel
-        );
-
-        L2TunnelPolicy l2TunnelPolicy = new DefaultL2TunnelPolicy(
-                tunnelId,
-                srcCp,
-                srcInnerTag,
-                srcOuterTag,
-                dstCp,
-                dstInnerTag,
-                dstOuterTag
-        );
-
-        return new DefaultL2TunnelDescription(l2Tunnel, l2TunnelPolicy);
-    }
-
-    /**
-     * Removes a pseudowire from the configuration tree.
-     * @param pwId Pseudowire id
-     * @return null if pwId did not exist, or the object representing the
-     * udpated configuration tree
-     */
-    public ObjectNode removePseudowire(String pwId) {
-
-        JsonNode value = object.remove(pwId);
-        if (value == null) {
-            return (ObjectNode) value;
-        } else {
-            return object;
-        }
-    }
-
-    /**
-     * Adds a pseudowire to the configuration tree of pwwas. It also checks
-     * if the configuration is valid, if not return null and does not add the node,
-     * if yes return the new configuration. Caller will propagate update events.
-     *
-     * If the pseudowire already exists in the configuration it gets updated.
-     *
-     * @param tunnelId Id of tunnel
-     * @param pwLabel PW label of tunnel
-     * @param cP1 Connection point 1
-     * @param cP1InnerVlan Inner vlan of cp1
-     * @param cP1OuterVlan Outer vlan of cp2
-     * @param cP2 Connection point 2
-     * @param cP2InnerVlan Inner vlan of cp2
-     * @param cP2OuterVlan Outer vlan of cp2
-     * @param mode Mode for the pw
-     * @param sdTag Service delimiting tag for the pw
-     * @return The ObjectNode config if configuration is valid with the new pseudowire
-     * or null.
-     */
-    public ObjectNode addPseudowire(String tunnelId, String pwLabel, String cP1,
-                                    String cP1InnerVlan, String cP1OuterVlan, String cP2,
-                                    String cP2InnerVlan, String cP2OuterVlan,
-                                    String mode, String sdTag) {
-
-
-        ObjectNode newPw = new ObjectNode(JsonNodeFactory.instance);
-
-        // add fields for pseudowire
-        newPw.put(SRC_CP, cP1);
-        newPw.put(DST_CP, cP2);
-        newPw.put(PW_LABEL, pwLabel);
-        newPw.put(SRC_INNER_TAG, cP1InnerVlan);
-        newPw.put(SRC_OUTER_TAG, cP1OuterVlan);
-        newPw.put(DST_INNER_TAG, cP2InnerVlan);
-        newPw.put(DST_OUTER_TAG, cP2OuterVlan);
-        newPw.put(SD_TAG, sdTag);
-        newPw.put(MODE, mode);
-
-        object.set(tunnelId, newPw);
-
-        if (!isValid()) {
-            log.info("Pseudowire could not be created : {}");
-            object.remove(tunnelId);
-            return null;
-        }
-
-        return object;
-    }
-}
diff --git a/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java b/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
index 2dc9de2..4b3272d 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
@@ -30,7 +30,6 @@
 import org.onosproject.net.Link;
 import org.onosproject.net.Path;
 import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigEvent;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
@@ -49,7 +48,6 @@
 import org.onosproject.segmentrouting.SegmentRoutingManager;
 import org.onosproject.segmentrouting.SegmentRoutingService;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.PwaasConfig;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.ConsistentMap;
 import org.onosproject.store.service.DistributedSet;
@@ -64,7 +62,6 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.VERSATILE;
 import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.INITIATION;
 import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.TERMINATION;
@@ -168,28 +165,14 @@
     }
 
     /**
-     * Deploys any pre-existing pseudowires in the configuration.
      * Used by manager only in initialization.
      */
     @Override
     public void init() {
-
-        PwaasConfig config = srManager.cfgService.getConfig(srManager.appId(), PwaasConfig.class);
-        if (config == null) {
-            return;
-        }
-
-        log.info("Deploying existing pseudowires");
-
-        // gather pseudowires
-        Set<L2TunnelDescription> pwToAdd = config
-                .getPwIds()
-                .stream()
-                .map(config::getPwDescription)
-                .collect(Collectors.toSet());
-
-        // deploy pseudowires
-        deploy(pwToAdd);
+        // Since we have no pseudowires in netcfg there
+        // is nothing to do in initialization.
+        // I leave it here because potentially we might need to
+        // use it in the future.
     }
 
     /**
@@ -254,25 +237,6 @@
         pwToUpdate.forEach(tun -> updatePw(tun, tun));
     }
 
-    @Override
-    public void processPwaasConfigAdded(NetworkConfigEvent event) {
-        checkArgument(event.config().isPresent(),
-                "Config is not presented in PwaasConfigAdded event {}", event);
-
-        log.info("Network event : Pseudowire configuration added!");
-        PwaasConfig config = (PwaasConfig) event.config().get();
-
-        // gather pseudowires
-        Set<L2TunnelDescription> pwToAdd = config
-                .getPwIds()
-                .stream()
-                .map(config::getPwDescription)
-                .collect(Collectors.toSet());
-
-        // deploy pseudowires
-        deploy(pwToAdd);
-    }
-
     /**
      * Returns the new vlan id for an ingress point of a
      * pseudowire. For double tagged, it is the outer,
@@ -334,10 +298,7 @@
     }
 
     /**
-     * Adds a single pseudowire from leaf to a leaf.
-     * This method can be called from cli commands
-     * without configuration updates, thus it does not check for mastership
-     * of the ingress pseudowire device.
+     * Adds a single pseudowire.
      *
      * @param pw The pseudowire
      * @param spinePw True if pseudowire is from leaf to spine
@@ -490,15 +451,10 @@
 
     /**
      * To deploy a number of pseudo wires.
-     * <p>
-     * Called ONLY when configuration changes, thus the check
-     * for the mastership of the device.
-     * <p>
-     * Only the master of CP1 will deploy this pseudowire.
      *
      * @param pwToAdd the set of pseudo wires to add
      */
-    private void deploy(Set<L2TunnelDescription> pwToAdd) {
+    public void deploy(Set<L2TunnelDescription> pwToAdd) {
 
         Result result;
 
@@ -507,11 +463,6 @@
             ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2();
             long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
 
-            // only the master of CP1 will program this pseudowire
-            if (!srManager.isMasterOf(cp1)) {
-                log.debug("Not the master of {}. Ignore pseudo wire deployment id={}", cp1, tunnelId);
-                continue;
-            }
 
             try {
                 // differentiate between leaf-leaf pseudowires and leaf-spine
@@ -550,57 +501,6 @@
         }
     }
 
-
-    @Override
-    public void processPwaasConfigUpdated(NetworkConfigEvent event) {
-        checkArgument(event.config().isPresent(),
-                "Config is not presented in PwaasConfigUpdated event {}", event);
-        checkArgument(event.prevConfig().isPresent(),
-                "PrevConfig is not presented in PwaasConfigUpdated event {}", event);
-
-        log.info("Pseudowire configuration updated.");
-
-        // We retrieve the old pseudo wires.
-        PwaasConfig prevConfig = (PwaasConfig) event.prevConfig().get();
-        Set<Long> prevPws = prevConfig.getPwIds();
-
-        // We retrieve the new pseudo wires.
-        PwaasConfig config = (PwaasConfig) event.config().get();
-        Set<Long> newPws = config.getPwIds();
-
-        // We compute the pseudo wires to update.
-        Set<Long> updPws = newPws.stream()
-                .filter(tunnelId -> prevPws.contains(tunnelId)
-                        && !config.getPwDescription(tunnelId).equals(prevConfig.getPwDescription(tunnelId)))
-                .collect(Collectors.toSet());
-
-        // The pseudo wires to remove.
-        Set<Long> rmvPWs = prevPws.stream()
-                .filter(tunnelId -> !newPws.contains(tunnelId)).collect(Collectors.toSet());
-
-        Set<L2TunnelDescription> pwToRemove = rmvPWs.stream()
-                .map(prevConfig::getPwDescription)
-                .collect(Collectors.toSet());
-        tearDown(pwToRemove);
-
-        // The pseudo wires to add.
-        Set<Long> addedPWs = newPws.stream()
-                .filter(tunnelId -> !prevPws.contains(tunnelId))
-                .collect(Collectors.toSet());
-        Set<L2TunnelDescription> pwToAdd = addedPWs.stream()
-                .map(config::getPwDescription)
-                .collect(Collectors.toSet());
-        deploy(pwToAdd);
-
-
-        // The pseudo wires to update.
-        updPws.forEach(tunnelId -> updatePw(prevConfig.getPwDescription(tunnelId),
-                                            config.getPwDescription(tunnelId)));
-
-        log.info("Pseudowires removed : {}, Pseudowires updated : {}, Pseudowires added : {}", rmvPWs,
-                 updPws, addedPWs);
-    }
-
     /**
      * Helper function to update a pw.
      * <p>
@@ -621,11 +521,6 @@
         ConnectPoint oldCp1 = oldPw.l2TunnelPolicy().cP1();
         long tunnelId = oldPw.l2Tunnel().tunnelId();
 
-        // only the master of CP1 will update this pseudowire
-        if (!srManager.isMasterOf(oldPw.l2TunnelPolicy().cP1())) {
-            log.debug("Not the master of {}. Ignore pseudo wire update id={}", oldCp1, tunnelId);
-            return;
-        }
         // only determine if the new pseudowire is leaf-spine, because
         // removal process is the same for both leaf-leaf and leaf-spine pws
         boolean newPwSpine;
@@ -815,24 +710,6 @@
         });
     }
 
-    @Override
-    public void processPwaasConfigRemoved(NetworkConfigEvent event) {
-        checkArgument(event.prevConfig().isPresent(),
-                "PrevConfig is not presented in PwaasConfigRemoved event {}", event);
-
-        log.info("Network event : Pseudowire configuration removed!");
-        PwaasConfig config = (PwaasConfig) event.prevConfig().get();
-
-        Set<L2TunnelDescription> pwToRemove = config
-                .getPwIds()
-                .stream()
-                .map(config::getPwDescription)
-                .collect(Collectors.toSet());
-
-        // We teardown all the pseudo wire deployed
-        tearDown(pwToRemove);
-    }
-
     /**
      * Helper function for removing a single pseudowire.
      * <p>
@@ -957,12 +834,6 @@
             ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2();
             long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
 
-            // only the master of CP1 will program this pseudowire
-            if (!srManager.isMasterOf(cp1)) {
-                log.debug("Not the master of {}. Ignore pseudo wire removal id={}", cp1, tunnelId);
-                continue;
-            }
-
             // no need to differentiate here between leaf-leaf and leaf-spine, because
             // the only change is in the groups, which we do not remove either way
             log.info("Removing pseudowire {}", tunnelId);
diff --git a/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java b/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
index 044ad41..5fce137 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
@@ -17,7 +17,6 @@
 package org.onosproject.segmentrouting.pwaas;
 
 import org.onosproject.net.Link;
-import org.onosproject.net.config.NetworkConfigEvent;
 
 import java.util.List;
 import java.util.Set;
@@ -48,27 +47,6 @@
     void processLinkDown(Link link);
 
     /**
-     * Processes Pwaas Config added event.
-     *
-     * @param event network config add event
-     */
-    void processPwaasConfigAdded(NetworkConfigEvent event);
-
-    /**
-     * Processes PWaaS Config updated event.
-     *
-     * @param event network config updated event
-     */
-    void processPwaasConfigUpdated(NetworkConfigEvent event);
-
-    /**
-     * Processes Pwaas Config removed event.
-     *
-     * @param event network config removed event
-     */
-    void processPwaasConfigRemoved(NetworkConfigEvent event);
-
-    /**
      * Helper function to handle the pw removal.
      * <p>
      * This method should for the mastership of the device because it is
diff --git a/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java b/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
new file mode 100644
index 0000000..fa2807e
--- /dev/null
+++ b/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright 2015-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.segmentrouting.pwaas;
+
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.intf.InterfaceService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class with static methods that help
+ * parse pseudowire related information and also
+ * verify that a pseudowire combination is valid.
+ */
+public final class PwaasUtil {
+
+    private static final Logger log = LoggerFactory.getLogger(PwaasUtil.class);
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    public static DeviceService deviceService = AbstractShellCommand.get(DeviceService.class);;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    public static InterfaceService intfService = AbstractShellCommand.get(InterfaceService.class);
+
+    private PwaasUtil() {
+        return;
+    }
+
+    /**
+     * Parses a vlan as a string. Returns the VlanId if
+     * provided String can be parsed as an integer or is '' / '*'
+     *
+     * @param vlan string as read from configuration
+     * @return VlanId null if error
+     */
+    public static VlanId parseVlan(String vlan) {
+
+        if (vlan.equals("*") || vlan.equals("Any")) {
+            return VlanId.vlanId("Any");
+        } else if (vlan.equals("") || vlan.equals("None")) {
+            return VlanId.vlanId("None");
+        } else {
+            try {
+                VlanId newVlan = VlanId.vlanId(vlan);
+                return newVlan;
+            } catch (IllegalArgumentException e) {
+                return null;
+            }
+        }
+    }
+
+    /**
+     *
+     * @param mode RAW or TAGGED
+     * @return the L2Mode if input is correct
+     */
+    public static L2Mode parseMode(String mode) {
+
+        if (!mode.equals("RAW") && !mode.equals("TAGGED")) {
+            return null;
+        }
+
+        return L2Mode.valueOf(mode);
+    }
+
+    /**
+     *
+     * @param label the mpls label of the pseudowire
+     * @return the MplsLabel
+     * @throws IllegalArgumentException if label is invalid
+     */
+    public static MplsLabel parsePWLabel(String label) {
+
+        try {
+            MplsLabel pwLabel = MplsLabel.mplsLabel(label);
+            return pwLabel;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * Parses a string as a pseudowire id - which is an integer.
+     *
+     * @param id The id of pw in string form
+     * @return The id of pw as an Integer or null if it failed the conversion.
+     */
+    public static Integer parsePwId(String id) {
+        try {
+            return Integer.parseInt(id);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+
+    /**
+     * Helper method to verify if the tunnel is whether or not
+     * supported.
+     *
+     * @param l2Tunnel the tunnel to verify
+     */
+    private static void verifyTunnel(L2Tunnel l2Tunnel) {
+
+        // Service delimiting tag not supported yet.
+        if (!l2Tunnel.sdTag().equals(VlanId.NONE)) {
+            throw new IllegalArgumentException(String.format("Service delimiting tag not supported yet for " +
+                                                                     "pseudowire %d.", l2Tunnel.tunnelId()));
+        }
+
+        // Tag mode not supported yet.
+        if (l2Tunnel.pwMode() == L2Mode.TAGGED) {
+            throw new IllegalArgumentException(String.format("Tagged mode not supported yet for pseudowire %d.",
+                                                             l2Tunnel.tunnelId()));
+        }
+
+        // Raw mode without service delimiting tag
+        // is the only mode supported for now.
+    }
+
+    /**
+     * Helper method to verify if the policy is whether or not
+     * supported and if policy will be successfully instantiated in the
+     * network.
+     *
+     * @param ingressInner the ingress inner tag
+     * @param ingressOuter the ingress outer tag
+     * @param egressInner the egress inner tag
+     * @param egressOuter the egress outer tag
+     */
+    private static void verifyPolicy(ConnectPoint cP1,
+                              ConnectPoint cP2,
+                              VlanId ingressInner,
+                              VlanId ingressOuter,
+                              VlanId egressInner,
+                              VlanId egressOuter,
+                              Long tunnelId) {
+
+        if (cP1.deviceId().equals(cP2.deviceId())) {
+            throw new IllegalArgumentException(String.format("Pseudowire connection points can not reside in the " +
+                                                                     "same node, in pseudowire %d.", tunnelId));
+        }
+
+        // We can have multiple tags, all of them can be NONE,
+        // indicating untagged traffic, however, the outer tag can
+        // not have value if the inner tag is None
+        if (ingressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) {
+            throw new IllegalArgumentException(String.format("Inner tag should not be empty when " +
+                                                                     "outer tag is set for pseudowire %d for cP1.",
+                                                             tunnelId));
+        }
+
+        if (egressInner.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Inner tag should not be empty when" +
+                                                                                    " outer tag is set for " +
+                                                                                    "pseudowire %d " +
+                                                                                    "for cP2.", tunnelId)));
+        }
+
+        if (ingressInner.equals(VlanId.ANY) ||
+                ingressOuter.equals(VlanId.ANY) ||
+                egressInner.equals(VlanId.ANY) ||
+                egressOuter.equals(VlanId.ANY)) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Wildcard VLAN matching not yet " +
+                                                                                    "supported for pseudowire %d.",
+                                                                            tunnelId)));
+        }
+
+        if (((!ingressOuter.equals(VlanId.NONE) && !ingressInner.equals(VlanId.NONE)) &&
+                (egressOuter.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE)))
+                || ((ingressOuter.equals(VlanId.NONE) && ingressInner.equals(VlanId.NONE)) &&
+                (!egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)))) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Support for double tag <-> untag is not" +
+                                                                                    "supported for pseudowire %d.",
+                                                                            tunnelId)));
+        }
+        if ((!ingressInner.equals(VlanId.NONE) &&
+                ingressOuter.equals(VlanId.NONE) &&
+                !egressOuter.equals(VlanId.NONE))
+                || (egressOuter.equals(VlanId.NONE) &&
+                !egressInner.equals(VlanId.NONE) &&
+                !ingressOuter.equals(VlanId.NONE))) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Support for double-tag<->" +
+                                                                                    "single-tag is not supported" +
+                                                                                    " for pseudowire %d.", tunnelId)));
+        }
+
+        if ((ingressInner.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE))
+                || (!ingressInner.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) {
+            throw new IllegalArgumentException(String.valueOf(String.format("single-tag <-> untag is not supported" +
+                                                                                    " for pseudowire %d.", tunnelId)));
+        }
+
+
+        if (!ingressInner.equals(egressInner) && !ingressOuter.equals(egressOuter)) {
+            throw new IllegalArgumentException(String.valueOf(String.format("We do not support changing both tags " +
+                                                                                    "in double tagged pws, only the " +
+                                                                                    "outer," +
+                                                                                    " for pseudowire %d.", tunnelId)));
+        }
+
+        // check if cp1 and port of cp1 exist
+        if (deviceService.getDevice(cP1.deviceId()) == null) {
+            throw new IllegalArgumentException(String.valueOf(String.format("cP1 device %s does not exist for" +
+                                                                                    " pseudowire %d.", cP1.deviceId(),
+                                                                            tunnelId)));
+        }
+
+        if (deviceService.getPort(cP1) == null) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP1 device %s does not" +
+                                                                                    " exist for pseudowire %d.",
+                                                                            cP1.port(),
+                                                                            cP1.deviceId(), tunnelId)));
+        }
+
+        // check if cp2 and port of cp2 exist
+        if (deviceService.getDevice(cP2.deviceId()) == null) {
+            throw new IllegalArgumentException(String.valueOf(String.format("cP2 device %s does not exist for" +
+                                                                                    " pseudowire %d.", cP2.deviceId(),
+                                                                            tunnelId)));
+        }
+
+        if (deviceService.getPort(cP2) == null) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP2 device %s does " +
+                                                                                    "not exist for pseudowire %d.",
+                                                                            cP2.port(), cP2.deviceId(), tunnelId)));
+        }
+    }
+
+    /**
+     * Verifies that the pseudowires will not conflict with each other.
+     *
+     * Further, check if vlans for connect points are already used.
+     *
+     * @param tunnel Tunnel for pw
+     * @param policy Policy for pw
+     * @param labelSet Label set used so far with this configuration
+     * @param vlanSet Vlan set used with this configuration
+     * @param tunnelSet Tunnel set used with this configuration
+     */
+    private static void verifyGlobalValidity(L2Tunnel tunnel,
+                                      L2TunnelPolicy policy,
+                                      Set<MplsLabel> labelSet,
+                                      Map<ConnectPoint, Set<VlanId>> vlanSet,
+                                      Set<Long> tunnelSet) {
+
+        if (tunnelSet.contains(tunnel.tunnelId())) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Tunnel Id %d already used by" +
+                                                                                    " another pseudowire, in " +
+                                                                                    "pseudowire %d!",
+                                                                            tunnel.tunnelId(),
+                                                                            tunnel.tunnelId())));
+        }
+        tunnelSet.add(tunnel.tunnelId());
+
+        // check if tunnel id is used again
+        ConnectPoint cP1 = policy.cP1();
+        ConnectPoint cP2 = policy.cP2();
+
+        // insert cps to hashmap if this is the first time seen
+        if (!vlanSet.containsKey(cP1)) {
+            vlanSet.put(cP1, new HashSet<VlanId>());
+        }
+        if (!vlanSet.containsKey(cP2)) {
+            vlanSet.put(cP2, new HashSet<VlanId>());
+        }
+
+        // if single tagged or untagged vlan is the inner
+        // if double tagged vlan is the outer
+        VlanId vlanToCheckCP1;
+        if (policy.cP1OuterTag().equals(VlanId.NONE)) {
+            vlanToCheckCP1 = policy.cP1InnerTag();
+        } else {
+            vlanToCheckCP1 = policy.cP1OuterTag();
+        }
+
+        VlanId vlanToCheckCP2;
+        if (policy.cP2OuterTag().equals(VlanId.NONE)) {
+            vlanToCheckCP2 = policy.cP2InnerTag();
+        } else {
+            vlanToCheckCP2 = policy.cP2OuterTag();
+        }
+
+        if (labelSet.contains(tunnel.pwLabel())) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Label %s already used by another" +
+                                                                                    " pseudowire, in pseudowire %d!",
+                                                                            tunnel.pwLabel(), tunnel.tunnelId())));
+        }
+        labelSet.add(tunnel.pwLabel());
+
+        if (vlanSet.get(cP1).contains(vlanToCheckCP1)) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already used " +
+                                                                                    "by another pseudowire, in " +
+                                                                                    "pseudowire" +
+                                                                                    " %d!", vlanToCheckCP1,  cP1,
+                                                                            tunnel.tunnelId())));
+        }
+        vlanSet.get(cP1).add(vlanToCheckCP1);
+
+        if (vlanSet.get(cP2).contains(vlanToCheckCP2)) {
+            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already used" +
+                                                                                    " by another pseudowire, in" +
+                                                                                    " pseudowire %d!", vlanToCheckCP2,
+                                                                            cP2,
+                                                                            tunnel.tunnelId())));
+        }
+        vlanSet.get(cP2).add(vlanToCheckCP2);
+
+        // check that vlans for the connect points are not used
+        intfService.getInterfacesByPort(cP1).stream()
+                .forEach(intf -> {
+
+                    // check if tagged pw affects tagged interface
+                    if (intf.vlanTagged().contains(vlanToCheckCP1)) {
+                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already" +
+                                                                                                " used for this" +
+                                                                                                " interface, in" +
+                                                                                                " pseudowire %d!",
+                                                                                        vlanToCheckCP1, cP1,
+                                                                                        tunnel.tunnelId())));
+                    }
+
+                    // if vlanNative != null this interface is configured with untagged traffic also
+                    // check if it collides with untagged interface
+                    if ((intf.vlanNative() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
+                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP1 " +
+                                                                                                "%s already used " +
+                                                                                                "for this " +
+                                                                                                "interface, in " +
+                                                                                                "pseudowire " +
+                                                                                                "%d!", cP1,
+                                                                                        tunnel.tunnelId())));
+                    }
+
+                    // if vlanUntagged != null this interface is configured only with untagged traffic
+                    // check if it collides with untagged interface
+                    if ((intf.vlanUntagged() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
+                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for " +
+                                                                                                "cP1 %s already" +
+                                                                                                " used for this" +
+                                                                                                " interface," +
+                                                                                                " in pseudowire %d!",
+                                                                                        cP1, tunnel.tunnelId())));
+                    }
+                });
+
+        intfService.getInterfacesByPort(cP2).stream()
+                .forEach(intf -> {
+                    if (intf.vlanTagged().contains(vlanToCheckCP2)) {
+                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s " +
+                                                                                                " used for  " +
+                                                                                                "this interface, " +
+                                                                                                "in pseudowire %d!",
+                                                                                        vlanToCheckCP2, cP2,
+                                                                                        tunnel.tunnelId())));
+                    }
+
+                    // if vlanNative != null this interface is configured with untagged traffic also
+                    // check if it collides with untagged interface
+                    if ((intf.vlanNative() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
+                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic " +
+                                                                                                "for cP2 %s " +
+                                                                                                "already " +
+                                                                                                "used for this" +
+                                                                                                " interface, " +
+                                                                                                "in pseudowire %d!",
+                                                                                        cP2, tunnel.tunnelId())));
+                    }
+
+                    // if vlanUntagged != null this interface is configured only with untagged traffic
+                    // check if it collides with untagged interface
+                    if ((intf.vlanUntagged() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
+                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s" +
+                                                                                                " already" +
+                                                                                                " used for " +
+                                                                                                "this interface, " +
+                                                                                                "in pseudowire %d!",
+                                                                                        cP2, tunnel.tunnelId())));
+                    }
+                });
+
+    }
+
+    /**
+     * Helper method to verify the integrity of the pseudo wire.
+     *
+     * @param l2TunnelDescription the pseudo wire description
+     */
+    private static void verifyPseudoWire(L2TunnelDescription l2TunnelDescription,
+                                  Set<MplsLabel> labelSet,
+                                  Map<ConnectPoint, Set<VlanId>> vlanset,
+                                  Set<Long> tunnelSet) {
+
+        L2Tunnel l2Tunnel = l2TunnelDescription.l2Tunnel();
+        L2TunnelPolicy l2TunnelPolicy = l2TunnelDescription.l2TunnelPolicy();
+
+        verifyTunnel(l2Tunnel);
+
+        verifyPolicy(
+                l2TunnelPolicy.cP1(),
+                l2TunnelPolicy.cP2(),
+                l2TunnelPolicy.cP1InnerTag(),
+                l2TunnelPolicy.cP1OuterTag(),
+                l2TunnelPolicy.cP2InnerTag(),
+                l2TunnelPolicy.cP2OuterTag(),
+                l2Tunnel.tunnelId()
+        );
+
+        verifyGlobalValidity(l2Tunnel,
+                             l2TunnelPolicy,
+                             labelSet,
+                             vlanset,
+                             tunnelSet);
+
+    }
+
+    public static boolean configurationValidity(Set<L2TunnelDescription> pseudowires) {
+
+        // structures to keep pw information
+        // in order to see if instantiating them will create
+        // problems
+        Set<Long> tunIds = new HashSet<>();
+        Set<MplsLabel> labelsUsed = new HashSet<>();
+        Map<ConnectPoint, Set<VlanId>> vlanIds = new HashMap<>();
+
+        // TODO : I know we should not use exceptions for flow control,
+        // however this code was originally implemented in the configuration
+        // addition where the exceptions were propagated and the configuration was
+        // deemed not valid. I plan in the future to refactor the parts that
+        // check the pseudowire validity.
+        //
+        // Ideally we would like to return a String which could also return to
+        // the user issuing the rest request for adding the pseudowire.
+        try {
+
+            // check that pseudowires can be instantiated in the network
+            // we try to guarantee that all the pws will work before
+            // instantiating any of them
+            for (L2TunnelDescription pw : pseudowires) {
+                verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds);
+            }
+        } catch (Exception e) {
+
+            log.error("Caught exception while validating pseudowire : {}", e.getMessage());
+            return false;
+        }
+
+        // return true
+        return true;
+    }
+
+}
diff --git a/app/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java b/app/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java
deleted file mode 100644
index 23d1233..0000000
--- a/app/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright 2016-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.segmentrouting;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.TestApplicationId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.segmentrouting.config.PwaasConfig;
-
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Mode;
-
-import java.io.InputStream;
-import java.util.Set;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.*;
-
-/**
- * Unit tests for class {@link PwaasConfig}.
- */
-public class PwaasConfigTest {
-
-    private static final String TUNNEL_ID_1 = "1";
-    private static final String TUNNEL_ID_2 = "20";
-    private static final String NOT_PRESENT_TUNNEL_ID = "2";
-    private static final ConnectPoint INGRESS_1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
-    private static final ConnectPoint INGRESS_2 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
-    private static final ConnectPoint EGRESS_1 = ConnectPoint.deviceConnectPoint("of:0000000000000002/1");
-    private static final ConnectPoint EGRESS_2 = ConnectPoint.deviceConnectPoint("of:0000000000000002/1");
-    private static final VlanId INGRESS_INNER_TAG_1 = VlanId.vlanId("10");
-    private static final VlanId INGRESS_INNER_TAG_2 = VlanId.vlanId("100");
-    private static final VlanId INGRESS_OUTER_TAG_1 = VlanId.vlanId("20");
-    private static final VlanId INGRESS_OUTER_TAG_2 = VlanId.vlanId("200");
-    private static final VlanId EGRESS_INNER_TAG_1 = VlanId.vlanId("10");
-    private static final VlanId EGRESS_INNER_TAG_2 = VlanId.vlanId("100");
-    private static final VlanId EGRESS_OUTER_TAG_1 = VlanId.vlanId("21");
-    private static final VlanId EGRESS_OUTER_TAG_2 = VlanId.vlanId("210");
-    private static final String MODE_1 = "RAW";
-    private static final String MODE_2 = "RAW";
-    private static final VlanId SD_TAG_1 = VlanId.NONE;
-    private static final VlanId SD_TAG_2 = VlanId.NONE;
-    private static final MplsLabel PW_LABEL_1 = MplsLabel.mplsLabel("255");
-    private static final MplsLabel PW_LABEL_2 = MplsLabel.mplsLabel("1255");
-
-    /*
-     * Configuration below copied from host handler test.
-     */
-
-    // Host Mac, VLAN
-    private static final ProviderId PROVIDER_ID = ProviderId.NONE;
-    private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
-    private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
-    private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
-    private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
-    private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
-    // Host IP
-    private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
-    private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
-    private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
-    private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
-    private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
-    private static final IpAddress HOST_IP32 = IpAddress.valueOf("10.0.3.2");
-    // Device
-    private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
-    private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
-    private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
-    private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
-    private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
-    private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
-    // Port
-    private static final PortNumber P1 = PortNumber.portNumber(1);
-    private static final PortNumber P2 = PortNumber.portNumber(2);
-    private static final PortNumber P3 = PortNumber.portNumber(3);
-    private static final PortNumber P9 = PortNumber.portNumber(9);
-    // Connect Point
-    private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
-    private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
-    private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
-    private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
-    private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
-    private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
-    private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
-    private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
-    private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
-    private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
-    // Connect Point for dual-homed host failover
-    private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
-    private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
-    private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
-    private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
-    private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
-    private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
-    private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
-    private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
-    // Conenct Point for mastership test
-    private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
-    private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
-    private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
-    private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
-    // Interface VLAN
-    private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
-    private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(VlanId.vlanId((short) 20));
-    private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
-    private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
-                                     VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
-    private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
-    // Interface subnet
-    private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
-    private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
-    private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
-    private static final InterfaceIpAddress INTF_IP1 =
-            new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
-    private static final InterfaceIpAddress INTF_IP2 =
-            new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
-    private static final InterfaceIpAddress INTF_IP3 =
-            new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
-    // Interfaces
-    private static final Interface INTF11 =
-            new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                          INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF12 =
-            new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                          INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF13 =
-            new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
-                          null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
-    private static final Interface INTF21 =
-            new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                          INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF22 =
-            new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                          INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF31 =
-            new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                          INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF32 =
-            new Interface(null, CP32, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
-                          INTF_VLAN_OTHER, null, null);
-    private static final Interface INTF39 =
-            new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                          null, INTF_VLAN_PAIR, null);
-    private static final Interface INTF41 =
-            new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                          INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF49 =
-            new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                          null, INTF_VLAN_PAIR, null);
-    // Host
-    private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
-                                                      HOST_VLAN_UNTAGGED,
-                                                      Sets.newHashSet(HOST_LOC11, HOST_LOC21),
-                                                      Sets.newHashSet(HOST_IP11),
-                                                      false);
-
-    // A set of hosts
-    private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
-    // A set of devices of which we have mastership
-    private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
-    // A set of interfaces
-    private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
-                                                                     INTF22, INTF31, INTF32, INTF39, INTF41, INTF49);
-
-    private PwaasConfig config;
-    private PwaasConfig invalidConfigVlan;
-    private PwaasConfig invalidConfigMode;
-    private PwaasConfig invalidConfigLabel;
-    private PwaasConfig invalidConfigConflictingVlan;
-
-    @Before
-    public void setUp() throws Exception {
-        InputStream jsonStream = PwaasConfig.class
-                .getResourceAsStream("/pwaas.json");
-        InputStream jsonStreamInvalid1 = PwaasConfig.class
-                .getResourceAsStream("/pwaas-invalid-mode.json");
-        InputStream jsonStreamInvalid2 = PwaasConfig.class
-                .getResourceAsStream("/pwaas-invalid-pwlabel.json");
-        InputStream jsonStreamInvalid3 = PwaasConfig.class
-                .getResourceAsStream("/pwaas-invalid-vlan.json");
-        InputStream jsonStreamInvalid4 = PwaasConfig.class
-                .getResourceAsStream("/pwaas-conflicting-vlan.json");
-
-        String key = SegmentRoutingManager.APP_NAME;
-        ApplicationId subject = new TestApplicationId(key);
-        ObjectMapper mapper = new ObjectMapper();
-
-        JsonNode jsonNode = mapper.readTree(jsonStream);
-        JsonNode jsonNodeInvalid1 = mapper.readTree(jsonStreamInvalid1);
-        JsonNode jsonNodeInvalid2 = mapper.readTree(jsonStreamInvalid2);
-        JsonNode jsonNodeInvalid3 = mapper.readTree(jsonStreamInvalid3);
-        JsonNode jsonNodeInvalid4 = mapper.readTree(jsonStreamInvalid4);
-
-        ConfigApplyDelegate delegate = new MockDelegate();
-
-        DeviceService devService = new MockDeviceService();
-        InterfaceService infService = new MockInterfaceService(INTERFACES);
-
-        // create two devices and add them
-        DefaultAnnotations.Builder builderDev1 = DefaultAnnotations.builder();
-        DefaultAnnotations.Builder builderDev2 = DefaultAnnotations.builder();
-
-        Device dev1 = new MockDevice(DEV1, builderDev1.build());
-        Device dev2 = new MockDevice(DEV2, builderDev2.build());
-        ((MockDeviceService) devService).addDevice(dev1);
-        ((MockDeviceService) devService).addDevice(dev2);
-
-        config = new PwaasConfig(devService, infService);
-        invalidConfigVlan = new PwaasConfig(devService, infService);
-        invalidConfigMode = new PwaasConfig(devService, infService);
-        invalidConfigLabel = new PwaasConfig(devService, infService);
-        invalidConfigConflictingVlan = new PwaasConfig(devService, infService);
-
-        config.init(subject, key, jsonNode, mapper, delegate);
-        invalidConfigVlan.init(subject, key, jsonNodeInvalid1, mapper, delegate);
-        invalidConfigMode.init(subject, key, jsonNodeInvalid2, mapper, delegate);
-        invalidConfigLabel.init(subject, key, jsonNodeInvalid3, mapper, delegate);
-        invalidConfigConflictingVlan.init(subject, key, jsonNodeInvalid4, mapper, delegate);
-
-        config.deviceService = devService;
-        config.intfService = infService;
-
-        invalidConfigVlan.deviceService = devService;
-        invalidConfigVlan.intfService = infService;
-
-        invalidConfigLabel.deviceService = devService;
-        invalidConfigLabel.intfService = infService;
-
-        invalidConfigMode.deviceService = devService;
-        invalidConfigMode.intfService = infService;
-
-        invalidConfigConflictingVlan.deviceService = devService;
-        invalidConfigConflictingVlan.intfService = infService;
-    }
-
-    /**
-     * Tests config validity.
-     */
-    @Test
-    public void testIsValid() {
-        try {
-            assertTrue(config.isValid());
-        } catch (IllegalArgumentException e) {
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Tests config in-validity.
-     */
-    @Test
-    public void testValid1() {
-        assertFalse(invalidConfigVlan.isValid());
-    }
-
-    @Test
-    public void testValid2() {
-        assertFalse(invalidConfigMode.isValid());
-    }
-
-    @Test
-    public void testValid3() {
-        assertFalse(invalidConfigLabel.isValid());
-    }
-
-    @Test
-    public void testValid4() {
-        assertFalse(invalidConfigConflictingVlan.isValid());
-    }
-
-    /**
-     * Tests getPwIds.
-     */
-    @Test
-    public void testGetPwIds() {
-        Set<Long> pwIds = config.getPwIds();
-
-        assertThat(pwIds.size(), is(2));
-        assertTrue(pwIds.contains(Long.parseLong(TUNNEL_ID_1)));
-        assertTrue(pwIds.contains(Long.parseLong(TUNNEL_ID_2)));
-        assertFalse(pwIds.contains(Long.parseLong(NOT_PRESENT_TUNNEL_ID)));
-    }
-
-    /**
-     * Tests getPwDescription.
-     */
-    @Test
-    public void testGetPwDescription() {
-        L2TunnelDescription l2TunnelDescription = null;
-
-        L2Tunnel l2Tunnel = new DefaultL2Tunnel(
-            L2Mode.valueOf(MODE_1),
-            SD_TAG_1,
-            Long.parseLong(TUNNEL_ID_1),
-            PW_LABEL_1
-        );
-        L2TunnelPolicy l2TunnelPolicy = new DefaultL2TunnelPolicy(
-                Long.parseLong(TUNNEL_ID_1),
-                INGRESS_1,
-                INGRESS_INNER_TAG_1,
-                INGRESS_OUTER_TAG_1,
-                EGRESS_1,
-                EGRESS_INNER_TAG_1,
-                EGRESS_OUTER_TAG_1
-        );
-
-        l2TunnelDescription = config.getPwDescription(Long.parseLong(TUNNEL_ID_1));
-        assertThat(l2TunnelDescription.l2Tunnel().pwMode(), is(l2Tunnel.pwMode()));
-        assertThat(l2TunnelDescription.l2Tunnel().sdTag(), is(l2Tunnel.sdTag()));
-        assertThat(l2TunnelDescription.l2Tunnel().tunnelId(), is(l2Tunnel.tunnelId()));
-        assertThat(l2TunnelDescription.l2Tunnel().pwLabel(), is(l2Tunnel.pwLabel()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().tunnelId(), is(l2TunnelPolicy.tunnelId()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP1InnerTag(), is(l2TunnelPolicy.cP1InnerTag()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP1OuterTag(), is(l2TunnelPolicy.cP1OuterTag()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP2InnerTag(), is(l2TunnelPolicy.cP2InnerTag()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP2OuterTag(), is(l2TunnelPolicy.cP2OuterTag()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP1(), is(l2TunnelPolicy.cP1()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP2(), is(l2TunnelPolicy.cP2()));
-
-        l2Tunnel = new DefaultL2Tunnel(
-                L2Mode.valueOf(MODE_2),
-                SD_TAG_2,
-                Long.parseLong(TUNNEL_ID_2),
-                PW_LABEL_2
-        );
-        l2TunnelPolicy = new DefaultL2TunnelPolicy(
-                Long.parseLong(TUNNEL_ID_2),
-                INGRESS_2,
-                INGRESS_INNER_TAG_2,
-                INGRESS_OUTER_TAG_2,
-                EGRESS_2,
-                EGRESS_INNER_TAG_2,
-                EGRESS_OUTER_TAG_2
-        );
-
-        l2TunnelDescription = config.getPwDescription(Long.parseLong(TUNNEL_ID_2));
-        assertThat(l2TunnelDescription.l2Tunnel().pwMode(), is(l2Tunnel.pwMode()));
-        assertThat(l2TunnelDescription.l2Tunnel().sdTag(), is(l2Tunnel.sdTag()));
-        assertThat(l2TunnelDescription.l2Tunnel().tunnelId(), is(l2Tunnel.tunnelId()));
-        assertThat(l2TunnelDescription.l2Tunnel().pwLabel(), is(l2Tunnel.pwLabel()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().tunnelId(), is(l2TunnelPolicy.tunnelId()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP1InnerTag(), is(l2TunnelPolicy.cP1InnerTag()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP1OuterTag(), is(l2TunnelPolicy.cP1OuterTag()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP2OuterTag(), is(l2TunnelPolicy.cP2OuterTag()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP2OuterTag(), is(l2TunnelPolicy.cP2OuterTag()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP1(), is(l2TunnelPolicy.cP1()));
-        assertThat(l2TunnelDescription.l2TunnelPolicy().cP2(), is(l2TunnelPolicy.cP2()));
-    }
-
-    private class MockDelegate implements ConfigApplyDelegate {
-        @Override
-        public void onApply(Config config) {
-        }
-    }
-
-}
diff --git a/web/src/main/java/org/onosproject/segmentrouting/package-info.java b/web/src/main/java/org/onosproject/segmentrouting/package-info.java
index ff9555e..1d50ba9 100644
--- a/web/src/main/java/org/onosproject/segmentrouting/package-info.java
+++ b/web/src/main/java/org/onosproject/segmentrouting/package-info.java
@@ -15,6 +15,6 @@
  */
 
 /**
- * Segment routing application components.
+ * Segment routing REST implementation.
  */
 package org.onosproject.segmentrouting.web;
\ No newline at end of file
diff --git a/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java b/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
index abfba3c..cebcf84 100644
--- a/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
+++ b/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
@@ -26,7 +26,6 @@
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
-import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -37,7 +36,7 @@
 /**
  * Query, create and remove segment routing plicies.
  */
-@Path("policy")
+// @Path("policy")
 public class PolicyWebResource extends AbstractWebResource {
 
     private static final PolicyCodec POLICY_CODEC = new PolicyCodec();
diff --git a/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java b/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
new file mode 100644
index 0000000..f2fe786
--- /dev/null
+++ b/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2015-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.segmentrouting.web;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
+import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
+import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
+import org.onosproject.segmentrouting.pwaas.L2Mode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
+
+/**
+ * Codec of PseudowireCodec class.
+ */
+public final class PseudowireCodec extends JsonCodec<DefaultL2TunnelDescription> {
+
+    // JSON field names
+    private static final String PW_ID = "pwId";
+    private static final String CP1 = "cP1";
+    private static final String CP2 = "cP2";
+    private static final String CP1_INNER_TAG = "cP1InnerTag";
+    private static final String CP1_OUTER_TAG = "cP1OuterTag";
+    private static final String CP2_INNER_TAG = "cP2InnerTag";
+    private static final String CP2_OUTER_TAG = "cP2OouterTag";
+    private static final String MODE = "mode";
+    private static final String SERVICE_DELIM_TAG = "serviceTag";
+    private static final String PW_LABEL = "pwLabel";
+
+    private static Logger log = LoggerFactory
+            .getLogger(PseudowireCodec.class);
+
+    @Override
+    public ObjectNode encode(DefaultL2TunnelDescription pseudowire, CodecContext context) {
+        final ObjectNode result = context.mapper().createObjectNode()
+                .put(PW_ID, pseudowire.l2Tunnel().tunnelId());
+
+        result.put(CP1, pseudowire.l2TunnelPolicy().cP1().toString());
+        result.put(CP2, pseudowire.l2TunnelPolicy().cP2().toString());
+
+        result.put(CP1_INNER_TAG, pseudowire.l2TunnelPolicy().cP1InnerTag().toString());
+        result.put(CP1_OUTER_TAG, pseudowire.l2TunnelPolicy().cP1OuterTag().toString());
+
+
+        result.put(CP2_INNER_TAG, pseudowire.l2TunnelPolicy().cP2InnerTag().toString());
+        result.put(CP2_OUTER_TAG, pseudowire.l2TunnelPolicy().cP2OuterTag().toString());
+
+        result.put(MODE, pseudowire.l2Tunnel().pwMode() == L2Mode.RAW ? "RAW" : "TAGGED");
+        result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString());
+        result.put(PW_LABEL, pseudowire.l2Tunnel().pwLabel().toString());
+
+        return result;
+    }
+
+    /**
+     * Decodes a json containg a single field with the pseudowire id.
+     *
+     * @param json Json to decode.
+     * @return The pseudowire id.
+     */
+    public Integer decodeId(ObjectNode json) {
+
+        Integer id = parsePwId(json.path(PW_ID).asText());
+        if (id == null) {
+            log.error("Pseudowire id is not an integer!");
+            return null;
+        }
+
+        return id;
+    }
+
+    @Override
+    public DefaultL2TunnelDescription decode(ObjectNode json, CodecContext context) {
+
+        String tempString;
+
+        Integer id = parsePwId(json.path(PW_ID).asText());
+        if (id == null) {
+            log.error("Pseudowire id is not an integer");
+            return null;
+        }
+
+        ConnectPoint cP1, cP2;
+        try {
+            tempString = json.path(CP1).asText();
+            cP1 = ConnectPoint.deviceConnectPoint(tempString);
+        } catch (Exception e) {
+            log.error("cP1 is not a valid connect point!");
+            return null;
+        }
+
+        try {
+            tempString = json.path(CP2).asText();
+            cP2 = ConnectPoint.deviceConnectPoint(tempString);
+        } catch (Exception e) {
+            log.error("cP2 is not a valid connect point!");
+            return null;
+        }
+
+        VlanId cP1InnerVlan = parseVlan(json.path(CP1_INNER_TAG).asText());
+        VlanId cP1OuterVlan = parseVlan(json.path(CP1_OUTER_TAG).asText());
+        VlanId cP2InnerVlan = parseVlan(json.path(CP2_INNER_TAG).asText());
+        VlanId cP2OuterVlan = parseVlan(json.path(CP2_OUTER_TAG).asText());
+        if ((cP1InnerVlan == null) || (cP1OuterVlan == null) ||
+                (cP2InnerVlan == null) || (cP2OuterVlan == null)) {
+            log.error("One or more vlan for cp1 or cp2 is malformed, it shouldbe an integer / Any / None / *");
+            return null;
+        }
+
+        L2Mode mode = parseMode(json.path(MODE).asText());
+        if (mode == null) {
+            log.error("Mode should be RAW or TAGGED!");
+            return null;
+        }
+
+        VlanId sdTag = parseVlan(json.path(SERVICE_DELIM_TAG).asText());
+        if (sdTag == null) {
+            log.error("SD tag is malformed, it should be an integer / Any / None / *");
+            return null;
+        }
+
+        MplsLabel pwLabel = parsePWLabel(json.path(PW_LABEL).asText());
+        if (pwLabel == null) {
+            log.error("PW label is malformed, should be an integer!");
+            return null;
+        }
+
+        DefaultL2Tunnel l2Tunnel;
+        DefaultL2TunnelPolicy l2Policy;
+
+        l2Tunnel = new DefaultL2Tunnel(mode, sdTag, id, pwLabel);
+        l2Policy = new DefaultL2TunnelPolicy(id, cP1, cP1InnerVlan, cP1OuterVlan,
+                                             cP2, cP2InnerVlan, cP2OuterVlan);
+
+        return new DefaultL2TunnelDescription(l2Tunnel, l2Policy);
+
+    }
+}
diff --git a/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java b/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
new file mode 100644
index 0000000..ba151a1
--- /dev/null
+++ b/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2015-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.segmentrouting.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.segmentrouting.SegmentRoutingService;
+import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
+import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
+import org.onosproject.segmentrouting.pwaas.L2Tunnel;
+import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Query, create and remove pseudowires.
+ */
+@Path("pseudowire")
+public class PseudowireWebResource extends AbstractWebResource {
+
+    private static final PseudowireCodec PSEUDOWIRE_CODEC = new PseudowireCodec();
+
+    private static Logger log = LoggerFactory
+            .getLogger(PseudowireWebResource.class);
+
+    /**
+     * Get all pseudowires.
+     * Returns an array of pseudowires.
+     *
+     * @return status of OK
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getPseudowire() {
+        SegmentRoutingService srService = get(SegmentRoutingService.class);
+
+        log.debug("Fetching pseudowires form rest api!");
+
+        List<L2TunnelPolicy> policies = srService.getL2Policies();
+        List<L2Tunnel> tunnels = srService.getL2Tunnels();
+        List<DefaultL2TunnelDescription> pseudowires = tunnels.stream()
+                .map(l2Tunnel -> {
+                    L2TunnelPolicy policy = null;
+                    for (L2TunnelPolicy l2Policy : policies) {
+                        if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
+                            policy = l2Policy;
+                            break;
+                        }
+                    }
+
+                    // return a copy
+                    return new DefaultL2TunnelDescription(l2Tunnel, policy);
+                })
+                .collect(Collectors.toList());
+
+        ObjectNode result = new ObjectMapper().createObjectNode();
+        result.set("pseudowires", new PseudowireCodec().encode(pseudowires, this));
+
+        return ok(result.toString()).build();
+    }
+
+    /**
+     * Create a new pseudowire.
+     *
+     * @param input JSON stream for pseudowire to create
+     * @return Response with appropriate status
+     * @throws IOException Throws IO exception.
+     * @onos.rsModel PseudowireCreate
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response createPseudowire(InputStream input) throws IOException {
+
+        ObjectMapper mapper = new ObjectMapper();
+        ObjectNode pseudowireJson = (ObjectNode) mapper.readTree(input);
+        SegmentRoutingService srService = get(SegmentRoutingService.class);
+
+        DefaultL2TunnelDescription pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this);
+        if (pseudowire == null) {
+            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
+        }
+
+        log.info("Creating pseudowire {} from rest api!", pseudowire.l2Tunnel().tunnelId());
+
+        L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
+        switch (res) {
+            case ADDITION_ERROR:
+                log.error("Pseudowire {} could not be added, error in configuration," +
+                                  " please check logs for more details!",
+                          pseudowire.l2Tunnel().tunnelId());
+                return Response.serverError().status(Response.Status.INTERNAL_SERVER_ERROR).build();
+
+            case SUCCESS:
+                log.info("Pseudowire {} succesfully deployed!", pseudowire.l2Tunnel().tunnelId());
+                return Response.ok().build();
+            default:
+                return Response.ok().build();
+        }
+    }
+
+    /**
+     * Delete a pseudowire.
+     *
+     * @param input JSON stream for pseudowire to delete
+     * @return Response with appropriate status
+     * @throws IOException Throws IO exception.
+     * @onos.rsModel PseudowireDelete
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response removePseudowire(InputStream input) throws IOException {
+
+        ObjectMapper mapper = new ObjectMapper();
+        ObjectNode pseudowireJson = (ObjectNode) mapper.readTree(input);
+        SegmentRoutingService srService = get(SegmentRoutingService.class);
+
+        Integer pseudowireId = PSEUDOWIRE_CODEC.decodeId(pseudowireJson);
+        if (pseudowireId == null) {
+            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
+        }
+
+        log.info("Deleting pseudowire {} from rest api!", pseudowireId);
+
+        L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
+        switch (res) {
+            case REMOVAL_ERROR:
+                log.error("Pseudowire {} could not be removed, error in configuration," +
+                                  " please check logs for more details!",
+                          pseudowireId);
+
+                return Response.noContent().build();
+            case SUCCESS:
+                log.info("Pseudowire {} was removed succesfully!", pseudowireId);
+                return Response.noContent().build();
+            default:
+                return Response.noContent().build();
+        }
+    }
+}
diff --git a/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java b/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
new file mode 100644
index 0000000..4aa1a71
--- /dev/null
+++ b/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015-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.segmentrouting.web;
+
+import org.onlab.rest.AbstractWebApplication;
+
+import java.util.Set;
+
+/**
+ * Segment Routing Web application.
+ */
+public class SegmentRoutingWebApplication extends AbstractWebApplication {
+    @Override
+    public Set<Class<?>> getClasses() {
+        return getClasses(PseudowireWebResource.class);
+    }
+}
diff --git a/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java b/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
index 7a368f5..476bcd8 100644
--- a/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
+++ b/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
@@ -26,7 +26,6 @@
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
-import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -37,7 +36,7 @@
 /**
  * Query, create and remove segment routing tunnels.
  */
-@Path("tunnel")
+// @Path("tunnel")
 public class TunnelWebResource extends AbstractWebResource {
 
     private static final TunnelCodec TUNNEL_CODEC = new TunnelCodec();
diff --git a/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java b/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java
index 101d40e..ff9555e 100644
--- a/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java
+++ b/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java
@@ -15,6 +15,6 @@
  */
 
 /**
- * Set of resources implementing the segment routing application REST API.
+ * Segment routing application components.
  */
 package org.onosproject.segmentrouting.web;
\ No newline at end of file
diff --git a/web/src/main/resources/definitions/PseudowireCreate.json b/web/src/main/resources/definitions/PseudowireCreate.json
new file mode 100644
index 0000000..feddd18
--- /dev/null
+++ b/web/src/main/resources/definitions/PseudowireCreate.json
@@ -0,0 +1,68 @@
+{
+  "type": "object",
+  "title": "pseudowire-creation",
+  "required": [
+    "pwId",
+    "cP1",
+    "cP2",
+    "cP1InnerTag",
+    "cP1OuterTag",
+    "cP2InnerTag",
+    "cP2OuterTag",
+    "mode",
+    "sdTag",
+    "pwLabel"
+  ],
+  "properties": {
+    "pwId": {
+      "type": "string",
+      "example": "42",
+      "description": "Id of pseudowire to create."
+    },
+    "cP1": {
+      "type": "string",
+      "example": "of:0000000000000227/25",
+      "description": "Pseudowire connection point 1."
+    },
+    "cP2": {
+      "type": "string",
+      "example": "of:0000000000000226/25",
+      "description": "Pseudowire connection point 2."
+    },
+    "cP1InnerTag": {
+      "type": "string",
+      "example": "101",
+      "description": "Inner vlan for pseudowire connection point 1."
+    },
+    "cP1OuterTag": {
+      "type": "string",
+      "example": "",
+      "description": "Outer vlan for pseudowire connection point 1."
+    },
+    "cP2InnerTag": {
+      "type": "string",
+      "example": "101",
+      "description": "Inner vlan for pseudowire connection point 2."
+    },
+    "cP2OuterTag": {
+      "type": "string",
+      "example": "",
+      "description": "Outer vlan for pseudowire connection point 2."
+    },
+    "mode": {
+      "type": "string",
+      "example": "RAW",
+      "description": "Working mode of pseudowire."
+    },
+    "sDTag": {
+      "type": "string",
+      "example": "",
+      "description": "Service delimiting tag of the pseudowire"
+    },
+    "pwLabel": {
+      "type": "256",
+      "example": "",
+      "description": "Pseudowire label."
+    }
+  }
+}
\ No newline at end of file
diff --git a/web/src/main/resources/definitions/PseudowireDelete.json b/web/src/main/resources/definitions/PseudowireDelete.json
new file mode 100644
index 0000000..4dd5c04
--- /dev/null
+++ b/web/src/main/resources/definitions/PseudowireDelete.json
@@ -0,0 +1,14 @@
+{
+  "type": "object",
+  "title": "pseudowire-deletion",
+  "required": [
+    "pwId"
+  ],
+  "properties": {
+    "pwId": {
+      "type": "string",
+      "example": "42",
+      "description": "Id of pseudowire to delete."
+    }
+  }
+}
\ No newline at end of file
diff --git a/web/src/main/webapp/WEB-INF/web.xml b/web/src/main/webapp/WEB-INF/web.xml
index 5aac978..73154e3 100644
--- a/web/src/main/webapp/WEB-INF/web.xml
+++ b/web/src/main/webapp/WEB-INF/web.xml
@@ -14,21 +14,38 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
          id="ONOS" version="2.5">
-    <display-name>Segment Routing REST API v1.0</display-name>
+    <display-name>Segment Routing Server REST API v1.0</display-name>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Secured</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>admin</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <security-role>
+        <role-name>admin</role-name>
+    </security-role>
+
+    <login-config>
+        <auth-method>BASIC</auth-method>
+        <realm-name>karaf</realm-name>
+    </login-config>
 
     <servlet>
         <servlet-name>JAX-RS Service</servlet-name>
         <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
         <init-param>
-            <param-name>jersey.config.server.provider.classnames</param-name>
-            <param-value>
-                org.onosproject.segmentrouting.web.TunnelWebResource,
-                org.onosproject.segmentrouting.web.PolicyWebResource
-            </param-value>
+            <param-name>javax.ws.rs.Application</param-name>
+            <param-value>org.onosproject.segmentrouting.web.SegmentRoutingWebApplication</param-value>
         </init-param>
         <load-on-startup>1</load-on-startup>
     </servlet>