ios-xe renderer now creates configuration per endpoint pair 54/42154/6
authorVladimir Lavor <vlavor@cisco.com>
Wed, 20 Jul 2016 12:00:20 +0000 (14:00 +0200)
committerVladimir Lavor <vlavor@cisco.com>
Mon, 25 Jul 2016 10:09:25 +0000 (10:09 +0000)
Change-Id: I097589bed0c2cd78249030e77be8a97a18f25605
Signed-off-by: Vladimir Lavor <vlavor@cisco.com>
12 files changed:
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyConfigurationContext.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImpl.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyManagerUtil.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/ServiceChainingUtil.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/StatusUtil.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/writer/PolicyWriter.java [deleted file]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/writer/PolicyWriterUtil.java
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImplTest.java
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyManagerUtilTest.java
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/ServiceChainingUtilTest.java
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/StatusUtilTest.java
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/writer/PolicyWriterUtilTest.java

index a6c7bc83d141a474003a30681e639c58653b4601..27c99b4a2b820a7622e0032e641e54e9672d560d 100644 (file)
@@ -10,7 +10,11 @@ package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
 
 import java.util.ArrayList;
 import java.util.List;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.unconfigured.rule.group.UnconfiguredResolvedRule;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Status;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.status.unconfigured.endpoints.UnconfiguredRendererEndpoint;
@@ -18,47 +22,60 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 /**
  * Purpose: placeholder for
  * <ul>
- *     <li>{@link PolicyWriter}</li>
- *     <li>{@link Status} parts</li>
+ * <li>{@link PolicyManagerImpl.PolicyMapLocation}</li>
+ * <li>{@link Status} parts</li>
  * </ul>
  */
 public class PolicyConfigurationContext {
 
     private final List<UnconfiguredRendererEndpoint> unconfiguredRendererEPBag;
-    private PolicyWriter policyWriter;
+    private final List<CheckedFuture<Boolean, TransactionCommitFailedException>> cumulativeResult;
+    private PolicyManagerImpl.PolicyMapLocation policyMapLocation;
     private RendererEndpoint currentRendererEP;
+    private UnconfiguredResolvedRule currentUnconfiguredRule;
 
     public PolicyConfigurationContext() {
         unconfiguredRendererEPBag = new ArrayList<>();
+        cumulativeResult = new ArrayList<>();
     }
 
     /**
-     * @return policyWriter for mountpoint currently being configured
+     * Set transaction result to result pool
+     *
+     * @param result current result
      */
-    public PolicyWriter getPolicyWriter() {
-        return policyWriter;
+    public void setFutureResult(final CheckedFuture<Boolean, TransactionCommitFailedException> result) {
+        cumulativeResult.add(result);
     }
 
     /**
-     * @param policyWriter for mountpoint currently being configured
+     * append given endpoint to collection of not configurable policies
+     *
+     * @param endpoint not configurable endpoint
      */
-    public void setPolicyWriter(final PolicyWriter policyWriter) {
-        this.policyWriter = policyWriter;
+    public void appendUnconfiguredRendererEP(UnconfiguredRendererEndpoint endpoint) {
+        unconfiguredRendererEPBag.add(endpoint);
     }
 
     /**
-     * @return list of not configurable policies
+     * @return policy-map location
      */
-    public List<UnconfiguredRendererEndpoint> getUnconfiguredRendererEPBag() {
-        return unconfiguredRendererEPBag;
+    public PolicyManagerImpl.PolicyMapLocation getPolicyMapLocation() {
+        return policyMapLocation;
     }
 
     /**
-     * append given endpoint to collection of not configurable policies
-     * @param endpoint not configurable endpoint
+     * @param policyMapLocation for actual policy-map/interface location
      */
-    public void appendUnconfiguredRendererEP(UnconfiguredRendererEndpoint endpoint) {
-        unconfiguredRendererEPBag.add(endpoint);
+    public void setPolicyMapLocation(final PolicyManagerImpl.PolicyMapLocation policyMapLocation) {
+        this.policyMapLocation = policyMapLocation;
+    }
+
+    /**
+     * @return endpoint currently being configured
+     */
+    public RendererEndpoint getCurrentRendererEP() {
+        return currentRendererEP;
     }
 
     /**
@@ -69,9 +86,32 @@ public class PolicyConfigurationContext {
     }
 
     /**
-     * @return endpoint currently being configured
+     * @return list of not configurable policies
      */
-    public RendererEndpoint getCurrentRendererEP() {
-        return currentRendererEP;
+    List<UnconfiguredRendererEndpoint> getUnconfiguredRendererEPBag() {
+        return unconfiguredRendererEPBag;
+    }
+
+    /**
+     * @return all unconfigured rules
+     */
+    public UnconfiguredResolvedRule getCurrentUnconfiguredRule() {
+        return currentUnconfiguredRule;
+    }
+
+    /**
+     * Add unconfigured rule to list
+     *
+     * @param unconfiguredResolvedRule unconfigured rule
+     */
+    public void setCurrentUnconfiguredRule(final UnconfiguredResolvedRule unconfiguredResolvedRule) {
+        this.currentUnconfiguredRule = unconfiguredResolvedRule;
+    }
+
+    /**
+     * @return get all transaction results as a list
+     */
+    ListenableFuture<List<Boolean>> getCumulativeResult() {
+        return Futures.allAsList(cumulativeResult);
     }
 }
index bfb4ee16afdf0f74da3328ee339737d3dcdb1d81..7c6694136a58a729312b2ba59073ca4bf04c7042 100644 (file)
@@ -13,10 +13,7 @@ import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.ma
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
@@ -31,8 +28,6 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.StatusUtil;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NetconfTransactionCreator;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
@@ -93,21 +88,26 @@ public class PolicyManagerImpl implements PolicyManager {
         });
     }
 
-    private ListenableFuture<Optional<Status>> syncEndpoints(final Configuration dataAfter, DsAction action) {
+    /**
+     * Resolve policy for all endpoint pairs
+     *
+     * @param dataAfter - data used while processing
+     * @param action    - specifies whether data are intended for creating or removing of configuration
+     * @return status of policy resolution
+     */
+    private ListenableFuture<Optional<Status>> syncEndpoints(final Configuration dataAfter, final DsAction action) {
         if (dataAfter.getRendererEndpoints() == null
                 || dataAfter.getRendererEndpoints().getRendererEndpoint() == null) {
-            LOG.debug("no configuration obtained - skipping");
+            LOG.debug("No configuration obtained - skipping");
             return Futures.immediateFuture(Optional.empty());
         }
-
         final PolicyConfigurationContext context = new PolicyConfigurationContext();
-        final Map<String, PolicyWriter> policyWriterPerDeviceCache = new HashMap<>();
+        // Renderer endpoint
         for (RendererEndpoint rendererEndpoint : dataAfter.getRendererEndpoints().getRendererEndpoint()) {
-            // Store the endpoint currently being configured
             context.setCurrentRendererEP(rendererEndpoint);
 
             if (dataAfter.getEndpoints() == null || dataAfter.getEndpoints().getAddressEndpointWithLocation() == null) {
-                final String info = "renderer-endpoint: missing address-endpoint-with-location";
+                final String info = "Renderer-endpoint: missing address-endpoint-with-location";
                 context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
                 continue;
             }
@@ -116,36 +116,29 @@ public class PolicyManagerImpl implements PolicyManager {
             final InstanceIdentifier mountpointIid = PolicyManagerUtil.getMountpointIidFromAbsoluteLocation(rendererEndpoint, endpointsWithLocation);
             final DataBroker mountpoint = nodeManager.getNodeMountPoint(mountpointIid);
             if (mountpoint == null) {
-                final String info = String.format("no data-broker for mount-point [%s] available", mountpointIid);
+                final String info = String.format("No data-broker for mount-point [%s] available", mountpointIid);
+                context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
+                continue;
+            }
+            final String managementIpAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
+            if (managementIpAddress == null) {
+                final String info = String.format("Can not create policyWriter, managementIpAddress for mountpoint %s is null",
+                        mountpointIid);
                 context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
                 continue;
             }
-            // Generate policy writer key - policy map name, composed from base value, interface name and node id
             final String interfaceName = PolicyManagerUtil.getInterfaceNameFromAbsoluteLocation(rendererEndpoint, endpointsWithLocation);
             final NodeId nodeId = nodeManager.getNodeIdByMountpointIid(mountpointIid);
             if (interfaceName == null || nodeId == null) {
-                LOG.warn("Cannot compose policy-map, missing value. Interface: {}, NodeId: {}", interfaceName, nodeId);
+                final String info = String.format("Cannot compose policy-map, missing value. Interface: %s, NodeId: %s", interfaceName, nodeId);
+                context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
+                LOG.warn(info);
                 continue;
             }
             final String policyMapName = BASE_POLICY_MAP_NAME.concat(interfaceName);
-            final String policyWriterKey = policyMapName.concat("-" + nodeId.getValue());
-            // Find appropriate writer
-            PolicyWriter policyWriter = policyWriterPerDeviceCache.get(policyWriterKey);
-            if (policyWriter == null) {
-                // Initialize new policy writer
-                final String managementIpAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
-                if (managementIpAddress == null) {
-                    final String info = String.format("can not create policyWriter, managementIpAddress for mountpoint %s is null",
-                            mountpointIid);
-                    context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
-                    continue;
-                }
-                policyWriter = new PolicyWriter(mountpoint, interfaceName, managementIpAddress, policyMapName, nodeId);
-                policyWriterPerDeviceCache.put(policyWriterKey, policyWriter);
-            }
-
-            // Assign policyWriter for current policy-map
-            context.setPolicyWriter(policyWriter);
+            final PolicyMapLocation policyMapLocation = new PolicyMapLocation(policyMapName, interfaceName, nodeId,
+                    managementIpAddress, mountpoint);
+            context.setPolicyMapLocation(policyMapLocation);
 
             final Sgt sourceSgt = PolicyManagerUtil.findSgtTag(rendererEndpoint, dataAfter.getEndpoints()
                     .getAddressEndpointWithLocation());
@@ -154,28 +147,27 @@ public class PolicyManagerImpl implements PolicyManager {
                 final Sgt destinationSgt = PolicyManagerUtil.findSgtTag(peerEndpoint, dataAfter.getEndpoints()
                         .getAddressEndpointWithLocation());
                 if (sourceSgt == null || destinationSgt == null) {
-                    final String info = String.format("endpoint-policy: missing sgt value(sourceSgt=%s, destinationSgt=%s)",
+                    final String info = String.format("Endpoint-policy: missing sgt value(sourceSgt=%s, destinationSgt=%s)",
                             sourceSgt, destinationSgt);
                     context.appendUnconfiguredRendererEP(
                             StatusUtil.assembleNotConfigurableRendererEPForPeer(context, peerEndpoint, info));
                     continue;
                 }
-                PolicyManagerUtil.syncResolvedPolicy(sourceSgt, destinationSgt, context, dataAfter, peerEndpoint,
-                        dataBroker, action);
+                // Resolve policy between endpoints
+                if (action.equals(Create)) {
+                    LOG.debug("Setting up policy between endpoint {}, sgt: {} and peer {}, sgt: {}", rendererEndpoint,
+                            sourceSgt, peerEndpoint, destinationSgt);
+                    PolicyManagerUtil.syncEndpointPairCreatePolicy(sourceSgt, destinationSgt, context, dataAfter,
+                            peerEndpoint, dataBroker);
+                } else {
+                    LOG.debug("Removing policy between endpoint {}, sgt: {} and peer {}, sgt: {}", rendererEndpoint,
+                            sourceSgt, peerEndpoint, destinationSgt);
+                    PolicyManagerUtil.syncEndpointPairRemovePolicy(sourceSgt, destinationSgt, context, dataAfter,
+                            peerEndpoint);
+                }
             }
         }
-
-        final List<CheckedFuture<Boolean, TransactionCommitFailedException>> allFutureResults = new ArrayList<>();
-        if (action.equals(Create)) {
-            // TODO ensure that last transaction is done before the next one starts
-            policyWriterPerDeviceCache.values().forEach((pw) -> allFutureResults.add(pw.commitToDatastore()));
-        } else if (action.equals(Delete)) {
-            policyWriterPerDeviceCache.values().forEach((pw) -> allFutureResults.add(pw.removeFromDatastore()));
-        } else {
-            LOG.info("unsupported policy manage action: {}", action);
-        }
-        final ListenableFuture<List<Boolean>> cumulativeResult = Futures.allAsList(allFutureResults);
-
+        final ListenableFuture<List<Boolean>> cumulativeResult = context.getCumulativeResult();
         return Futures.transform(cumulativeResult, new Function<List<Boolean>, Optional<Status>>() {
             @Nullable
             @Override
@@ -194,14 +186,9 @@ public class PolicyManagerImpl implements PolicyManager {
         });
     }
 
-    private CheckedFuture<Void, TransactionCommitFailedException> reportPolicy(long version, @Nonnull final Optional<Status> statusValue) {
-        final Optional<ReadWriteTransaction> optionalReadWriteTransaction =
-                NetconfTransactionCreator.netconfReadWriteTransaction(dataBroker);
-        if (!optionalReadWriteTransaction.isPresent()) {
-            LOG.warn("Failed to create transaction, mountpoint: {}", dataBroker);
-            return Futures.immediateCheckedFuture(null);
-        }
-        final ReadWriteTransaction readWriteTransaction = optionalReadWriteTransaction.get();
+    private CheckedFuture<Void, TransactionCommitFailedException> reportPolicy(final long version,
+                                                                               @Nonnull final Optional<Status> statusValue) {
+        final ReadWriteTransaction readWriteTransaction = dataBroker.newReadWriteTransaction();
         final InstanceIdentifier<RendererPolicy> iid = InstanceIdentifier.create(Renderers.class)
                 .child(Renderer.class, new RendererKey(NodeManager.iosXeRenderer))
                 .child(RendererPolicy.class);
@@ -218,7 +205,48 @@ public class PolicyManagerImpl implements PolicyManager {
         //NOOP
     }
 
-    public enum DsAction {Create, Delete}
+    enum DsAction {Create, Delete}
 
     public enum ActionCase {ALLOW, CHAIN}
-}
+
+    /**
+     * Wrapper class - contains all necessary information to clearly localize policy-map/interface/node in network
+     */
+    public static class PolicyMapLocation {
+
+        private final String policyMapName;
+        private final String interfaceName;
+        private final NodeId nodeId;
+        private final String managementIpAddress;
+        private final DataBroker mountpoint;
+
+        public PolicyMapLocation(final String policyMapName, final String interfaceName, final NodeId nodeId,
+                                 final String managementIpAddress, final DataBroker mountpoint) {
+            this.policyMapName = Preconditions.checkNotNull(policyMapName);
+            this.interfaceName = Preconditions.checkNotNull(interfaceName);
+            this.nodeId = Preconditions.checkNotNull(nodeId);
+            this.managementIpAddress = Preconditions.checkNotNull(managementIpAddress);
+            this.mountpoint = Preconditions.checkNotNull(mountpoint);
+        }
+
+        public String getPolicyMapName() {
+            return policyMapName;
+        }
+
+        public String getInterfaceName() {
+            return interfaceName;
+        }
+
+        public NodeId getNodeId() {
+            return nodeId;
+        }
+
+        public String getManagementIpAddress() {
+            return managementIpAddress;
+        }
+
+        public DataBroker getMountpoint() {
+            return mountpoint;
+        }
+    }
+}
\ No newline at end of file
index 2d0ff18f756e2df4af96324985f3ecf3c9afaac5..56f829a99f704c45c6d209f1ed5d5a1f1bc49e56 100644 (file)
@@ -9,8 +9,6 @@
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
 
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
-import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Create;
-import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Delete;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -20,13 +18,16 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyConfigurationContext;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriterUtil;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.PolicyActionType;
@@ -66,6 +67,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;
@@ -81,6 +83,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.p
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.AddressEndpointWithLocationAug;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -90,36 +93,76 @@ public class PolicyManagerUtil {
     private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerUtil.class);
 
     /**
-     * Main method which looks for all actions specified in rules between two endpoints. Whichever action has been found,
-     * it is resolved. Only chain action is supported for now.
+     * Main method for policy creation which looks for all actions specified in rules between two endpoints. Whichever
+     * action has been found, it is resolved (only chain action is supported for now).
      *
      * @param sourceSgt      - security group tag of source endpoint
      * @param destinationSgt - security group tag of destination endpoint
-     * @param context        - stores policy writer and info about not configurable rules
-     * @param dataAfter      - new data, used to found appropriate rule group
+     * @param context        - stores info about location of classifier/policy-map and status
+     * @param data           - new data, used to found appropriate rule group
      * @param peerEndpoint   - contains info about rule groups between endpoint pairs
      * @param dataBroker     - data provider for odl controller
-     * @param action         - required action crate/delete
      */
-    public static void syncResolvedPolicy(final Sgt sourceSgt, final Sgt destinationSgt, final PolicyConfigurationContext context,
-                                          final Configuration dataAfter, final PeerEndpoint peerEndpoint,
-                                          final DataBroker dataBroker, final PolicyManagerImpl.DsAction action) {
+    public static void syncEndpointPairCreatePolicy(final Sgt sourceSgt, final Sgt destinationSgt,
+                                                    final PolicyConfigurationContext context, final Configuration data,
+                                                    final PeerEndpoint peerEndpoint, final DataBroker dataBroker) {
+        // Create appropriate policy map
+        if (!PolicyManagerUtil.constructEmptyPolicyMapWithInterface(context)) {
+            final String policyMapName = context.getPolicyMapLocation().getPolicyMapName();
+            final String interfaceName = context.getPolicyMapLocation().getInterfaceName();
+            final String info = String.format("Unable to create policy-map %s on interface %s", policyMapName, interfaceName);
+            context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
+            LOG.warn(info);
+            return;
+        }
+
         // Find actions from acquired data
-        final Map<ActionCase, ActionInDirection> actionMap = PolicyManagerUtil.getActionInDirection(dataAfter, peerEndpoint);
+        final Map<ActionCase, ActionInDirection> actionMap = PolicyManagerUtil.getActionInDirection(data, peerEndpoint);
         if (actionMap.isEmpty()) {
-            LOG.debug("no usable action found for EP-sgt[{}] | peerEP-sgt[{}]",
-                    sourceSgt, destinationSgt);
+            LOG.debug("No usable action found for EP-sgt[{}] | peerEP-sgt[{}]", sourceSgt, destinationSgt);
             return;
         }
 
         // Chain action
-        if (actionMap.containsKey(ActionCase.CHAIN) && action.equals(Create)) {
-            ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, context,
+        if (actionMap.containsKey(ActionCase.CHAIN)) {
+            ServiceChainingUtil.newChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, context,
                     dataBroker);
         }
-        if (actionMap.containsKey(ActionCase.CHAIN) && action.equals(Delete)) {
+    }
+
+    /**
+     * Method for policy removal which looks for all actions specified in rules between two endpoints. Whichever
+     * action has been found, it is resolved (only chain action is supported).
+     *
+     * @param sourceSgt      - security group tag of source endpoint
+     * @param destinationSgt - security group tag of destination endpoint
+     * @param context        - stores info about location of classifier/policy-map and status
+     * @param data           - data used to identify all elements marked to remove
+     * @param peerEndpoint   - contains info about rule groups between endpoint pairs
+     */
+    public static void syncEndpointPairRemovePolicy(final Sgt sourceSgt, final Sgt destinationSgt,
+                                                    final PolicyConfigurationContext context, final Configuration data,
+                                                    final PeerEndpoint peerEndpoint) {
+        // Find actions from acquired data
+        final Map<ActionCase, ActionInDirection> actionMap = PolicyManagerUtil.getActionInDirection(data, peerEndpoint);
+        if (actionMap.isEmpty()) {
+            LOG.debug("no usable action found for EP-sgt[{}] | peerEP-sgt[{}]",
+                    sourceSgt, destinationSgt);
+            return;
+        }
+
+        // Chain action
+        if (actionMap.containsKey(ActionCase.CHAIN)) {
             ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap,
-                    context.getPolicyWriter());
+                    context);
+        }
+
+        // Remove policy-map if empty
+        if (!deleteEmptyPolicyMapWithInterface(context.getPolicyMapLocation())) {
+            final PolicyManagerImpl.PolicyMapLocation location = context.getPolicyMapLocation();
+            final String info = String.format("Unable to remove policy-map %s and interface %s", location.getPolicyMapName(),
+                    location.getInterfaceName());
+            LOG.warn(info);
         }
     }
 
@@ -166,6 +209,82 @@ public class PolicyManagerUtil {
         return augmentation.getSgt();
     }
 
+    /**
+     * Creates empty policy-map if does not exist and bounds it to interface if it is not. If policy-map exists, method
+     * checks whether it is connected to correct interface and creates it if necessary. If policy-map does not exist,
+     * it is created with particular interface
+     *
+     * @param context - all data required to create/localize policy-map
+     * @return true if policy-map and interface is present/written on the device, false otherwise
+     */
+    private static boolean constructEmptyPolicyMapWithInterface(final PolicyConfigurationContext context) {
+        final PolicyManagerImpl.PolicyMapLocation policyMapLocation = context.getPolicyMapLocation();
+        final String policyMapName = policyMapLocation.getPolicyMapName();
+        final DataBroker mountpoint = policyMapLocation.getMountpoint();
+        final String interfaceName = policyMapLocation.getInterfaceName();
+        final NodeId nodeId = policyMapLocation.getNodeId();
+        final InstanceIdentifier<PolicyMap> policyMapIid = PolicyWriterUtil.policyMapInstanceIdentifier(policyMapName);
+        final Optional<PolicyMap> optionalPolicyMap =
+                Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, policyMapIid));
+        if (optionalPolicyMap.isPresent()) {
+            LOG.trace("Policy map with name {} on interface {} already exists", policyMapName, interfaceName);
+            final InstanceIdentifier<ServicePolicy> servicePolicyIid = PolicyWriterUtil.interfaceInstanceIdentifier(interfaceName);
+            final Optional<ServicePolicy> optionalServicePolicy =
+                    Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, servicePolicyIid));
+            if (optionalServicePolicy.isPresent()) {
+                LOG.trace("Policy map {} is bound to correct interface {} ", policyMapName, interfaceName);
+                return true;
+            } else {
+                boolean iResult = PolicyWriterUtil.writeInterface(context.getPolicyMapLocation());
+                context.setFutureResult(Futures.immediateCheckedFuture(iResult));
+                return iResult;
+            }
+        } else {
+            final PolicyMap emptyMap = createEmptyPolicyMap(policyMapName);
+            boolean pmResult = PolicyWriterUtil.writePolicyMap(emptyMap, context.getPolicyMapLocation());
+            context.setFutureResult(Futures.immediateCheckedFuture(pmResult));
+            if (pmResult) {
+                LOG.info("Created policy-map {} on node {}", policyMapName, nodeId.getValue());
+                LOG.trace("Adding policy-map {} to interface {}", policyMapName, interfaceName);
+                boolean iResult = PolicyWriterUtil.writeInterface(context.getPolicyMapLocation());
+                context.setFutureResult(Futures.immediateCheckedFuture(iResult));
+                return iResult;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Removes empty policy-map and its interface
+     *
+     * @param policyMapLocation - location of policy-map
+     * @return true if policy-map is present and not empty or if it is successfully removed also with interface, false
+     * otherwise
+     */
+    private static boolean deleteEmptyPolicyMapWithInterface(PolicyManagerImpl.PolicyMapLocation policyMapLocation) {
+        final String policyMapName = policyMapLocation.getPolicyMapName();
+        final DataBroker mountpoint = policyMapLocation.getMountpoint();
+        final InstanceIdentifier<PolicyMap> policyMapIid = PolicyWriterUtil.policyMapInstanceIdentifier(policyMapName);
+        // Read policy map
+        final Optional<PolicyMap> optionalPolicyMap = Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, policyMapIid));
+        if (optionalPolicyMap.isPresent()) {
+            final PolicyMap policyMap = optionalPolicyMap.get();
+            if (policyMap.getXmlClass() == null || policyMap.getXmlClass().isEmpty()) {
+                // No entries, remove
+                if (PolicyWriterUtil.removePolicyMap(policyMapLocation)) {
+                    // Remove interface binding if exists
+                    LOG.info("Policy-map {} removed", policyMapName);
+                    return PolicyWriterUtil.removeInterface(policyMapLocation);
+                }
+                return false;
+            }
+            LOG.debug("Policy-map {} still contains entries, cannot be removed", policyMapLocation.getPolicyMapName());
+            return true;
+        }
+        return true;
+
+    }
+
     public static ServicePolicy createServicePolicy(final String chainName, final Direction direction) {
         // Service Chain
         final ServiceChainBuilder serviceChainBuilder = new ServiceChainBuilder();
@@ -181,20 +300,18 @@ public class PolicyManagerUtil {
         return servicePolicyBuilder.build();
     }
 
-    public static PolicyMap createPolicyMap(final String policyMapName, final Set<Class> policyMapEntries) {
+    private static PolicyMap createEmptyPolicyMap(String policyMapName) {
         // TODO maybe could be better to create also class-default entry with pass-through value than not to create any default entry at all
         // Construct policy map
-        final List<Class> policyMapEntriesList = new ArrayList<>(policyMapEntries);
         final PolicyMapBuilder policyMapBuilder = new PolicyMapBuilder();
         policyMapBuilder.setName(policyMapName)
                 .setKey(new PolicyMapKey(policyMapName))
-                .setType(PolicyMap.Type.ServiceChain)
-                .setXmlClass(policyMapEntriesList);
+                .setType(PolicyMap.Type.ServiceChain);
         return policyMapBuilder.build();
     }
 
-    static Class createPolicyEntry(final String policyClassName, final RenderedServicePath renderedPath,
-                                   final ActionCase actionCase) {
+    static Class createPolicyMapEntry(final String policyClassName, final RenderedServicePath renderedPath,
+                                      final ActionCase actionCase) {
         // Forward Case
         final ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
         if (actionCase.equals(CHAIN) && renderedPath != null) {
@@ -236,6 +353,7 @@ public class PolicyManagerUtil {
         return matchBuilder.build();
     }
 
+    @Nonnull
     static ClassMap createClassMap(final String classMapName, final Match match) {
         final ClassMapBuilder cmBuilder = new ClassMapBuilder();
         cmBuilder.setName(classMapName)
@@ -289,11 +407,12 @@ public class PolicyManagerUtil {
         for (ResolvedRule resolvedRule : rulesInDirection) {
             // TODO only first action used for now
             final Action action = resolvedRule.getAction().get(0);
+            final RuleName name = resolvedRule.getName();
             if (action.getActionDefinitionId() != null) {
                 final ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
                 // Currently only chain action is supported
                 if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
-                    ActionInDirection actionInDirection = new ActionInDirection(action, participation, direction);
+                    ActionInDirection actionInDirection = new ActionInDirection(name, action, participation, direction);
                     result.put(ActionCase.CHAIN, actionInDirection);
                     return result;
                 }
@@ -357,18 +476,25 @@ public class PolicyManagerUtil {
      */
     static class ActionInDirection {
 
+        private final RuleName ruleName;
         private final Action action;
         private final EndpointPolicyParticipation participation;
         private final HasDirection.Direction direction;
 
-        ActionInDirection(final Action action,
+        ActionInDirection(final RuleName ruleName,
+                          final Action action,
                           final EndpointPolicyParticipation participation,
                           final HasDirection.Direction direction) {
+            this.ruleName = Preconditions.checkNotNull(ruleName);
             this.action = Preconditions.checkNotNull(action);
             this.participation = Preconditions.checkNotNull(participation);
             this.direction = Preconditions.checkNotNull(direction);
         }
 
+        RuleName getRuleName() {
+            return ruleName;
+        }
+
         Action getAction() {
             return action;
         }
index dbbba527470357ef9ba6464108642995729814a9..c099b39638f58bf6fde062295123fd31d4d951b5 100644 (file)
@@ -11,7 +11,7 @@ package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil.ActionInDirection;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil.createClassMap;
-import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil.createPolicyEntry;
+import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil.createPolicyMapEntry;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil.createSecurityGroupMatch;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil.generateClassMapName;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil.getTenantId;
@@ -21,6 +21,7 @@ import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ren
 import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation.PROVIDER;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -31,6 +32,7 @@ import java.util.function.Supplier;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -39,7 +41,7 @@ import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyConfigurationContext;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NetconfTransactionCreator;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriterUtil;
 import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
@@ -84,10 +86,12 @@ import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.serv
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.ServicesBuilder;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.ServiceTypeChoice;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.service.type.choice.ServiceFunctionForwarderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.unconfigured.rule.group.UnconfiguredResolvedRuleBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
@@ -103,24 +107,31 @@ public class ServiceChainingUtil {
     private static long timeout = 5000L;
 
     /**
-     * According to input, creates class-maps ({@link ClassMap}) and entries into policy-map ({@link Class}). These
-     * components are created when particular RSP is build by SFC ios-xe renderer. If so, method continues by resolving
-     * first RSP hop in {@link this#resolveRemoteSfcComponents(RenderedServicePath, PolicyWriter)}.
+     * According to provided action, this method gets service function path and collects all info about participation
+     * and orientation of path. According to path symmetricity, participation and direction, one of these cases happens:
+     * 1. Path is asymmetric, and it starts in  this classifier (specified by context) - direct chain is created
+     * 2. Path is asymmetric, and it starts in classifier on opposite side of the chain - skipped
+     * 3. Path is symmetric, and it starts in this classifier - direct chain is created
+     * 2. Path is symmetric, and it starts in classifier on opposite side of the chain - reversed path is created
+     * <p>
+     * Behaviour is correct also in case when "this" and "opposite" classifier is the same
      *
      * @param peerEndpoint   - peer endpoint, used to generate status and access to tenant ID
      * @param sourceSgt      - security group tag of source endpoint
      * @param destinationSgt - security group tag of destination endpoint
      * @param actionMap      - contains all info to evaluate correct chain orientation according to endpoint participation
-     * @param context        - contains policy writer
+     * @param context        - contains policy-map location and status info
      * @param dataBroker     - to access odl datastore
      */
-    static void resolveNewChainAction(final PeerEndpoint peerEndpoint, final Sgt sourceSgt,
-                                      final Sgt destinationSgt, final Map<PolicyManagerImpl.ActionCase, ActionInDirection> actionMap,
-                                      final PolicyConfigurationContext context, final DataBroker dataBroker) {
+    static void newChainAction(final PeerEndpoint peerEndpoint, final Sgt sourceSgt,
+                               final Sgt destinationSgt, final Map<PolicyManagerImpl.ActionCase, ActionInDirection> actionMap,
+                               final PolicyConfigurationContext context, final DataBroker dataBroker) {
         final ActionInDirection actionInDirection = actionMap.get(ActionCase.CHAIN);
         if (actionInDirection == null) {
             return;
         }
+        context.setCurrentUnconfiguredRule(new UnconfiguredResolvedRuleBuilder()
+                .setRuleName(new RuleName(actionInDirection.getRuleName())).build());
         // Rule action + orientation
         final Action action = actionInDirection.getAction();
         final EndpointPolicyParticipation participation = actionInDirection.getParticipation();
@@ -140,71 +151,40 @@ public class ServiceChainingUtil {
             context.appendUnconfiguredRendererEP(StatusUtil.assembleNotConfigurableRendererEPForPeer(context, peerEndpoint, info));
             return;
         }
-        RenderedServicePath renderedServicePath;
         boolean sfcPartSuccessful = true;
-        // Symmetric chain - create direct or reversed rendered service path in corresponding direction
-        if (servicePath.isSymmetric()) {
-            if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
-                    (participation.equals(CONSUMER) && direction.equals(In))) {
-                renderedServicePath = ServiceChainingUtil.createRenderedPath(servicePath, tenantId, dataBroker);
-                // Rsp found, create class-map and policy-map entry
-                final String classMapName = generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
-                final Match match = createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
-                final ClassMap classMap = createClassMap(classMapName, match);
-                final Class policyMapEntry = createPolicyEntry(classMapName, renderedServicePath, ActionCase.CHAIN);
-                context.getPolicyWriter().cache(classMap);
-                context.getPolicyWriter().cache(policyMapEntry);
-                sfcPartSuccessful = resolveRemoteSfcComponents(renderedServicePath, context.getPolicyWriter());
-            } else {
-                // Direct path required if reversed has to be created
-                final RenderedServicePath directPath = ServiceChainingUtil.createRenderedPath(servicePath, tenantId, dataBroker);
-                // Create reversed path
-                renderedServicePath =
-                        ServiceChainingUtil.createReversedRenderedPath(servicePath, directPath, tenantId, dataBroker);
-                // Rsp found, create class-map and policy-map entry
-                final String classMapName = generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
-                final Match match = createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
-                final ClassMap classMap = createClassMap(classMapName, match);
-                final Class policyMapEntry = createPolicyEntry(classMapName, renderedServicePath, ActionCase.CHAIN);
-                context.getPolicyWriter().cache(classMap);
-                context.getPolicyWriter().cache(policyMapEntry);
-                sfcPartSuccessful = resolveRemoteSfcComponents(renderedServicePath, context.getPolicyWriter());
-            }
-        }
-        // Asymmetric chain - create direct path if corresponding direction or skip
-        else if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
+        // Creates direct path in corresponding direction
+        if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
                 (participation.equals(CONSUMER) && direction.equals(In))) {
-            renderedServicePath = ServiceChainingUtil.createRenderedPath(servicePath, tenantId, dataBroker);
-            // Rsp found, create class-map and policy-map entry
-            final String classMapName = generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
-            final Match match = createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
-            final ClassMap classMap = createClassMap(classMapName, match);
-            final Class policyMapEntry = createPolicyEntry(classMapName, renderedServicePath, ActionCase.CHAIN);
-            context.getPolicyWriter().cache(classMap);
-            context.getPolicyWriter().cache(policyMapEntry);
-            sfcPartSuccessful = resolveRemoteSfcComponents(renderedServicePath, context.getPolicyWriter());
+            final RenderedServicePath renderedServicePath = ServiceChainingUtil.resolveRenderedServicePath(servicePath,
+                    tenantId, dataBroker, sourceSgt, destinationSgt, context);
+            sfcPartSuccessful = resolveRemoteSfcComponents(renderedServicePath, context);
+            // Creates reversed path if symmetric
+        } else if (servicePath.isSymmetric()) {
+            final RenderedServicePath renderedServicePath =
+                    ServiceChainingUtil.resolveReversedRenderedServicePath(servicePath, tenantId, dataBroker, sourceSgt,
+                            destinationSgt, context);
+            sfcPartSuccessful = resolveRemoteSfcComponents(renderedServicePath, context);
         }
-        // Create appropriate service path && remote forwarder
         if (!sfcPartSuccessful) {
-            //TODO: extract resolved-rule name
             final String info = String.format("failed during sfc-part execution (sourceSgt=%s, destinationSgt=%s)",
                     sourceSgt, destinationSgt);
-            //context.appendUnconfiguredRendererEP(StatusUtil.assembleNotConfigurableRendererEPForPeerAndAction(context, peerEndpoint, info));
+            context.appendUnconfiguredRendererEP(StatusUtil.assembleNotConfigurableRendererEPForPeer(context,
+                    peerEndpoint, info));
         }
     }
 
     /**
-     * Removes class-map and policy-map entry in policy between endpoint pair. If necessary, method deletes remote SFC
-     * components.
+     * According to service function path and direction, creates appropriate rendered service path name {@link RspName}
+     * and starts appropriate method which removes policy for resolved endpoint pair
      *
-     * @param peerEndpoint    - contains info about tenant ID
-     * @param sourceSgt       - security group tag of source endpoint
-     * @param destinationSgt- security group tag of destination endpoint
-     * @param actionMap       - contains all info to evaluate correct chain orientation according to endpoint participation
-     * @param policyWriter    - used to access ios-xe capable device
+     * @param peerEndpoint   - contains info about tenant ID
+     * @param sourceSgt      - security group tag of source endpoint
+     * @param destinationSgt - security group tag of destination endpoint
+     * @param actionMap      - contains all info to evaluate correct chain orientation according to endpoint participation
+     * @param context        - contains policy-map location and status info
      */
     static void resolveRemovedChainAction(final PeerEndpoint peerEndpoint, final Sgt sourceSgt, final Sgt destinationSgt,
-                                          final Map<ActionCase, ActionInDirection> actionMap, PolicyWriter policyWriter) {
+                                          final Map<ActionCase, ActionInDirection> actionMap, final PolicyConfigurationContext context) {
         final ActionInDirection actionInDirection = actionMap.get(ActionCase.CHAIN);
         final Action action = actionInDirection.getAction();
         final EndpointPolicyParticipation participation = actionInDirection.getParticipation();
@@ -218,75 +198,14 @@ public class ServiceChainingUtil {
             return;
         }
         //Symmetric chain
-        if (servicePath.isSymmetric()) {
-            if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
-                    (participation.equals(CONSUMER) && direction.equals(In))) {
-                // Cache class-maps, appropriate policy-map entries and service-chains
-                final String classMapName = PolicyManagerUtil.generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
-                final ClassMap classMap = PolicyManagerUtil.createClassMap(classMapName, null);
-                final Class policyMapEntry = PolicyManagerUtil.createPolicyEntry(classMapName, null, PolicyManagerImpl.ActionCase.CHAIN);
-                policyWriter.cache(classMap);
-                policyWriter.cache(policyMapEntry);
-
-                final RspName rspName = generateRspName(servicePath, tenantId);
-                final RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
-                final ServiceFunctionForwarder firstHopSff = getFirstHopSff(renderedServicePath);
-                if (firstHopSff != null && firstHopSff.getIpMgmtAddress() != null &&
-                        firstHopSff.getIpMgmtAddress().getIpv4Address() != null) {
-                    final String sffMgmtIpValue = firstHopSff.getIpMgmtAddress().getIpv4Address().getValue();
-                    if (!sffMgmtIpValue.equals(policyWriter.getManagementIpAddress())) {
-                        // Remove service chain and remote forwarder
-                        final ServiceChain serviceChain = createServiceChain(renderedServicePath);
-                        final ServiceFfName remoteForwarder = createRemoteForwarder(firstHopSff);
-                        policyWriter.cache(serviceChain);
-                        policyWriter.cache(remoteForwarder);
-                    }
-                }
-            } else {
-                final String oppositeClassMapName = PolicyManagerUtil.generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
-                final ClassMap oppositeClassMap = PolicyManagerUtil.createClassMap(oppositeClassMapName, null);
-                final Class policyMapEntry = PolicyManagerUtil.createPolicyEntry(oppositeClassMapName, null, PolicyManagerImpl.ActionCase.CHAIN);
-                policyWriter.cache(oppositeClassMap);
-                policyWriter.cache(policyMapEntry);
-
-                final RspName reversedRspName = generateReversedRspName(servicePath, tenantId);
-                final RenderedServicePath reversedRenderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(reversedRspName);
-                final ServiceFunctionForwarder reversedFirstHopSff = getFirstHopSff(reversedRenderedServicePath);
-                if (reversedFirstHopSff != null && reversedFirstHopSff.getIpMgmtAddress() != null &&
-                        reversedFirstHopSff.getIpMgmtAddress().getIpv4Address() != null) {
-                    final String reversedSffMgmtIpValue = reversedFirstHopSff.getIpMgmtAddress().getIpv4Address().getValue();
-                    if (!reversedSffMgmtIpValue.equals(policyWriter.getManagementIpAddress())) {
-                        // Remove service chain and remote forwarder
-                        final ServiceChain serviceChain = createServiceChain(reversedRenderedServicePath);
-                        final ServiceFfName remoteForwarder = createRemoteForwarder(reversedFirstHopSff);
-                        policyWriter.cache(serviceChain);
-                        policyWriter.cache(remoteForwarder);
-                    }
-                }
-            }
-        } else if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
+        if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
                 (participation.equals(CONSUMER) && direction.equals(In))) {
-            // Asymmetric chain
-            final String classMapName = PolicyManagerUtil.generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
-            final ClassMap classMap = PolicyManagerUtil.createClassMap(classMapName, null);
-            final Class policyMapEntry = PolicyManagerUtil.createPolicyEntry(classMapName, null, PolicyManagerImpl.ActionCase.CHAIN);
-            policyWriter.cache(classMap);
-            policyWriter.cache(policyMapEntry);
-
             final RspName rspName = generateRspName(servicePath, tenantId);
-            final RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
-            final ServiceFunctionForwarder firstHopSff = getFirstHopSff(renderedServicePath);
-            if (firstHopSff != null && firstHopSff.getIpMgmtAddress() != null &&
-                    firstHopSff.getIpMgmtAddress().getIpv4Address() != null) {
-                final String sffMgmtIpValue = firstHopSff.getIpMgmtAddress().getIpv4Address().getValue();
-                if (!sffMgmtIpValue.equals(policyWriter.getManagementIpAddress())) {
-                    // Remove service chain and remote forwarder
-                    final ServiceChain serviceChain = createServiceChain(renderedServicePath);
-                    final ServiceFfName remoteForwarder = createRemoteForwarder(firstHopSff);
-                    policyWriter.cache(serviceChain);
-                    policyWriter.cache(remoteForwarder);
-                }
-            }
+            resolveRemovedRenderedServicePath(rspName, sourceSgt, destinationSgt, context);
+
+        } else if (servicePath.isSymmetric()) {
+            final RspName rspName = generateReversedRspName(servicePath, tenantId);
+            resolveRemovedRenderedServicePath(rspName, sourceSgt, destinationSgt, context);
         }
     }
 
@@ -295,13 +214,15 @@ public class ServiceChainingUtil {
      * chain. Classifier has to be able to reach first service function forwarder in order to send packet to chain. If
      * first service function forwarder is present on the same node as classifier, service-path entry should be already
      * present (created by IOS-XE renderer in SFC) also with appropriate remote SFF if necessary. If first SFF is on
-     * different node, classifier has to create it's own service-path entry with remote SFF.
+     * different node (remote classifier), classifier has to create it's own service-path entry with remote SFF.
      *
-     * @param renderedServicePath classifier has to reach
-     * @param policyWriter        policy entries writer
+     * @param renderedServicePath - path classifier has to reach
+     * @param context             - contains policy-map location and status info
      * @return true if everything went good, false otherwise
      */
-    static boolean resolveRemoteSfcComponents(final RenderedServicePath renderedServicePath, PolicyWriter policyWriter) {
+    public static boolean resolveRemoteSfcComponents(final RenderedServicePath renderedServicePath,
+                                                      final PolicyConfigurationContext context) {
+        final PolicyManagerImpl.PolicyMapLocation location = context.getPolicyMapLocation();
         final ServiceFunctionForwarder forwarder = getFirstHopSff(renderedServicePath);
         if (forwarder == null) {
             return false;
@@ -328,13 +249,14 @@ public class ServiceChainingUtil {
                     .map(Ipv4Address::getValue)
                     .map(addressValue -> {
                         final ServiceTypeChoice serviceTypeChoice;
-                        if (!addressValue.equals(policyWriter.getManagementIpAddress())) {
+                        if (!addressValue.equals(location.getManagementIpAddress())) {
                             // Remote forwarder
                             final ServiceFfNameBuilder remoteSffBuilder = new ServiceFfNameBuilder();
                             remoteSffBuilder.setName(sffName.getValue())
                                     .setKey(new ServiceFfNameKey(sffName.getValue()))
                                     .setIp(new IpBuilder().setAddress(new Ipv4Address(remoteForwarderStringIp)).build());
-                            policyWriter.cache(remoteSffBuilder.build());
+                            boolean rsResult = PolicyWriterUtil.writeRemote(remoteSffBuilder.build(), location);
+                            context.setFutureResult(Futures.immediateCheckedFuture(rsResult));
                             serviceTypeChoice = createForwarderTypeChoice(sffName.getValue());
                             // Service chain
                             final List<Services> services = new ArrayList<>();
@@ -353,7 +275,8 @@ public class ServiceChainingUtil {
                             final ServiceChainBuilder chainBuilder = new ServiceChainBuilder();
                             chainBuilder.setServicePath(servicePaths);
                             final ServiceChain serviceChain = chainBuilder.build();
-                            policyWriter.cache(serviceChain);
+                            boolean scResult = PolicyWriterUtil.writeServicePath(serviceChain, location);
+                            context.setFutureResult(Futures.immediateCheckedFuture(scResult));
                         }
                         return true;
                     }).orElseGet(createNegativePathWithLogSupplier(sffName.getValue(),
@@ -364,6 +287,15 @@ public class ServiceChainingUtil {
         return false;
     }
 
+    /**
+     * Investigates provided parameter values and derives service chain name. This name is used to find service function
+     * path
+     *
+     * @param params - list of parameters
+     * @return - service function path if found, null if provided parameters does not correspond with any chain or there
+     * is no service function path defined by that chain
+     */
+    @Nullable
     static ServiceFunctionPath findServicePathFromParameterValues(final List<ParameterValue> params) {
         if (params == null || params.isEmpty()) {
             LOG.error("Cannot found service path, parameter value is null");
@@ -413,61 +345,129 @@ public class ServiceChainingUtil {
     /**
      * Creates {@link RenderedServicePath} if not exist. If created, ios-xe renderer in SFC is invoked, so this method
      * has to wait till SFC part is done to prevent transaction collisions in {@link this#checkRspManagerStatus(RspName,
-     * DataBroker)}
+     * DataBroker)}. If this operation is successful, class-map {@link ClassMap} and entry in policy-map {@link Class}
+     * is written
      *
-     * @param sfp        - path used to create RSP
-     * @param tenantId   - used to generate RSP name according to GBP standards
-     * @param dataBroker - data provider to access odl controller
+     * @param sfp            - path used to create RSP
+     * @param tenantId       - used to generate RSP name according to GBP standards
+     * @param dataBroker     - data provider to access odl controller
+     * @param sourceSgt      - source security group tag
+     * @param destinationSgt - destination security group tag
+     * @param context        - contains policy-map location and status info
      * @return read/created RSP
      */
-    static RenderedServicePath createRenderedPath(final ServiceFunctionPath sfp, final TenantId tenantId,
-                                                  final DataBroker dataBroker) {
-        RenderedServicePath renderedServicePath;
-        // Try to read existing RSP
+    static RenderedServicePath resolveRenderedServicePath(final ServiceFunctionPath sfp, final TenantId tenantId,
+                                                                  final DataBroker dataBroker, final Sgt sourceSgt, final Sgt destinationSgt,
+                                                                  final PolicyConfigurationContext context) {
+        // Get rendered service path
         final RspName rspName = generateRspName(sfp, tenantId);
-        renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
-        if (renderedServicePath != null) {
-            return renderedServicePath;
+        RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+        if (renderedServicePath == null) {
+            LOG.info("Rendered service path with name {} not found, creating a new one ..", rspName.getValue());
+            final CreateRenderedPathInput input = new CreateRenderedPathInputBuilder()
+                    .setParentServiceFunctionPath(sfp.getName().getValue())
+                    .setName(rspName.getValue())
+                    .setSymmetric(sfp.isSymmetric())
+                    .build();
+            renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, input);
+            LOG.info("Rendered service path {} created", rspName.getValue());
+            checkRspManagerStatus(rspName, dataBroker);
         }
-        LOG.info("Rendered service path with name {} not found, creating a new one ..", rspName.getValue());
-        final CreateRenderedPathInput input = new CreateRenderedPathInputBuilder()
-                .setParentServiceFunctionPath(sfp.getName().getValue())
-                .setName(rspName.getValue())
-                .setSymmetric(sfp.isSymmetric())
-                .build();
-        renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, input);
-        LOG.info("Rendered service path {} created", rspName.getValue());
-        checkRspManagerStatus(rspName, dataBroker);
+        // Create class-map and policy-map entry
+        final String classMapName = generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
+        final Match match = createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
+        final ClassMap classMap = createClassMap(classMapName, match);
+        final Class policyMapEntry = createPolicyMapEntry(classMapName, renderedServicePath, ActionCase.CHAIN);
+        boolean cmResult = PolicyWriterUtil.writeClassMap(classMap, context.getPolicyMapLocation());
+        context.setFutureResult(Futures.immediateCheckedFuture(cmResult));
+        boolean pmeResult = PolicyWriterUtil.writePolicyMapEntry(policyMapEntry, context.getPolicyMapLocation());
+        context.setFutureResult(Futures.immediateCheckedFuture(pmeResult));
         return renderedServicePath;
     }
 
     /**
      * Creates reversed {@link RenderedServicePath} if not exist. To be successful, direct path has to exist.
      * If created, ios-xe renderer in SFC is invoked, so this method has to wait till SFC part is done to prevent
-     * transaction collisions in {@link this#checkRspManagerStatus(RspName, DataBroker)}
+     * transaction collisions. If this operation is successful, class-map {@link ClassMap} and entry in policy-map
+     * {@link Class} is written
      *
-     * @param sfp        - path used to create RSP
-     * @param rsp        - appropriate direct RSP, used when the reversed path is created
-     * @param tenantId   - used to generate RSP name according to GBP standards
-     * @param dataBroker - data provider to access odl controller
+     * @param sfp            - path used to create RSP
+     * @param tenantId       - used to generate RSP name according to GBP standards
+     * @param dataBroker     - data provider to access odl controller
+     * @param sourceSgt      - source security group tag
+     * @param destinationSgt - destination security group tag
+     * @param context        - contains policy-map location and status info
      * @return read/created RSP
      */
-    static RenderedServicePath createReversedRenderedPath(final ServiceFunctionPath sfp, final RenderedServicePath rsp,
-                                                          final TenantId tenantId, final DataBroker dataBroker) {
-        RenderedServicePath reversedRenderedPath;
-        // Try to read existing RSP
-        final RspName rspName = generateReversedRspName(sfp, tenantId);
-        reversedRenderedPath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
-        if (reversedRenderedPath != null) {
-            return reversedRenderedPath;
+    public static RenderedServicePath resolveReversedRenderedServicePath(final ServiceFunctionPath sfp, final TenantId tenantId,
+                                                                          final DataBroker dataBroker, final Sgt sourceSgt,
+                                                                          final Sgt destinationSgt, final PolicyConfigurationContext context) {
+        // Get rendered service path
+        final RspName rspName = generateRspName(sfp, tenantId);
+        RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+        if (renderedServicePath == null) {
+            LOG.info("Rendered service path with name {} not found, creating a new one ..", rspName.getValue());
+            final CreateRenderedPathInput input = new CreateRenderedPathInputBuilder()
+                    .setParentServiceFunctionPath(sfp.getName().getValue())
+                    .setName(rspName.getValue())
+                    .setSymmetric(sfp.isSymmetric())
+                    .build();
+            renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, input);
+            LOG.info("Rendered service path {} created", rspName.getValue());
+            checkRspManagerStatus(rspName, dataBroker);
         }
-        LOG.info("Reversed rendered service path with name {} not found, creating a new one ..", rspName.getValue());
-        reversedRenderedPath = SfcProviderRenderedPathAPI.createReverseRenderedServicePathEntry(rsp);
-        LOG.info("Rendered service path {} created", rspName.getValue());
-        checkRspManagerStatus(rspName, dataBroker);
+        // Get reversed rendered service path
+        final RspName reversedRspName = generateReversedRspName(sfp, tenantId);
+        RenderedServicePath reversedRenderedPath = SfcProviderRenderedPathAPI.readRenderedServicePath(reversedRspName);
+        if (reversedRenderedPath == null) {
+            LOG.info("Reversed rendered service path with name {} not found, creating a new one ..", reversedRspName.getValue());
+            reversedRenderedPath = SfcProviderRenderedPathAPI.createReverseRenderedServicePathEntry(renderedServicePath);
+            LOG.info("Rendered service path {} created", reversedRspName.getValue());
+            checkRspManagerStatus(reversedRspName, dataBroker);
+        }
+        // Create class-map and policy-map entry
+        final String classMapName = generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
+        final Match match = createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
+        final ClassMap classMap = createClassMap(classMapName, match);
+        final Class policyMapEntry = createPolicyMapEntry(classMapName, renderedServicePath, ActionCase.CHAIN);
+        boolean cmResult = PolicyWriterUtil.writeClassMap(classMap, context.getPolicyMapLocation());
+        context.setFutureResult(Futures.immediateCheckedFuture(cmResult));
+        boolean pmeResult = PolicyWriterUtil.writePolicyMapEntry(policyMapEntry, context.getPolicyMapLocation());
+        context.setFutureResult(Futures.immediateCheckedFuture(pmeResult));
+        resolveRemoteSfcComponents(renderedServicePath, context);
         return reversedRenderedPath;
     }
 
+    /**
+     * Removes all policy setup created according to rendered service path.
+     *
+     * @param rspName        - rendered service path name
+     * @param sourceSgt      - source security group tag
+     * @param destinationSgt - destination security group tag
+     * @param context        - context with policy-map location
+     */
+    private static void resolveRemovedRenderedServicePath(final RspName rspName, final Sgt sourceSgt, final Sgt destinationSgt,
+                                                          final PolicyConfigurationContext context) {
+        final String classMapName = PolicyManagerUtil.generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
+        final ClassMap classMap = PolicyManagerUtil.createClassMap(classMapName, null);
+        final Class policyMapEntry = PolicyManagerUtil.createPolicyMapEntry(classMapName, null, PolicyManagerImpl.ActionCase.CHAIN);
+        PolicyWriterUtil.removePolicyMapEntry(policyMapEntry, context.getPolicyMapLocation());
+        PolicyWriterUtil.removeClassMap(classMap, context.getPolicyMapLocation());
+        final RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+        final ServiceFunctionForwarder firstHopSff = getFirstHopSff(renderedServicePath);
+        if (firstHopSff != null && firstHopSff.getIpMgmtAddress() != null &&
+                firstHopSff.getIpMgmtAddress().getIpv4Address() != null) {
+            final String sffMgmtIpValue = firstHopSff.getIpMgmtAddress().getIpv4Address().getValue();
+            if (!sffMgmtIpValue.equals(context.getPolicyMapLocation().getManagementIpAddress())) {
+                // Remove service chain and remote forwarder
+                final ServiceChain serviceChain = createServiceChain(renderedServicePath);
+                final ServiceFfName remoteForwarder = createRemoteForwarder(firstHopSff);
+                PolicyWriterUtil.removeServicePath(serviceChain, context.getPolicyMapLocation());
+                PolicyWriterUtil.removeRemote(remoteForwarder, context.getPolicyMapLocation());
+            }
+        }
+    }
+
     static ServiceFfName createRemoteForwarder(ServiceFunctionForwarder firstHopSff) {
         final ServiceFfNameBuilder serviceFfNameBuilder = new ServiceFfNameBuilder();
         serviceFfNameBuilder.setName(firstHopSff.getName().getValue());
@@ -584,10 +584,11 @@ public class ServiceChainingUtil {
 
     /**
      * Only for test purposes
+     *
      * @param value - set actual timeout value
      */
     @VisibleForTesting
     public static void setTimeout(long value) {
         timeout = value;
     }
-}
+}
\ No newline at end of file
index 8f8cb2086138ef3e284a4aecef347f0a389b228f..f6d811027975adcf33d3a88a729f4343d581b9f1 100644 (file)
@@ -8,15 +8,17 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
 
-import com.google.common.annotations.VisibleForTesting;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import com.google.common.annotations.VisibleForTesting;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyConfigurationContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.UnconfiguredRuleGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.UnconfiguredRuleGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.unconfigured.rule.group.UnconfiguredResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.unconfigured.rule.group.UnconfiguredResolvedRuleBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Status;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpoint;
@@ -46,46 +48,60 @@ public class StatusUtil {
     public static UnconfiguredRendererEndpoint assembleFullyNotConfigurableRendererEP(final PolicyConfigurationContext context,
                                                                                       final String info) {
         final RendererEndpoint rendererEndpoint = context.getCurrentRendererEP();
-        LOG.trace("fully not configurable EP: {}", info);
+        LOG.trace("Fully not configurable EP: {}", info);
         return new UnconfiguredRendererEndpointBuilder(rendererEndpoint)
-                .setUnconfiguredPeerEndpoint(assemblePeerEndpoint(rendererEndpoint.getPeerEndpoint().stream()))
+                .setUnconfiguredPeerEndpoint(assemblePeerEndpoint(rendererEndpoint.getPeerEndpoint().stream(), context))
                 .setInfo(info)
                 .build();
     }
 
     /**
-     * @param context holder of actual configuration state
-     * @param info    detailed message for not configurable item
+     * @param context      holder of actual configuration state
+     * @param peerEndpoint peer endpoint
+     * @param info         detailed message for not configurable item
      * @return filtered collection of not configurable items under given endpoint and peer
      */
     public static UnconfiguredRendererEndpoint assembleNotConfigurableRendererEPForPeer(final PolicyConfigurationContext context,
                                                                                         final PeerEndpoint peerEndpoint,
                                                                                         final String info) {
         final RendererEndpoint rendererEndpoint = context.getCurrentRendererEP();
-        LOG.trace("not configurable EP for peer: {}", info);
+        LOG.trace("Not configurable EP for peer: {}", info);
         return new UnconfiguredRendererEndpointBuilder(rendererEndpoint)
-                .setUnconfiguredPeerEndpoint(assemblePeerEndpoint(Stream.of(peerEndpoint)))
+                .setUnconfiguredPeerEndpoint(assemblePeerEndpoint(Stream.of(peerEndpoint), context))
                 .setInfo(info)
                 .build();
     }
 
     @VisibleForTesting
-    static List<UnconfiguredPeerEndpoint> assemblePeerEndpoint(final Stream<PeerEndpoint> peerEndpoint) {
+    static List<UnconfiguredPeerEndpoint> assemblePeerEndpoint(final Stream<PeerEndpoint> peerEndpoint,
+                                                               final PolicyConfigurationContext context) {
         return peerEndpoint
                 .map((peerEP) -> new UnconfiguredPeerEndpointBuilder(peerEP)
                         .setUnconfiguredRuleGroup(
-                                assembleRuleGroups(peerEP.getRuleGroupWithRendererEndpointParticipation().stream())
+                                assembleRuleGroups(peerEP.getRuleGroupWithRendererEndpointParticipation().stream(), context)
                         ).build())
                 .collect(Collectors.toList());
     }
 
     @VisibleForTesting
-    static List<UnconfiguredRuleGroup> assembleRuleGroups(final Stream<RuleGroupWithRendererEndpointParticipation> stream) {
+    static List<UnconfiguredRuleGroup> assembleRuleGroups(final Stream<RuleGroupWithRendererEndpointParticipation> stream,
+                                                          final PolicyConfigurationContext context) {
         return stream
                 .filter(Objects::nonNull)
                 .map((ruleGroup) -> new UnconfiguredRuleGroupBuilder(ruleGroup)
                         .setRendererEndpointParticipation(ruleGroup.getRendererEndpointParticipation())
-                        // TODO: find rule-group and append names of resolved rules ...setUnconfiguredResolvedRule()
+                        .setUnconfiguredResolvedRule(assembleResolvedRule(Stream.of(context.getCurrentUnconfiguredRule()), context))
+                        .build())
+                .collect(Collectors.toList());
+    }
+
+    @VisibleForTesting
+    private static List<UnconfiguredResolvedRule> assembleResolvedRule(final Stream<UnconfiguredResolvedRule> stream,
+                                                                       final PolicyConfigurationContext context) {
+        return stream
+                .filter(Objects::nonNull)
+                .map((unconfiguredRule) -> new UnconfiguredResolvedRuleBuilder(context.getCurrentUnconfiguredRule())
+                        .setRuleName(context.getCurrentUnconfiguredRule().getRuleName())
                         .build())
                 .collect(Collectors.toList());
     }
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/writer/PolicyWriter.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/writer/PolicyWriter.java
deleted file mode 100644 (file)
index 6532cdb..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer;
-
-import java.util.HashSet;
-import java.util.Set;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfName;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PolicyWriter {
-
-    private static final Logger LOG = LoggerFactory.getLogger(PolicyWriter.class);
-
-    private final DataBroker mountpoint;
-    // Local cache
-    private final Set<ClassMap> classMapEntries;
-    private final Set<Class> policyMapEntries;
-    private final Set<ServiceFfName> remoteForwarders;
-    private final Set<ServiceChain> serviceChains;
-    private final NodeId nodeId;
-    private final String interfaceName;
-    private final String policyMapName;
-    private final String managementIpAddress;
-
-    public PolicyWriter(final DataBroker dataBroker, final String interfaceName, final String ipAddress,
-                        final String policyMapName, final NodeId nodeId) {
-        classMapEntries = new HashSet<>();
-        policyMapEntries = new HashSet<>();
-        remoteForwarders = new HashSet<>();
-        serviceChains = new HashSet<>();
-
-        this.nodeId = Preconditions.checkNotNull(nodeId);
-        mountpoint = Preconditions.checkNotNull(dataBroker);
-        managementIpAddress = Preconditions.checkNotNull(ipAddress);
-        this.interfaceName = Preconditions.checkNotNull(interfaceName);
-        this.policyMapName = Preconditions.checkNotNull(policyMapName);
-    }
-
-    public CheckedFuture<Boolean, TransactionCommitFailedException> commitToDatastore() {
-        LOG.debug("Configuring policy on node {}, interface {} ... ", nodeId.getValue(), interfaceName);
-        if (policyMapEntries.isEmpty()) {
-            LOG.debug("Policy map {} is empty, skipping", policyMapName);
-            return Futures.immediateCheckedFuture(true);
-        }
-        // SFC
-        boolean remoteResult = PolicyWriterUtil.writeRemote(remoteForwarders, nodeId, mountpoint);
-        boolean servicePathsResult = PolicyWriterUtil.writeServicePaths(serviceChains, nodeId, mountpoint);
-        // GBP - maintain order!
-        boolean classMapResult = PolicyWriterUtil.writeClassMaps(classMapEntries, nodeId, mountpoint);
-        boolean policyMapResult = PolicyWriterUtil.writePolicyMap(policyMapName, policyMapEntries, nodeId, mountpoint);
-        boolean interfaceResult = PolicyWriterUtil.writeInterface(policyMapName, interfaceName, nodeId, mountpoint);
-        // Result
-        LOG.info("Policy-map created on node {}, interface {}", nodeId.getValue(), interfaceName);
-        return Futures.immediateCheckedFuture(classMapResult && policyMapResult && interfaceResult && remoteResult
-                && servicePathsResult);
-    }
-
-    public CheckedFuture<Boolean, TransactionCommitFailedException> removeFromDatastore() {
-        LOG.debug("Removing policy from node {}, interface {} ... ", nodeId.getValue(), interfaceName);
-        if (policyMapEntries.isEmpty()) {
-            LOG.debug("Policy map {} is empty, nothing to remove", policyMapName);
-            return Futures.immediateCheckedFuture(true);
-        }
-        // GBP - maintain order!
-        boolean policyMapEntriesResult = PolicyWriterUtil.removePolicyMapEntries(policyMapName, policyMapEntries,
-                nodeId, mountpoint);
-        boolean classMapResult = PolicyWriterUtil.removeClassMaps(classMapEntries, nodeId, mountpoint);
-        // SFC
-        boolean remoteSffResult = PolicyWriterUtil.removeRemote(remoteForwarders, nodeId, mountpoint);
-        boolean servicePathsResult = PolicyWriterUtil.removeServicePaths(serviceChains, nodeId, mountpoint);
-        // Result
-        LOG.info("Policy-map removed from node {}, interface {}", nodeId.getValue(), interfaceName);
-        return Futures.immediateCheckedFuture(classMapResult && policyMapEntriesResult && servicePathsResult
-                && remoteSffResult);
-    }
-
-    public void cache(ClassMap classMap) {
-        classMapEntries.add(classMap);
-    }
-
-    public void cache(Class policyMapEntry) {
-        this.policyMapEntries.add(policyMapEntry);
-    }
-
-    public void cache(ServiceFfName remoteForwarder) {
-        remoteForwarders.add(remoteForwarder);
-    }
-
-    public void cache(ServiceChain serviceChain) {
-        serviceChains.add(serviceChain);
-    }
-
-    public String getManagementIpAddress() {
-        return managementIpAddress;
-    }
-
-    public DataBroker getMountpoint() {
-        return mountpoint;
-    }
-
-    public NodeId getNodeId() {
-        return nodeId;
-    }
-}
index f2cd572594c992bf8bdbce4cd6efd969e9bd59ea..b3aee34644525e97855d1f86d631e63f4e738ed3 100644 (file)
@@ -8,8 +8,8 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer;
 
+import javax.annotation.Nonnull;
 import java.util.List;
-import java.util.Set;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -18,6 +18,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
@@ -46,56 +47,53 @@ import org.slf4j.LoggerFactory;
 /**
  * Purpose: Util class for every policy writer
  */
-class PolicyWriterUtil {
+public class PolicyWriterUtil {
 
     private static final Logger LOG = LoggerFactory.getLogger(PolicyWriterUtil.class);
 
-    static boolean writeClassMaps(final Set<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
+    public static boolean writeClassMap(@Nonnull final ClassMap classMap,
+                                        final PolicyManagerImpl.PolicyMapLocation policyMapLocation) {
         boolean result = true;
-        if (classMapEntries == null || classMapEntries.isEmpty()) {
-            return true;
-        }
-        for (ClassMap entry : classMapEntries) {
-            final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
-            netconfWrite(mountpoint, classMapIid, entry);
-            // Check
-            final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
-            if (checkCreated.isPresent()) {
-                LOG.trace("Created class-map {} on node {}", entry.getName(), nodeId.getValue());
-            }
-            else {
-                LOG.warn("Failed to create class-map {} on node {}", entry.getName(), nodeId.getValue());
-                result = false;
-            }
+        final DataBroker mountpoint = policyMapLocation.getMountpoint();
+        final NodeId nodeId = policyMapLocation.getNodeId();
+        final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(classMap);
+        netconfWrite(mountpoint, classMapIid, classMap);
+        // Check
+        final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
+        if (checkCreated.isPresent()) {
+            LOG.trace("Created class-map {} on node {}", classMap.getName(), nodeId.getValue());
+        } else {
+            LOG.warn("Failed to create class-map {} on node {}", classMap.getName(), nodeId.getValue());
+            result = false;
+
         }
         return result;
     }
 
-    static boolean removeClassMaps(final Set<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
+    public static boolean removeClassMap(final ClassMap classMap, final PolicyManagerImpl.PolicyMapLocation location) {
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
         boolean result = true;
-        if (classMapEntries == null || classMapEntries.isEmpty()) {
+        if (classMap == null) {
             return true;
         }
-        for (ClassMap entry : classMapEntries) {
-            final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
-            netconfDeleteIfPresent(mountpoint, classMapIid);
-            // Check
-            final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
-            if (checkCreated.isPresent()) {
-                LOG.warn("Failed to remove class-map {} on node {}", entry.getName(), nodeId.getValue());
-                result = false;
-            }
-            else {
-                LOG.trace("Class-map {} removed from node {}", entry.getName(), nodeId.getValue());
-            }
+        final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(classMap);
+        netconfDeleteIfPresent(mountpoint, classMapIid);
+        // Check
+        final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
+        if (checkCreated.isPresent()) {
+            LOG.warn("Failed to remove class-map {} on node {}", classMap.getName(), nodeId.getValue());
+            result = false;
+        } else {
+            LOG.trace("Class-map {} removed from node {}", classMap.getName(), nodeId.getValue());
         }
         return result;
     }
 
-    static boolean writePolicyMap(final String policyMapName, final Set<Class> policyMapEntries, NodeId nodeId,
-                                  final DataBroker mountpoint) {
-        final PolicyMap policyMap = PolicyManagerUtil.createPolicyMap(policyMapName, policyMapEntries);
-        final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMapName);
+    public static boolean writePolicyMap(final PolicyMap policyMap, final PolicyManagerImpl.PolicyMapLocation location) {
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
+        final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMap.getName());
         netconfWrite(mountpoint, policyMapIid, policyMap);
         // Check
         if (netconfRead(mountpoint, policyMapIid) == null) {
@@ -106,130 +104,177 @@ class PolicyWriterUtil {
         return true;
     }
 
-    static boolean removePolicyMapEntries(final String policyMapName, final Set<Class> policyMapEntries,
-                                          final NodeId nodeId, final DataBroker mountpoint) {
-        if (policyMapEntries == null || policyMapEntries.isEmpty()) {
+    public static boolean removePolicyMap(final PolicyManagerImpl.PolicyMapLocation location) {
+        final String policyMapName = location.getPolicyMapName();
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
+        final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMapName);
+        netconfDeleteIfPresent(mountpoint, policyMapIid);
+        // Check
+        if (netconfRead(mountpoint, policyMapIid) != null) {
+            LOG.warn("Failed to remove policy-map {} from node {}", policyMapName, nodeId.getValue());
+            return false;
+        }
+        LOG.trace("Policy-map {} removed from node {}", policyMapName, nodeId.getValue());
+        return true;
+    }
+
+    public static boolean writePolicyMapEntry(final Class policyMapEntry,
+                                              final PolicyManagerImpl.PolicyMapLocation location) {
+        final String policyMapName = location.getPolicyMapName();
+        final NodeId nodeId = location.getNodeId();
+        final DataBroker mountpoint = location.getMountpoint();
+        final ClassNameType entryName = policyMapEntry.getName();
+        final InstanceIdentifier<Class> policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, entryName);
+        netconfWrite(mountpoint, policyMapEntryIid, policyMapEntry);
+        // Check
+        if (netconfRead(mountpoint, policyMapEntryIid) == null) {
+            LOG.warn("Failed to create entry in policy-map {} on node {}. Entry: {}", policyMapName, nodeId.getValue(),
+                    policyMapEntry);
+            return false;
+        }
+        LOG.trace("Created entry in policy-map {} on node {}. Entry: {}", policyMapName, nodeId.getValue(), policyMapEntry);
+        return true;
+    }
+
+    public static boolean removePolicyMapEntry(final Class policyMapEntry, final PolicyManagerImpl.PolicyMapLocation location) {
+        final String policyMapName = location.getPolicyMapName();
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
+        if (policyMapEntry == null) {
             return true;
         }
         boolean result = true;
-        for (Class entry : policyMapEntries) {
-            final InstanceIdentifier policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, entry.getName());
-            if (netconfDeleteIfPresent(mountpoint, policyMapEntryIid)) {
-                LOG.trace("Policy-map entry {} removed from node {}", entry.getName(), nodeId.getValue());
-            }
-            else {
-                LOG.warn("Failed to remove policy-map entry {} from node {}", entry.getName(), nodeId.getValue());
-                result = false;
-            }
+        final InstanceIdentifier policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, policyMapEntry.getName());
+        if (netconfDeleteIfPresent(mountpoint, policyMapEntryIid)) {
+            LOG.trace("Policy-map entry {} removed from node {}", policyMapEntry.getName(), nodeId.getValue());
+        } else {
+            LOG.warn("Failed to remove policy-map entry {} from node {}", policyMapEntry.getName(), nodeId.getValue());
+            result = false;
         }
         return result;
     }
 
-    static boolean writeInterface(final String policyMapName, final String interfaceName, final NodeId nodeId,
-                                  final DataBroker mountpoint) {
+    public static boolean writeInterface(final PolicyManagerImpl.PolicyMapLocation location) {
+        final String policyMapName = location.getPolicyMapName();
+        final String interfaceName = location.getInterfaceName();
+        final NodeId nodeId = location.getNodeId();
+        final DataBroker mountpoint = location.getMountpoint();
         final ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
         final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
         if (netconfWrite(mountpoint, servicePolicyIid, servicePolicy)) {
             LOG.trace("Service-policy interface {}, bound to policy-map {} created on  node {}",
                     interfaceName, policyMapName, nodeId.getValue());
             return true;
-        }
-        else {
+        } else {
             LOG.warn("Failed to write service-policy interface {} to policy-map {} on  node {}",
                     interfaceName, policyMapName, nodeId.getValue());
             return false;
         }
     }
 
-    static boolean writeRemote(final Set<ServiceFfName> remoteForwarders, final NodeId nodeId,
-                               final DataBroker mountpoint) {
-        if (remoteForwarders == null || remoteForwarders.isEmpty()) {
+    public static boolean removeInterface(final PolicyManagerImpl.PolicyMapLocation location) {
+        final String policyMapName = location.getPolicyMapName();
+        final String interfaceName = location.getInterfaceName();
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
+        final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
+        if (netconfDeleteIfPresent(mountpoint, servicePolicyIid)) {
+            LOG.trace("Service-policy interface {}, removed from node {}",
+                    interfaceName, policyMapName, nodeId.getValue());
+            return true;
+        } else {
+            LOG.warn("Failed to remove service-policy interface {} from  node {}",
+                    interfaceName, policyMapName, nodeId.getValue());
+            return false;
+        }
+    }
+
+    public static boolean writeRemote(final ServiceFfName remoteForwarder,
+                                      final PolicyManagerImpl.PolicyMapLocation location) {
+        // TODO writeNE
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
+        if (remoteForwarder == null) {
             return true;
         }
         boolean result = true;
-        for (ServiceFfName forwarder : remoteForwarders) {
-            final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
-            if (netconfWrite(mountpoint, forwarderIid, forwarder)) {
-                LOG.trace("Remote forwarder {} created on node {}", forwarder.getName(), nodeId.getValue());
-            }
-            else {
-                LOG.warn("Failed to create remote forwarder {} on node {}", forwarder.getName(), nodeId.getValue());
-                result = false;
-            }
+        final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(remoteForwarder);
+        if (netconfWrite(mountpoint, forwarderIid, remoteForwarder)) {
+            LOG.trace("Remote forwarder {} created on node {}", remoteForwarder.getName(), nodeId.getValue());
+        } else {
+            LOG.warn("Failed to create remote forwarder {} on node {}", remoteForwarder.getName(), nodeId.getValue());
+            result = false;
         }
         return result;
     }
 
-    static boolean removeRemote(final Set<ServiceFfName> remoteForwarders, final NodeId nodeId,
-                                final DataBroker mountpoint) {
-        if (remoteForwarders == null || remoteForwarders.isEmpty()) {
+    public static boolean removeRemote(final ServiceFfName remoteForwarder, final PolicyManagerImpl.PolicyMapLocation location) {
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
+        if (remoteForwarder == null) {
             return true;
         }
         boolean result = true;
-        for (ServiceFfName forwarder : remoteForwarders) {
-            final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
-            if (netconfDeleteIfPresent(mountpoint, forwarderIid)) {
-                LOG.trace("Remote forwarder {} removed from node {}", forwarder.getName(), nodeId.getValue());
-            }
-            else {
-                LOG.warn("Failed to remove forwarder {} from node {}", forwarder.getName(), nodeId.getValue());
-                result = false;
-            }
+        final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(remoteForwarder);
+        if (netconfDeleteIfPresent(mountpoint, forwarderIid)) {
+            LOG.trace("Remote forwarder {} removed from node {}", remoteForwarder.getName(), nodeId.getValue());
+        } else {
+            LOG.warn("Failed to remove forwarder {} from node {}", remoteForwarder.getName(), nodeId.getValue());
+            result = false;
         }
         return result;
     }
 
-    static boolean writeServicePaths(final Set<ServiceChain> serviceChains, final NodeId nodeId,
-                                     final DataBroker mountpoint) {
+    public static boolean writeServicePath(final ServiceChain serviceChain,
+                                           final PolicyManagerImpl.PolicyMapLocation location) {
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
         boolean result = true;
-        for (org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain serviceChain : serviceChains) {
-            for (ServicePath entry : serviceChain.getServicePath()) {
-                final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
-                if (netconfWrite(mountpoint, servicePathIid, entry)) {
-                    LOG.trace("Service-path with ID: {} created on node {}", entry.getServicePathId(), nodeId.getValue());
-                }
-                else {
-                    LOG.warn("Failed to create service-path with ID: {} on node {}", entry.getServicePathId(), nodeId.getValue());
-                    result = false;
-                }
+        for (ServicePath entry : serviceChain.getServicePath()) {
+            final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
+            if (netconfWrite(mountpoint, servicePathIid, entry)) {
+                LOG.trace("Service-path with ID: {} created on node {}", entry.getServicePathId(), nodeId.getValue());
+            } else {
+                LOG.warn("Failed to create service-path with ID: {} on node {}", entry.getServicePathId(), nodeId.getValue());
+                result = false;
             }
         }
         return result;
     }
 
-    static boolean removeServicePaths(final Set<ServiceChain> serviceChains, final NodeId nodeId,
-                                      final DataBroker mountpoint) {
-        if (serviceChains == null || serviceChains.isEmpty()) {
+    public static boolean removeServicePath(final ServiceChain serviceChain, final PolicyManagerImpl.PolicyMapLocation location) {
+        final DataBroker mountpoint = location.getMountpoint();
+        final NodeId nodeId = location.getNodeId();
+        if (serviceChain == null) {
             return true;
         }
         boolean result = true;
-        for (ServiceChain chain : serviceChains) {
-            List<ServicePath> servicePaths = chain.getServicePath();
-            if (servicePaths == null || servicePaths.isEmpty()) {
-                continue;
-            }
-            for (ServicePath servicePath : servicePaths) {
-                final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(servicePath.getKey());
-                if (netconfDeleteIfPresent(mountpoint, servicePathIid)) {
-                    LOG.trace("Service-path with ID: {} removed from node {}", servicePath.getServicePathId(),
-                            nodeId.getValue());
-                }
-                else {
-                    LOG.warn("Failed to remove service-path with ID: {} from node {}", servicePath.getServicePathId(),
-                            nodeId.getValue());
-                    result = false;
-                }
+        List<ServicePath> servicePaths = serviceChain.getServicePath();
+        if (servicePaths == null || servicePaths.isEmpty()) {
+            return true;
+        }
+        for (ServicePath servicePath : servicePaths) {
+            final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(servicePath.getKey());
+            if (netconfDeleteIfPresent(mountpoint, servicePathIid)) {
+                LOG.trace("Service-path with ID: {} removed from node {}", servicePath.getServicePathId(),
+                        nodeId.getValue());
+            } else {
+                LOG.warn("Failed to remove service-path with ID: {} from node {}", servicePath.getServicePathId(),
+                        nodeId.getValue());
+                result = false;
             }
         }
         return result;
     }
 
+
     private static InstanceIdentifier<ClassMap> classMapInstanceIdentifier(final ClassMap classMap) {
         return InstanceIdentifier.builder(Native.class)
                 .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
     }
 
-    private static InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier(final String policyMapName) {
+    public static InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier(final String policyMapName) {
         return InstanceIdentifier.builder(Native.class)
                 .child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
     }
@@ -241,7 +286,7 @@ class PolicyWriterUtil {
                 .child(Class.class, new ClassKey(classNameType)).build();
     }
 
-    private static InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(final String ethernetName) {
+    public static InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(final String ethernetName) {
         return InstanceIdentifier.builder(Native.class)
                 .child(Interface.class)
                 .child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
@@ -263,8 +308,9 @@ class PolicyWriterUtil {
     }
 
     private static <U extends DataObject> boolean netconfWrite(final DataBroker mountpoint,
-                                                            final InstanceIdentifier<U> addIID,
-                                                            final U data) {
+                                                               final InstanceIdentifier<U> addIID,
+                                                               final U data) {
+        // TODO consider to move netconfWrite, netconfDeleteIfPresent and netconfRead methods (+ methods in NetconfTransactionCreator) to gbp base
         final java.util.Optional<WriteTransaction> optionalWriteTransaction =
                 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
         if (!optionalWriteTransaction.isPresent()) {
@@ -312,8 +358,8 @@ class PolicyWriterUtil {
         return false;
     }
 
-    private static <U extends DataObject> U netconfRead(final DataBroker mountpoint,
-                                                        final InstanceIdentifier<U> readIID) {
+    public static <U extends DataObject> U netconfRead(final DataBroker mountpoint,
+                                                       final InstanceIdentifier<U> readIID) {
         final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
                 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
         if (!optionalReadTransaction.isPresent()) {
index c58e86382f299e43372a930e646f6cef69100bae..f28d307c043b1601966c01732cd04aed2d79cf0e 100644 (file)
@@ -17,6 +17,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
@@ -114,16 +115,16 @@ public class PolicyManagerImplTest {
     private PolicyManagerImpl policyManager;
     private DataBroker mountpoint;
     private NodeManager nodeManager;
-    private WriteTransaction writeTransaction;
+    private ReadWriteTransaction readWriteTransaction;
 
     @Before
     public void init() {
         mountpoint = mock(DataBroker.class);
-        writeTransaction = mock(WriteTransaction.class);
+        readWriteTransaction = mock(ReadWriteTransaction.class);
         nodeManager = mock(NodeManager.class);
         policyManager = new PolicyManagerImpl(mountpoint, nodeManager);
-        when(mountpoint.newWriteOnlyTransaction()).thenReturn(writeTransaction);
-        when(writeTransaction.submit()).thenReturn(Futures.immediateCheckedFuture((Void) null));
+        when(mountpoint.newReadWriteTransaction()).thenReturn(readWriteTransaction);
+        when(readWriteTransaction.submit()).thenReturn(Futures.immediateCheckedFuture((Void) null));
     }
 
     @Test
@@ -265,7 +266,7 @@ public class PolicyManagerImplTest {
         ServiceFunctionPath sfp = createServiceFunctionPath();
         stub(method(ServiceChainingUtil.class, "findServicePathFromParameterValues")).toReturn(sfp);
         RenderedServicePath rsp = createRenderedServicePath();
-        stub(method(ServiceChainingUtil.class, "createRenderedPath")).toReturn(rsp);
+        stub(method(ServiceChainingUtil.class, "resolveRenderedServicePath")).toReturn(rsp);
         ServiceFunctionForwarder serviceFunctionForwarder = createServiceForwarder();
         stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder"))
                 .toReturn(serviceFunctionForwarder);
index ac248b9bf19c84a35137d2f9a6c397c31890dbb9..ac95a22eac920d08077f990b7d829c9e0689c3df 100644 (file)
@@ -8,9 +8,11 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
 
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Collections;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.Futures;
-import java.util.Collections;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -25,6 +27,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyConfigurationContext;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.sfc.provider.OpendaylightSfc;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
@@ -40,10 +44,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import static org.junit.Assert.assertNotNull;
-
 /**
  * Test for {@link PolicyManagerUtil}.
  */
@@ -96,15 +100,23 @@ public class PolicyManagerUtilTest {
 
     @Test
     public void testCreateRenderedPath() throws Exception {
+        final String POLICY_MAP = "policy-map";
+        final String INTERFACE = "interface";
+        final NodeId nodeId = new NodeId("node-id");
+        final String IP_ADDRESS = "ip-address";
         final TenantId tenantId = new TenantId("tenant-id-01");
         final RenderedServicePath renderedSP = new RenderedServicePathBuilder().build();
+        final PolicyManagerImpl.PolicyMapLocation location = new PolicyManagerImpl.PolicyMapLocation(POLICY_MAP, INTERFACE,
+                nodeId, IP_ADDRESS, dataBroker);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(location);
 
         Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(roTx);
         Mockito.when(roTx.read(Matchers.eq(LogicalDatastoreType.OPERATIONAL), rendererServicePathIICaptor.capture()))
                 .thenReturn(Futures.immediateCheckedFuture(Optional.of(renderedSP)));
 
-        final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(serviceFunctionPath, tenantId,
-                dataBroker);
+        final RenderedServicePath renderedPath = ServiceChainingUtil.resolveRenderedServicePath(serviceFunctionPath, tenantId,
+                dataBroker, new Sgt(1), new Sgt(2), context);
         Assert.assertEquals(renderedSP, renderedPath);
         final InstanceIdentifier<RenderedServicePath> ii = rendererServicePathIICaptor.getValue();
         Assert.assertEquals("sfp-name-01-tenant-id-01-gbp-rsp", ii.firstKeyOf(RenderedServicePath.class).getName().getValue());
@@ -112,6 +124,14 @@ public class PolicyManagerUtilTest {
 
     @Test
     public void testCreateSymmetricRenderedPath() throws Exception {
+        final String POLICY_MAP = "policy-map";
+        final String INTERFACE = "interface";
+        final NodeId nodeId = new NodeId("node-id");
+        final String IP_ADDRESS = "ip-address";
+        final PolicyManagerImpl.PolicyMapLocation location = new PolicyManagerImpl.PolicyMapLocation(POLICY_MAP, INTERFACE,
+                nodeId, IP_ADDRESS, dataBroker);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(location);
         final RenderedServicePath renderedServicePath = new RenderedServicePathBuilder().build();
         final TenantId tenantId = new TenantId("tenant-id-02");
 
@@ -119,9 +139,8 @@ public class PolicyManagerUtilTest {
         Mockito.when(roTx.read(Matchers.eq(LogicalDatastoreType.OPERATIONAL), rendererServicePathIICaptor.capture()))
                 .thenReturn(Futures.immediateCheckedFuture(Optional.of(renderedServicePath)));
 
-
-        final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createReversedRenderedPath(
-                serviceFunctionPath, renderedServicePath, tenantId, dataBroker);
+        final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.resolveReversedRenderedServicePath(
+                serviceFunctionPath, tenantId, dataBroker, new Sgt(1), new Sgt(2), context);
         Assert.assertEquals(renderedServicePath, symmetricRenderedPath);
         final InstanceIdentifier<RenderedServicePath> ii = rendererServicePathIICaptor.getValue();
         Assert.assertEquals("sfp-name-01-tenant-id-02-gbp-rsp-Reverse", ii.firstKeyOf(RenderedServicePath.class).getName().getValue());
index ddaa2e069f6e1253860591af91b5e0c85ea9cff3..6e9f6746ccd44d4b38fc813bd0c69909195e887b 100644 (file)
@@ -15,14 +15,14 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.ALLOW;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
 import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction.In;
 import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction.Out;
 import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation.PROVIDER;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
 import static org.powermock.api.support.membermodification.MemberMatcher.method;
 import static org.powermock.api.support.membermodification.MemberModifier.stub;
 
@@ -41,9 +41,10 @@ import org.mockito.Mock;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyConfigurationContext;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil.ActionInDirection;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriterUtil;
 import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
@@ -75,6 +76,7 @@ import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.serv
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameBuilder;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
@@ -86,6 +88,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
@@ -99,7 +102,7 @@ import org.powermock.modules.junit4.PowerMockRunner;
         SfcProviderServicePathAPI.class,
         SfcProviderRenderedPathAPI.class,
         PolicyManagerUtil.class,
-        PolicyWriter.class
+        PolicyWriterUtil.class
 })
 public class ServiceChainingUtilTest {
 
@@ -108,9 +111,10 @@ public class ServiceChainingUtilTest {
     private final String TENANT_ID = "tenant-id";
     private final String IP_ADDRESS = "170.0.0.1";
     private final String SERVICE_FUNCTION_FORWARDER = "service-function-forwarder";
+    private final RuleName RULE_NAME = new RuleName("rule-name");
 
     private DataBroker dataBroker;
-    private PolicyWriter policyWriter;
+    private PolicyWriterUtil policyWriterUtil;
 
 
     @Captor
@@ -133,7 +137,7 @@ public class ServiceChainingUtilTest {
     @Before
     public void setUp() {
         dataBroker = mock(DataBroker.class);
-        policyWriter = mock(PolicyWriter.class);
+        policyWriterUtil = mock(PolicyWriterUtil.class);
     }
 
     @Test
@@ -142,10 +146,10 @@ public class ServiceChainingUtilTest {
         final Action action = actionBuilder(null);
         final PolicyConfigurationContext context = policyConfigurationContextBuilder();
 
-        ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(ALLOW, action, In), context, dataBroker);
+        ServiceChainingUtil.newChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
+                resolvedActionBuilder(RULE_NAME, ALLOW, action, In), context, dataBroker);
 
-        verifyNoMoreInteractions(policyWriter);
+        verifyNoMoreInteractions(policyWriterUtil);
         verifyNoMoreInteractions(dataBroker);
     }
 
@@ -155,10 +159,10 @@ public class ServiceChainingUtilTest {
         final Action action = actionBuilder(null);
         final PolicyConfigurationContext context = policyConfigurationContextBuilder();
 
-        ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, In), context, dataBroker);
+        ServiceChainingUtil.newChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
+                resolvedActionBuilder(RULE_NAME, CHAIN, action, In), context, dataBroker);
 
-        verifyNoMoreInteractions(policyWriter);
+        verifyNoMoreInteractions(policyWriterUtil);
         verifyNoMoreInteractions(dataBroker);
     }
 
@@ -180,10 +184,10 @@ public class ServiceChainingUtilTest {
         stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(pathsBuilder.build());
         stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(null);
 
-        ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, In), context, dataBroker);
+        ServiceChainingUtil.newChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
+                resolvedActionBuilder(RULE_NAME, CHAIN, action, In), context, dataBroker);
 
-        verifyNoMoreInteractions(policyWriter);
+        verifyNoMoreInteractions(policyWriterUtil);
         verifyNoMoreInteractions(dataBroker);
     }
 
@@ -206,10 +210,10 @@ public class ServiceChainingUtilTest {
         stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(pathsBuilder.build());
         stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(new TenantId(TENANT_ID));
 
-        ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, In), context, dataBroker);
+        ServiceChainingUtil.newChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
+                resolvedActionBuilder(RULE_NAME, CHAIN, action, In), context, dataBroker);
 
-        verifyNoMoreInteractions(policyWriter);
+        verifyNoMoreInteractions(policyWriterUtil);
         verifyNoMoreInteractions(dataBroker);
     }
 
@@ -230,16 +234,15 @@ public class ServiceChainingUtilTest {
         final PolicyConfigurationContext context = policyConfigurationContextBuilder();
 
         stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(pathsBuilder.build());
-        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(buildRsp(null));
-        stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(new TenantId(TENANT_ID));
+        stub(method(PolicyWriterUtil.class, "writeClassMap")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "writePolicyMapEntry")).toReturn(true);
 
-        ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, Out), context, dataBroker);
+        ServiceChainingUtil.newChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
+                resolvedActionBuilder(RULE_NAME, CHAIN, action, Out), context, dataBroker);
 
-        verify(policyWriter).cache(any(ClassMap.class));
-        verify(policyWriter).cache(any(Class.class));
-        verifyNoMoreInteractions(policyWriter);
-        verifyNoMoreInteractions(dataBroker);
+        verifyStatic(times(1));
+        PolicyWriterUtil.writeClassMap(any(ClassMap.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.writePolicyMapEntry(any(Class.class), any(PolicyManagerImpl.PolicyMapLocation.class));
     }
 
     @Test
@@ -259,16 +262,15 @@ public class ServiceChainingUtilTest {
         final PolicyConfigurationContext context = policyConfigurationContextBuilder();
 
         stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(pathsBuilder.build());
-        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(buildRsp(null));
-        stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(new TenantId(TENANT_ID));
+        stub(method(PolicyWriterUtil.class, "writeClassMap")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "writePolicyMapEntry")).toReturn(true);
 
-        ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, Out), context, dataBroker);
+        ServiceChainingUtil.newChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
+                resolvedActionBuilder(RULE_NAME, CHAIN, action, Out), context, dataBroker);
 
-        verify(policyWriter).cache(any(ClassMap.class));
-        verify(policyWriter).cache(any(Class.class));
-        verifyNoMoreInteractions(policyWriter);
-        verifyNoMoreInteractions(dataBroker);
+        verifyStatic(times(1));
+        PolicyWriterUtil.writeClassMap(any(ClassMap.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.writePolicyMapEntry(any(Class.class), any(PolicyManagerImpl.PolicyMapLocation.class));
     }
 
     @Test
@@ -288,31 +290,34 @@ public class ServiceChainingUtilTest {
         final PolicyConfigurationContext context = policyConfigurationContextBuilder();
 
         stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(pathsBuilder.build());
-        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(buildRsp(null));
-        stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(new TenantId(TENANT_ID));
+        stub(method(PolicyWriterUtil.class, "writeClassMap")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "writePolicyMapEntry")).toReturn(true);
 
-        ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, In), context, dataBroker);
+        ServiceChainingUtil.newChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
+                resolvedActionBuilder(RULE_NAME, CHAIN, action, In), context, dataBroker);
 
-        verify(policyWriter).cache(any(ClassMap.class));
-        verify(policyWriter).cache(any(Class.class));
-        verifyNoMoreInteractions(policyWriter);
-        verifyNoMoreInteractions(dataBroker);
+        verifyStatic(times(1));
+        PolicyWriterUtil.writeClassMap(any(ClassMap.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.writePolicyMapEntry(any(Class.class), any(PolicyManagerImpl.PolicyMapLocation.class));
     }
 
     @Test
     public void testResolveRemovedChainAction_noParameterValue() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final PeerEndpoint peerEndpoint = peerEndpointBuilder();
         final Action action = actionBuilder(null);
 
         ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, In), policyWriter);
+                resolvedActionBuilder(new RuleName("rule-name"), CHAIN, action, In), context);
 
-        verifyNoMoreInteractions(policyWriter);
+        verifyNoMoreInteractions(policyWriterUtil);
     }
 
     @Test
     public void testResolveRemovedChainAction_noTenantId() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ParameterValueBuilder parameterValueBuilder = new ParameterValueBuilder();
         parameterValueBuilder.setName(new ParameterName(SFC_CHAIN_NAME)).setStringValue(SFC_CHAIN_NAME);
         final ParameterValue parameterValue = parameterValueBuilder.build();
@@ -329,13 +334,15 @@ public class ServiceChainingUtilTest {
         stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(null);
 
         ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, In), policyWriter);
+                resolvedActionBuilder(new RuleName("rule-name"), CHAIN, action, In), context);
 
-        verifyNoMoreInteractions(policyWriter);
+        verifyNoMoreInteractions(policyWriterUtil);
     }
 
     @Test
     public void testResolveRemovedChainAction_asymmetricChainOpposite() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ParameterValueBuilder parameterValueBuilder = new ParameterValueBuilder();
         parameterValueBuilder.setName(new ParameterName(SFC_CHAIN_NAME)).setStringValue(SFC_CHAIN_NAME);
         final ParameterValue parameterValue = parameterValueBuilder.build();
@@ -353,13 +360,15 @@ public class ServiceChainingUtilTest {
         stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(new TenantId(TENANT_ID));
 
         ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, In), policyWriter);
+                resolvedActionBuilder(new RuleName("rule-name"), CHAIN, action, In), context);
 
-        verifyNoMoreInteractions(policyWriter);
+        verifyNoMoreInteractions(policyWriterUtil);
     }
 
     @Test
     public void testResolveRemovedChainAction_asymmetricChainDirect() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ParameterValueBuilder parameterValueBuilder = new ParameterValueBuilder();
         parameterValueBuilder.setName(new ParameterName(SFC_CHAIN_NAME)).setStringValue(SFC_CHAIN_NAME);
         final ParameterValue parameterValue = parameterValueBuilder.build();
@@ -372,29 +381,30 @@ public class ServiceChainingUtilTest {
         final Action action = actionBuilder(Collections.singletonList(parameterValue));
         final RenderedServicePathHopBuilder hopBuilder = new RenderedServicePathHopBuilder();
         hopBuilder.setServiceFunctionForwarder(new SffName(SERVICE_FUNCTION_FORWARDER));
-        final List<RenderedServicePathHop> hops = Collections.singletonList(hopBuilder.build());
         final ServiceFunctionForwarderBuilder forwarder = new ServiceFunctionForwarderBuilder();
         forwarder.setName(new SffName(SERVICE_FUNCTION_FORWARDER))
                 .setIpMgmtAddress(new IpAddress(new Ipv4Address(IP_ADDRESS)));
 
         stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(pathsBuilder.build());
-        stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder")).toReturn(forwarder.build());
-        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(buildRsp(hops));
-        stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(new TenantId(TENANT_ID));
+        stub(method(PolicyWriterUtil.class, "removeClassMap")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removePolicyMapEntry")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removeServicePath")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removeRemote")).toReturn(true);
 
         ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, Out), policyWriter);
+                resolvedActionBuilder(new RuleName("rule-name"), CHAIN, action, Out), context);
 
-        verify(policyWriter).cache(any(ClassMap.class));
-        verify(policyWriter).cache(any(Class.class));
-        verify(policyWriter).getManagementIpAddress();
-        verify(policyWriter).cache(any(ServiceChain.class));
-        verify(policyWriter).cache(any(ServiceFfName.class));
-        verifyNoMoreInteractions(policyWriter);
+        verifyStatic(times(1));
+        PolicyWriterUtil.removeClassMap(any(ClassMap.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removePolicyMapEntry(any(Class.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removeServicePath(any(ServiceChain.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removeRemote(any(ServiceFfName.class), any(PolicyManagerImpl.PolicyMapLocation.class));
     }
 
     @Test
     public void testResolveRemovedChainAction_symmetricChainDirect() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ParameterValueBuilder parameterValueBuilder = new ParameterValueBuilder();
         parameterValueBuilder.setName(new ParameterName(SFC_CHAIN_NAME)).setStringValue(SFC_CHAIN_NAME);
         final ParameterValue parameterValue = parameterValueBuilder.build();
@@ -407,29 +417,30 @@ public class ServiceChainingUtilTest {
         final Action action = actionBuilder(Collections.singletonList(parameterValue));
         final RenderedServicePathHopBuilder hopBuilder = new RenderedServicePathHopBuilder();
         hopBuilder.setServiceFunctionForwarder(new SffName(SERVICE_FUNCTION_FORWARDER));
-        final List<RenderedServicePathHop> hops = Collections.singletonList(hopBuilder.build());
         final ServiceFunctionForwarderBuilder forwarder = new ServiceFunctionForwarderBuilder();
         forwarder.setName(new SffName(SERVICE_FUNCTION_FORWARDER))
                 .setIpMgmtAddress(new IpAddress(new Ipv4Address(IP_ADDRESS)));
 
         stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(pathsBuilder.build());
-        stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder")).toReturn(forwarder.build());
-        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(buildRsp(hops));
-        stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(new TenantId(TENANT_ID));
+        stub(method(PolicyWriterUtil.class, "removeClassMap")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removePolicyMapEntry")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removeServicePath")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removeRemote")).toReturn(true);
 
         ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, Out), policyWriter);
+                resolvedActionBuilder(new RuleName("rule-name"), CHAIN, action, Out), context);
 
-        verify(policyWriter).cache(any(ClassMap.class));
-        verify(policyWriter).cache(any(Class.class));
-        verify(policyWriter).getManagementIpAddress();
-        verify(policyWriter).cache(any(ServiceChain.class));
-        verify(policyWriter).cache(any(ServiceFfName.class));
-        verifyNoMoreInteractions(policyWriter);
+        verifyStatic(times(1));
+        PolicyWriterUtil.removeClassMap(any(ClassMap.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removePolicyMapEntry(any(Class.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removeServicePath(any(ServiceChain.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removeRemote(any(ServiceFfName.class), any(PolicyManagerImpl.PolicyMapLocation.class));
     }
 
     @Test
     public void testResolveRemovedChainAction_symmetricChainReversed() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ParameterValueBuilder parameterValueBuilder = new ParameterValueBuilder();
         parameterValueBuilder.setName(new ParameterName(SFC_CHAIN_NAME)).setStringValue(SFC_CHAIN_NAME);
         final ParameterValue parameterValue = parameterValueBuilder.build();
@@ -442,35 +453,38 @@ public class ServiceChainingUtilTest {
         final Action action = actionBuilder(Collections.singletonList(parameterValue));
         final RenderedServicePathHopBuilder hopBuilder = new RenderedServicePathHopBuilder();
         hopBuilder.setServiceFunctionForwarder(new SffName(SERVICE_FUNCTION_FORWARDER));
-        final List<RenderedServicePathHop> hops = Collections.singletonList(hopBuilder.build());
         final ServiceFunctionForwarderBuilder forwarder = new ServiceFunctionForwarderBuilder();
         forwarder.setName(new SffName(SERVICE_FUNCTION_FORWARDER))
                 .setIpMgmtAddress(new IpAddress(new Ipv4Address(IP_ADDRESS)));
 
         stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(pathsBuilder.build());
-        stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder")).toReturn(forwarder.build());
-        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(buildRsp(hops));
-        stub(method(PolicyManagerUtil.class, "getTenantId")).toReturn(new TenantId(TENANT_ID));
+        stub(method(PolicyWriterUtil.class, "removeClassMap")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removePolicyMapEntry")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removeServicePath")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "removeRemote")).toReturn(true);
 
         ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sgtBuilder(10), sgtBuilder(20),
-                resolvedActionBuilder(CHAIN, action, In), policyWriter);
+                resolvedActionBuilder(new RuleName("rule-name"), CHAIN, action, In), context);
 
-        verify(policyWriter).cache(any(ClassMap.class));
-        verify(policyWriter).cache(any(Class.class));
-        verify(policyWriter).getManagementIpAddress();
-        verify(policyWriter).cache(any(ServiceChain.class));
-        verify(policyWriter).cache(any(ServiceFfName.class));
-        verifyNoMoreInteractions(policyWriter);
+        verifyStatic(times(1));
+        PolicyWriterUtil.removeClassMap(any(ClassMap.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removePolicyMapEntry(any(Class.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removeServicePath(any(ServiceChain.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.removeRemote(any(ServiceFfName.class), any(PolicyManagerImpl.PolicyMapLocation.class));
     }
 
     @Test
     public void testResolveRemoteSfcComponents_noForwarder() {
-        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(buildRsp(null), policyWriter);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
+        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(buildRsp(), context);
         assertFalse(result);
     }
 
     @Test
     public void testResolveRemoteSfcComponents_noForwarderLocator() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ServiceFunctionForwarderBuilder forwarderBuilder = new ServiceFunctionForwarderBuilder();
         forwarderBuilder.setName(new SffName(SERVICE_FUNCTION_FORWARDER));
         final RenderedServicePathHopBuilder hopBuilder = new RenderedServicePathHopBuilder();
@@ -480,13 +494,14 @@ public class ServiceChainingUtilTest {
 
         stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder")).toReturn(forwarderBuilder.build());
 
-        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), policyWriter);
+        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), context);
         assertFalse(result);
-        verifyZeroInteractions(policyWriter);
     }
 
     @Test
     public void testResolveRemoteSfcComponents_dplWithoutLocatorType() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final DataPlaneLocatorBuilder dplBuilder = new DataPlaneLocatorBuilder();
         final SffDataPlaneLocatorBuilder sffDplBuilder = new SffDataPlaneLocatorBuilder();
         sffDplBuilder.setDataPlaneLocator(dplBuilder.build());
@@ -500,13 +515,14 @@ public class ServiceChainingUtilTest {
 
         stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder")).toReturn(forwarderBuilder.build());
 
-        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), policyWriter);
+        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), context);
         assertFalse(result);
-        verifyZeroInteractions(policyWriter);
     }
 
     @Test
     public void testResolveRemoteSfcComponents_dplWithoutIp() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final DataPlaneLocatorBuilder dplBuilder = new DataPlaneLocatorBuilder();
         dplBuilder.setLocatorType(new IpBuilder().build());
         final SffDataPlaneLocatorBuilder sffDplBuilder = new SffDataPlaneLocatorBuilder();
@@ -521,13 +537,14 @@ public class ServiceChainingUtilTest {
 
         stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder")).toReturn(forwarderBuilder.build());
 
-        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), policyWriter);
+        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), context);
         assertFalse(result);
-        verifyZeroInteractions(policyWriter);
     }
 
     @Test
     public void testResolveRemoteSfcComponents_sffWithoutMgmtAddress() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final DataPlaneLocatorBuilder dplBuilder = new DataPlaneLocatorBuilder();
         dplBuilder.setLocatorType(new IpBuilder().setIp(new IpAddress(new Ipv4Address(IP_ADDRESS))).build());
         final SffDataPlaneLocatorBuilder sffDplBuilder = new SffDataPlaneLocatorBuilder();
@@ -542,13 +559,14 @@ public class ServiceChainingUtilTest {
 
         stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder")).toReturn(forwarderBuilder.build());
 
-        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), policyWriter);
+        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), context);
         assertFalse(result);
-        verifyZeroInteractions(policyWriter);
     }
 
     @Test
     public void testResolveRemoteSfcComponents_remoteCase() {
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final DataPlaneLocatorBuilder dplBuilder = new DataPlaneLocatorBuilder();
         dplBuilder.setLocatorType(new IpBuilder().setIp(new IpAddress(new Ipv4Address("190.1.1.12"))).build());
         final SffDataPlaneLocatorBuilder sffDplBuilder = new SffDataPlaneLocatorBuilder();
@@ -563,13 +581,14 @@ public class ServiceChainingUtilTest {
         rspBuilder.setRenderedServicePathHop(Collections.singletonList(hopBuilder.build()));
 
         stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder")).toReturn(forwarderBuilder.build());
+        stub(method(PolicyWriterUtil.class, "writeServicePath")).toReturn(true);
+        stub(method(PolicyWriterUtil.class, "writeRemote")).toReturn(true);
 
-        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), policyWriter);
+        boolean result = ServiceChainingUtil.resolveRemoteSfcComponents(rspBuilder.build(), context);
         assertTrue(result);
-        verify(policyWriter).getManagementIpAddress();
-        verify(policyWriter).cache(any(ServiceChain.class));
-        verify(policyWriter).cache(any(ServiceFfName.class));
-        verifyNoMoreInteractions(policyWriter);
+        verifyStatic(times(1));
+        PolicyWriterUtil.writeServicePath(any(ServiceChain.class), any(PolicyManagerImpl.PolicyMapLocation.class));
+        PolicyWriterUtil.writeRemote(any(ServiceFfName.class), any(PolicyManagerImpl.PolicyMapLocation.class));
     }
 
     @Test
@@ -669,6 +688,10 @@ public class ServiceChainingUtilTest {
 
     @Test
     public void testCreateRenderedPath_renderedPathFound() {
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ServiceFunctionPathBuilder serviceFunctionPathBuilder = new ServiceFunctionPathBuilder();
         serviceFunctionPathBuilder.setName(new SfpName(SFC_PATH_NAME))
                 .setSymmetric(true);
@@ -677,13 +700,18 @@ public class ServiceChainingUtilTest {
 
         stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(new RenderedServicePathBuilder().build());
 
-        final RenderedServicePath result = ServiceChainingUtil.createRenderedPath(serviceFunctionPath, tenantId, dataBroker);
+        final RenderedServicePath result = ServiceChainingUtil.resolveRenderedServicePath(serviceFunctionPath, tenantId,
+                dataBroker, sourceSgt, destinationSgt, context);
         assertNotNull(result);
     }
 
     @Test
     public void testCreateRenderedPath_renderedPathCreated() {
         ServiceChainingUtil.setTimeout(1L);
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ServiceFunctionPathBuilder serviceFunctionPathBuilder = new ServiceFunctionPathBuilder();
         serviceFunctionPathBuilder.setName(new SfpName(SFC_PATH_NAME))
                 .setSymmetric(true);
@@ -694,12 +722,17 @@ public class ServiceChainingUtilTest {
         stub(method(SfcProviderRenderedPathAPI.class, "createRenderedServicePathAndState", ServiceFunctionPath.class,
                 CreateRenderedPathInput.class)).toReturn(new RenderedServicePathBuilder().build());
 
-        final RenderedServicePath result = ServiceChainingUtil.createRenderedPath(serviceFunctionPath, tenantId, dataBroker);
+        final RenderedServicePath result = ServiceChainingUtil.resolveRenderedServicePath(serviceFunctionPath, tenantId,
+                dataBroker, sourceSgt, destinationSgt, context);
         assertNotNull(result);
     }
 
     @Test
     public void testCreateReversedRenderedPath_renderedPathFound() {
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ServiceFunctionPathBuilder serviceFunctionPathBuilder = new ServiceFunctionPathBuilder();
         serviceFunctionPathBuilder.setName(new SfpName(SFC_PATH_NAME))
                 .setSymmetric(true);
@@ -708,27 +741,30 @@ public class ServiceChainingUtilTest {
 
         stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(new RenderedServicePathBuilder().build());
 
-        final RenderedServicePath result = ServiceChainingUtil.createReversedRenderedPath(serviceFunctionPath, null,
-                tenantId, dataBroker);
+        final RenderedServicePath result = ServiceChainingUtil.resolveReversedRenderedServicePath(serviceFunctionPath,
+                tenantId, dataBroker, sourceSgt, destinationSgt, context);
         assertNotNull(result);
     }
 
     @Test
     public void testCreateReversedRenderedPath_renderedPathCreated() {
         ServiceChainingUtil.setTimeout(1L);
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
         final ServiceFunctionPathBuilder serviceFunctionPathBuilder = new ServiceFunctionPathBuilder();
         serviceFunctionPathBuilder.setName(new SfpName(SFC_PATH_NAME))
                 .setSymmetric(true);
         final ServiceFunctionPath serviceFunctionPath = serviceFunctionPathBuilder.build();
         final TenantId tenantId = new TenantId(TENANT_ID);
-        final RenderedServicePath renderedServicePath = new RenderedServicePathBuilder().build();
 
         stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(null);
         stub(method(SfcProviderRenderedPathAPI.class, "createReverseRenderedServicePathEntry"))
                 .toReturn(new RenderedServicePathBuilder().build());
 
-        final RenderedServicePath result = ServiceChainingUtil.createReversedRenderedPath(serviceFunctionPath, renderedServicePath,
-                tenantId, dataBroker);
+        final RenderedServicePath result = ServiceChainingUtil.resolveReversedRenderedServicePath(serviceFunctionPath,
+                tenantId, dataBroker, sourceSgt, destinationSgt, context);
         assertNotNull(result);
     }
 
@@ -745,7 +781,6 @@ public class ServiceChainingUtilTest {
         assertEquals(testForwarder, result);
     }
 
-
     @Test
     public void testGetServicePath() throws Exception {
         final String sfcNameValue = "123";
@@ -771,13 +806,18 @@ public class ServiceChainingUtilTest {
         final String sfcNameValue = "123";
         final ServiceFunctionPath sfp = createSfp(sfcNameValue);
         final TenantId tenantId = new TenantId("unit-tenant-01");
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
 
         final RenderedServicePath rsp = createRsp("unit-rsp-01");
 
         PowerMockito.mockStatic(SfcProviderRenderedPathAPI.class);
         PowerMockito.when(SfcProviderRenderedPathAPI.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(rsp);
 
-        final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(sfp, tenantId, dataBroker);
+        final RenderedServicePath renderedPath = ServiceChainingUtil.resolveRenderedServicePath(sfp, tenantId,
+                dataBroker, sourceSgt, destinationSgt, context);
 
         assertEquals("123_plain-unit-tenant-01-gbp-rsp", rspNameCaptor.getValue().getValue());
         assertEquals(rsp, renderedPath);
@@ -788,11 +828,18 @@ public class ServiceChainingUtilTest {
         final ServiceFunctionPath sfp = createSfp("unit-sfp-02");
         final RenderedServicePath rsp = createRsp("unit-rsp-02");
         final TenantId tenantId = new TenantId("tenant-02");
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setPolicyMapLocation(getLocation());
 
         PowerMockito.mockStatic(SfcProviderRenderedPathAPI.class);
         PowerMockito.when(SfcProviderRenderedPathAPI.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(rsp);
+        stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder"))
+                .toReturn(new ServiceFunctionForwarderBuilder().setName(new SffName("sff-name")).build());
 
-        final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createReversedRenderedPath(sfp, rsp, tenantId, dataBroker);
+        final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.resolveReversedRenderedServicePath(sfp,
+                tenantId, dataBroker, sourceSgt, destinationSgt, context);
 
         assertEquals("unit-sfp-02_plain-tenant-02-gbp-rsp-Reverse", rspNameCaptor.getValue().getValue());
         assertEquals(rsp, symmetricRenderedPath);
@@ -814,9 +861,9 @@ public class ServiceChainingUtilTest {
 
     // Auxiliary methods
 
-    private RenderedServicePath buildRsp(List<RenderedServicePathHop> hop) {
+    private RenderedServicePath buildRsp() {
         RenderedServicePathBuilder renderedServicePathBuilder = new RenderedServicePathBuilder();
-        renderedServicePathBuilder.setRenderedServicePathHop(hop);
+        renderedServicePathBuilder.setRenderedServicePathHop(null);
         return renderedServicePathBuilder.build();
     }
 
@@ -850,17 +897,17 @@ public class ServiceChainingUtilTest {
         return peerEndpointBuilder.build();
     }
 
-    private Map<ActionCase, ActionInDirection> resolvedActionBuilder(@Nonnull final ActionCase actionCase,
+    private Map<ActionCase, ActionInDirection> resolvedActionBuilder(@Nonnull final RuleName ruleName,
+                                                                     @Nonnull final ActionCase actionCase,
                                                                      @Nonnull final Action action,
                                                                      @Nonnull final Direction direction) {
-        final ActionInDirection actionInDirection = new ActionInDirection(action, PROVIDER, direction);
+        final ActionInDirection actionInDirection = new ActionInDirection(ruleName, action, PROVIDER, direction);
         return Collections.singletonMap(actionCase, actionInDirection);
     }
 
     private PolicyConfigurationContext policyConfigurationContextBuilder() {
         final RendererEndpointBuilder rendererEndpointBuilder = new RendererEndpointBuilder();
         final PolicyConfigurationContext context = new PolicyConfigurationContext();
-        context.setPolicyWriter(policyWriter);
         context.setCurrentRendererEP(rendererEndpointBuilder.build());
         return context;
     }
@@ -874,4 +921,12 @@ public class ServiceChainingUtilTest {
         actionBuilder.setParameterValue(parameters);
         return actionBuilder.build();
     }
+
+    private PolicyManagerImpl.PolicyMapLocation getLocation() {
+        final String POLICY_MAP = "policy-map";
+        final String INTERFACE = "interface";
+        final NodeId nodeId = new NodeId("node-id");
+        final String IP_ADDRESS = "ip-address";
+        return new PolicyManagerImpl.PolicyMapLocation(POLICY_MAP, INTERFACE, nodeId, IP_ADDRESS, dataBroker);
+    }
 }
\ No newline at end of file
index 9b1fdb02207d387db0429d2f2d52a4ae467768fe..569021d3ae637e7eaf9ca8f4ee6c8fd71d72c2e7 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.P
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
@@ -27,6 +28,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.UnconfiguredRuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.unconfigured.rule.group.UnconfiguredResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.unconfigured.rule.groups.unconfigured.rule.group.UnconfiguredResolvedRuleBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpoint;
@@ -39,14 +42,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
  */
 public class StatusUtilTest {
 
-    public static final TenantId TENANT_ID = new TenantId("unit-tenant-1");
-    public static final SubjectName SUBJECT_NAME = new SubjectName("unit-subject-1");
-    public static final ContractId CONTRACT_ID = new ContractId("unit-contract-1");
-    public static final String ADDRESS_1 = "unit-address-1";
-    public static final ContextId CONTEXT_ID_1 = new ContextId("unit-context-1");
-    public static final String ADDRESS_2 = "unit-address-2";
-    public static final ContextId CONTEXT_ID_2 = new ContextId("unit-context-2");
-    public static final String INFO_MESSAGE = "unit-info-1";
+    private static final TenantId TENANT_ID = new TenantId("unit-tenant-1");
+    private static final SubjectName SUBJECT_NAME = new SubjectName("unit-subject-1");
+    private static final ContractId CONTRACT_ID = new ContractId("unit-contract-1");
+    private static final String ADDRESS_1 = "unit-address-1";
+    private static final ContextId CONTEXT_ID_1 = new ContextId("unit-context-1");
+    private static final String ADDRESS_2 = "unit-address-2";
+    private static final ContextId CONTEXT_ID_2 = new ContextId("unit-context-2");
+    private static final String INFO_MESSAGE = "unit-info-1";
     private PolicyConfigurationContext context;
 
     @Before
@@ -117,7 +120,7 @@ public class StatusUtilTest {
     @Test
     public void testAssemblePeerEndpoint() throws Exception {
         final PeerEndpoint peerEndpoint = createPeer(ADDRESS_1, CONTEXT_ID_1);
-        final List<UnconfiguredPeerEndpoint> gatheredPeers = StatusUtil.assemblePeerEndpoint(Stream.of(peerEndpoint));
+        final List<UnconfiguredPeerEndpoint> gatheredPeers = StatusUtil.assemblePeerEndpoint(Stream.of(peerEndpoint), null);
 
         Assert.assertEquals(1, gatheredPeers.size());
         final UnconfiguredPeerEndpoint actual = gatheredPeers.get(0);
@@ -134,6 +137,11 @@ public class StatusUtilTest {
 
     @Test
     public void testAssembleRuleGroups() throws Exception {
+        final UnconfiguredResolvedRuleBuilder unconfiguredResolvedRuleBuilder = new UnconfiguredResolvedRuleBuilder();
+        unconfiguredResolvedRuleBuilder.setRuleName(new RuleName("rule-name"));
+        final UnconfiguredResolvedRule resolvedRule = unconfiguredResolvedRuleBuilder.build();
+        final PolicyConfigurationContext context = new PolicyConfigurationContext();
+        context.setCurrentUnconfiguredRule(resolvedRule);
         final RuleGroupWithRendererEndpointParticipation ruleGroup =
                 new RuleGroupWithRendererEndpointParticipationBuilder()
                         .setTenantId(TENANT_ID)
@@ -141,14 +149,14 @@ public class StatusUtilTest {
                         .setContractId(CONTRACT_ID)
                         .setRendererEndpointParticipation(EndpointPolicyParticipation.CONSUMER)
                         .build();
-        final List<UnconfiguredRuleGroup> gatheredRuleGroups = StatusUtil.assembleRuleGroups(Stream.of(ruleGroup));
+        final List<UnconfiguredRuleGroup> gatheredRuleGroups = StatusUtil.assembleRuleGroups(Stream.of(ruleGroup), context);
 
         Assert.assertEquals(1, gatheredRuleGroups.size());
         final UnconfiguredRuleGroup actual = gatheredRuleGroups.get(0);
         Assert.assertEquals(TENANT_ID, actual.getTenantId());
         Assert.assertEquals(SUBJECT_NAME, actual.getSubjectName());
         Assert.assertEquals(CONTRACT_ID, actual.getContractId());
-        Assert.assertEquals(null, actual.getUnconfiguredResolvedRule());
+        Assert.assertEquals(Collections.singletonList(resolvedRule), actual.getUnconfiguredResolvedRule());
         Assert.assertEquals(EndpointPolicyParticipation.CONSUMER, actual.getRendererEndpointParticipation());
     }
 }
\ No newline at end of file
index 1e5510e148b852826f84e3037020b25905bbdfa8..4b29026973620e43f5b69c7bef637801b01d7b7b 100644 (file)
@@ -24,10 +24,13 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.ServiceChainingUtil;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapBuilder;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChainBuilder;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
@@ -35,6 +38,7 @@ import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassBu
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathBuilder;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfName;
 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.powermock.api.mockito.PowerMockito;
@@ -70,205 +74,175 @@ public class PolicyWriterUtilTest {
     }
 
     @Test
-    public void testWriteClassMaps() throws Exception {
-        LOG.debug("scenario: pass through with null classMapEntries collection");
-        Assert.assertTrue(PolicyWriterUtil.writeClassMaps(null, NODE_ID, dataBroker));
-
-        LOG.debug("scenario: pass through with empty classMapEntries collection");
-        final Set<ClassMap> classMapEntries = new HashSet<>();
-        Assert.assertTrue(PolicyWriterUtil.writeClassMaps(classMapEntries, NODE_ID, dataBroker));
-
+    public void testWriteClassMap() throws Exception {
         LOG.debug("scenario: fail with one entry, no writeOnlyTransaction");
-        classMapEntries.add(new ClassMapBuilder().setName("unit-classMapEntry-name").build());
-        Assert.assertFalse(PolicyWriterUtil.writeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        final ClassMap classMap = new ClassMapBuilder().setName("unit-classMapEntry-name").build();
+        Assert.assertFalse(PolicyWriterUtil.writeClassMap(classMap, getLocation()));
 
         LOG.debug("scenario: fail with one entry, available writeOnlyTransaction, no readOnlyTransaction");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction")).toReturn(wTxOptional);
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
-        Assert.assertFalse(PolicyWriterUtil.writeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.writeClassMap(classMap, getLocation()));
 
         LOG.debug("scenario: succeed with one entry, available writeOnlyTransaction, available readOnlyTransaction");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfReadOnlyTransaction")).toReturn(rTxOptional);
         Mockito.when(rTx.read(Mockito.eq(LogicalDatastoreType.CONFIGURATION), Matchers.<InstanceIdentifier<ClassMap>>any()))
                 .thenReturn(Futures.immediateCheckedFuture(Optional.of(
                         new ClassMapBuilder().setName("asd").build())));
-        Assert.assertTrue(PolicyWriterUtil.writeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.writeClassMap(classMap, getLocation()));
 
         LOG.debug("scenario: fail with one entry, available writeOnlyTransaction, available readOnlyTransaction, check->null");
         PowerMockito.stub(PowerMockito.method(PolicyWriterUtil.class, "netconfRead")).toReturn(null);
-        Assert.assertFalse(PolicyWriterUtil.writeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.writeClassMap(classMap, getLocation()));
     }
 
     @Test
-    public void testRemoveClassMaps() throws Exception {
+    public void testRemoveClassMap() throws Exception {
         LOG.debug("scenario: pass through with null classMapEntries collection");
-        Assert.assertTrue(PolicyWriterUtil.removeClassMaps(null, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.removeClassMap(null, getLocation()));
 
         LOG.debug("scenario: pass through with empty classMapEntries collection");
-        final Set<ClassMap> classMapEntries = new HashSet<>();
-        Assert.assertTrue(PolicyWriterUtil.removeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        final ClassMap classMap = new ClassMapBuilder().setName("unit-classMapEntry-name").build();
+        Assert.assertTrue(PolicyWriterUtil.removeClassMap(classMap, getLocation()));
 
         LOG.debug("scenario: fail with one entry, no writeOnlyTransaction");
-        classMapEntries.add(new ClassMapBuilder().setName("unit-classMapEntry-name").build());
         PowerMockito.stub(PowerMockito.method(PolicyWriterUtil.class, "netconfRead")).toReturn(new ClassBuilder().build());
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction"))
                 .toReturn(java.util.Optional.empty());
-        Assert.assertFalse(PolicyWriterUtil.removeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.removeClassMap(classMap, getLocation()));
 
         LOG.debug("scenario: fail with one entry, available writeOnlyTransaction, no readOnlyTransaction");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction")).toReturn(wTxOptional);
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
-        Assert.assertFalse(PolicyWriterUtil.removeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.removeClassMap(classMap, getLocation()));
 
         LOG.debug("scenario: succeed with one entry, available writeOnlyTransaction, available readOnlyTransaction");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfReadOnlyTransaction")).toReturn(rTxOptional);
         PowerMockito.stub(PowerMockito.method(PolicyWriterUtil.class, "netconfRead")).toReturn(null);
         Mockito.when(rTx.read(Mockito.eq(LogicalDatastoreType.CONFIGURATION), Matchers.<InstanceIdentifier<ClassMap>>any()))
                 .thenReturn(Futures.immediateCheckedFuture(Optional.absent()));
-        Assert.assertTrue(PolicyWriterUtil.removeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.removeClassMap(classMap, getLocation()));
 
         LOG.debug("scenario: fail with one entry, available writeOnlyTransaction, available readOnlyTransaction, check->false");
         PowerMockito.stub(PowerMockito.method(PolicyWriterUtil.class, "netconfRead")).toReturn(new ClassBuilder().build());
-        Assert.assertFalse(PolicyWriterUtil.removeClassMaps(classMapEntries, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.removeClassMap(classMap, getLocation()));
     }
 
     @Test
     public void testWritePolicyMap() throws Exception {
-        final Set<Class> classEntries = new HashSet<>();
-
         LOG.debug("scenario: fail with one entry, no writeOnlyTransaction");
-        classEntries.add(new ClassBuilder().setName(new ClassNameType("unit-classEntry-name")).build());
-        Assert.assertFalse(PolicyWriterUtil.writePolicyMap(POLICY_MAP_NAME, classEntries, NODE_ID, dataBroker));
+        final PolicyMap policyMap = new PolicyMapBuilder().setName("unit-policyMap-name").build();
+        Assert.assertFalse(PolicyWriterUtil.writePolicyMap(policyMap, getLocation()));
 
         LOG.debug("scenario: fail with one entry, available writeOnlyTransaction, no readOnlyTransaction");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction")).toReturn(wTxOptional);
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
-        Assert.assertFalse(PolicyWriterUtil.writePolicyMap(POLICY_MAP_NAME, classEntries, NODE_ID, dataBroker));
-
-        LOG.debug("scenario: fail with null classEntries collection");
-        try {
-            PolicyWriterUtil.writePolicyMap(POLICY_MAP_NAME, null, NODE_ID, dataBroker);
-            Assert.fail("expected NPE caused by classEntries parameter");
-        } catch (Exception e) {
-            // expected
-        }
+        Assert.assertFalse(PolicyWriterUtil.writePolicyMap(policyMap, getLocation()));
 
         LOG.debug("scenario: fail with empty classEntries collection");
-        Assert.assertFalse(PolicyWriterUtil.writePolicyMap(POLICY_MAP_NAME, classEntries, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.writePolicyMap(policyMap, getLocation()));
 
         LOG.debug("scenario: succeed with one entry, available writeOnlyTransaction, available readOnlyTransaction");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfReadOnlyTransaction")).toReturn(rTxOptional);
         Mockito.when(rTx.read(Mockito.eq(LogicalDatastoreType.CONFIGURATION), Matchers.<InstanceIdentifier<ClassMap>>any()))
                 .thenReturn(Futures.immediateCheckedFuture(Optional.of(
                         new ClassMapBuilder().setName("asd").build())));
-        Assert.assertTrue(PolicyWriterUtil.writePolicyMap(POLICY_MAP_NAME, classEntries, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.writePolicyMap(policyMap, getLocation()));
 
         LOG.debug("scenario: fail with one entry, available writeOnlyTransaction, available readOnlyTransaction, check->null");
         PowerMockito.stub(PowerMockito.method(PolicyWriterUtil.class, "netconfRead")).toReturn(null);
-        Assert.assertFalse(PolicyWriterUtil.writePolicyMap(POLICY_MAP_NAME, classEntries, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.writePolicyMap(policyMap, getLocation()));
     }
 
     @Test
-    public void testRemovePolicyMapEntries() throws Exception {
-        LOG.debug("scenario: pass through with null classEntries collection");
-        Assert.assertTrue(PolicyWriterUtil.removePolicyMapEntries(POLICY_MAP_NAME, null, NODE_ID, dataBroker));
-
+    public void testRemovePolicyMapEntry() throws Exception {
         LOG.debug("scenario: pass through with empty classEntries collection");
-        final Set<Class> classEntries = new HashSet<>();
-        Assert.assertTrue(PolicyWriterUtil.removePolicyMapEntries(POLICY_MAP_NAME, classEntries, NODE_ID, dataBroker));
+        final Class entry = new ClassBuilder().setName(new ClassNameType("unit-class-name")).build();
+        Assert.assertTrue(PolicyWriterUtil.removePolicyMapEntry(entry, getLocation()));
 
         LOG.debug("scenario: fail with one entry, no writeOnlyTransaction");
-        classEntries.add(new ClassBuilder().setName(new ClassNameType("unit-classMapEntry-name")).build());
         PowerMockito.stub(PowerMockito.method(PolicyWriterUtil.class, "netconfRead")).toReturn(new ClassBuilder().build());
-        Assert.assertFalse(PolicyWriterUtil.removePolicyMapEntries(POLICY_MAP_NAME, classEntries, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.removePolicyMapEntry(entry, getLocation()));
 
         LOG.debug("scenario: fail with one entry, available writeOnlyTransaction, no readOnlyTransaction");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction")).toReturn(wTxOptional);
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
-        Assert.assertTrue(PolicyWriterUtil.removePolicyMapEntries(POLICY_MAP_NAME, classEntries, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.removePolicyMapEntry(entry, getLocation()));
     }
 
     @Test
     public void testWriteInterface() throws Exception {
         LOG.debug("scenario: fail with no writeOnlyTransaction");
-        final String interfaceName = "unit-interface-1";
-        Assert.assertFalse(PolicyWriterUtil.writeInterface(POLICY_MAP_NAME, interfaceName, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.writeInterface(getLocation()));
 
         LOG.debug("scenario: fail - available writeOnlyTransaction, no submit future");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction")).toReturn(wTxOptional);
-        Assert.assertFalse(PolicyWriterUtil.writeInterface(POLICY_MAP_NAME, interfaceName, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.writeInterface(getLocation()));
 
         LOG.debug("scenario: succeed - available writeOnlyTransaction, available future");
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
-        Assert.assertTrue(PolicyWriterUtil.writeInterface(POLICY_MAP_NAME, interfaceName, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.writeInterface(getLocation()));
     }
 
     @Test
     public void testWriteRemote() throws Exception {
-        LOG.debug("scenario: succeed with null List<ServiceFfName>");
-        Assert.assertTrue(PolicyWriterUtil.writeRemote(null, NODE_ID, dataBroker));
-
         LOG.debug("scenario: succeed with empty List<ServiceFfName>");
-        Assert.assertTrue(PolicyWriterUtil.writeRemote(Collections.emptySet(), NODE_ID, dataBroker));
-
-        LOG.debug("scenario: fail with no writeOnlyTransaction");
-        final Set<ServiceFfName> remotes = Collections.singleton(new ServiceFfNameBuilder().build());
-        Assert.assertFalse(PolicyWriterUtil.writeRemote(remotes, NODE_ID, dataBroker));
+        final ServiceFfName forwarder = new ServiceFfNameBuilder().setName("unit-service-forwarder-name").build();
+        Assert.assertFalse(PolicyWriterUtil.writeRemote(forwarder, getLocation()));
 
         LOG.debug("scenario: fail - available writeOnlyTransaction, no submit future");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction")).toReturn(wTxOptional);
-        Assert.assertFalse(PolicyWriterUtil.writeRemote(remotes, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.writeRemote(forwarder, getLocation()));
 
         LOG.debug("scenario: succeed - available writeOnlyTransaction, available future");
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
-        Assert.assertTrue(PolicyWriterUtil.writeRemote(remotes, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.writeRemote(forwarder, getLocation()));
     }
 
     @Test
-    public void testWriteServicePaths() throws Exception {
-        LOG.debug("scenario: succeed with empty List<remote>");
-        Assert.assertTrue(PolicyWriterUtil.writeServicePaths(Collections.emptySet(), NODE_ID, dataBroker));
-
+    public void testWriteServicePath() throws Exception {
         LOG.debug("scenario: fail with no writeOnlyTransaction");
-        final Set<ServiceChain> serviceChains = Collections.singleton(new ServiceChainBuilder()
+        final ServiceChain serviceChain = new ServiceChainBuilder()
                 .setServicePath(Collections.singletonList(new ServicePathBuilder()
                         .setServicePathId(42L)
                         .build()))
-                .build());
-        Assert.assertFalse(PolicyWriterUtil.writeServicePaths(serviceChains, NODE_ID, dataBroker));
+                .build();
+        Assert.assertFalse(PolicyWriterUtil.writeServicePath(serviceChain, getLocation()));
 
         LOG.debug("scenario: fail - available writeOnlyTransaction, no submit future");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction")).toReturn(wTxOptional);
-        Assert.assertFalse(PolicyWriterUtil.writeServicePaths(serviceChains, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.writeServicePath(serviceChain, getLocation()));
 
         LOG.debug("scenario: succeed - available writeOnlyTransaction, available future");
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
-        Assert.assertTrue(PolicyWriterUtil.writeServicePaths(serviceChains, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.writeServicePath(serviceChain, getLocation()));
     }
 
     @Test
-    public void testRemoveServicePaths() throws Exception {
-        LOG.debug("scenario: succeed with service path present null");
-        Assert.assertTrue(PolicyWriterUtil.removeServicePaths(null, NODE_ID, dataBroker));
-
-        LOG.debug("scenario: succeed with no service path present");
-        Assert.assertTrue(PolicyWriterUtil.removeServicePaths(Collections.emptySet(), NODE_ID, dataBroker));
-
+    public void testRemoveServicePath() throws Exception {
         LOG.debug("scenario: fail with service path present, no writeOnlyTransaction");
         PowerMockito.stub(PowerMockito.method(PolicyWriterUtil.class, "netconfRead")).toReturn(new ClassBuilder().build());
-        final Set<ServiceChain> serviceChains = Collections.singleton(new ServiceChainBuilder()
+        final ServiceChain serviceChain = new ServiceChainBuilder()
                 .setServicePath(Collections.singletonList(new ServicePathBuilder()
                         .setServicePathId(42L)
                         .build()))
-                .build());
-        Assert.assertFalse(PolicyWriterUtil.removeServicePaths(serviceChains, NODE_ID, dataBroker));
+                .build();
+        Assert.assertFalse(PolicyWriterUtil.removeServicePath(serviceChain, getLocation()));
 
         LOG.debug("scenario: fail with service path present, available writeOnlyTransaction, no submit future");
         PowerMockito.stub(PowerMockito.method(NetconfTransactionCreator.class, "netconfWriteOnlyTransaction")).toReturn(wTxOptional);
-        Assert.assertFalse(PolicyWriterUtil.removeServicePaths(serviceChains, NODE_ID, dataBroker));
+        Assert.assertFalse(PolicyWriterUtil.removeServicePath(serviceChain, getLocation()));
 
         LOG.debug("scenario: fail with service path present, available writeOnlyTransaction, available future");
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
-        Assert.assertTrue(PolicyWriterUtil.removeServicePaths(serviceChains, NODE_ID, dataBroker));
+        Assert.assertTrue(PolicyWriterUtil.removeServicePath(serviceChain, getLocation()));
+    }
+
+    private PolicyManagerImpl.PolicyMapLocation getLocation() {
+        final String POLICY_MAP = "policy-map";
+        final String INTERFACE = "interface";
+        final NodeId nodeId = new NodeId("node-id");
+        final String IP_ADDRESS = "ip-address";
+        return new PolicyManagerImpl.PolicyMapLocation(POLICY_MAP, INTERFACE, nodeId, IP_ADDRESS, dataBroker);
     }
 }
\ No newline at end of file