Merge "Tenant selector"
authorMartin Sunal <msunal@cisco.com>
Tue, 21 Jun 2016 14:12:44 +0000 (14:12 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 21 Jun 2016 14:12:44 +0000 (14:12 +0000)
87 files changed:
features/pom.xml
features/src/main/features/features.xml
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/NeutronMapper.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSecurityGroupAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/SecRuleEntityDecoder.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/SecRuleNameDecoder.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/SecurityRuleUtils.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronRouterAwareDataStoreTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSecurityGroupAwareDataStoreTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/NeutronSecurityRuleAwareDataStoreTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/NeutronSecurityRuleAwareTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/SecRuleEntityDecoderTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/SecRuleNameDecoderTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronEntityFactory.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/PolicyAssert.java
neutron-vpp-mapper/pom.xml
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAware.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NeutronListener.java
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortAware.java [moved from neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/BaseEndpointByPortListener.java with 92% similarity]
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java
neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAwareTest.java [new file with mode: 0644]
neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NeutronListenerTest.java
pom.xml
renderers/ios-xe/pom.xml
renderers/ios-xe/src/main/config/default-config.xml
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/api/manager/PolicyManager.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/IosXeRendererProviderImpl.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/cache/EpPolicyCacheImpl.java [deleted file]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/EpPolicyTemplateBySgtListenerImpl.java [deleted file]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/RendererConfigurationListenerImpl.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/NodeManager.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/manager/PolicyManagerZipImpl.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyMapper.java [deleted file]
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/PolicyWriter.java [deleted file]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/ServiceChainingUtil.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/writer/NodeWriter.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/NodeWriter.java with 99% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/writer/PolicyWriter.java [new file with mode: 0644]
renderers/ios-xe/src/main/yang/netconf/ietf-inet-types.yang [deleted file]
renderers/ios-xe/src/main/yang/netconf/ned.yang
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/cache/EpPolicyCacheImplTest.java [deleted file]
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/EpPolicyTemplateBySgtListenerImplTest.java [deleted file]
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/RendererConfigurationListenerImplTest.java
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/NodeManagerTest.java [new file with mode: 0644]
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImplTest.java [new file with mode: 0644]
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerZipImplTest.java
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/NodeWriterTest.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 [new file with mode: 0644]
renderers/vpp/pom.xml
renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/api/BridgeDomainManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppEndpointLocationProvider.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppNodeListener.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/BridgeDomainManagerImpl.java [deleted file]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImpl.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java
renderers/vpp/src/main/yang/vpp-renderer.yang
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImplTest.java [moved from renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/BridgeDomainManagerImplTest.java with 92% similarity]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java
sxp-mapper/src/main/config/default-config.xml
sxp-mapper/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_mapper/SxpMapperProviderModule.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/ReadableAsyncByKey.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/ReadableByKey.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpEndpointAugmentorImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperProviderImpl.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperReactorImpl.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPPolicyTemplateDaoImpl.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EpPolicyTemplateValueKey.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/cache/EpPolicyTemplateCacheKey.java with 87% similarity]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EpPolicyTemplateValueKeyFactory.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/cache/EpPolicyTemplateCacheKeyFactory.java with 53% similarity]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/MasterDatabaseBindingDaoImpl.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPPolicyTemplateListenerImpl.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/MasterDatabaseBindingListenerImpl.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/EPTemplateUtil.java
sxp-mapper/src/main/yang/sxp-mapper-cfg.yang
sxp-mapper/src/main/yang/sxp-mapper-model.yang
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpEndpointAugmentorImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPPolicyTemplateDaoImplTest.java
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/MasterDatabaseBindingDaoImplTest.java
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPPolicyTemplateListenerImplTest.java
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/MasterDatabaseBindingListenerImplTest.java

index 2bb1d8c3d1573b8439648479c72f0ee6eeacb57b..6d518b44fed2688b9470853f8a597603c8498f3e 100755 (executable)
       <version>${neutron.version}</version>
       <type>xml</type>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.neutron</groupId>
-      <artifactId>dummyprovider</artifactId>
-      <version>${neutron.version}</version>
-    </dependency>
 
     <!-- Faas -->
     <dependency>
index bc6072c93a88d34a4c28c8d1c92161dbb404c043..133ca2ff856a8ffe052f5fb4474fa7d224de15b1 100755 (executable)
         <feature version="${neutron.version}">odl-neutron-service</feature>
         <feature version="${project.version}">odl-groupbasedpolicy-base</feature>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}</bundle>
-        <bundle>mvn:org.opendaylight.neutron/dummyprovider/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/neutron-mapper/{{VERSION}}</bundle>
         <configfile finalname="${config.configfile.directory}/15-l2-l3-domain-extension.xml">mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}/xml/config</configfile>
         <configfile finalname="${config.configfile.directory}/15-neutron-mapper.xml">mvn:org.opendaylight.groupbasedpolicy/neutron-mapper/{{VERSION}}/xml/config</configfile>
index 3309e03e65bfe23516c642a9dedb2212ae84eb8d..207fc3357819479ea344b40f6616515be69e8ed1 100644 (file)
@@ -69,27 +69,27 @@ import com.google.common.collect.PeekingIterator;
 public class NeutronMapper implements DataTreeChangeListener<Neutron>, AutoCloseable {
 
     private final static SecurityRuleBuilder EIG_INGRESS_IPV4_SEC_RULE_BUILDER = new SecurityRuleBuilder()
-        .setId(new Uuid("0a629f80-2408-11e6-b67b-9e71128cae77"))
+        .setUuid(new Uuid("0a629f80-2408-11e6-b67b-9e71128cae77"))
         .setDirection(DirectionIngress.class)
         .setEthertype(EthertypeV4.class)
         .setSecurityGroupId(MappingUtils.EIG_UUID);
     private final static SecurityRuleBuilder EIG_EGRESS_IPV4_SEC_RULE_BUILDER = new SecurityRuleBuilder()
-        .setId(new Uuid("0f1789be-2408-11e6-b67b-9e71128cae77"))
+        .setUuid(new Uuid("0f1789be-2408-11e6-b67b-9e71128cae77"))
         .setDirection(DirectionEgress.class)
         .setEthertype(EthertypeV4.class)
         .setSecurityGroupId(MappingUtils.EIG_UUID);
     private final static SecurityRuleBuilder EIG_INGRESS_IPV6_SEC_RULE_BUILDER = new SecurityRuleBuilder()
-        .setId(new Uuid("139b7f90-2408-11e6-b67b-9e71128cae77"))
+        .setUuid(new Uuid("139b7f90-2408-11e6-b67b-9e71128cae77"))
         .setDirection(DirectionIngress.class)
         .setEthertype(EthertypeV6.class)
         .setSecurityGroupId(MappingUtils.EIG_UUID);
     private final static SecurityRuleBuilder EIG_EGRESS_IPV6_SEC_RULE_BUILDER = new SecurityRuleBuilder()
-        .setId(new Uuid("17517202-2408-11e6-b67b-9e71128cae77"))
+        .setUuid(new Uuid("17517202-2408-11e6-b67b-9e71128cae77"))
         .setDirection(DirectionEgress.class)
         .setEthertype(EthertypeV6.class)
         .setSecurityGroupId(MappingUtils.EIG_UUID);
     private final static SecurityGroupBuilder EIG_SEC_GROUP_BUILDER =
-            new SecurityGroupBuilder().setUuid(MappingUtils.EIG_UUID).setDescription("EXTERNAL_group");
+            new SecurityGroupBuilder().setUuid(MappingUtils.EIG_UUID);
 
     private final NeutronNetworkAware networkAware;
     private final NeutronSecurityGroupAware securityGroupAware;
index 7bd5b1c188da01723a24ddf35ff5e13e61c28459..2b7ed54607d47f3122172f7776408edeeef33123 100644 (file)
@@ -322,7 +322,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
     private AddressEndpointRegBuilder createBasicMacAddrEpInputBuilder(Port port,
             NetworkDomainId networkContainment, @Nullable List<EndpointGroupId> endpointGroupsToAdd) {
         AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
-            .setAddress(port.getMacAddress())
+            .setAddress(port.getMacAddress().getValue())
             .setAddressType(MacAddressType.class)
             .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
             .setContextId(new ContextId(port.getNetworkId().getValue()))
@@ -385,7 +385,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
             Port port) {
         return new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder().setL2Context(
                 new L2BridgeDomainId(port.getNetworkId().getValue()))
-            .setMacAddress(new MacAddress(port.getMacAddress()))
+            .setMacAddress(new MacAddress(port.getMacAddress().getValue()))
             .setTenant(new TenantId(port.getTenantId().getValue()))
             .setTimestamp(System.currentTimeMillis());
     }
@@ -412,7 +412,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
         }
         UniqueId portId = new UniqueId(port.getUuid().getValue());
         EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress(
-                port.getMacAddress()));
+                port.getMacAddress().getValue()));
         LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getUuid()
             .getValue(), port.getDeviceOwner(), epKey);
         EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
@@ -431,7 +431,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
         if (isUnregisteredEndpoint) {
             UniqueId portId = new UniqueId(port.getUuid().getValue());
             EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress(
-                    port.getMacAddress()));
+                    port.getMacAddress().getValue()));
             LOG.trace("Removing Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getUuid()
                 .getValue(), port.getDeviceOwner(), epKey);
             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
@@ -475,10 +475,10 @@ public class NeutronPortAware implements NeutronAware<Port> {
         if (isUnregisteredBaseEndpoint) {
             UniqueId portId = new UniqueId(port.getUuid().getValue());
             EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress(
-                    port.getMacAddress()));
+                    port.getMacAddress().getValue()));
             LOG.trace("Removing Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
                     port.getUuid().getValue(), port.getDeviceOwner(), epKey);
-            PortByBaseEndpointKey portByBaseEndpointKey = new PortByBaseEndpointKey(port.getMacAddress(),
+            PortByBaseEndpointKey portByBaseEndpointKey = new PortByBaseEndpointKey(port.getMacAddress().getValue(),
                     MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
                     NeutronGbpIidFactory.baseEndpointByPortIid(portId), rwTx);
@@ -570,7 +570,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
         UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
         List<AddressEndpointUnreg> list = new ArrayList<>();
         AddressEndpointUnregBuilder addrL2EpUnregBuilder = new AddressEndpointUnregBuilder();
-        addrL2EpUnregBuilder.setAddress(port.getMacAddress())
+        addrL2EpUnregBuilder.setAddress(port.getMacAddress().getValue())
             .setAddressType(MacAddressType.class)
             .setContextId(new ContextId(port.getNetworkId().getValue()))
             .setContextType(MappingUtils.L2_BRDIGE_DOMAIN);
@@ -595,7 +595,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder inputBuilder =
                 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder();
         L2 l2Ep = new L2Builder().setL2Context(new L2BridgeDomainId(port.getNetworkId().getValue()))
-            .setMacAddress(new MacAddress(port.getMacAddress()))
+            .setMacAddress(new MacAddress(port.getMacAddress().getValue()))
             .build();
         inputBuilder.setL2(ImmutableList.of(l2Ep));
         // we've registered EP with only first IP so remove only EP with first IP
index 4fac5829259f30277d1f7b3501dbe29cdbeb7d31..76b9edf6c6e05fd7f0ab029594fc6b5ccb0c9bdc 100644 (file)
@@ -74,15 +74,6 @@ public class NeutronSecurityGroupAware implements NeutronAware<SecurityGroup> {
                 LOG.debug("Name exception", e);
             }
         }
-        if (!Strings.isNullOrEmpty(secGroup.getDescription())) {
-            try {
-                epgBuilder.setDescription(new Description(secGroup.getDescription()));
-            } catch (Exception e) {
-                LOG.info("Description '{}' of Neutron Security-group '{}' is ignored.",
-                        secGroup.getDescription(), secGroup.getUuid().getValue());
-                LOG.debug("Description exception", e);
-            }
-        }
         epgBuilder.setIntraGroupPolicy(IntraGroupPolicy.RequireContract);
         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tId, epgId),
                 epgBuilder.build(), true);
index 2c3037439cd4914dfd243b9e3c86ae57106d1164..9381f5b0a14841e6cff888af3eb88af69469e5ec 100644 (file)
@@ -16,7 +16,6 @@ import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFact
 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
@@ -106,7 +105,7 @@ public class NeutronSubnetAware implements
             org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet subnet,
             IpAddress virtualRouterIp) {
         SubnetBuilder sb = new SubnetBuilder();
-        sb.setIpPrefix(Utils.createIpPrefix(subnet.getCidr()));
+        sb.setIpPrefix(subnet.getCidr());
         sb.setVirtualRouterIp(virtualRouterIp);
         NetworkDomainBuilder ndb = new NetworkDomainBuilder();
         if (!Strings.isNullOrEmpty(subnet.getName())) {
@@ -164,7 +163,7 @@ public class NeutronSubnetAware implements
                 LOG.debug("Name exception", e);
             }
         }
-        subnetBuilder.setIpPrefix(Utils.createIpPrefix(subnet.getCidr()));
+        subnetBuilder.setIpPrefix(subnet.getCidr());
         subnetBuilder.setVirtualRouterIp(virtualRouterIp);
         return subnetBuilder.build();
     }
index 579e858f8843ce5cafd84596523bf4ec029408de..f88d29562c8f76b02e51a5823aab6c8e8e109a39 100755 (executable)
@@ -55,6 +55,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmpV6;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolUdp;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;\r
 \r
 import com.google.common.collect.ImmutableList;\r
@@ -66,7 +67,7 @@ public class SecRuleEntityDecoder {
     }\r
 \r
     public static ContractId getContractId(SecurityRule secRule) {\r
-        return new ContractId(secRule.getId().getValue());\r
+        return new ContractId(secRule.getUuid().getValue());\r
     }\r
 \r
     public static ClassifierInstance getClassifierInstance(SecurityRule secRule) {\r
@@ -243,21 +244,26 @@ public class SecRuleEntityDecoder {
      *         {@link ProtocolUdp}, {@link ProtocolIcmp}, {@link ProtocolIcmpV6}\r
      */\r
     public static Long getProtocol(SecurityRule secRule) {\r
-        Class<? extends ProtocolBase> protocol = secRule.getProtocol();\r
+        SecurityRuleAttributes.Protocol protocol = secRule.getProtocol();\r
         if (protocol == null) {\r
             return null;\r
         }\r
-        if (protocol.isAssignableFrom(ProtocolTcp.class)) {\r
-            return IpProtoClassifierDefinition.TCP_VALUE;\r
+        if (protocol.getUint8() != null) {\r
+            return protocol.getUint8().longValue();\r
         }\r
-        if (protocol.isAssignableFrom(ProtocolUdp.class)) {\r
-            return IpProtoClassifierDefinition.UDP_VALUE;\r
-        }\r
-        if (protocol.isAssignableFrom(ProtocolIcmp.class)) {\r
-            return IpProtoClassifierDefinition.ICMP_VALUE;\r
-        }\r
-        if (protocol.isAssignableFrom(ProtocolIcmpV6.class)) {\r
-            return IpProtoClassifierDefinition.ICMPv6_VALUE;\r
+        if (protocol.getIdentityref() != null) {\r
+            if (protocol.getIdentityref().equals(ProtocolTcp.class)) {\r
+                return IpProtoClassifierDefinition.TCP_VALUE;\r
+            }\r
+            if (protocol.getIdentityref().equals(ProtocolUdp.class)) {\r
+                return IpProtoClassifierDefinition.UDP_VALUE;\r
+            }\r
+            if (protocol.getIdentityref().equals(ProtocolIcmp.class)) {\r
+                return IpProtoClassifierDefinition.ICMP_VALUE;\r
+            }\r
+            if (protocol.getIdentityref().equals(ProtocolIcmpV6.class)) {\r
+                return IpProtoClassifierDefinition.ICMPv6_VALUE;\r
+            }\r
         }\r
         throw new IllegalArgumentException("Neutron Security Rule Protocol value " + protocol + " is not supported.");\r
     }\r
index cfaa2de99fbecb93b8d072eb2f961ea6e843887e..9592c5ec0b1b66bcb4c9baa82cabfbbbf4ce3011 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
 
 public class SecRuleNameDecoder {
@@ -76,14 +77,20 @@ public class SecRuleNameDecoder {
                     .append(portMax.longValue());
             }
         }
-        Class<? extends ProtocolBase> protocol = secRule.getProtocol();
+        SecurityRuleAttributes.Protocol protocol = secRule.getProtocol();
         if (protocol != null) {
             if (keyBuilder.length() > 0) {
                 keyBuilder.append(MappingUtils.NAME_DOUBLE_DELIMETER);
             }
+            String protocolString = "";
+            if (protocol.getUint8() != null) {
+                protocolString = protocol.getUint8().toString();
+            } else if (protocol.getIdentityref() != null) {
+                protocolString = protocol.getIdentityref().getSimpleName();
+            }
             keyBuilder.append(IpProtoClassifierDefinition.DEFINITION.getName().getValue())
                 .append(MappingUtils.NAME_VALUE_DELIMETER)
-                .append(protocol.getSimpleName());
+                .append(protocolString);
         }
         Class<? extends EthertypeBase> ethertype = secRule.getEthertype();
         if (ethertype != null) {
index c96de98ee7cf7e7607b1271223bc5b0c2f5bda3b..b85576306f08da4e89c848f6bc519ed4a26e34f1 100644 (file)
@@ -33,7 +33,7 @@ public class SecurityRuleUtils {
             return Optional.absent();
         }
         for (SecurityRule secRule : securityRules.getSecurityRule()) {
-            if (secRule.getId().equals(uuid)) {
+            if (secRule.getUuid().equals(uuid)) {
                 return Optional.of(secRule);
             }
         }
index a5d1f4d4502828c61ae425932d0b41d4924f9e2c..ce53a0b1c533ecd2f2a4e7eabd9bd132bc02ee8a 100644 (file)
@@ -24,8 +24,10 @@ import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperAssert;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput;
@@ -166,7 +168,7 @@ public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest {
             .setDeviceId("deviceId")
             .setFixedIps(ImmutableList.of(portIpWithSubnet))
             .setNetworkId(networkUuid)
-            .setMacAddress("00:00:00:00:35:02")
+            .setMacAddress(new MacAddress("00:00:00:00:35:02"))
             .build();
         Port neutronPort2 = new PortBuilder().setTenantId(new Uuid(tenantUuid))
             .setFixedIps(ImmutableList.of(portIpWithSubnet))
@@ -176,7 +178,7 @@ public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest {
             .setDeviceOwner(PortUtils.DEVICE_OWNER_DHCP)
             .setFixedIps(ImmutableList.of(portIpWithSubnet))
             .setNetworkId(networkUuid)
-            .setMacAddress("00:00:00:00:35:02")
+            .setMacAddress(new MacAddress("00:00:00:00:35:02"))
             .build();
         Ports neutronPorts = new PortsBuilder().setPort(ImmutableList.of(neutronPort1, neutronPort2)).build();
         when(neutron.getPorts()).thenReturn(neutronPorts);
@@ -229,7 +231,7 @@ public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest {
             .setUuid(portUuid)
             .setDeviceId("deviceId")
             .setNetworkId(networkUuid)
-            .setMacAddress("00:00:00:00:35:02");
+            .setMacAddress(new MacAddress("00:00:00:00:35:02"));
     }
 
     private Subnets createSubnets() {
@@ -237,7 +239,7 @@ public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest {
             .setUuid(subnetUuid)
             .setName("subnetName")
             .setNetworkId(networkUuid)
-            .setCidr("10.0.0.0/24")
+            .setCidr(Utils.createIpPrefix("10.0.0.0/24"))
             .build();
         return new SubnetsBuilder().setSubnet(ImmutableList.of(subnet)).build();
     }
index f7fb7305f951fb77de25346f11ac3f88e3b34ab4..8b4c46190d5c9d134afd42e5ed1bc2be15e8f928 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
@@ -314,7 +315,7 @@ public class NeutronRouterAwareDataStoreTest extends NeutronMapperDataBrokerTest
             .setName("subnetName")
             .setNetworkId(networkUuid)
             .setGatewayIp(ipAddress)
-            .setCidr("10.0.0.0/24")
+            .setCidr(Utils.createIpPrefix("10.0.0.0/24"))
             .build();
         return new SubnetsBuilder().setSubnet(ImmutableList.of(subnet)).build();
     }
index 90fc4ad67c3301dd81dfb21ab6a082ca0dfc3e12..9cc2f53d4ceb7fa9a889572d4e655d7ffba4fd77 100644 (file)
@@ -107,7 +107,6 @@ public class NeutronSecurityGroupAwareDataStoreTest extends NeutronMapperDataBro
         SecurityGroup secGroupA = new SecurityGroupBuilder().setUuid(new Uuid(uuid))
             .setTenantId(new Uuid(tenantId))
             .setName("correctName")
-            .setDescription("correct description")
             .build();
         groupAware.onCreated(secGroupA, null);
 
@@ -121,7 +120,6 @@ public class NeutronSecurityGroupAwareDataStoreTest extends NeutronMapperDataBro
         SecurityGroup secGroupA = new SecurityGroupBuilder().setUuid(new Uuid(uuid))
             .setTenantId(new Uuid(tenantId))
             .setName("123")
-            .setDescription(longDescription)
             .build();
         groupAware.onCreated(secGroupA, null);
 
index 9d3c199983760401578353d2a6f9e83dee45ea4d..0b5606ca5417756fed57f68fa40f67629f5d29cb 100644 (file)
@@ -31,6 +31,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.NeutronBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.SecurityGroupsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRulesBuilder;
@@ -59,17 +60,18 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
                 "dabfd4da-af89-45dd-85f8-181768c1b4c9", tenant, EthertypeV4.class, DirectionEgress.class, goldSecGrp,
                 null);
         String serverSecGrp = "71cf4fe5-b146-409e-8151-cd921298ce32";
-        SecurityRule serverIn80Tcp10_1_1_0 = new SecurityRuleBuilder().setId(new Uuid("9dbb533d-d9b2-4dc9-bae7-ee60c8df184d"))
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        SecurityRule serverIn80Tcp10_1_1_0 = new SecurityRuleBuilder().setUuid(new Uuid("9dbb533d-d9b2-4dc9-bae7-ee60c8df184d"))
                 .setTenantId(new Uuid(tenant))
                 .setEthertype(EthertypeV4.class)
-                .setProtocol(ProtocolTcp.class)
+                .setProtocol(protocolTcp)
                 .setPortRangeMin(80)
                 .setPortRangeMax(80)
                 .setDirection(DirectionIngress.class)
                 .setSecurityGroupId(new Uuid(serverSecGrp))
                 .setRemoteIpPrefix(new IpPrefix(new Ipv4Prefix("10.1.1.0/24")))
                 .build();
-        SecurityRule serverInIp20_1_1_0 = new SecurityRuleBuilder().setId(new Uuid("adf7e558-de47-4f9e-a9b8-96e19db5d1ac"))
+        SecurityRule serverInIp20_1_1_0 = new SecurityRuleBuilder().setUuid(new Uuid("adf7e558-de47-4f9e-a9b8-96e19db5d1ac"))
                 .setTenantId(new Uuid(tenant))
                 .setEthertype(EthertypeV4.class)
                 .setDirection(DirectionIngress.class)
@@ -101,27 +103,27 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
             .get();
         assertTrue(potentialTenant.isPresent());
         Optional<Contract> potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(goldInIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(goldInIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         Contract contract = potentialContract.get();
         PolicyAssert.assertContract(contract, goldInIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(goldOutIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(goldOutIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, goldOutIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(serverOutIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(serverOutIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, serverOutIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(serverIn80Tcp10_1_1_0.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(serverIn80Tcp10_1_1_0.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContractWithEic(contract, serverIn80Tcp10_1_1_0);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(serverInIp20_1_1_0.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(serverInIp20_1_1_0.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContractWithEic(contract, serverInIp20_1_1_0);
@@ -131,19 +133,19 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
         EndpointGroup epg = potentialEpg.get();
         PolicyAssert.assertConsumerNamedSelectors(
                 epg,
-                ImmutableSet.of(new ContractId(goldInIpv4.getId().getValue()),
-                        new ContractId(goldOutIpv4.getId().getValue()),
-                        new ContractId(serverIn80Tcp10_1_1_0.getId().getValue()),
-                        new ContractId(serverInIp20_1_1_0.getId().getValue()),
-                        new ContractId(serverOutIpv4.getId().getValue())));
+                ImmutableSet.of(new ContractId(goldInIpv4.getUuid().getValue()),
+                        new ContractId(goldOutIpv4.getUuid().getValue()),
+                        new ContractId(serverIn80Tcp10_1_1_0.getUuid().getValue()),
+                        new ContractId(serverInIp20_1_1_0.getUuid().getValue()),
+                        new ContractId(serverOutIpv4.getUuid().getValue())));
         potentialEpg = rwTx.read(LogicalDatastoreType.CONFIGURATION,
                 IidFactory.endpointGroupIid(tenantId, new EndpointGroupId(serverSecGrp))).get();
         assertTrue(potentialEpg.isPresent());
         epg = potentialEpg.get();
         PolicyAssert.assertConsumerNamedSelectors(epg, ImmutableSet.of(
-                new ContractId(serverIn80Tcp10_1_1_0.getId().getValue()),
-                new ContractId(serverInIp20_1_1_0.getId().getValue()),
-                new ContractId(goldInIpv4.getId().getValue())));
+                new ContractId(serverIn80Tcp10_1_1_0.getUuid().getValue()),
+                new ContractId(serverInIp20_1_1_0.getUuid().getValue()),
+                new ContractId(goldInIpv4.getUuid().getValue())));
     }
 
     @Test
@@ -281,22 +283,22 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
         ruleAware.addNeutronSecurityRule(serverInIpv4, neutron, rwTx);
         TenantId tenantId = new TenantId(tenant);
         Optional<Contract> potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(goldInIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(goldInIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         Contract contract = potentialContract.get();
         PolicyAssert.assertContract(contract, goldInIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(goldOutIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(goldOutIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, goldOutIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(serverOutIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(serverOutIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, serverOutIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(serverInIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(serverInIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, serverInIpv4);
@@ -306,19 +308,19 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
         EndpointGroup epg = potentialEpg.get();
         PolicyAssert.assertConsumerNamedSelectors(
                 epg,
-                ImmutableSet.of(new ContractId(goldInIpv4.getId().getValue()),
-                        new ContractId(goldOutIpv4.getId().getValue()),
-                        new ContractId(serverOutIpv4.getId().getValue()),
-                        new ContractId(serverInIpv4.getId().getValue())));
+                ImmutableSet.of(new ContractId(goldInIpv4.getUuid().getValue()),
+                        new ContractId(goldOutIpv4.getUuid().getValue()),
+                        new ContractId(serverOutIpv4.getUuid().getValue()),
+                        new ContractId(serverInIpv4.getUuid().getValue())));
         potentialEpg = rwTx.read(LogicalDatastoreType.CONFIGURATION,
                 IidFactory.endpointGroupIid(tenantId, new EndpointGroupId(serverSecGrp))).get();
         assertTrue(potentialEpg.isPresent());
         PolicyAssert.assertConsumerNamedSelectors(
                 epg,
-                ImmutableSet.of(new ContractId(goldInIpv4.getId().getValue()),
-                        new ContractId(goldOutIpv4.getId().getValue()),
-                        new ContractId(serverOutIpv4.getId().getValue()),
-                        new ContractId(serverInIpv4.getId().getValue())));
+                ImmutableSet.of(new ContractId(goldInIpv4.getUuid().getValue()),
+                        new ContractId(goldOutIpv4.getUuid().getValue()),
+                        new ContractId(serverOutIpv4.getUuid().getValue()),
+                        new ContractId(serverInIpv4.getUuid().getValue())));
     }
 
     @Test
@@ -335,10 +337,11 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
         SecurityRule serverOutIpv4 = NeutronEntityFactory.securityRuleWithEtherType(
                 "8b9c48d3-44a8-46be-be35-6f3237d98071", tenant, EthertypeV4.class, DirectionEgress.class, serverSecGrp,
                 null);
-        SecurityRule serverIn80TcpIpv4 = new SecurityRuleBuilder().setId(new Uuid("adf7e558-de47-4f9e-a9b8-96e19db5d1ac"))
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        SecurityRule serverIn80TcpIpv4 = new SecurityRuleBuilder().setUuid(new Uuid("adf7e558-de47-4f9e-a9b8-96e19db5d1ac"))
                 .setTenantId(new Uuid(tenant))
                 .setEthertype(EthertypeV4.class)
-                .setProtocol(ProtocolTcp.class)
+                .setProtocol(protocolTcp)
                 .setPortRangeMin(80)
                 .setPortRangeMax(80)
                 .setDirection(DirectionIngress.class)
@@ -361,22 +364,22 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
         ruleAware.addNeutronSecurityRule(serverIn80TcpIpv4, neutron, rwTx);
         TenantId tenantId = new TenantId(tenant);
         Optional<Contract> potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(goldInIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(goldInIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         Contract contract = potentialContract.get();
         PolicyAssert.assertContract(contract, goldInIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(goldOutIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(goldOutIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, goldOutIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(serverOutIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(serverOutIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, serverOutIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(serverIn80TcpIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(serverIn80TcpIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, serverIn80TcpIpv4);
@@ -386,18 +389,18 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
         EndpointGroup epg = potentialEpg.get();
         PolicyAssert.assertConsumerNamedSelectors(
                 epg,
-                ImmutableSet.of(new ContractId(goldInIpv4.getId().getValue()),
-                        new ContractId(goldOutIpv4.getId().getValue()),
-                        new ContractId(serverOutIpv4.getId().getValue()),
-                        new ContractId(serverIn80TcpIpv4.getId().getValue())));
+                ImmutableSet.of(new ContractId(goldInIpv4.getUuid().getValue()),
+                        new ContractId(goldOutIpv4.getUuid().getValue()),
+                        new ContractId(serverOutIpv4.getUuid().getValue()),
+                        new ContractId(serverIn80TcpIpv4.getUuid().getValue())));
         potentialEpg = rwTx.read(LogicalDatastoreType.CONFIGURATION,
                 IidFactory.endpointGroupIid(tenantId, new EndpointGroupId(serverSecGrp))).get();
         assertTrue(potentialEpg.isPresent());
         epg = potentialEpg.get();
         PolicyAssert.assertConsumerNamedSelectors(
                 epg,
-                ImmutableSet.of(new ContractId(goldInIpv4.getId().getValue()),
-                        new ContractId(serverIn80TcpIpv4.getId().getValue())));
+                ImmutableSet.of(new ContractId(goldInIpv4.getUuid().getValue()),
+                        new ContractId(serverIn80TcpIpv4.getUuid().getValue())));
     }
 
     @Test
@@ -429,22 +432,22 @@ public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrok
         ruleAware.addNeutronSecurityRule(defaultOutIpv6, neutron, rwTx);
         TenantId tenantId = new TenantId(tenant);
         Optional<Contract> potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(defaultInIpv4Default.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(defaultInIpv4Default.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         Contract contract = potentialContract.get();
         PolicyAssert.assertContract(contract, defaultInIpv4Default);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(defaultInIpv6Default.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(defaultInIpv6Default.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, defaultInIpv6Default);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(defaultOutIpv4.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(defaultOutIpv4.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, defaultOutIpv4);
         potentialContract = rwTx.read(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.contractIid(tenantId, new ContractId(defaultOutIpv6.getId().getValue()))).get();
+                IidFactory.contractIid(tenantId, new ContractId(defaultOutIpv6.getUuid().getValue()))).get();
         assertTrue(potentialContract.isPresent());
         contract = potentialContract.get();
         PolicyAssert.assertContract(contract, defaultOutIpv6);
index d824e8a5e050338f4fa5fb6ff558fdf184cc17fe..93ead3bec93376df14ecfc823f260bfcbd170a68 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.NeutronBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.SecurityGroupsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
@@ -84,13 +85,14 @@ public class NeutronSecurityRuleAwareTest extends NeutronMapperDataBrokerTest {
 
     // create neutron security rule
     private SecurityRule buildNeutronSecurityRule() {
-        return new SecurityRuleBuilder().setId(new Uuid(RULE_ID))
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        return new SecurityRuleBuilder().setUuid(new Uuid(RULE_ID))
             .setTenantId(new Uuid(RULE_TENANT_ID))
             .setSecurityGroupId(new Uuid(RULE_GROUP_ID))
             .setRemoteIpPrefix(new IpPrefix(new Ipv4Prefix("192.0.0.1/24")))
             .setPortRangeMin(1000)
             .setPortRangeMax(5000)
-            .setProtocol(ProtocolTcp.class)
+            .setProtocol(protocolTcp)
             .setEthertype(EthertypeV4.class)
             .setDirection(DirectionIngress.class)
             .build();
index 6d5e50d512c438d51b7d245f0f3d88fbbc0a623b..9d98ec36c5981529e525e46fe3bd212ff88a0e97 100644 (file)
@@ -42,6 +42,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolUdp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRuleBuilder;
 
@@ -54,7 +55,7 @@ public class SecRuleEntityDecoderTest {
 
     @Before
     public void setUp() throws Exception {
-        secRuleBuilder = new SecurityRuleBuilder().setId(new Uuid("01234567-abcd-ef01-0123-0123456789ab"));
+        secRuleBuilder = new SecurityRuleBuilder().setUuid(new Uuid("01234567-abcd-ef01-0123-0123456789ab"));
     }
 
     @Test
@@ -86,7 +87,8 @@ public class SecRuleEntityDecoderTest {
     @Test
     public final void testGetClassifierInstance_EthertypeAndProtocol() {
         secRuleBuilder.setEthertype(EthertypeV4.class);
-        secRuleBuilder.setProtocol(ProtocolTcp.class);
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        secRuleBuilder.setProtocol(protocolTcp);
         ClassifierInstance ci = SecRuleEntityDecoder.getClassifierInstance(secRuleBuilder.build());
         Assert.assertEquals(IpProtoClassifierDefinition.DEFINITION.getId(), ci.getClassifierDefinitionId());
         // name is ip_proto_tcp__ether_type_IPv4
@@ -124,7 +126,8 @@ public class SecRuleEntityDecoderTest {
     @Test
     public final void testGetClassifierInstance_EthertypeAndProtocolAndPort() {
         secRuleBuilder.setEthertype(EthertypeV4.class);
-        secRuleBuilder.setProtocol(ProtocolTcp.class);
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        secRuleBuilder.setProtocol(protocolTcp);
         secRuleBuilder.setPortRangeMin(5);
         secRuleBuilder.setPortRangeMax(5);
         ClassifierInstance ci = SecRuleEntityDecoder.getClassifierInstance(secRuleBuilder.build());
@@ -184,7 +187,8 @@ public class SecRuleEntityDecoderTest {
     @Test
     public final void testGetClassifierInstance_EthertypeAndProtocolAndPorts() {
         secRuleBuilder.setEthertype(EthertypeV4.class);
-        secRuleBuilder.setProtocol(ProtocolTcp.class);
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        secRuleBuilder.setProtocol(protocolTcp);
         secRuleBuilder.setPortRangeMin(5);
         secRuleBuilder.setPortRangeMax(10);
         ClassifierInstance ci = SecRuleEntityDecoder.getClassifierInstance(secRuleBuilder.build());
@@ -335,14 +339,16 @@ public class SecRuleEntityDecoderTest {
 
     @Test
     public void testIsProtocolOfOneWithinTwo_oneProtocolTcpTwoProtocolTcp() {
-        SecurityRule one = secRuleBuilder.setProtocol(ProtocolTcp.class).build();
-        SecurityRule two = secRuleBuilder.setProtocol(ProtocolTcp.class).build();
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        SecurityRule one = secRuleBuilder.setProtocol(protocolTcp).build();
+        SecurityRule two = secRuleBuilder.setProtocol(protocolTcp).build();
         assertTrue(SecRuleEntityDecoder.isProtocolOfOneWithinTwo(one, two));
     }
 
     @Test
     public void testIsProtocolOfOneWithinTwo_oneProtocolTcpTwoProtocolNull() {
-        SecurityRule one = secRuleBuilder.setProtocol(ProtocolTcp.class).build();
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        SecurityRule one = secRuleBuilder.setProtocol(protocolTcp).build();
         SecurityRule two = secRuleBuilder.setProtocol(null).build();
         assertTrue(SecRuleEntityDecoder.isProtocolOfOneWithinTwo(one, two));
     }
@@ -356,15 +362,18 @@ public class SecRuleEntityDecoderTest {
 
     @Test
     public void testIsProtocolOfOneWithinTwo_oneProtocolTcpTwoProtocolUdp() {
-        SecurityRule one = secRuleBuilder.setProtocol(ProtocolTcp.class).build();
-        SecurityRule two = secRuleBuilder.setProtocol(ProtocolUdp.class).build();
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        SecurityRule one = secRuleBuilder.setProtocol(protocolTcp).build();
+        SecurityRuleAttributes.Protocol protocolUdp = new SecurityRuleAttributes.Protocol(ProtocolUdp.class);
+        SecurityRule two = secRuleBuilder.setProtocol(protocolUdp).build();
         assertFalse(SecRuleEntityDecoder.isProtocolOfOneWithinTwo(one, two));
     }
 
     @Test
     public void testIsProtocolOfOneWithinTwo_oneProtocolNullTwoProtocolTcp() {
         SecurityRule one = secRuleBuilder.setProtocol(null).build();
-        SecurityRule two = secRuleBuilder.setProtocol(ProtocolTcp.class).build();
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        SecurityRule two = secRuleBuilder.setProtocol(protocolTcp).build();
         assertFalse(SecRuleEntityDecoder.isProtocolOfOneWithinTwo(one, two));
     }
 
@@ -458,19 +467,22 @@ public class SecRuleEntityDecoderTest {
 
     @Test
     public final void testGetProtocol_protoTcp() {
-        secRuleBuilder.setProtocol(ProtocolTcp.class);
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        secRuleBuilder.setProtocol(protocolTcp);
         Assert.assertEquals(IpProtoClassifierDefinition.TCP_VALUE, SecRuleEntityDecoder.getProtocol(secRuleBuilder.build()));
     }
 
     @Test
     public final void testGetProtocol_protoUdp() {
-        secRuleBuilder.setProtocol(ProtocolUdp.class);
+        SecurityRuleAttributes.Protocol protocolUdp = new SecurityRuleAttributes.Protocol(ProtocolUdp.class);
+        secRuleBuilder.setProtocol(protocolUdp);
         Assert.assertEquals(IpProtoClassifierDefinition.UDP_VALUE, SecRuleEntityDecoder.getProtocol(secRuleBuilder.build()));
     }
 
     @Test
     public final void testGetProtocol_protoIcmp() {
-        secRuleBuilder.setProtocol(ProtocolIcmp.class);
+        SecurityRuleAttributes.Protocol protocolIcmp = new SecurityRuleAttributes.Protocol(ProtocolIcmp.class);
+        secRuleBuilder.setProtocol(protocolIcmp);
         Assert.assertEquals(IpProtoClassifierDefinition.ICMP_VALUE, SecRuleEntityDecoder.getProtocol(secRuleBuilder.build()));
     }
 
@@ -482,7 +494,8 @@ public class SecRuleEntityDecoderTest {
 
     @Test
     public final void testGetProtocol_protoUnknown() {
-        secRuleBuilder.setProtocol(UnknownProtocol.class);
+        SecurityRuleAttributes.Protocol protocolUnknown = new SecurityRuleAttributes.Protocol(UnknownProtocol.class);
+        secRuleBuilder.setProtocol(protocolUnknown);
         thrown.expect(IllegalArgumentException.class);
         SecRuleEntityDecoder.getProtocol(secRuleBuilder.build());
     }
index 482d283afa57d3369c223aed919bfcaf96171c41..6e77ba096633687eb64b28b782a14fcedd43f52e 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionIngress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV4;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRuleBuilder;
 
 public class SecRuleNameDecoderTest {
@@ -25,7 +26,7 @@ public class SecRuleNameDecoderTest {
 
     @Before
     public void setUp() throws Exception {
-        secRule = new SecurityRuleBuilder().setId(new Uuid("01234567-abcd-ef01-0123-0123456789ab"));
+        secRule = new SecurityRuleBuilder().setUuid(new Uuid("01234567-abcd-ef01-0123-0123456789ab"));
     }
 
     @Test
@@ -45,7 +46,8 @@ public class SecRuleNameDecoderTest {
     public final void testGetClassifierInstanceName() {
         secRule.setDirection(DirectionIngress.class);
         secRule.setEthertype(EthertypeV4.class);
-        secRule.setProtocol(ProtocolTcp.class);
+        SecurityRuleAttributes.Protocol protocolTcp = new SecurityRuleAttributes.Protocol(ProtocolTcp.class);
+        secRule.setProtocol(protocolTcp);
         secRule.setPortRangeMin(8010);
         secRule.setPortRangeMax(8020);
         StringBuilder frmtBuilder = new StringBuilder();
@@ -66,7 +68,7 @@ public class SecRuleNameDecoderTest {
             .append(EtherTypeClassifierDefinition.DEFINITION.getName().getValue())
             .append(MappingUtils.NAME_VALUE_DELIMETER)
             .append("%s");
-        String frmtClsfName = String.format(frmtBuilder.toString(), 8010, 8020, secRule.getProtocol().getSimpleName(),
+        String frmtClsfName = String.format(frmtBuilder.toString(), 8010, 8020, secRule.getProtocol().getIdentityref().getSimpleName(),
                 secRule.getEthertype().getSimpleName());
         ClassifierName expectedClsfInstanceName = new ClassifierName(frmtClsfName);
         assertEquals(expectedClsfInstanceName, SecRuleNameDecoder.getClassifierInstanceName(secRule.build()));
index b4f3392b6a9e8b47183f0a5e98eb8adbc6d9e383..69418b0f65abd7e0afa8cedbba499c47d14a4fce 100644 (file)
@@ -4,6 +4,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
@@ -27,12 +28,13 @@ public final class NeutronEntityFactory {
 
     public static SecurityRule securityRuleWithoutGroupIds(String id, String tenant, Class<? extends EthertypeBase> etherType,
             Class<? extends DirectionBase> direction, Class<? extends ProtocolBase> protocol, int portMin, int portMax) {
+        SecurityRuleAttributes.Protocol proto = new SecurityRuleAttributes.Protocol(protocol);
         SecurityRuleBuilder secRule = new SecurityRuleBuilder();
-        secRule.setId(new Uuid(id));
+        secRule.setUuid(new Uuid(id));
         secRule.setTenantId(new Uuid(tenant));
         secRule.setEthertype(etherType);
         secRule.setDirection(direction);
-        secRule.setProtocol(protocol);
+        secRule.setProtocol(proto);
         secRule.setPortRangeMin(portMin);
         secRule.setPortRangeMax(portMax);
         return secRule.build();
@@ -41,7 +43,7 @@ public final class NeutronEntityFactory {
     public static SecurityRule securityRuleWithEtherType(String id, String tenant,
             Class<? extends EthertypeBase> etherType, Class<? extends DirectionBase> direction, String ownerGroupId,
             String remoteGroupId) {
-        SecurityRuleBuilder securityRuleBuilder = new SecurityRuleBuilder().setId(new Uuid(id))
+        SecurityRuleBuilder securityRuleBuilder = new SecurityRuleBuilder().setUuid(new Uuid(id))
             .setTenantId(new Uuid(tenant))
             .setEthertype(etherType)
             .setDirection(direction)
index 8cece96194a6284d15f7b811195b32e46d6c5a4c..570a57d8ac1d85a8364dbc2b0a78958e64b292f0 100644 (file)
@@ -86,7 +86,7 @@ public final class PolicyAssert {
     }
 
     public static void assertContractWithEic(Contract contract, SecurityRule secRule) {
-        assertEquals(new ContractId(secRule.getId().getValue()), contract.getId());
+        assertEquals(new ContractId(secRule.getUuid().getValue()), contract.getId());
         assertNull(contract.getQuality());
         assertNull(contract.getTarget());
         assertOneClauseWithEicWithOneSubject(contract, secRule);
@@ -110,7 +110,7 @@ public final class PolicyAssert {
     }
 
     public static void assertContract(Contract contract, SecurityRule secRule) {
-        assertEquals(new ContractId(secRule.getId().getValue()), contract.getId());
+        assertEquals(new ContractId(secRule.getUuid().getValue()), contract.getId());
         assertNull(contract.getQuality());
         assertNull(contract.getTarget());
         assertOneClauseWithOneSubject(contract, secRule);
index 3159e24302c8b412afa7778fc617ef982feadd4f..4cd23267b0213d66f154b43c3b5df18e485d76ab 100644 (file)
       <artifactId>neutron-mapper</artifactId>
       <version>${project.version}</version>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.neutron</groupId>
-      <artifactId>neutron-spi</artifactId>
-      <version>${neutron.version}</version>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.groupbasedpolicy</groupId>
       <artifactId>vpp-renderer</artifactId>
@@ -88,4 +83,4 @@
       </plugin>
     </plugins>
   </build>
-</project>
\ No newline at end of file
+</project>
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAware.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAware.java
new file mode 100644 (file)
index 0000000..03c27ec
--- /dev/null
@@ -0,0 +1,166 @@
+/*\r
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.processors;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.FlatNetwork;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.NetworkTypeBase;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VlanNetwork;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomain;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomainBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomainKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.bridge.domain.PhysicalLocationRef;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.bridge.domain.PhysicalLocationRefBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeFlat;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVlan;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.google.common.annotations.VisibleForTesting;\r
+import com.google.common.base.Function;\r
+import com.google.common.base.Optional;\r
+import com.google.common.collect.Lists;\r
+\r
+public class NetworkAware implements MappingProvider<Network> {\r
+\r
+    private static final Logger LOG = LoggerFactory.getLogger(NetworkAware.class);\r
+\r
+    private final DataBroker dataBroker;\r
+\r
+    public NetworkAware(DataBroker dataBroker) {\r
+        this.dataBroker = dataBroker;\r
+    }\r
+\r
+    @Override\r
+    public InstanceIdentifier<Network> getNeutronDtoIid() {\r
+        return InstanceIdentifier.builder(Neutron.class).child(Networks.class).child(Network.class).build();\r
+    }\r
+\r
+    @Override\r
+    public void processCreatedNeutronDto(Network network) {\r
+        BridgeDomain bridgeDomain = createBridgeDomain(network);\r
+        if (bridgeDomain != null) {\r
+            ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();\r
+            rwTx.put(LogicalDatastoreType.CONFIGURATION, getBridgeDomainIid(bridgeDomain.getId()), bridgeDomain);\r
+            DataStoreHelper.submitToDs(rwTx);\r
+        }\r
+    }\r
+\r
+    @VisibleForTesting\r
+    BridgeDomain createBridgeDomain(Network network) {\r
+        BridgeDomainBuilder bridgeDomainBuilder = new BridgeDomainBuilder();\r
+        String description = (network.getName() != null) ? network.getName() : "Neutron network";\r
+        bridgeDomainBuilder.setDescription(description);\r
+        bridgeDomainBuilder.setId(network.getUuid().getValue());\r
+        NetworkProviderExtension providerAug = network.getAugmentation(NetworkProviderExtension.class);\r
+        if (providerAug == null || providerAug.getNetworkType() == null) {\r
+            LOG.error("Cannot create VPP bridge domain. Network type not specified in neutron network: {}", network);\r
+            return null;\r
+        }\r
+        bridgeDomainBuilder.setPhysicalLocationRef(resolveDomainLocations(providerAug));\r
+        bridgeDomainBuilder.setType(convertNetworkType(providerAug.getNetworkType()));\r
+        if (providerAug.getNetworkType().isAssignableFrom(NetworkTypeVlan.class)\r
+                && providerAug.getSegmentationId() != null) {\r
+            try {\r
+                bridgeDomainBuilder.setVlan(new VlanId(Integer.valueOf(providerAug.getSegmentationId())));\r
+            } catch (NumberFormatException e) {\r
+                LOG.error("Neutron network {}. Cannot create VLAN ID from segmentation-id: {}. {}",\r
+                        providerAug.getSegmentationId(), network.getUuid(), e);\r
+                return null;\r
+            }\r
+        }\r
+        return bridgeDomainBuilder.build();\r
+    }\r
+\r
+    @VisibleForTesting\r
+    List<PhysicalLocationRef> resolveDomainLocations(NetworkProviderExtension providerAug) {\r
+        List<PhysicalLocationRef> locationRefs = new ArrayList<>();\r
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
+        if (providerAug.getPhysicalNetwork() == null) {\r
+            return null;\r
+        }\r
+        Optional<Topology> readTopology = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                getTopologyIid(new TopologyId(providerAug.getPhysicalNetwork())), rTx);\r
+        if (readTopology.isPresent()) {\r
+            Topology topology = readTopology.get();\r
+            for (Node node : topology.getNode()) {\r
+                PhysicalLocationRefBuilder location = new PhysicalLocationRefBuilder();\r
+                location.setNodeId(node.getNodeId());\r
+                location.setInterface(Lists.transform(node.getTerminationPoint(),\r
+                        new Function<TerminationPoint, String>() {\r
+\r
+                            @Override\r
+                            public String apply(TerminationPoint input) {\r
+                                return input.getTpId().getValue();\r
+                            }\r
+                        }));\r
+                locationRefs.add(location.build());\r
+            }\r
+        }\r
+        return locationRefs;\r
+    }\r
+\r
+    public static Class<? extends NetworkTypeBase> convertNetworkType(\r
+            Class<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeBase> base) {\r
+        if (base.isAssignableFrom(NetworkTypeFlat.class)) {\r
+            return FlatNetwork.class;\r
+        }\r
+        if (base.isAssignableFrom(NetworkTypeVlan.class)) {\r
+            return VlanNetwork.class;\r
+        }\r
+        throw new IllegalStateException("Unsupported network type: " + base);\r
+    }\r
+\r
+    InstanceIdentifier<Topology> getTopologyIid(TopologyId topologyId) {\r
+        return InstanceIdentifier.builder(NetworkTopology.class)\r
+            .child(Topology.class, new TopologyKey(topologyId))\r
+            .build();\r
+    }\r
+\r
+    InstanceIdentifier<BridgeDomain> getBridgeDomainIid(String id) {\r
+        return InstanceIdentifier.builder(Config.class).child(BridgeDomain.class, new BridgeDomainKey(id)).build();\r
+    }\r
+\r
+    @Override\r
+    public void processUpdatedNeutronDto(Network originalNetwork, Network updatedNetwork) {\r
+        InstanceIdentifier<BridgeDomain> bdId = getBridgeDomainIid(originalNetwork.getUuid().getValue());\r
+        ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();\r
+        rwTx.delete(LogicalDatastoreType.CONFIGURATION, bdId);\r
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, bdId, createBridgeDomain(updatedNetwork));\r
+        DataStoreHelper.submitToDs(rwTx);\r
+    }\r
+\r
+    @Override\r
+    public void processDeletedNeutronDto(Network network) {\r
+        InstanceIdentifier<BridgeDomain> bdId = getBridgeDomainIid(network.getUuid().getValue());\r
+        ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();\r
+        rwTx.delete(LogicalDatastoreType.CONFIGURATION, bdId);\r
+        DataStoreHelper.submitToDs(rwTx);\r
+    }\r
+}\r
index 353120c35d6cb1d5815b37158bf79b0a10c339b9..8f80cc385765d8c9f6d604bca6f9914f99c2e4ed 100644 (file)
@@ -51,7 +51,8 @@ public class NeutronListener implements DataTreeChangeListener<Neutron>, Closeab
 \r
     private void registerHandlersAndListeners(DataBroker dataBroker, SocketInfo socketInfo) {\r
         PortHandler portHandler = new PortHandler(dataBroker, socketInfo);\r
-        dataChangeProviders.add(new BaseEndpointByPortListener(portHandler, dataBroker));\r
+        dataChangeProviders.add(new PortAware(portHandler, dataBroker));\r
+        dataChangeProviders.add(new NetworkAware(dataBroker));\r
     }\r
 \r
     @Override\r
@@ -20,12 +20,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gb
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;\r
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
 \r
-public class BaseEndpointByPortListener extends DataTreeChangeHandler<BaseEndpointByPort> implements\r
+public class PortAware extends DataTreeChangeHandler<BaseEndpointByPort> implements\r
         MappingProvider<Port> {\r
 \r
     private final PortHandler portHandler;\r
 \r
-    protected BaseEndpointByPortListener(PortHandler portHandler, DataBroker dataProvider) {\r
+    protected PortAware(PortHandler portHandler, DataBroker dataProvider) {\r
         super(dataProvider);\r
         this.portHandler = portHandler;\r
         registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,\r
index 5bce99cce32874db3177bbee9e9ab8b51a0d293f..74a0f6be9b417fb226ef8eb20825fd12e34ff5de 100644 (file)
@@ -56,12 +56,12 @@ public class PortHandler implements TransactionChainListener {
 \r
     private static final Logger LOG = LoggerFactory.getLogger(MappingProvider.class);\r
 \r
-    private static final String COMPUTE_OWNER = "compute";\r
+    private static final String[] COMPUTE_OWNER = {"compute"};\r
     private static final String VHOST_USER = "vhostuser";\r
     private static final String NETCONF_TOPOLOGY_ID = "topology-netconf";\r
 \r
     private BindingTransactionChain transactionChain;\r
-    BaseEndpointByPortListener portByBaseEpListener;\r
+    PortAware portByBaseEpListener;\r
     DataBroker dataBroker;\r
     SocketInfo socketInfo;\r
 \r
@@ -106,8 +106,12 @@ public class PortHandler implements TransactionChainListener {
             String vifType = portBindingExt.getVifType();\r
             String deviceOwner = port.getDeviceOwner();\r
             if (vifType != null && deviceOwner != null) {\r
-                if (vifType.contains(VHOST_USER) && deviceOwner.contains(COMPUTE_OWNER)) {\r
-                    return true;\r
+                if (vifType.contains(VHOST_USER)) {\r
+                    for (String computeOwner : COMPUTE_OWNER) {\r
+                        if (deviceOwner.contains(computeOwner)) {\r
+                            return true;\r
+                        }\r
+                    }\r
                 }\r
             }\r
         }\r
diff --git a/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAwareTest.java b/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAwareTest.java
new file mode 100644 (file)
index 0000000..c3eab90
--- /dev/null
@@ -0,0 +1,176 @@
+/*\r
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.processors;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertTrue;\r
+\r
+import java.util.List;\r
+import java.util.UUID;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.mockito.Mockito;\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.FlatNetwork;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VlanNetwork;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomain;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.bridge.domain.PhysicalLocationRef;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeFlat;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVlan;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtensionBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;\r
+\r
+import com.google.common.base.Optional;\r
+import com.google.common.collect.ImmutableList;\r
+\r
+public class NetworkAwareTest extends AbstractDataBrokerTest {\r
+\r
+    private DataBroker dataBroker;\r
+    private NetworkAware networkAware;\r
+    private NetworkProviderExtensionBuilder netExtBuilder;\r
+\r
+    @Before\r
+    public void init() {\r
+        dataBroker = Mockito.spy(getDataBroker());\r
+        networkAware = new NetworkAware(dataBroker);\r
+        netExtBuilder = new NetworkProviderExtensionBuilder();\r
+        netExtBuilder.setPhysicalNetwork("physicalNet");\r
+    }\r
+\r
+    @Test\r
+    public void testProcessCreatedNeutronDto_flat() {\r
+        netExtBuilder.setNetworkType(NetworkTypeFlat.class);\r
+        Network network = createTestNetwork("net", netExtBuilder.build());\r
+        networkAware.processCreatedNeutronDto(network);\r
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
+        Optional<BridgeDomain> optBrDomain = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                networkAware.getBridgeDomainIid(network.getUuid().getValue()), rTx);\r
+        assertTrue(optBrDomain.isPresent());\r
+    }\r
+\r
+    @Test\r
+    public void testProcessUpdatedNeutronDto() {\r
+        netExtBuilder.setNetworkType(NetworkTypeFlat.class);\r
+        Network network1 = createTestNetwork("net1", netExtBuilder.build());\r
+        Network network2 = new NetworkBuilder(network1).setName("net2")\r
+            .addAugmentation(NetworkProviderExtension.class, netExtBuilder.build())\r
+            .build();\r
+        networkAware.processUpdatedNeutronDto(network1, network2);\r
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
+        Optional<BridgeDomain> optBrDomain = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                networkAware.getBridgeDomainIid(network2.getUuid().getValue()), rTx);\r
+        assertTrue(optBrDomain.isPresent());\r
+        assertEquals(optBrDomain.get().getDescription(), "net2");\r
+    }\r
+\r
+    @Test\r
+    public void testProcessDeletedNeutronDto() {\r
+        netExtBuilder.setNetworkType(NetworkTypeFlat.class);\r
+        Network network = createTestNetwork("net1", netExtBuilder.build());\r
+        networkAware.processDeletedNeutronDto(network);\r
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
+        Optional<BridgeDomain> optBrDomain = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                networkAware.getBridgeDomainIid(network.getUuid().getValue()), rTx);\r
+        assertFalse(optBrDomain.isPresent());\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBridgeDomain_vlanNetwork() {\r
+        netExtBuilder.setNetworkType(NetworkTypeVlan.class);\r
+        netExtBuilder.setSegmentationId("2016");\r
+        Network vlanNetwork = createTestNetwork("VlanNet", netExtBuilder.build());\r
+        BridgeDomain bridgeDomain = networkAware.createBridgeDomain(vlanNetwork);\r
+        assertEquals(bridgeDomain.getId(), vlanNetwork.getUuid().getValue());\r
+        assertEquals(bridgeDomain.getDescription(), vlanNetwork.getName());\r
+        assertEquals(bridgeDomain.getType(), VlanNetwork.class);\r
+        assertEquals(bridgeDomain.getVlan(), new VlanId(Integer.valueOf(2016)));\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBridgeDomain_flatNetwork() {\r
+        netExtBuilder.setNetworkType(NetworkTypeFlat.class);\r
+        Network flatNetwork = createTestNetwork("FlatNet", netExtBuilder.build());\r
+        BridgeDomain bridgeDomain = networkAware.createBridgeDomain(flatNetwork);\r
+        assertEquals(bridgeDomain.getId(), flatNetwork.getUuid().getValue());\r
+        assertEquals(bridgeDomain.getDescription(), flatNetwork.getName());\r
+        assertEquals(bridgeDomain.getType(), FlatNetwork.class);\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBridgeDomain_noPhysicalNetwork() {\r
+        netExtBuilder.setNetworkType(NetworkTypeFlat.class);\r
+        netExtBuilder.setPhysicalNetwork(null);\r
+        Network flatNetwork = createTestNetwork("FlatNet", netExtBuilder.build());\r
+        BridgeDomain bridgeDomain = networkAware.createBridgeDomain(flatNetwork);\r
+        assertNull(bridgeDomain.getPhysicalLocationRef());\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBridgeDomain_noNetworkType() {\r
+        Network vlanNetwork = createTestNetwork("noTypeNet", new NetworkProviderExtensionBuilder().build());\r
+        BridgeDomain bridgeDomain = networkAware.createBridgeDomain(vlanNetwork);\r
+        assertNull(bridgeDomain);\r
+    }\r
+\r
+    @Test\r
+    public void testResolveDomainLocations() {\r
+        NodeId nodeId = new NodeId("node1");\r
+        TpId tpId = new TpId("tp1");\r
+        TopologyId topologyId = new TopologyId("physicalNet");\r
+        writeBasicTopology(topologyId, nodeId, tpId);\r
+        NetworkProviderExtension netExt = new NetworkProviderExtensionBuilder().setPhysicalNetwork("physicalNet")\r
+            .build();\r
+        List<PhysicalLocationRef> resolvedLocations = networkAware.resolveDomainLocations(netExt);\r
+        PhysicalLocationRef physLocationRef = resolvedLocations.get(0);\r
+        assertEquals(nodeId, physLocationRef.getNodeId());\r
+        assertEquals(tpId.getValue(), physLocationRef.getInterface().get(0));\r
+    }\r
+\r
+    private Network createTestNetwork(String name, NetworkProviderExtension ext) {\r
+        return new NetworkBuilder().setUuid(new Uuid(UUID.randomUUID().toString()))\r
+            .setName(name)\r
+            .addAugmentation(NetworkProviderExtension.class, ext)\r
+            .build();\r
+    }\r
+\r
+    private void writeBasicTopology(TopologyId topologyId, NodeId nodeId, TpId tpId) {\r
+        TerminationPoint tp = new TerminationPointBuilder().setTpId(tpId).build();\r
+        Node node = new NodeBuilder().setNodeId(new NodeId(nodeId))\r
+            .setTerminationPoint(ImmutableList.<TerminationPoint>of(tp))\r
+            .build();\r
+        Topology topology = new TopologyBuilder().setTopologyId(topologyId)\r
+            .setNode(ImmutableList.<Node>of(node))\r
+            .build();\r
+        WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();\r
+        wTx.put(LogicalDatastoreType.CONFIGURATION, networkAware.getTopologyIid(new TopologyId("physicalNet")),\r
+                topology, true);\r
+        DataStoreHelper.submitToDs(wTx);\r
+    }\r
+}\r
index ee359c18d6b05a1e309f609b7ee1aac634c9be53..0c81dfedc51de340543e945dd0119294c1e72aee 100644 (file)
@@ -40,7 +40,7 @@ public class NeutronListenerTest extends AbstractDataBrokerTest {
     private Port port;\r
     private BaseEndpointByPort bebp;\r
     private NeutronListener neutronListener;\r
-    private BaseEndpointByPortListener baseEpByPortListener;\r
+    private PortAware baseEpByPortListener;\r
 \r
     @Before\r
     public void init() {\r
@@ -50,7 +50,7 @@ public class NeutronListenerTest extends AbstractDataBrokerTest {
         dataBroker = getDataBroker();\r
         neutronListener = new NeutronListener(dataBroker, socketInfo);\r
         neutronListener.clearDataChangeProviders();\r
-        baseEpByPortListener = Mockito.spy(new BaseEndpointByPortListener(new PortHandler(\r
+        baseEpByPortListener = Mockito.spy(new PortAware(new PortHandler(\r
                 dataBroker, socketInfo), dataBroker));\r
         neutronListener.addDataChangeProvider(baseEpByPortListener);\r
     }\r
@@ -69,7 +69,7 @@ public class NeutronListenerTest extends AbstractDataBrokerTest {
                         .child(GbpByNeutronMappings.class)\r
                         .child(BaseEndpointsByPorts.class)\r
                         .child(BaseEndpointByPort.class)\r
-                        .build())), any(BaseEndpointByPortListener.class));\r
+                        .build())), any(PortAware.class));\r
         neutronListener.close();\r
     }\r
 \r
diff --git a/pom.xml b/pom.xml
index 6b9946ef86ee4c7afe86b4f96fade8fb13d7fb56..cbf1f5bbdf61bc72bfc042701cd40cd8d34dacd8 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -5,6 +5,13 @@
   and is available at http://www.eclipse.org/legal/epl-v10.html --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
+  <parent>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <artifactId>odlparent-lite</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
   <groupId>org.opendaylight.groupbasedpolicy</groupId>
   <artifactId>groupbasedpolicy.project</artifactId>
   <version>0.4.0-SNAPSHOT</version>
     <module>sxp-mapper</module>
   </modules>
 
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/groupbasedpolicy.git</connection>
     <developerConnection>scm:git:ssh://git.opendaylight.org:29418/groupbasedpolicy.git</developerConnection>
index ba40c2ecb98c4545f1791bc11cffec2009bd272d..da4bf774ee18d3ca7ce78d6c5cf963f3ddcec480 100755 (executable)
             <groupId>org.opendaylight.netconf</groupId>
             <artifactId>sal-netconf-connector</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>ietf-inet-types-2013-07-15</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-module-junit4</artifactId>
+            <version>1.6.4</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-api-mockito</artifactId>
+            <version>1.6.4</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index ec77ae96610d2f4849e22ae08aafa6a2cb42a079..218d476e506e5f613c893c8f538f6a7168b1a531 100755 (executable)
@@ -34,7 +34,7 @@
                         <name>policy-validator-registry</name>
                     </policy-validator-registry>
 
-                    <renderer-name>ios-xe</renderer-name>
+                    <renderer-name>ios-xe-renderer</renderer-name>
                 </module>
             </modules>
         </data>
index 7774d8c5d859468cc1f83330064ff1b8b01ed956..71109ad7fd01d2e90687b97963548a05de798dcf 100644 (file)
@@ -8,9 +8,10 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager;
 
-import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 /**
  * Purpose: general policy manager prescription
  */
@@ -20,8 +21,9 @@ public interface PolicyManager extends AutoCloseable {
      * synchronize given configuration with device
      *  @param dataBefore
      * @param dataAfter
+     * @param version version needed to by apply
      */
-    ListenableFuture<Boolean> syncPolicy(Configuration dataBefore, Configuration dataAfter);
+    ListenableFuture<Boolean> syncPolicy(Configuration dataBefore, Configuration dataAfter, long version);
 
     @Override
     void close();
index d6e5ad4f8e53cba70d590cc0fb889560f7619530..c1c1eca9cf16c897283c6037e0a30ddcfcfa6ab8 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl;
 
+import com.google.common.base.Preconditions;
 import java.util.List;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -18,8 +19,6 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.IosXeRendererProvider;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyCacheImpl;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.EpPolicyTemplateBySgtListenerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.IosXeCapableNodeListenerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.RendererConfigurationListenerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.NodeManager;
@@ -43,12 +42,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
-
 /**
  * Purpose: bootstrap provider implementation of Ios-xe renderer
  */
@@ -59,11 +56,7 @@ public class IosXeRendererProviderImpl implements IosXeRendererProvider, Binding
     private final DataBroker dataBroker;
     private final RendererName rendererName;
     private RendererConfigurationListenerImpl rendererConfigurationListener;
-    private EpPolicyTemplateBySgtListenerImpl epPolicyTemplateBySgtListener;
     private IosXeCapableNodeListenerImpl iosXeCapableNodeListener;
-    private EpPolicyCacheImpl epPolicyCache;
-    private PolicyManager policyManager;
-    private NodeManager nodeManager;
 
     public IosXeRendererProviderImpl(final DataBroker dataBroker, final BindingAwareBroker broker,
                                      final RendererName rendererName) {
@@ -80,15 +73,9 @@ public class IosXeRendererProviderImpl implements IosXeRendererProvider, Binding
         if (rendererConfigurationListener != null) {
             rendererConfigurationListener.close();
         }
-        if (epPolicyTemplateBySgtListener != null) {
-            epPolicyTemplateBySgtListener.close();
-        }
         if (iosXeCapableNodeListener != null) {
             iosXeCapableNodeListener.close();
         }
-        if (epPolicyCache != null) {
-            epPolicyCache.invalidateAll();
-        }
     }
 
     @Override
@@ -96,15 +83,12 @@ public class IosXeRendererProviderImpl implements IosXeRendererProvider, Binding
         LOG.info("starting ios-xe renderer");
         //TODO register listeners:
         // node-manager
-        nodeManager = new NodeManager(dataBroker, providerContext);
-        // ep-policy-template-by-sgt
-        epPolicyCache = new EpPolicyCacheImpl();
-        epPolicyTemplateBySgtListener = new EpPolicyTemplateBySgtListenerImpl(dataBroker, epPolicyCache);
+        NodeManager nodeManager = new NodeManager(dataBroker, providerContext);
         // network-topology
         iosXeCapableNodeListener = new IosXeCapableNodeListenerImpl(dataBroker, nodeManager);
 
         // policy-manager and delegates
-        policyManager = new PolicyManagerImpl(dataBroker, epPolicyCache);
+        PolicyManager policyManager = new PolicyManagerImpl(dataBroker, nodeManager);
         final PolicyManager policyManagerZip = new PolicyManagerZipImpl(policyManager);
 
         // renderer-configuration endpoints
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/cache/EpPolicyCacheImpl.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/cache/EpPolicyCacheImpl.java
deleted file mode 100644 (file)
index 8752c04..0000000
+++ /dev/null
@@ -1,58 +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.cache;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
-
-/**
- * Purpose: cache for {@link EndpointPolicyTemplateBySgt}
- */
-public class EpPolicyCacheImpl implements DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> {
-
-    private final ConcurrentMap<EpPolicyTemplateCacheKey, Sgt> cache;
-    private final EpPolicyTemplateCacheKeyFactory keyFactory;
-
-    public EpPolicyCacheImpl() {
-        cache = new ConcurrentHashMap<>();
-        keyFactory = new EpPolicyTemplateCacheKeyFactory(RendererPolicyUtil.createEndpointGroupIdOrdering(),
-                RendererPolicyUtil.createConditionNameOrdering());
-    }
-
-    @Override
-    public void invalidate(final EndpointPolicyTemplateBySgt exSource) {
-        cache.remove(keyFactory.createKey(exSource));
-    }
-
-    @Override
-    public void add(final EndpointPolicyTemplateBySgt newSource) {
-        final EpPolicyTemplateCacheKey key = keyFactory.createKey(newSource);
-        cache.put(key, newSource.getSgt());
-    }
-
-    @Override
-    public void update(final EndpointPolicyTemplateBySgt before, final EndpointPolicyTemplateBySgt after) {
-        cache.remove(keyFactory.createKey(before));
-        cache.put(keyFactory.createKey(after), after.getSgt());
-    }
-
-    @Override
-    public Sgt lookupValue(final EpPolicyTemplateCacheKey key) {
-        return cache.get(keyFactory.createKey(key));
-    }
-
-    @Override
-    public void invalidateAll() {
-        cache.clear();
-    }
-}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/EpPolicyTemplateBySgtListenerImpl.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/EpPolicyTemplateBySgtListenerImpl.java
deleted file mode 100644 (file)
index 26aa107..0000000
+++ /dev/null
@@ -1,82 +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.listener;
-
-import com.google.common.base.Preconditions;
-import java.util.Collection;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.SxpMapper;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Purpose: listen to {@link EndpointPolicyTemplateBySgt} changes for caching purposes
- */
-public class EpPolicyTemplateBySgtListenerImpl implements DataTreeChangeListener<EndpointPolicyTemplateBySgt>, AutoCloseable {
-
-    private static final Logger LOG = LoggerFactory.getLogger(EpPolicyTemplateBySgtListenerImpl.class);
-
-    private final ListenerRegistration<EpPolicyTemplateBySgtListenerImpl> listenerRegistration;
-    private final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> cache;
-
-    public EpPolicyTemplateBySgtListenerImpl(final DataBroker dataBroker,
-                                             final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> cache) {
-        this.cache = Preconditions.checkNotNull(cache, "missing ep-policy-template cache");
-        final InstanceIdentifier<EndpointPolicyTemplateBySgt> templatePath = InstanceIdentifier.create(SxpMapper.class)
-                .child(EndpointPolicyTemplateBySgt.class);
-
-        final DataTreeIdentifier<EndpointPolicyTemplateBySgt> treePath = new DataTreeIdentifier<>(
-                LogicalDatastoreType.CONFIGURATION, templatePath);
-        listenerRegistration = dataBroker.registerDataTreeChangeListener(treePath, this);
-        LOG.info("ep-policy-template listener registered");
-    }
-
-    @Override
-    public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<EndpointPolicyTemplateBySgt>> collection) {
-        LOG.debug("ep-policy-template changed");
-        for (DataTreeModification<EndpointPolicyTemplateBySgt> epPolicyTemplateModification : collection) {
-            final DataObjectModification<EndpointPolicyTemplateBySgt> rootNode = epPolicyTemplateModification
-                    .getRootNode();
-            final DataObjectModification.ModificationType modificationType = rootNode.getModificationType();
-            switch (modificationType) {
-                case DELETE:
-                    // invalidate cache
-                    cache.invalidate(rootNode.getDataBefore());
-                    break;
-                case WRITE:
-                    // extend cache
-                    cache.add(rootNode.getDataAfter());
-                    break;
-                case SUBTREE_MODIFIED:
-                    // update cache
-                    cache.update(rootNode.getDataBefore(), rootNode.getDataAfter());
-                    break;
-                default:
-                    LOG.warn("modification type not supported: {}", modificationType);
-            }
-        }
-    }
-
-    @Override
-    public void close() {
-        listenerRegistration.close();
-    }
-}
index de2de6009efa06036c29868a762815aa988a9b2a..6daf50d81ccf19a2d6f98c1ab06fbf98497e79e7 100644 (file)
@@ -9,8 +9,6 @@
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener;
 
 import com.google.common.base.Preconditions;
-import java.util.Collection;
-import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
@@ -23,11 +21,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.annotation.Nonnull;
+import java.util.Collection;
+import java.util.Optional;
+
 /**
  * Purpose: process changes of configured renderer policies
  */
@@ -59,15 +62,20 @@ public class RendererConfigurationListenerImpl implements DataTreeChangeListener
 
             final RendererPolicy dataBefore = rootNode.getDataBefore();
             final RendererPolicy dataAfter = rootNode.getDataAfter();
-            if (dataAfter != null && dataBefore == null) {
-                policyManager.syncPolicy(dataAfter.getConfiguration(), null);
-            }
-            else if (dataAfter == null && dataBefore != null) {
-                policyManager.syncPolicy(null, dataBefore.getConfiguration());
+            // Policy configuration
+            Configuration oldConfig = null;
+            Configuration newConfig = null;
+            long version = 0;
+            if (dataBefore != null) {
+                oldConfig = dataBefore.getConfiguration();
             }
-            else if (dataAfter != null) {
-                policyManager.syncPolicy(dataAfter.getConfiguration(), dataBefore.getConfiguration());
+            if (dataAfter != null) {
+                newConfig = dataAfter.getConfiguration();
+                if (dataAfter.getVersion() != null) {
+                    version = dataAfter.getVersion();
+                }
             }
+            policyManager.syncPolicy(newConfig, oldConfig, version);
         }
     }
 
index 3214c5753a876722d082065e8ef0ea880d0af4dd..9916b3446d129f7acaabfeca4e30042fcf2b57a8 100644 (file)
@@ -10,11 +10,16 @@ package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.MountPoint;
 import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.NodeWriter;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NodeWriter;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeBuilder;
@@ -22,6 +27,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
@@ -32,9 +38,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connected;
 import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connecting;
@@ -45,7 +49,6 @@ public class NodeManager {
     public static final RendererName iosXeRenderer = new RendererName("ios-xe-renderer");
     private static final TopologyId TOPOLOGY_ID = new TopologyId("topology-netconf");
     private static final Logger LOG = LoggerFactory.getLogger(NodeManager.class);
-    private static final Map<InstanceIdentifier, DataBroker> netconfNodeCache = new HashMap<>();
     private final DataBroker dataBroker;
     private final MountPointService mountService;
     private final List<String> requiredCapabilities;
@@ -56,10 +59,6 @@ public class NodeManager {
         requiredCapabilities = new RequiredCapabilities().initializeRequiredCapabilities();
     }
 
-    static DataBroker getDataBrokerFromCache(InstanceIdentifier iid) {
-        return netconfNodeCache.get(iid); // TODO read from DS
-    }
-
     public void syncNodes(Node dataAfter, Node dataBefore) {
         // New node
         if (dataBefore == null && dataAfter != null) {
@@ -127,14 +126,19 @@ public class NodeManager {
         InstanceIdentifier mountPointIid = getMountpointIid(node);
         // Mountpoint iid == path in renderer-node
         RendererNode rendererNode = remapNode(mountPointIid);
-        DataBroker mountpoint = getNodeMountPoint(mountPointIid);
         NodeWriter nodeWriter = new NodeWriter();
         nodeWriter.cache(rendererNode);
         if (isCapableNetconfDevice(node, netconfNode)) {
+            resolveDisconnectedNode(node);
+            return;
+        }
+        IpAddress managementIpAddress = netconfNode.getHost().getIpAddress();
+        if (managementIpAddress == null) {
+            LOG.warn("Node {} does not contain management ip address", node.getNodeId().getValue());
+            resolveDisconnectedNode(node);
             return;
         }
         nodeWriter.commitToDatastore(dataBroker);
-        netconfNodeCache.put(mountPointIid, mountpoint);
     }
 
     private void resolveDisconnectedNode(Node node) {
@@ -143,7 +147,6 @@ public class NodeManager {
         NodeWriter nodeWriter = new NodeWriter();
         nodeWriter.cache(rendererNode);
         nodeWriter.removeFromDatastore(dataBroker);
-        netconfNodeCache.remove(mountPointIid);
     }
 
     private RendererNode remapNode(InstanceIdentifier path) {
@@ -183,7 +186,10 @@ public class NodeManager {
         return true;
     }
 
-    private DataBroker getNodeMountPoint(InstanceIdentifier mountPointIid) {
+    DataBroker getNodeMountPoint(InstanceIdentifier mountPointIid) {
+        if (mountPointIid == null) {
+            return null;
+        }
         Optional<MountPoint> optionalObject = mountService.getMountPoint(mountPointIid);
         MountPoint mountPoint;
         if (optionalObject.isPresent()) {
@@ -202,6 +208,44 @@ public class NodeManager {
         return null;
     }
 
+    NodeId getNodeIdByMountpointIid(InstanceIdentifier mountpointIid) {
+        NodeKey identifier = (NodeKey) mountpointIid.firstKeyOf(Node.class);
+        return identifier.getNodeId();
+    }
+
+    String getNodeManagementIpByMountPointIid(InstanceIdentifier mountpointIid) {
+        NodeId nodeId = getNodeIdByMountpointIid(mountpointIid);
+        InstanceIdentifier<Node> nodeIid = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId(NodeManager.TOPOLOGY_ID)))
+                .child(Node.class, new NodeKey(nodeId)).build();
+        ReadWriteTransaction rwt = dataBroker.newReadWriteTransaction();
+        try {
+            CheckedFuture<Optional<Node>, ReadFailedException> submitFuture =
+                    rwt.read(LogicalDatastoreType.CONFIGURATION, nodeIid);
+            Optional<Node> optional = submitFuture.checkedGet();
+            if (optional != null && optional.isPresent()) {
+                Node node = optional.get();
+                if (node != null) {
+                    NetconfNode netconfNode = getNodeAugmentation(node);
+                    if (netconfNode != null && netconfNode.getHost() != null) {
+                        IpAddress ipAddress = netconfNode.getHost().getIpAddress();
+                        if (ipAddress != null && ipAddress.getIpv4Address() != null) {
+                            return ipAddress.getIpv4Address().getValue();
+                        }
+                        return null;
+                    }
+                }
+            } else {
+                LOG.debug("Failed to read. {}", Thread.currentThread().getStackTrace()[1]);
+            }
+        } catch (ReadFailedException e) {
+            LOG.warn("Read transaction failed to {} ", e);
+        } catch (Exception e) {
+            LOG.error("Failed to .. {}", e.getMessage());
+        }
+        return null;
+    }
+
     private NetconfNode getNodeAugmentation(Node node) {
         NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
         if (netconfNode == null) {
@@ -228,9 +272,8 @@ public class NodeManager {
          * @return list of string representations of required capabilities
          */
         List<String> initializeRequiredCapabilities() {
-            String writableDataStore = "urn:ietf:params:netconf:capability:writable-running:1.0";
             String capabilityEntries[] = {ned, tailfCommon, tailfCliExtension, tailfMetaExtension, ietfYangTypes,
-                    ietfInetTypes, writableDataStore};
+                    ietfInetTypes};
             return Arrays.asList(capabilityEntries);
         }
     }
index 12aa97385d201de838bc61cd57a1d21c2d270e29..b1cd010cf9472cfb937e6759afd3f9debfa9c7ed 100644 (file)
 
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
 
+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 com.google.common.base.Function;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.groupbasedpolicy.api.sf.AllowActionDefinition;
-import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
+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.TransactionCommitFailedException;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyWriter;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
-import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
-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.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-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.ServiceChainBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
-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.ServicePath;
-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.ServicePathKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.LocalBuilder;
-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.ios.rev160308._native.service.chain.service.path.ConfigServiceChainPathModeBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.ServiceIndexBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.Services;
-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.ios.rev160308.config.service.chain.grouping.IpBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
-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.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;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
 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.PeerEndpointWithPolicy;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
-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.classifiers.Classifier;
-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.sxp.mapper.EndpointPolicyTemplateBySgt;
 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;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-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.CONSUMER;
-import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation.PROVIDER;
-
 public class PolicyManagerImpl implements PolicyManager {
 
-    private static final Logger LOG = LoggerFactory.getLogger(PolicyMapper.class);
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerImpl.class);
+    private static final String policyMapName = "service-chains";
     private final DataBroker dataBroker;
-    private DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> epPolicyCache;
-    private final PolicyMapper mapper;
-    private final String policyMapName = "service-chains";
-    private Map<DataBroker, PolicyWriter> perDeviceWriterCache = new HashMap<>();
-
-    public enum ActionCase { ALLOW, CHAIN }
-
+    private final NodeManager nodeManager;
 
     public PolicyManagerImpl(final DataBroker dataBroker,
-                             final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> epPolicyCache) {
+                             final NodeManager nodeManager) {
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
-        this.epPolicyCache = Preconditions.checkNotNull(epPolicyCache);
-        mapper = new PolicyMapper(dataBroker);
+        this.nodeManager = Preconditions.checkNotNull(nodeManager);
     }
 
     @Override
-    public ListenableFuture<Boolean> syncPolicy(final Configuration dataBefore, final Configuration dataAfter) {
-        // CREATE
+    public ListenableFuture<Boolean> syncPolicy(final Configuration dataAfter, final Configuration dataBefore,
+                                                final long version) {
+        final ListenableFuture<Boolean> result;
+        if (dataBefore == null && dataAfter != null) {
+            result = syncPolicy(dataAfter, Create);
+        } else if (dataBefore != null && dataAfter == null) {
+            result = syncPolicy(dataBefore, Delete);
+        } else {
+            // TODO implement
+            result = Futures.immediateFuture(false);
+        }
+
+        reportVersion(version);
+
+        // chain version update (TODO: status)
+        return Futures.transform(result, new AsyncFunction<Boolean, Boolean>() {
+            @Override
+            public ListenableFuture<Boolean> apply(final Boolean input) throws Exception {
+                if (input != null && input) {
+                    return Futures.transform(reportVersion(version), new Function<Void, Boolean>() {
+                        @Nullable
+                        @Override
+                        public Boolean apply(@Nullable final Void input) {
+                            return Boolean.TRUE;
+                        }
+                    });
+                } else {
+                    return Futures.immediateFuture(input);
+                }
+            }
+        });
+    }
+
+    private ListenableFuture<Boolean> syncPolicy(final Configuration dataAfter, DsAction action) {
+        if (dataAfter.getRendererEndpoints() == null
+                || dataAfter.getRendererEndpoints().getRendererEndpoint() == null) {
+            LOG.debug("no configuration obtained - skipping");
+            return Futures.immediateFuture(true);
+        }
+        final Map<DataBroker, PolicyWriter> policyWriterPerDeviceCache = new HashMap<>();
         for (RendererEndpoint rendererEndpoint : dataAfter.getRendererEndpoints().getRendererEndpoint()) {
-            // Get mountpoint
-            if (dataAfter.getEndpoints() == null) {
+            if (dataAfter.getEndpoints() == null || dataAfter.getEndpoints().getAddressEndpointWithLocation() == null) {
+                LOG.debug("renderer-endpoint: missing address-endpoint-with-location");
+                //TODO: dump all resolvedRule-rule-peerEP-EP combinantions to status
                 continue;
             }
-            DataBroker mountpoint = getAbsoluteLocationMountpoint(rendererEndpoint, dataAfter.getEndpoints()
-                    .getAddressEndpointWithLocation());
+
+            final List<AddressEndpointWithLocation> endpointsWithLocation = dataAfter.getEndpoints()
+                    .getAddressEndpointWithLocation();
+            final InstanceIdentifier mountpointIid = PolicyManagerUtil.getAbsoluteLocationMountpoint(rendererEndpoint, endpointsWithLocation);
+            final DataBroker mountpoint = nodeManager.getNodeMountPoint(mountpointIid);
             if (mountpoint == null) {
+                LOG.debug("no data-broker for mount-point [{}] available", mountpointIid);
+                //TODO: dump all resolvedRule-rule-peerEP-EP combinantions to status
                 continue;
             }
-            // Initialize appropriate writer
-            PolicyWriter policyWriter;
-            if (perDeviceWriterCache.containsKey(mountpoint)) {
-                policyWriter = perDeviceWriterCache.get(mountpoint);
-            } else {
-                policyWriter = new PolicyWriter(mountpoint);
-                perDeviceWriterCache.put(mountpoint, policyWriter);
+
+            // Find policy writer
+            PolicyWriter policyWriter = policyWriterPerDeviceCache.get(mountpoint);
+            if (policyWriter == null) {
+                // Initialize new policy writer
+                final String interfaceName = PolicyManagerUtil.getInterfaceNameForPolicyMap(rendererEndpoint, endpointsWithLocation);
+                final NodeId nodeId = nodeManager.getNodeIdByMountpointIid(mountpointIid);
+                final String managementIpAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
+                if (interfaceName == null || managementIpAddress == null) {
+                    LOG.debug("can not create policyWriter: interface={}, managementIpAddress={}",
+                            interfaceName, managementIpAddress);
+                    //TODO: dump all resolvedRule-rule-peerEP-EP combinantions to status
+                    continue;
+                }
+                policyWriter = new PolicyWriter(mountpoint, interfaceName, managementIpAddress, policyMapName, nodeId);
+                policyWriterPerDeviceCache.put(mountpoint, policyWriter);
             }
+
+            final Sgt sourceSgt = PolicyManagerUtil.findSgtTag(rendererEndpoint, dataAfter.getEndpoints()
+                    .getAddressEndpointWithLocation());
             // Peer Endpoint
             for (PeerEndpointWithPolicy peerEndpoint : rendererEndpoint.getPeerEndpointWithPolicy()) {
-                // Sgt Tags
-                final Sgt sourceSgt = findSgtTag(rendererEndpoint, dataAfter.getEndpoints()
-                        .getAddressEndpointWithLocation());
-                final Sgt destinationSgt = findSgtTag(peerEndpoint, dataAfter.getEndpoints()
+                final Sgt destinationSgt = PolicyManagerUtil.findSgtTag(peerEndpoint, dataAfter.getEndpoints()
                         .getAddressEndpointWithLocation());
                 if (sourceSgt == null || destinationSgt == null) {
+                    LOG.debug("endpoint-policy: missing sgt value(sourceSgt={}, destinationSgt={})",
+                            sourceSgt, destinationSgt);
+                    //TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
                     continue;
                 }
-                syncPolicyEntities(sourceSgt, destinationSgt, policyWriter, dataAfter, peerEndpoint);
+                PolicyManagerUtil.syncPolicyEntities(sourceSgt, destinationSgt, policyWriter, dataAfter, peerEndpoint);
             }
         }
-        // Flush
-        perDeviceWriterCache.values().forEach(PolicyWriter::commitToDatastore);
-        perDeviceWriterCache.clear();
-
-        return Futures.immediateFuture(true);
-    }
-
-    private void syncPolicyEntities(final Sgt sourceSgt, final Sgt destinationSgt, PolicyWriter policyWriter,
-                                   final Configuration dataAfter, final PeerEndpointWithPolicy peerEndpoint) {
-        // Class map
-        String classMapName = generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
-        Match match = mapper.createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
-        ClassMap classMap = mapper.createClassMap(classMapName, match);
-        policyWriter.write(classMap);
-
-        Map<ActionCase, Action> actionMap = getActionInDirection(dataAfter, peerEndpoint);
-        if (actionMap == null || actionMap.isEmpty()) {
-            return;
-        }
-        // Policy map entry
-        List<Class> policyMapEntries = new ArrayList<>();
-        if (actionMap.containsKey(ActionCase.ALLOW)) {
-            policyMapEntries = resolveAllowAction();
-        }
-        if (actionMap.containsKey(ActionCase.CHAIN)) {
-            policyMapEntries = resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName);
-        }
-        policyWriter.write(policyMapEntries);
-    }
 
-    private Sgt findSgtTag(final AddressEndpointKey endpointKey,
-                            final List<AddressEndpointWithLocation> endpointsWithLocation) {
-        if (endpointKey == null || endpointsWithLocation == null) {
-            return null;
-        }
-        AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
-                endpointsWithLocation);
-        return epPolicyCache.lookupValue(new EpPolicyTemplateCacheKey(endpointWithLocation));
-    }
+        //TODO: return real (cumulated) future
+        final List<CheckedFuture<Void, TransactionCommitFailedException>> allFutureResults = new ArrayList<>();
+        if (action.equals(Create)) {
+            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);
 
-    private List<Class> resolveChainAction(final PeerEndpointWithPolicy peerEndpoint, final Sgt sourceSgt,
-                                           final Sgt destinationSgt, final Map<ActionCase, Action> actionMap,
-                                           final String classMapName) {
-        List<Class> entries = new ArrayList<>();
-        final Action action = actionMap.get(ActionCase.CHAIN);
-        ServiceFunctionPath servicePath = PolicyManagerUtil.getServicePath(action.getParameterValue());
-        if (servicePath == null) {
-            return null;
         }
-        TenantId tenantId = getTenantId(peerEndpoint);
-        if (tenantId == null) {
-            return  null;
-        }
-        RenderedServicePath renderedPath = PolicyManagerUtil.createRenderedPath(servicePath, tenantId);
-        entries.add(mapper.createPolicyEntry(classMapName, renderedPath, ActionCase.CHAIN));
-        if (servicePath.isSymmetric()) {
-            // symmetric path is in opposite direction. Roles of renderer and peer endpoint will invert
-            RenderedServicePath symmetricPath = PolicyManagerUtil
-                    .createSymmetricRenderedPath(servicePath, renderedPath, tenantId);
-            String oppositeClassMapName = generateClassMapName(destinationSgt.getValue(), sourceSgt.getValue());
-            entries.add(mapper.createPolicyEntry(oppositeClassMapName, symmetricPath, ActionCase.CHAIN));
-        }
-        return entries;
-    }
 
-    private List<Class> resolveAllowAction() {
-        List<Class> entries = new ArrayList<>();
-        entries.add(mapper.createPolicyEntry(policyMapName, null, ActionCase.ALLOW));
-        return entries;
-    }
+        final ListenableFuture<List<Void>> cumulativeResult = Futures.allAsList(allFutureResults);
 
-    private DataBroker getAbsoluteLocationMountpoint(final RendererEndpoint endpoint,
-                                                     final List<AddressEndpointWithLocation> endpointsWithLocation) {
-        if (endpoint == null || endpointsWithLocation == null) {
-            return null;
-        }
-        AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
-                endpointsWithLocation);
-        final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
-        final LocationType locationType = absoluteLocation.getLocationType();
-        ExternalLocationCase location = (ExternalLocationCase) locationType;
-        if (location == null) {
-            LOG.warn("Endpoint {} does not contain info about external location",
-                    endpointWithLocation.getKey().toString());
-            return null;
-        }
-        InstanceIdentifier mountPointId = location.getExternalNodeMountPoint();
-        return NodeManager.getDataBrokerFromCache(mountPointId);
-    }
-
-    private String generateClassMapName(Integer sourceTag, Integer destinationTag) {
-        return "srcTag" + sourceTag + "_dstTag" + destinationTag;
-    }
-
-    private Map<ActionCase, Action> getActionInDirection(Configuration data, PeerEndpointWithPolicy peer) {
-        List<ResolvedRule> rulesInDirection = new ArrayList<>();
-        // Find all rules in desired direction
-        for (RuleGroupWithRendererEndpointParticipation ruleGroupKey :
-                peer.getRuleGroupWithRendererEndpointParticipation()) {
-            EndpointPolicyParticipation participation = ruleGroupKey.getRendererEndpointParticipation();
-            RuleGroup ruleGroup = findRuleGroup(data, ruleGroupKey);
-            if (ruleGroup == null || ruleGroup.getResolvedRule() == null) {
-                continue;
-            }
-
-            for (ResolvedRule resolvedRule : ruleGroup.getResolvedRule()) {
-                if (resolvedRule == null) {
-                    continue;
-                }
-                if (resolvedRule.getClassifier() == null || resolvedRule.getAction() == null) {
-                    continue;
-                }
-                // TODO only first Classifier used
-                Classifier classifier = resolvedRule.getClassifier().get(0);
-                HasDirection.Direction direction = classifier.getDirection();
-                if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
-                        (participation.equals(CONSUMER) && direction.equals(In))) {
-                    rulesInDirection.add(resolvedRule);
-                }
-            }
-        }
-        if (rulesInDirection.isEmpty()) {
-            return null; // TODO define drop?
-        }
-        // TODO use only first rule with ActionDefinitionID for now
-        Map<ActionCase, Action> result = new HashMap<>();
-        for (ResolvedRule resolvedRule : rulesInDirection) {
-            // TODO only first action used for now
-            Action action = resolvedRule.getAction().get(0);
-            if (action.getActionDefinitionId() != null) {
-                ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
-                if (actionDefinitionId.equals(AllowActionDefinition.ID)) {
-                    result.put(ActionCase.ALLOW, action);
-                    return result;
-                } else if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
-                    result.put(ActionCase.CHAIN, action);
-                    return result;
-                }
-            }
-        }
-        return null;
-    }
-
-    private RuleGroup findRuleGroup(final Configuration data,
-                                    final RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation) {
-        final TenantId tenantId = ruleGroupWithParticipation.getTenantId();
-        final ContractId contractId = ruleGroupWithParticipation.getContractId();
-        final SubjectName subjectName = ruleGroupWithParticipation.getSubjectName();
-        for (RuleGroup ruleGroup : data.getRuleGroups().getRuleGroup()) {
-            if (!ruleGroup.getTenantId().equals(tenantId))
-                continue;
-            if (!ruleGroup.getContractId().equals(contractId)) {
-                continue;
-            }
-            if (ruleGroup.getSubjectName().equals(subjectName)) {
-                return ruleGroup;
-            }
-        }
-        return null;
-    }
-
-    private TenantId getTenantId(PeerEndpointWithPolicy peer) {
-        for (RuleGroupWithRendererEndpointParticipation ruleGroup :
-                peer.getRuleGroupWithRendererEndpointParticipation()) {
-            if (ruleGroup.getTenantId() != null) {
-                return ruleGroup.getTenantId();
+        return Futures.transform(cumulativeResult, new Function<List<Void>, Boolean>() {
+            @Nullable
+            @Override
+            public Boolean apply(@Nullable final List<Void> input) {
+                LOG.trace("considering all submits as successful - otherwise there will be exception");
+                return Boolean.TRUE;
             }
-        }
-        return null;
-    }
-
-
-    private void resolveFirstSffOnClassifier(final Ipv4Address nodeIpAddress,
-                                             final Set<RenderedServicePath> firstHops) {
-        // Local forwarder
-        LocalBuilder localSffBuilder = new LocalBuilder();
-        localSffBuilder.setIp(new IpBuilder().setAddress(nodeIpAddress).build());
-
-        // TODO add sff to writer
-
-        for (RenderedServicePath renderedPath : firstHops) {
-            // Remote forwarder
-            RenderedServicePathHop firstRenderedPathHop = renderedPath.getRenderedServicePathHop().get(0);
-            SffName sffName = firstRenderedPathHop.getServiceFunctionForwarder();
-
-            // Remap sff and its management ip address
-            org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder serviceFunctionForwarder =
-                    SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName);
-            String sffMgmtIpAddress = serviceFunctionForwarder.getIpMgmtAddress().getIpv4Address().getValue();
-
-            ServiceFfNameBuilder remoteSffBuilder = new ServiceFfNameBuilder();
-            remoteSffBuilder.setName(sffName.getValue())
-                    .setKey(new ServiceFfNameKey(sffName.getValue()))
-                    .setIp(new IpBuilder().setAddress(new Ipv4Address(sffMgmtIpAddress)).build());
-            // TODO add sff to writer
-
-            // Service chain
-            List<Services> services = new ArrayList<>();
-            ServiceTypeChoice serviceTypeChoice = sffTypeChoice(sffName.getValue());
-            ServicesBuilder servicesBuilder = new ServicesBuilder();
-            servicesBuilder.setServiceIndexId(renderedPath.getStartingIndex())
-                    .setServiceTypeChoice(serviceTypeChoice);
-            List<ServicePath> servicePaths = new ArrayList<>();
-            ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
-            servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
-                    .setServicePathId(renderedPath.getPathId())
-                    .setConfigServiceChainPathMode(new ConfigServiceChainPathModeBuilder()
-                            .setServiceIndex(new ServiceIndexBuilder()
-                                    .setServices(services).build()).build());
-            servicePaths.add(servicePathBuilder.build());
-            ServiceChainBuilder chainBuilder = new ServiceChainBuilder();
-            chainBuilder.setServicePath(servicePaths);
-            ServiceChain serviceChain = chainBuilder.build();
-            // TODO add service-chain to writer
-        }
+        });
     }
 
-    private ServiceTypeChoice sffTypeChoice(String forwarderName) {
-        ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder();
-        sffBuilder.setServiceFunctionForwarder(forwarderName);
-        return sffBuilder.build();
+    private CheckedFuture<Void, TransactionCommitFailedException> reportVersion(long version) {
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        InstanceIdentifier<RendererPolicy> iid = InstanceIdentifier.create(Renderers.class)
+                .child(Renderer.class, new RendererKey(NodeManager.iosXeRenderer))
+                .child(RendererPolicy.class);
+        wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, new RendererPolicyBuilder().setVersion(version).build());
+        return wtx.submit();
     }
 
     @Override
     public void close() {
         //NOOP
     }
+
+    enum DsAction {Create, Delete}
+
+    public enum ActionCase {ALLOW, CHAIN}
 }
index 5e4e066f2974e9c61f0a8ad1087332514e94a6d6..7700831232f427a82d0d5514dedbfc1a985e04e1 100644 (file)
@@ -8,24 +8,26 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
 
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import java.util.concurrent.Callable;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BinaryOperator;
+
 import org.apache.commons.lang3.tuple.MutablePair;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
 /**
  * Purpose: wrap {@link PolicyManager} with state compression mechanism
  */
@@ -72,7 +74,7 @@ public class PolicyManagerZipImpl implements PolicyManager {
     }
 
     @Override
-    public ListenableFuture<Boolean> syncPolicy(final Configuration dataBefore, final Configuration dataAfter) {
+    public ListenableFuture<Boolean> syncPolicy(final Configuration dataBefore, final Configuration dataAfter, final long version) {
         LOG.trace("firing configuration zip");
         // add config to zipping storage
         final ConfigPairBox configPair = new ConfigPairBox(dataBefore, dataAfter);
@@ -86,7 +88,7 @@ public class PolicyManagerZipImpl implements PolicyManager {
                 public ListenableFuture<Boolean> call() throws Exception {
                     final ConfigPairBox configPairBox = configPairKeeper.getAndSet(null);
                     LOG.debug("delegating policy configuration");
-                    return delegate.syncPolicy(configPairBox.getLeft(), configPair.getRight());
+                    return delegate.syncPolicy(configPairBox.getLeft(), configPair.getRight(), version);
                 }
             }));
         } else {
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyMapper.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyMapper.java
deleted file mode 100644 (file)
index 917d9d0..0000000
+++ /dev/null
@@ -1,126 +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.manager;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-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;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Destination;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.DestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Source;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.SourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.Type;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.TypeBuilder;
-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.ClassMapKey;
-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.PolicyMapKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionList;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.ForwardCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.ForwardBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePath;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
-
-class PolicyMapper {
-
-    private final DataBroker dataBroker;
-    private static final Logger LOG = LoggerFactory.getLogger(PolicyMapper.class);
-
-    PolicyMapper(final DataBroker dataBroker) {
-        this.dataBroker = Preconditions.checkNotNull(dataBroker);
-    }
-
-    Match createSecurityGroupMatch(int sourceTag, int destinationTag) {
-        MatchBuilder matchBuilder = new MatchBuilder();
-        SecurityGroupBuilder sgBuilder = new SecurityGroupBuilder();
-        Source source = new SourceBuilder().setTag(sourceTag).build();
-        Destination destination = new DestinationBuilder().setTag(destinationTag).build();
-        sgBuilder.setSource(source)
-                .setDestination(destination);
-        return matchBuilder.setSecurityGroup(sgBuilder.build()).build();
-    }
-
-    ClassMap createClassMap(final String classMapName, Match match) {
-        ClassMapBuilder cmBuilder = new ClassMapBuilder();
-        cmBuilder.setName(classMapName)
-                .setKey(new ClassMapKey(classMapName))
-                .setMatch(match)
-                .setPrematch(ClassMap.Prematch.MatchAll);
-        return cmBuilder.build();
-    }
-
-    Class createPolicyEntry(String policyClassName, RenderedServicePath renderedPath,
-                            PolicyManagerImpl.ActionCase actionCase) {
-        // Forward Case
-        ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
-        if (actionCase.equals(CHAIN) && renderedPath != null) {
-            // Chain Action
-            ForwardBuilder forwardBuilder = new ForwardBuilder();
-            List<ServicePath> servicePaths = new ArrayList<>();
-            ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
-            servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
-                    .setServicePathId(renderedPath.getPathId())
-                    .setServiceIndex(renderedPath.getStartingIndex());
-            servicePaths.add(servicePathBuilder.build());
-            forwardBuilder.setServicePath(servicePaths);
-            forwardCaseBuilder.setForward(forwardBuilder.build());
-        }
-        // Create Action List
-        List<ActionList> actionList = new ArrayList<>();
-        ActionListBuilder actionListBuilder = new ActionListBuilder();
-        actionListBuilder.setKey(new ActionListKey(PolicyActionType.Forward))
-                .setActionType(PolicyActionType.Forward)
-                .setActionParam(forwardCaseBuilder.build());
-        actionList.add(actionListBuilder.build());
-        // Build class entry
-        ClassBuilder policyClassBuilder = new ClassBuilder();
-        policyClassBuilder.setName(new ClassNameType(policyClassName))
-                .setKey(new ClassKey(new ClassNameType(policyClassName)))
-                .setActionList(actionList);
-        return policyClassBuilder.build();
-    }
-
-    public Type getServicePolicyType(String name) {
-        TypeBuilder typeBuilder = new TypeBuilder();
-        org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder serviceChainBuilder =
-                new org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder();
-        serviceChainBuilder.setName(name)
-                .setDirection(org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction.Input);
-        typeBuilder.setServiceChain(serviceChainBuilder.build());
-        return typeBuilder.build();
-    }
-
-    PolicyMap policyMap(String policyMapName) {
-        PolicyMapBuilder pmBuilder = new PolicyMapBuilder();
-        pmBuilder.setName(policyMapName)
-                .setKey(new PolicyMapKey(policyMapName))
-                .setType(null);
-        return pmBuilder.build();
-    }
-}
index 85b7737b1062d1dd06f1be02329faad665953fa4..55ed2993c0aa5635c6d956c11968bda75531e3c1 100644 (file)
 
 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.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.CONSUMER;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation.PROVIDER;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
-import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
-import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
-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.rsp.rev140701.CreateRenderedPathInput;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
 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.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.PolicyActionType;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroup;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Destination;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.DestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Source;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.TypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder;
+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.ClassMapKey;
+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.PolicyMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionList;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.AppnavPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.ForwardCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.ForwardBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePath;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
+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.SubjectName;
 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.HasDirection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
+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.renderers.renderer.renderer.policy.Configuration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+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.PeerEndpointWithPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
+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.classifiers.Classifier;
+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.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 public class PolicyManagerUtil {
 
     private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerUtil.class);
 
-    public static ServiceFunctionPath getServicePath(List<ParameterValue> params) {
-        if (params == null || params.isEmpty()) {
-            LOG.error("Cannot found service path, parameter value is null");
+    public static void syncPolicyEntities(final Sgt sourceSgt, final Sgt destinationSgt, PolicyWriter policyWriter,
+                                          final Configuration dataAfter, final PeerEndpointWithPolicy peerEndpoint) {
+        // Class map
+        final String classMapName = PolicyManagerUtil.generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
+        final Match match = PolicyManagerUtil.createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
+        final ClassMap classMap = PolicyManagerUtil.createClassMap(classMapName, match);
+        final Map<PolicyManagerImpl.ActionCase, Action> actionMap = PolicyManagerUtil.getActionInDirection(dataAfter, peerEndpoint);
+        if (actionMap == null || actionMap.isEmpty()) {
+            LOG.debug("no usable action found for EP-sgt[{}] | peerEP-sgt[{}]",
+                    sourceSgt, destinationSgt);
+            return;
+        }
+        policyWriter.cache(classMap);
+
+        // Policy map entry
+        if (actionMap.containsKey(PolicyManagerImpl.ActionCase.CHAIN)) {
+            ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+        }
+    }
+
+    public static Sgt findSgtTag(final AddressEndpointKey endpointKey,
+                                 final List<AddressEndpointWithLocation> endpointsWithLocation) {
+        if (endpointKey == null || endpointsWithLocation == null) {
             return null;
         }
-        Map<String, Object> paramsMap = new HashMap<>();
-        for (ParameterValue value : params) {
-            if (value.getName() == null)
-                continue;
-            if (value.getIntValue() != null) {
-                paramsMap.put(value.getName().getValue(), value.getIntValue());
-            } else if (value.getStringValue() != null) {
-                paramsMap.put(value.getName().getValue(), value.getStringValue());
-            }
+        final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
+                endpointsWithLocation);
+        final AddressEndpointWithLocationAug augmentation = endpointWithLocation.getAugmentation(AddressEndpointWithLocationAug.class);
+        if (augmentation == null) {
+            return null;
         }
-        String chainName = null;
-        for (String name : paramsMap.keySet()) {
-            if (name.equals(ChainActionDefinition.SFC_CHAIN_NAME)) {
-                chainName = (String) paramsMap.get(name);
+
+        return augmentation.getSgt();
+    }
+
+    private static Match createSecurityGroupMatch(final int sourceTag, final int destinationTag) {
+        final SecurityGroupBuilder sgBuilder = new SecurityGroupBuilder();
+        final Source source = new SourceBuilder().setTag(sourceTag).build();
+        final Destination destination = new DestinationBuilder().setTag(destinationTag).build();
+        sgBuilder.setDestination(destination)
+                .setSource(source);
+        final SecurityGroup securityGroup = sgBuilder.build();
+        final MatchBuilder matchBuilder = new MatchBuilder();
+        matchBuilder.setSecurityGroup(securityGroup);
+        return matchBuilder.build();
+    }
+
+    static ClassMap createClassMap(final String classMapName, final Match match) {
+        final ClassMapBuilder cmBuilder = new ClassMapBuilder();
+        cmBuilder.setName(classMapName)
+                .setKey(new ClassMapKey(classMapName))
+                .setPrematch(ClassMap.Prematch.MatchAll)
+                .setMatch(match);
+        return cmBuilder.build();
+    }
+
+    static TenantId getTenantId(final PeerEndpointWithPolicy peer) {
+        for (RuleGroupWithRendererEndpointParticipation ruleGroup :
+                peer.getRuleGroupWithRendererEndpointParticipation()) {
+            if (ruleGroup.getTenantId() != null) {
+                return ruleGroup.getTenantId();
             }
         }
-        if (chainName == null) {
-            LOG.error("Cannot found service path, chain name is null");
+        return null;
+    }
+
+    static String generateClassMapName(final int sourceTag, final int destinationTag) {
+        return "srcTag" + sourceTag + "_dstTag" + destinationTag;
+    }
+
+    static Class createPolicyEntry(final String policyClassName, final RenderedServicePath renderedPath,
+                                   final PolicyManagerImpl.ActionCase actionCase) {
+        // Forward Case
+        final ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
+        if (actionCase.equals(CHAIN) && renderedPath != null) {
+            // Chain Action
+            final ForwardBuilder forwardBuilder = new ForwardBuilder();
+            final List<ServicePath> servicePaths = new ArrayList<>();
+            final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
+            servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
+                    .setServicePathId(renderedPath.getPathId())
+                    .setServiceIndex(renderedPath.getStartingIndex());
+            servicePaths.add(servicePathBuilder.build());
+            forwardBuilder.setServicePath(servicePaths);
+            forwardCaseBuilder.setForward(forwardBuilder.build());
+        }
+        // Create Action List
+        final List<ActionList> actionList = new ArrayList<>();
+        final ActionListBuilder actionListBuilder = new ActionListBuilder();
+        actionListBuilder.setKey(new ActionListKey(PolicyActionType.Forward))
+                .setActionType(PolicyActionType.Forward)
+                .setActionParam(forwardCaseBuilder.build());
+        actionList.add(actionListBuilder.build());
+        // Build class entry
+        final ClassBuilder policyClassBuilder = new ClassBuilder();
+        policyClassBuilder.setName(new ClassNameType(policyClassName))
+                .setKey(new ClassKey(new ClassNameType(policyClassName)))
+                .setActionList(actionList);
+        return policyClassBuilder.build();
+    }
+
+    public static PolicyMap createPolicyMap(final String policyMapName, final List<Class> policyMapEntries) {
+        // Create default class entry
+        final AppnavPolicyBuilder appnavPolicyBuilder = new AppnavPolicyBuilder();
+        appnavPolicyBuilder.setPassThrough(true);
+        final ClassBuilder defaultBuilder = new ClassBuilder();
+        defaultBuilder.setName(new ClassNameType("class-default"))
+                .setKey(new ClassKey(new ClassNameType("class-default")))
+                .setAppnavPolicy(appnavPolicyBuilder.build());
+        policyMapEntries.add(defaultBuilder.build());
+        // Construct policy map
+        final PolicyMapBuilder policyMapBuilder = new PolicyMapBuilder();
+        policyMapBuilder.setName(policyMapName)
+                .setKey(new PolicyMapKey(policyMapName))
+                .setType(PolicyMap.Type.ServiceChain)
+                .setXmlClass(policyMapEntries);
+        return policyMapBuilder.build();
+    }
+
+    public static ServicePolicy createServicePolicy(final String chainName, final ServiceChain.Direction direction) {
+        // Service Chain
+        final ServiceChainBuilder serviceChainBuilder = new ServiceChainBuilder();
+        serviceChainBuilder.setName(chainName) // Same as the policy map name
+                .setDirection(direction);
+        // Service policy
+        final TypeBuilder typeBuilder = new TypeBuilder();
+        typeBuilder.setServiceChain(serviceChainBuilder.build());
+        // Service Policy
+        ServicePolicyBuilder servicePolicyBuilder = new ServicePolicyBuilder();
+        servicePolicyBuilder.setType(typeBuilder.build());
+
+        return servicePolicyBuilder.build();
+    }
+
+    public static InstanceIdentifier getAbsoluteLocationMountpoint(final RendererEndpoint endpoint,
+                                                                   final List<AddressEndpointWithLocation> endpointsWithLocation) {
+        if (endpointsWithLocation.isEmpty()) {
             return null;
         }
-        ServiceFunctionPath serviceFunctionPath = findServiceFunctionPath(new SfcName(chainName));
-        if (serviceFunctionPath == null) {
-            LOG.error("Service function path not found for name {}", chainName);
+        AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
+                endpointsWithLocation);
+        final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
+        final LocationType locationType = absoluteLocation.getLocationType();
+        ExternalLocationCase location = (ExternalLocationCase) locationType;
+        if (location == null) {
+            LOG.warn("Endpoint {} does not contain info about external location",
+                    endpointWithLocation.getKey().toString());
             return null;
         }
-        return serviceFunctionPath;
+        return location.getExternalNodeMountPoint();
     }
 
-    public static RenderedServicePath createRenderedPath(ServiceFunctionPath sfp, TenantId tenantId) {
-        RenderedServicePath renderedServicePath;
-        // Try to read existing RSP
-        RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp");
-        renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
-        if (renderedServicePath != null) {
-            return renderedServicePath;
+    public static String getInterfaceNameForPolicyMap(final RendererEndpoint endpoint,
+                                                      final List<AddressEndpointWithLocation> endpointsWithLocation) {
+        if (endpoint == null || endpointsWithLocation == null) {
+            return null;
         }
-        LOG.info("Rendered service path with name {} not found, creating a new one ..", rspName.getValue());
-        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());
-        return renderedServicePath;
+        final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
+                endpointsWithLocation);
+        final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
+        final LocationType locationType = absoluteLocation.getLocationType();
+        final ExternalLocationCase location = (ExternalLocationCase) locationType;
+        if (location == null) {
+            LOG.warn("Endpoint {} does not contain info about external location",
+                    endpointWithLocation.getKey().toString());
+            return null;
+        }
+        return location.getExternalNodeConnector();
     }
 
-    private static ServiceFunctionPath findServiceFunctionPath(SfcName chainName) {
-        ServiceFunctionPaths allPaths = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
-        for (ServiceFunctionPath serviceFunctionPath : allPaths.getServiceFunctionPath()) {
-            if (serviceFunctionPath.getServiceChainName().equals(chainName)) {
-                return serviceFunctionPath;
+
+    private static Map<PolicyManagerImpl.ActionCase, Action> getActionInDirection(final Configuration data, final PeerEndpointWithPolicy peer) {
+        final List<ResolvedRule> rulesInDirection = new ArrayList<>();
+        // Find all rules in desired direction
+        for (RuleGroupWithRendererEndpointParticipation ruleGroupKey :
+                peer.getRuleGroupWithRendererEndpointParticipation()) {
+            final EndpointPolicyParticipation participation = ruleGroupKey.getRendererEndpointParticipation();
+            final RuleGroup ruleGroup = findRuleGroup(data, ruleGroupKey);
+            if (ruleGroup == null || ruleGroup.getResolvedRule() == null) {
+                continue;
+            }
+
+            for (ResolvedRule resolvedRule : ruleGroup.getResolvedRule()) {
+                if (resolvedRule == null) {
+                    continue;
+                }
+                if (resolvedRule.getClassifier() == null || resolvedRule.getAction() == null) {
+                    continue;
+                }
+                // TODO only first Classifier used
+                final Classifier classifier = resolvedRule.getClassifier().get(0);
+                final HasDirection.Direction direction = classifier.getDirection();
+                if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
+                        (participation.equals(CONSUMER) && direction.equals(In))) {
+                    rulesInDirection.add(resolvedRule);
+                }
+            }
+        }
+        if (rulesInDirection.isEmpty()) {
+            return null;
+        }
+        // TODO use only first rule with ActionDefinitionID for now
+        final Map<PolicyManagerImpl.ActionCase, Action> result = new HashMap<>();
+        for (ResolvedRule resolvedRule : rulesInDirection) {
+            // TODO only first action used for now
+            final Action action = resolvedRule.getAction().get(0);
+            if (action.getActionDefinitionId() != null) {
+                final ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
+                // Currently only chain action is supported
+                if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
+                    result.put(PolicyManagerImpl.ActionCase.CHAIN, action);
+                    return result;
+                }
             }
         }
         return null;
     }
 
-    public static RenderedServicePath createSymmetricRenderedPath(ServiceFunctionPath sfp, RenderedServicePath rsp,
-                                                                  TenantId tenantId) {
-        RenderedServicePath reversedRenderedPath;
-        // Try to read existing RSP
-        RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp-Reverse");
-        reversedRenderedPath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
-        if (reversedRenderedPath != null) {
-            return reversedRenderedPath;
+    private static RuleGroup findRuleGroup(final Configuration data,
+                                           final RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation) {
+        final TenantId tenantId = ruleGroupWithParticipation.getTenantId();
+        final ContractId contractId = ruleGroupWithParticipation.getContractId();
+        final SubjectName subjectName = ruleGroupWithParticipation.getSubjectName();
+        for (RuleGroup ruleGroup : data.getRuleGroups().getRuleGroup()) {
+            if (!ruleGroup.getTenantId().equals(tenantId)) {
+                continue;
+            }
+            if (!ruleGroup.getContractId().equals(contractId)) {
+                continue;
+            }
+            if (ruleGroup.getSubjectName().equals(subjectName)) {
+                return ruleGroup;
+            }
         }
-        LOG.info("Reversed rendered service path with name {} not found, creating a new one ..", rspName.getValue());
-        reversedRenderedPath = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
-        LOG.info("Rendered service path {} created", rspName.getValue());
-        return reversedRenderedPath;
+        return null;
     }
 
 }
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyWriter.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyWriter.java
deleted file mode 100644 (file)
index f7827a4..0000000
+++ /dev/null
@@ -1,78 +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.util;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-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.TransactionCommitFailedException;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class PolicyWriter {
-
-    private static final Logger LOG = LoggerFactory.getLogger(PolicyWriter.class);
-
-    private final DataBroker mountpoint;
-    // Local cache
-    private List<ClassMap> classMapEntries;
-    private List<Class> policyMapEntries;
-
-    public PolicyWriter(final DataBroker dataBroker) {
-        mountpoint = Preconditions.checkNotNull(dataBroker);
-        classMapEntries = new ArrayList<>();
-        policyMapEntries = new ArrayList<>();
-    }
-
-    public void write(ClassMap classMap) {
-        classMapEntries.add(classMap);
-    }
-
-    public void write(List<Class> policyMapEntries) {
-        this.policyMapEntries.addAll(policyMapEntries);
-    }
-
-    public void commitToDatastore() {
-        // create and write service-policy
-        // create and write policy-map with policyMapEntries
-        // create and write class-maps
-
-        WriteTransaction wtx = mountpoint.newWriteOnlyTransaction();
-        // Class maps
-        for (ClassMap entry : classMapEntries) {
-            InstanceIdentifier<ClassMap> iid = classMapInstanceIdentifier(entry);
-            try {
-                wtx.merge(LogicalDatastoreType.CONFIGURATION, iid, entry, true);
-                CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
-                submitFuture.checkedGet();
-                // Clear cache
-                classMapEntries.clear();
-            } catch (TransactionCommitFailedException e) {
-                LOG.error("Write transaction failed to {}", e.getMessage());
-            } catch (Exception e) {
-                LOG.error("Failed to .. {}", e.getMessage());
-            }
-        }
-    }
-
-    private InstanceIdentifier<ClassMap> classMapInstanceIdentifier(ClassMap classMap) {
-        return InstanceIdentifier.builder(Native.class)
-                .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
-    }
-}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/ServiceChainingUtil.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/ServiceChainingUtil.java
new file mode 100644 (file)
index 0000000..185d4d7
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * 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.util;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+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;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
+import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
+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.SffName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
+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.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
+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.config.service.chain.grouping.IpBuilder;
+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.ServicePath;
+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.ServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.Local;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.LocalBuilder;
+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.ios.rev160308._native.service.chain.service.path.ConfigServiceChainPathModeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.ServiceIndexBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.Services;
+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.ServiceFunctionBuilder;
+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.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.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicy;
+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;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ServiceChainingUtil {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ServiceChainingUtil.class);
+
+    static ServiceFunctionPath getServicePath(final List<ParameterValue> params) {
+        if (params == null || params.isEmpty()) {
+            LOG.error("Cannot found service path, parameter value is null");
+            return null;
+        }
+        final Map<String, Object> paramsMap = new HashMap<>();
+        for (ParameterValue value : params) {
+            if (value.getName() == null)
+                continue;
+            if (value.getIntValue() != null) {
+                paramsMap.put(value.getName().getValue(), value.getIntValue());
+            } else if (value.getStringValue() != null) {
+                paramsMap.put(value.getName().getValue(), value.getStringValue());
+            }
+        }
+        String chainName = null;
+        for (String name : paramsMap.keySet()) {
+            if (name.equals(ChainActionDefinition.SFC_CHAIN_NAME)) {
+                chainName = (String) paramsMap.get(name);
+            }
+        }
+        if (chainName == null) {
+            LOG.error("Cannot found service path, chain name is null");
+            return null;
+        }
+        final ServiceFunctionPath serviceFunctionPath = findServiceFunctionPath(new SfcName(chainName));
+        if (serviceFunctionPath == null) {
+            LOG.error("Service function path not found for name {}", chainName);
+            return null;
+        }
+        return serviceFunctionPath;
+    }
+
+    static void resolveChainAction(final PeerEndpointWithPolicy peerEndpoint, final Sgt sourceSgt,
+                                   final Sgt destinationSgt, final Map<PolicyManagerImpl.ActionCase, Action> actionMap,
+                                   final String classMapName, PolicyWriter policyWriter) {
+        final List<Class> entries = new ArrayList<>();
+        final Action action = actionMap.get(PolicyManagerImpl.ActionCase.CHAIN);
+        final ServiceFunctionPath servicePath = ServiceChainingUtil.getServicePath(action.getParameterValue());
+        if (servicePath == null) {
+            //TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
+            return;
+        }
+        final TenantId tenantId = PolicyManagerUtil.getTenantId(peerEndpoint);
+        if (tenantId == null) {
+            //TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
+            return;
+        }
+        final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(servicePath, tenantId);
+        // Create appropriate service path && remote forwarder
+        final boolean sfcPartSucessful = setSfcPart(renderedPath, policyWriter);
+        if (!sfcPartSucessful) {
+            //TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
+            return;
+        }
+
+        // atomic creation of symmetric policy-entries
+        final Class policyEntry = PolicyManagerUtil.createPolicyEntry(classMapName, renderedPath, PolicyManagerImpl.ActionCase.CHAIN);
+        if (!servicePath.isSymmetric()) {
+            entries.add(policyEntry);
+        } else {
+            // symmetric path is in opposite direction. Roles of renderer and peer endpoint will invert
+            final RenderedServicePath symmetricPath = ServiceChainingUtil
+                    .createSymmetricRenderedPath(servicePath, renderedPath, tenantId);
+            if (symmetricPath == null) {
+                //TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
+                return;
+            } else {
+                final String oppositeClassMapName = PolicyManagerUtil.generateClassMapName(destinationSgt.getValue(),
+                        sourceSgt.getValue());
+                final Class policyEntrySymmetric = PolicyManagerUtil.createPolicyEntry(oppositeClassMapName,
+                        symmetricPath, PolicyManagerImpl.ActionCase.CHAIN);
+
+                entries.add(policyEntry);
+                entries.add(policyEntrySymmetric);
+            }
+        }
+        policyWriter.cache(entries);
+    }
+
+    static RenderedServicePath createRenderedPath(final ServiceFunctionPath sfp, final TenantId tenantId) {
+        RenderedServicePath renderedServicePath;
+        // Try to read existing RSP
+        final RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp");
+        renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+        if (renderedServicePath != null) {
+            return renderedServicePath;
+        }
+        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());
+        return renderedServicePath;
+    }
+
+    static RenderedServicePath createSymmetricRenderedPath(final ServiceFunctionPath sfp, final RenderedServicePath rsp,
+                                                           final TenantId tenantId) {
+        RenderedServicePath reversedRenderedPath;
+        // Try to read existing RSP
+        final RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp-Reverse");
+        reversedRenderedPath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+        if (reversedRenderedPath != null) {
+            return reversedRenderedPath;
+        }
+        LOG.info("Reversed rendered service path with name {} not found, creating a new one ..", rspName.getValue());
+        reversedRenderedPath = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
+        LOG.info("Rendered service path {} created", rspName.getValue());
+        return reversedRenderedPath;
+    }
+
+    /**
+     * Method checks up, whether a {@link Local} Service Function Forwarder is present on device or not.
+     *
+     * @param mountpoint used to access specific device
+     * @return true if Local Forwarder is present, false otherwise
+     */
+    static boolean checkLocalForwarderPresence(DataBroker mountpoint) {
+        InstanceIdentifier<Local> localSffIid = InstanceIdentifier.builder(Native.class)
+                .child(ServiceChain.class)
+                .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
+                .child(Local.class).build();
+        ReadWriteTransaction rwt = mountpoint.newReadWriteTransaction();
+        CheckedFuture<Optional<Local>, ReadFailedException> submitFuture = rwt.read(LogicalDatastoreType.CONFIGURATION,
+                localSffIid);
+        try {
+            Optional<Local> optionalLocalSff = submitFuture.checkedGet();
+            return optionalLocalSff.isPresent();
+        } catch (ReadFailedException e) {
+            LOG.warn("Read transaction failed to {} ", e);
+        } catch (Exception e) {
+            LOG.error("Failed to .. {}", e.getMessage());
+        }
+        return false;
+    }
+
+    /**
+     * Method checks up, if some {@link ServicePath} is present on device.
+     *
+     * @param mountpoint used to access specific device
+     * @return true if service chain does not exist, is null or does not contain any service path. False otherwise
+     */
+    public static boolean checkServicePathPresence(DataBroker mountpoint) {
+        InstanceIdentifier<ServiceChain> serviceChainIid = InstanceIdentifier.builder(Native.class)
+                .child(ServiceChain.class).build();
+        ReadWriteTransaction rwt = mountpoint.newReadWriteTransaction();
+        CheckedFuture<Optional<ServiceChain>, ReadFailedException> submitFuture = rwt.read(LogicalDatastoreType.CONFIGURATION,
+                serviceChainIid);
+        try {
+            Optional<ServiceChain> optionalServiceChain = submitFuture.checkedGet();
+            if (optionalServiceChain.isPresent()) {
+                ServiceChain chain = optionalServiceChain.get();
+                return chain == null || chain.getServicePath() == null || chain.getServicePath().isEmpty();
+            } else {
+                return true;
+            }
+        } catch (ReadFailedException e) {
+            LOG.warn("Read transaction failed to {} ", e);
+        } catch (Exception e) {
+            LOG.error("Failed to .. {}", e.getMessage());
+        }
+        return false;
+    }
+
+    static ServiceFunctionPath findServiceFunctionPath(final SfcName chainName) {
+        final ServiceFunctionPaths allPaths = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
+        for (ServiceFunctionPath serviceFunctionPath : allPaths.getServiceFunctionPath()) {
+            if (serviceFunctionPath.getServiceChainName().equals(chainName)) {
+                return serviceFunctionPath;
+            }
+        }
+        return null;
+    }
+
+    static boolean setSfcPart(final RenderedServicePath renderedServicePath, PolicyWriter policyWriter) {
+        // TODO: break into smaller methods with partial result
+        if (renderedServicePath != null && renderedServicePath.getRenderedServicePathHop() != null &&
+                !renderedServicePath.getRenderedServicePathHop().isEmpty()) {
+            final RenderedServicePathHop firstHop = renderedServicePath.getRenderedServicePathHop().get(0);
+            if (firstHop == null) {
+                LOG.error("Rendered service path {} does not contain any hop", renderedServicePath.getName().getValue());
+                return false;
+            }
+            final SffName sffName = firstHop.getServiceFunctionForwarder();
+            final ServiceFunctionForwarder serviceFunctionForwarder = SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName);
+            if (serviceFunctionForwarder == null) {
+                LOG.error("Sff with name {} does not exist", sffName.getValue());
+                return false;
+            }
+            // Forwarders
+            //
+            // If classifier node is also forwarder, first entry in service path has to point to first service function
+            // (Local case)
+            //
+            // If first hop Sff is on different node, first service path entry has to point to that specific service
+            // forwarder (Remote case)
+
+            // Local case (only when does not exist)
+
+            if (!checkLocalForwarderPresence(policyWriter.getCurrentMountpoint())) {
+                final LocalBuilder localSffBuilder = new LocalBuilder();
+                localSffBuilder.setIp(new IpBuilder().setAddress(new Ipv4Address(policyWriter.getManagementIpAddress()))
+                        .build());
+                policyWriter.cache(localSffBuilder.build());
+            } else {
+                LOG.info("Local forwarder for node {} is already created", policyWriter.getCurrentNodeId());
+            }
+            // Set up choice. If remote, this choice is overwritten
+            ServiceTypeChoice serviceTypeChoice = functionTypeChoice(firstHop.getServiceFunctionName().getValue());
+            // Remote case
+            if (serviceFunctionForwarder.getIpMgmtAddress() == null
+                    || serviceFunctionForwarder.getIpMgmtAddress().getIpv4Address() == null) {
+                LOG.error("Cannot create remote forwarder, SFF {} does not contain management ip address",
+                        sffName.getValue());
+                return false;
+            }
+            final String sffMgmtIpAddress = serviceFunctionForwarder.getIpMgmtAddress().getIpv4Address().getValue();
+            // If local SFF has the same ip as first hop sff, it's the same SFF; no need to create a remote one
+            if (!sffMgmtIpAddress.equals(policyWriter.getManagementIpAddress())) {
+                final ServiceFfNameBuilder remoteSffBuilder = new ServiceFfNameBuilder();
+                remoteSffBuilder.setName(sffName.getValue())
+                        .setKey(new ServiceFfNameKey(sffName.getValue()))
+                        .setIp(new IpBuilder().setAddress(new Ipv4Address(sffMgmtIpAddress)).build());
+                policyWriter.cache(remoteSffBuilder.build());
+                serviceTypeChoice = forwarderTypeChoice(sffName.getValue());
+            }
+
+            // Service chain
+            final List<Services> services = new ArrayList<>();
+            final ServicesBuilder servicesBuilder = new ServicesBuilder();
+            servicesBuilder.setServiceIndexId(renderedServicePath.getStartingIndex())
+                    .setServiceTypeChoice(serviceTypeChoice);
+            final List<ServicePath> servicePaths = new ArrayList<>();
+            final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
+            servicePathBuilder.setKey(new ServicePathKey(renderedServicePath.getPathId()))
+                    .setServicePathId(renderedServicePath.getPathId())
+                    .setConfigServiceChainPathMode(new ConfigServiceChainPathModeBuilder()
+                            .setServiceIndex(new ServiceIndexBuilder()
+                                    .setServices(services).build()).build());
+            servicePaths.add(servicePathBuilder.build());
+            final ServiceChainBuilder chainBuilder = new ServiceChainBuilder();
+            chainBuilder.setServicePath(servicePaths);
+            final ServiceChain serviceChain = chainBuilder.build();
+            policyWriter.cache(serviceChain);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    static ServiceTypeChoice forwarderTypeChoice(final String forwarderName) {
+        final ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder();
+        sffBuilder.setServiceFunctionForwarder(forwarderName);
+        return sffBuilder.build();
+    }
+
+    static ServiceTypeChoice functionTypeChoice(final String functionName) {
+        final ServiceFunctionBuilder sfBuilder = new ServiceFunctionBuilder();
+        sfBuilder.setServiceFunction(functionName);
+        return sfBuilder.build();
+    }
+
+}
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer;
 
 import com.google.common.util.concurrent.CheckedFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
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
new file mode 100644 (file)
index 0000000..4f387bb
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+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.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.ServiceChainingUtil;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.Interface;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernet;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernetKey;
+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.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePath;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.Local;
+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.ServiceFfNameKey;
+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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PolicyWriter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyWriter.class);
+
+    private final DataBroker mountpoint;
+    // Local cache
+    private final List<ClassMap> classMapEntries;
+    private final List<Class> policyMapEntries;
+    private final List<ServiceFfName> remoteForwarders;
+    private final List<ServiceChain> serviceChains;
+    private final NodeId nodeId;
+    private final String interfaceName;
+    private final String policyMapName;
+    private final String managementIpAddress;
+    private Local localForwarder;
+
+    public PolicyWriter(final DataBroker dataBroker, final String interfaceName, final String ipAddress,
+                        final String policyMapName, final NodeId nodeId) {
+        classMapEntries = new ArrayList<>();
+        policyMapEntries = new ArrayList<>();
+        remoteForwarders = new ArrayList<>();
+        serviceChains = new ArrayList<>();
+
+        this.nodeId = Preconditions.checkNotNull(nodeId);
+        mountpoint = Preconditions.checkNotNull(dataBroker);
+        managementIpAddress = Preconditions.checkNotNull(ipAddress);
+        this.interfaceName = Preconditions.checkNotNull(interfaceName);
+        this.policyMapName = Preconditions.checkNotNull(policyMapName);
+    }
+
+    public void cache(ClassMap classMap) {
+        classMapEntries.add(classMap);
+    }
+
+    public void cache(List<Class> policyMapEntries) {
+        this.policyMapEntries.addAll(policyMapEntries);
+    }
+
+    public void cache(Local localForwarder) {
+        this.localForwarder = localForwarder;
+    }
+
+    public void cache(ServiceFfName remoteForwarder) {
+        remoteForwarders.add(remoteForwarder);
+    }
+
+    public void cache(ServiceChain serviceChain) {
+        serviceChains.add(serviceChain);
+    }
+
+    public CheckedFuture<Void, TransactionCommitFailedException> commitToDatastore() {
+        WriteTransaction wtx = mountpoint.newWriteOnlyTransaction();
+        // GBP
+        // Class maps
+        for (ClassMap entry : classMapEntries) {
+            InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
+            wtx.merge(LogicalDatastoreType.CONFIGURATION, classMapIid, entry);
+            LOG.info("Created class-map {} on node {}", entry.getName(), nodeId.getValue());
+        }
+
+        // Policy map
+        PolicyMap policyMap = PolicyManagerUtil.createPolicyMap(policyMapName, policyMapEntries);
+        InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier();
+        wtx.merge(LogicalDatastoreType.CONFIGURATION, policyMapIid, policyMap);
+        LOG.info("Created policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
+
+        // Interface
+        ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
+        InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
+        wtx.merge(LogicalDatastoreType.CONFIGURATION, servicePolicyIid, servicePolicy);
+        LOG.info("Service-policy interface {}, bound to policy-map {} created on  node {}",
+                interfaceName, policyMap.getName(), nodeId.getValue());
+
+        //SFC
+        // Local forwarder (if some service chain exists, otherwise is useless)
+        if (!serviceChains.isEmpty()) {
+            InstanceIdentifier<Local> localIid = localSffInstanceIdentifier();
+            wtx.merge(LogicalDatastoreType.CONFIGURATION, localIid, localForwarder);
+            LOG.info("Local forwarder created on node {}", nodeId.getValue());
+        }
+
+        // Remote forwarders
+        for (ServiceFfName forwarder : remoteForwarders) {
+            InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
+            wtx.merge(LogicalDatastoreType.CONFIGURATION, forwarderIid, forwarder);
+            LOG.info("Remote forwarder {} created on node {}", forwarder.getName(), nodeId.getValue());
+        }
+
+        // Service paths
+        for (ServiceChain serviceChain : serviceChains) {
+            for (ServicePath entry : serviceChain.getServicePath()) {
+                InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
+                wtx.merge(LogicalDatastoreType.CONFIGURATION, servicePathIid, entry);
+                LOG.info("Service path with Id {} created on node {}", entry.getServicePathId(), nodeId.getValue());
+            }
+        }
+
+        return wtx.submit();
+    }
+
+    public CheckedFuture<Void, TransactionCommitFailedException> removeFromDatastore() {
+        ReadWriteTransaction wtx = mountpoint.newReadWriteTransaction();
+        //GBP
+        // Interface
+        InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
+        wtx.delete(LogicalDatastoreType.CONFIGURATION, servicePolicyIid);
+        LOG.info("Service-policy removed from interface {} on node {}", interfaceName, nodeId.getValue());
+
+        // Policy map
+        InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier();
+        wtx.delete(LogicalDatastoreType.CONFIGURATION, policyMapIid);
+        LOG.info("Policy-map removed from node node {}", nodeId.getValue());
+
+        // Class map
+        for (ClassMap entry : classMapEntries) {
+            InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
+            wtx.delete(LogicalDatastoreType.CONFIGURATION, classMapIid);
+            LOG.info("Class-map {} removed from node {}", entry.getName(), nodeId.getValue());
+        }
+
+        //SFC
+        // Service paths
+        for (ServiceChain serviceChain : serviceChains) {
+            for (ServicePath entry : serviceChain.getServicePath()) {
+                InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
+                wtx.delete(LogicalDatastoreType.CONFIGURATION, servicePathIid);
+                LOG.info("Service path with Id {} removed from node {}", entry.getServicePathId(), nodeId.getValue());
+            }
+        }
+
+        // Remote forwarders
+        for (ServiceFfName forwarder : remoteForwarders) {
+            InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
+            wtx.delete(LogicalDatastoreType.CONFIGURATION, forwarderIid);
+            LOG.info("Remote forwarder {} removed from node {}", forwarder.getName(), nodeId.getValue());
+        }
+
+        // Local forwarder - remove only if there is no more service-paths on device. If paths removed above were last
+        // ones, remove local forwarder. If there are still some paths present, they were created by sfc and local
+        // forwarder cannot be removed (because it was created by sfc as well)
+        if (ServiceChainingUtil.checkServicePathPresence(mountpoint)) {
+            InstanceIdentifier<Local> localIid = localSffInstanceIdentifier();
+            wtx.delete(LogicalDatastoreType.CONFIGURATION, localIid);
+            LOG.info("Local forwarder removed from node {}", nodeId.getValue());
+        }
+
+        return wtx.submit();
+    }
+
+    private InstanceIdentifier<ClassMap> classMapInstanceIdentifier(ClassMap classMap) {
+        return InstanceIdentifier.builder(Native.class)
+                .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
+    }
+
+    private InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier() {
+        return InstanceIdentifier.builder(Native.class)
+                .child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
+    }
+
+    private InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(String ethernetName) {
+        return InstanceIdentifier.builder(Native.class)
+                .child(Interface.class)
+                .child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
+                .child(ServicePolicy.class)
+                .build();
+    }
+
+    private InstanceIdentifier<Local> localSffInstanceIdentifier() {
+        return InstanceIdentifier.builder(Native.class)
+                .child(ServiceChain.class)
+                .child(ServiceFunctionForwarder.class)
+                .child(Local.class).build();
+    }
+
+    private InstanceIdentifier<ServiceFfName> remoteSffInstanceIdentifier(ServiceFfName sffName) {
+        return InstanceIdentifier.builder(Native.class)
+                .child(ServiceChain.class)
+                .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
+                .child(ServiceFfName.class, new ServiceFfNameKey(sffName.getName())).build();
+    }
+
+    private InstanceIdentifier<ServicePath> servicePathInstanceIdentifier(ServicePathKey key) {
+        return InstanceIdentifier.builder(Native.class)
+                .child(ServiceChain.class)
+                .child(ServicePath.class, key).build();
+    }
+
+    public String getManagementIpAddress() {
+        return managementIpAddress;
+    }
+
+    public DataBroker getCurrentMountpoint() {
+        return mountpoint;
+    }
+
+    public NodeId getCurrentNodeId() {
+        return nodeId;
+    }
+}
diff --git a/renderers/ios-xe/src/main/yang/netconf/ietf-inet-types.yang b/renderers/ios-xe/src/main/yang/netconf/ietf-inet-types.yang
deleted file mode 100644 (file)
index 5624a95..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-module ietf-inet-types {
-
-  namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
-  prefix "inet";
-
-  organization
-   "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
-
-  contact
-   "WG Web:   <http://tools.ietf.org/wg/netmod/>
-    WG List:  <mailto:netmod@ietf.org>
-
-    WG Chair: David Kessens
-              <mailto:david.kessens@nsn.com>
-
-    WG Chair: Juergen Schoenwaelder
-              <mailto:j.schoenwaelder@jacobs-university.de>
-
-    Editor:   Juergen Schoenwaelder
-              <mailto:j.schoenwaelder@jacobs-university.de>";
-
-  description
-   "This module contains a collection of generally useful derived
-    YANG data types for Internet addresses and related things.
-
-    Copyright (c) 2013 IETF Trust and the persons identified as
-    authors of the code.  All rights reserved.
-
-    Redistribution and use in source and binary forms, with or
-    without modification, is permitted pursuant to, and subject
-    to the license terms contained in, the Simplified BSD License
-    set forth in Section 4.c of the IETF Trust's Legal Provisions
-    Relating to IETF Documents
-    (http://trustee.ietf.org/license-info).
-
-    This version of this YANG module is part of RFC 6991; see
-    the RFC itself for full legal notices.";
-
-  revision 2013-07-15 {
-    description
-     "This revision adds the following new data types:
-      - ip-address-no-zone
-      - ipv4-address-no-zone
-      - ipv6-address-no-zone";
-    reference
-     "RFC 6991: Common YANG Data Types";
-  }
-
-  revision 2010-09-24 {
-    description
-     "Initial revision.";
-    reference
-     "RFC 6021: Common YANG Data Types";
-  }
-
-  /*** collection of types related to protocol fields ***/
-
-  typedef ip-version {
-    type enumeration {
-      enum unknown {
-        value "0";
-        description
-         "An unknown or unspecified version of the Internet
-          protocol.";
-      }
-      enum ipv4 {
-        value "1";
-        description
-         "The IPv4 protocol as defined in RFC 791.";
-      }
-      enum ipv6 {
-        value "2";
-        description
-         "The IPv6 protocol as defined in RFC 2460.";
-      }
-    }
-    description
-     "This value represents the version of the IP protocol.
-
-      In the value set and its semantics, this type is equivalent
-      to the InetVersion textual convention of the SMIv2.";
-    reference
-     "RFC  791: Internet Protocol
-      RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
-      RFC 4001: Textual Conventions for Internet Network Addresses";
-  }
-
-  typedef dscp {
-    type uint8 {
-      range "0..63";
-    }
-    description
-     "The dscp type represents a Differentiated Services Code Point
-      that may be used for marking packets in a traffic stream.
-      In the value set and its semantics, this type is equivalent
-      to the Dscp textual convention of the SMIv2.";
-    reference
-     "RFC 3289: Management Information Base for the Differentiated
-                Services Architecture
-      RFC 2474: Definition of the Differentiated Services Field
-                (DS Field) in the IPv4 and IPv6 Headers
-      RFC 2780: IANA Allocation Guidelines For Values In
-                the Internet Protocol and Related Headers";
-  }
-
-  typedef ipv6-flow-label {
-    type uint32 {
-      range "0..1048575";
-    }
-    description
-     "The ipv6-flow-label type represents the flow identifier or Flow
-      Label in an IPv6 packet header that may be used to
-      discriminate traffic flows.
-
-      In the value set and its semantics, this type is equivalent
-      to the IPv6FlowLabel textual convention of the SMIv2.";
-    reference
-     "RFC 3595: Textual Conventions for IPv6 Flow Label
-      RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
-  }
-
-  typedef port-number {
-    type uint16 {
-      range "0..65535";
-    }
-    description
-     "The port-number type represents a 16-bit port number of an
-      Internet transport-layer protocol such as UDP, TCP, DCCP, or
-      SCTP.  Port numbers are assigned by IANA.  A current list of
-      all assignments is available from <http://www.iana.org/>.
-
-      Note that the port number value zero is reserved by IANA.  In
-      situations where the value zero does not make sense, it can
-      be excluded by subtyping the port-number type.
-      In the value set and its semantics, this type is equivalent
-      to the InetPortNumber textual convention of the SMIv2.";
-    reference
-     "RFC  768: User Datagram Protocol
-      RFC  793: Transmission Control Protocol
-      RFC 4960: Stream Control Transmission Protocol
-      RFC 4340: Datagram Congestion Control Protocol (DCCP)
-      RFC 4001: Textual Conventions for Internet Network Addresses";
-  }
-
-  /*** collection of types related to autonomous systems ***/
-
-  typedef as-number {
-    type uint32;
-    description
-     "The as-number type represents autonomous system numbers
-      which identify an Autonomous System (AS).  An AS is a set
-      of routers under a single technical administration, using
-      an interior gateway protocol and common metrics to route
-      packets within the AS, and using an exterior gateway
-      protocol to route packets to other ASes.  IANA maintains
-      the AS number space and has delegated large parts to the
-      regional registries.
-
-      Autonomous system numbers were originally limited to 16
-      bits.  BGP extensions have enlarged the autonomous system
-      number space to 32 bits.  This type therefore uses an uint32
-      base type without a range restriction in order to support
-      a larger autonomous system number space.
-
-      In the value set and its semantics, this type is equivalent
-      to the InetAutonomousSystemNumber textual convention of
-      the SMIv2.";
-    reference
-     "RFC 1930: Guidelines for creation, selection, and registration
-                of an Autonomous System (AS)
-      RFC 4271: A Border Gateway Protocol 4 (BGP-4)
-      RFC 4001: Textual Conventions for Internet Network Addresses
-      RFC 6793: BGP Support for Four-Octet Autonomous System (AS)
-                Number Space";
-  }
-
-  /*** collection of types related to IP addresses and hostnames ***/
-
-  typedef ip-address {
-    type union {
-      type inet:ipv4-address;
-      type inet:ipv6-address;
-    }
-    description
-     "The ip-address type represents an IP address and is IP
-      version neutral.  The format of the textual representation
-      implies the IP version.  This type supports scoped addresses
-      by allowing zone identifiers in the address format.";
-    reference
-     "RFC 4007: IPv6 Scoped Address Architecture";
-  }
-
-  typedef ipv4-address {
-    type string {
-      pattern
-        '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
-      +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
-      + '(%[\p{N}\p{L}]+)?';
-    }
-    description
-      "The ipv4-address type represents an IPv4 address in
-       dotted-quad notation.  The IPv4 address may include a zone
-       index, separated by a % sign.
-
-       The zone index is used to disambiguate identical address
-       values.  For link-local addresses, the zone index will
-       typically be the interface index number or the name of an
-       interface.  If the zone index is not present, the default
-       zone of the device will be used.
-
-       The canonical format for the zone index is the numerical
-       format";
-  }
-
-  typedef ipv6-address {
-    type string {
-      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
-            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
-            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
-            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
-            + '(%[\p{N}\p{L}]+)?';
-      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
-            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
-            + '(%.+)?';
-    }
-    description
-     "The ipv6-address type represents an IPv6 address in full,
-      mixed, shortened, and shortened-mixed notation.  The IPv6
-      address may include a zone index, separated by a % sign.
-
-      The zone index is used to disambiguate identical address
-      values.  For link-local addresses, the zone index will
-      typically be the interface index number or the name of an
-      interface.  If the zone index is not present, the default
-      zone of the device will be used.
-
-
-
-      The canonical format of IPv6 addresses uses the textual
-      representation defined in Section 4 of RFC 5952.  The
-      canonical format for the zone index is the numerical
-      format as described in Section 11.2 of RFC 4007.";
-    reference
-     "RFC 4291: IP Version 6 Addressing Architecture
-      RFC 4007: IPv6 Scoped Address Architecture
-      RFC 5952: A Recommendation for IPv6 Address Text
-                Representation";
-  }
-
-  typedef ip-address-no-zone {
-    type union {
-      type inet:ipv4-address-no-zone;
-      type inet:ipv6-address-no-zone;
-    }
-    description
-     "The ip-address-no-zone type represents an IP address and is
-      IP version neutral.  The format of the textual representation
-      implies the IP version.  This type does not support scoped
-      addresses since it does not allow zone identifiers in the
-      address format.";
-    reference
-     "RFC 4007: IPv6 Scoped Address Architecture";
-  }
-
-  typedef ipv4-address-no-zone {
-    type inet:ipv4-address {
-      pattern '[0-9\.]*';
-    }
-    description
-      "An IPv4 address without a zone index.  This type, derived from
-       ipv4-address, may be used in situations where the zone is
-       known from the context and hence no zone index is needed.";
-  }
-
-  typedef ipv6-address-no-zone {
-    type inet:ipv6-address {
-      pattern '[0-9a-fA-F:\.]*';
-    }
-    description
-      "An IPv6 address without a zone index.  This type, derived from
-       ipv6-address, may be used in situations where the zone is
-       known from the context and hence no zone index is needed.";
-    reference
-     "RFC 4291: IP Version 6 Addressing Architecture
-      RFC 4007: IPv6 Scoped Address Architecture
-      RFC 5952: A Recommendation for IPv6 Address Text
-                Representation";
-  }
-
-  typedef ip-prefix {
-    type union {
-      type inet:ipv4-prefix;
-      type inet:ipv6-prefix;
-    }
-    description
-     "The ip-prefix type represents an IP prefix and is IP
-      version neutral.  The format of the textual representations
-      implies the IP version.";
-  }
-
-  typedef ipv4-prefix {
-    type string {
-      pattern
-         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
-       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
-       + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
-    }
-    description
-     "The ipv4-prefix type represents an IPv4 address prefix.
-      The prefix length is given by the number following the
-      slash character and must be less than or equal to 32.
-
-      A prefix length value of n corresponds to an IP address
-      mask that has n contiguous 1-bits from the most
-      significant bit (MSB) and all other bits set to 0.
-
-      The canonical format of an IPv4 prefix has all bits of
-      the IPv4 address set to zero that are not part of the
-      IPv4 prefix.";
-  }
-
-  typedef ipv6-prefix {
-    type string {
-      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
-            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
-            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
-            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
-            + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
-      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
-            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
-            + '(/.+)';
-    }
-
-
-    description
-     "The ipv6-prefix type represents an IPv6 address prefix.
-      The prefix length is given by the number following the
-      slash character and must be less than or equal to 128.
-
-      A prefix length value of n corresponds to an IP address
-      mask that has n contiguous 1-bits from the most
-      significant bit (MSB) and all other bits set to 0.
-
-      The IPv6 address should have all bits that do not belong
-      to the prefix set to zero.
-
-      The canonical format of an IPv6 prefix has all bits of
-      the IPv6 address set to zero that are not part of the
-      IPv6 prefix.  Furthermore, the IPv6 address is represented
-      as defined in Section 4 of RFC 5952.";
-    reference
-     "RFC 5952: A Recommendation for IPv6 Address Text
-                Representation";
-  }
-
-  /*** collection of domain name and URI types ***/
-
-  typedef domain-name {
-    type string {
-      pattern
-        '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
-      + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
-      + '|\.';
-      length "1..253";
-    }
-    description
-     "The domain-name type represents a DNS domain name.  The
-      name SHOULD be fully qualified whenever possible.
-
-      Internet domain names are only loosely specified.  Section
-      3.5 of RFC 1034 recommends a syntax (modified in Section
-      2.1 of RFC 1123).  The pattern above is intended to allow
-      for current practice in domain name use, and some possible
-      future expansion.  It is designed to hold various types of
-      domain names, including names used for A or AAAA records
-      (host names) and other records, such as SRV records.  Note
-      that Internet host names have a stricter syntax (described
-      in RFC 952) than the DNS recommendations in RFCs 1034 and
-      1123, and that systems that want to store host names in
-      schema nodes using the domain-name type are recommended to
-      adhere to this stricter standard to ensure interoperability.
-
-      The encoding of DNS names in the DNS protocol is limited
-      to 255 characters.  Since the encoding consists of labels
-      prefixed by a length bytes and there is a trailing NULL
-      byte, only 253 characters can appear in the textual dotted
-      notation.
-
-      The description clause of schema nodes using the domain-name
-      type MUST describe when and how these names are resolved to
-      IP addresses.  Note that the resolution of a domain-name value
-      may require to query multiple DNS records (e.g., A for IPv4
-      and AAAA for IPv6).  The order of the resolution process and
-      which DNS record takes precedence can either be defined
-      explicitly or may depend on the configuration of the
-      resolver.
-
-      Domain-name values use the US-ASCII encoding.  Their canonical
-      format uses lowercase US-ASCII characters.  Internationalized
-      domain names MUST be A-labels as per RFC 5890.";
-    reference
-     "RFC  952: DoD Internet Host Table Specification
-      RFC 1034: Domain Names - Concepts and Facilities
-      RFC 1123: Requirements for Internet Hosts -- Application
-                and Support
-      RFC 2782: A DNS RR for specifying the location of services
-                (DNS SRV)
-      RFC 5890: Internationalized Domain Names in Applications
-                (IDNA): Definitions and Document Framework";
-  }
-
-  typedef host {
-    type union {
-      type inet:ip-address;
-      type inet:domain-name;
-    }
-    description
-     "The host type represents either an IP address or a DNS
-      domain name.";
-  }
-
-  typedef uri {
-    type string;
-    description
-     "The uri type represents a Uniform Resource Identifier
-      (URI) as defined by STD 66.
-
-      Objects using the uri type MUST be in US-ASCII encoding,
-      and MUST be normalized as described by RFC 3986 Sections
-      6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
-      percent-encoding is removed, and all case-insensitive
-      characters are set to lowercase except for hexadecimal
-      digits, which are normalized to uppercase as described in
-      Section 6.2.2.1.
-
-      The purpose of this normalization is to help provide
-      unique URIs.  Note that this normalization is not
-      sufficient to provide uniqueness.  Two URIs that are
-      textually distinct after this normalization may still be
-      equivalent.
-
-      Objects using the uri type may restrict the schemes that
-      they permit.  For example, 'data:' and 'urn:' schemes
-      might not be appropriate.
-
-      A zero-length URI is not a valid URI.  This can be used to
-      express 'URI absent' where required.
-
-      In the value set and its semantics, this type is equivalent
-      to the Uri SMIv2 textual convention defined in RFC 5017.";
-    reference
-     "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
-      RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
-                Group: Uniform Resource Identifiers (URIs), URLs,
-                and Uniform Resource Names (URNs): Clarifications
-                and Recommendations
-      RFC 5017: MIB Textual Conventions for Uniform Resource
-                Identifiers (URIs)";
-  }
-
-}
\ No newline at end of file
index 5c51b7c16364a8266f189db1fb60282f19823094..7e394d6a34c6de95109b3de19f752c32116e51f2 100644 (file)
@@ -1735,29 +1735,6 @@ module ned {
         }
     }
 
-    grouping config-service-chain-grouping {
-        leaf description {
-            tailf:info "Service function forwarder description";
-            description "Service function forwarder description";
-            tailf:cli-multi-value;
-            type string {
-                tailf:info "LINE;;Up to 256 characters describing this " + "service function forwarder";
-                length "1..256";
-            }
-        }
-        container ip {
-            tailf:info "IP address for Service Function Forwarder";
-            description "IP address for Service Function Forwarder";
-            leaf address {
-                tailf:info "Set IPv4 address";
-                description "Set IPv4 address";
-                type inet:ipv4-address {
-                    tailf:info "A.B.C.D;;IP address of Service Function Forwarder";
-                }
-            }
-        }
-    }
-
     grouping interface-atm-grouping {
         // Removed body
     }
@@ -6619,6 +6596,29 @@ module ned {
 /// service-chain
 /// ========================================================================
 
+        grouping config-service-chain-grouping {
+            leaf description {
+                tailf:info "Service function forwarder description";
+                description "Service function forwarder description";
+                tailf:cli-multi-value;
+                type string {
+                    tailf:info "LINE;;Up to 256 characters describing this " + "service function forwarder";
+                    length "1..256";
+                }
+            }
+            container ip {
+                tailf:info "IP address for Service Function Forwarder";
+                description "IP address for Service Function Forwarder";
+                leaf address {
+                    tailf:info "Set IPv4 address";
+                    description "Set IPv4 address";
+                    type inet:ipv4-address {
+                        tailf:info "A.B.C.D;;IP address of Service Function Forwarder";
+                    }
+                }
+            }
+        }
+
         container service-chain {
             tailf:info "Service Chain mode";
             description "Service Chain mode";
diff --git a/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/cache/EpPolicyCacheImplTest.java b/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/cache/EpPolicyCacheImplTest.java
deleted file mode 100644 (file)
index 6d700a9..0000000
+++ /dev/null
@@ -1,153 +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.cache;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
-
-/**
- * Test for {@link EpPolicyCacheImpl}.
- */
-public class EpPolicyCacheImplTest {
-
-    private static final int SGT1 = 1;
-    private static final int SGT2 = 2;
-    private static final String TENANT1 = "tenant1";
-    private static final String TENANT2 = "tenant2";
-
-    private static final EpPolicyTemplateCacheKey KEY_1 = createKey(TENANT1, new String[]{"n1", "n2"});
-    private static final EpPolicyTemplateCacheKey KEY_2 = createKey(TENANT2, new String[]{"n3"});
-
-    private static final EndpointPolicyTemplateBySgt TEMPLATE_1 = createTemplate(SGT1, TENANT1, new String[]{"n1", "n2"});
-    private static final EndpointPolicyTemplateBySgt TEMPLATE_2 = createTemplate(SGT2, TENANT2, new String[]{"n3"});
-
-    private EpPolicyCacheImpl cache;
-
-    @Before
-    public void setUp() throws Exception {
-        cache = new EpPolicyCacheImpl();
-    }
-
-    @Test
-    public void testInvalidate() throws Exception {
-        cache.add(TEMPLATE_1);
-        cache.add(TEMPLATE_2);
-
-        checkValuePresence(KEY_1, SGT1);
-
-        checkValuePresence(KEY_2, SGT2);
-
-        cache.invalidate(TEMPLATE_1);
-        Assert.assertNull(cache.lookupValue(KEY_1));
-        Assert.assertNotNull(cache.lookupValue(KEY_2));
-    }
-
-    @Test
-    public void testAdd() throws Exception {
-        cache.add(TEMPLATE_1);
-        checkValuePresence(KEY_1, SGT1);
-    }
-
-    @Test
-    public void testUpdate() throws Exception {
-        cache.add(TEMPLATE_1);
-        checkValuePresence(KEY_1, SGT1);
-
-        cache.update(TEMPLATE_1, TEMPLATE_2);
-
-        Assert.assertNull(cache.lookupValue(KEY_1));
-        checkValuePresence(KEY_2, SGT2);
-    }
-
-    @Test
-    public void testLookupValue() throws Exception {
-        cache.add(TEMPLATE_1);
-        checkValuePresence(KEY_1, SGT1);
-    }
-
-    private void checkValuePresence(final EpPolicyTemplateCacheKey key, final int expectedSgt) {
-        final Sgt sgt = cache.lookupValue(key);
-        Assert.assertNotNull(sgt);
-        Assert.assertEquals(expectedSgt, sgt.getValue().intValue());
-    }
-
-    @Test
-    public void testLookupValue_withChangedOrder() throws Exception {
-        Assert.assertNull(cache.lookupValue(KEY_1));
-        cache.add(TEMPLATE_1);
-        checkValuePresence(KEY_1, SGT1);
-
-        final EpPolicyTemplateCacheKey twistedKey1 = createKey(TENANT1, new String[]{"n1", "n2"}, new String[]{"n2", "n1"});
-        checkValuePresence(twistedKey1, SGT1);
-
-        final EpPolicyTemplateCacheKey twistedKey2 = createKey(TENANT1, new String[]{"n2", "n1"}, new String[]{"n1", "n2"});
-        checkValuePresence(twistedKey2, SGT1);
-    }
-
-    @Test
-    public void testInvalidateAll() throws Exception {
-        cache.add(TEMPLATE_1);
-        cache.add(TEMPLATE_2);
-        checkValuePresence(KEY_1, SGT1);
-
-        cache.invalidateAll();
-        Assert.assertNull(cache.lookupValue(KEY_1));
-        Assert.assertNull(cache.lookupValue(KEY_2));
-    }
-
-    private static EndpointPolicyTemplateBySgt createTemplate(final int sgt, final String tenant, final String[] names) {
-        final List<ConditionName> conditions = buildConditions(names);
-        final List<EndpointGroupId> endpointGroupIds = buildEndpointGroupIds(names);
-
-        return new EndpointPolicyTemplateBySgtBuilder()
-                .setSgt(new Sgt(sgt))
-                .setTenant(new TenantId(tenant))
-                .setConditions(conditions)
-                .setEndpointGroups(endpointGroupIds)
-                .build();
-    }
-
-    private static List<EndpointGroupId> buildEndpointGroupIds(final String[] names) {
-        final List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
-        for (String epgId : names) {
-            endpointGroupIds.add(new EndpointGroupId(epgId));
-        }
-        return endpointGroupIds;
-    }
-
-    private static List<ConditionName> buildConditions(final String[] names) {
-        final List<ConditionName> conditions = new ArrayList<>();
-        for (String condition : names) {
-            conditions.add(new ConditionName(condition));
-        }
-        return conditions;
-    }
-
-    private static EpPolicyTemplateCacheKey createKey(final String tenant, final String[] names) {
-        return createKey(tenant, names, names);
-    }
-
-    private static EpPolicyTemplateCacheKey createKey(final String tenant, final String[] epgIds, final String[] conditionNames) {
-        return new EpPolicyTemplateCacheKey(new AddressEndpointWithLocationBuilder()
-                .setTenant(new TenantId(tenant))
-                .setEndpointGroup(buildEndpointGroupIds(epgIds))
-                .setCondition(buildConditions(conditionNames))
-                .build());
-    }
-}
\ No newline at end of file
diff --git a/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/EpPolicyTemplateBySgtListenerImplTest.java b/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/EpPolicyTemplateBySgtListenerImplTest.java
deleted file mode 100644 (file)
index 6c6931a..0000000
+++ /dev/null
@@ -1,129 +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.listener;
-
-import com.google.common.collect.Lists;
-import java.util.Collections;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Matchers;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-
-/**
- * Test for {@link EpPolicyTemplateBySgtListenerImpl}.
- */
-@RunWith(MockitoJUnitRunner.class)
-public class EpPolicyTemplateBySgtListenerImplTest {
-
-    private static final Sgt SGT1 = new Sgt(1);
-    private static final TenantId TENANT1 = new TenantId("tenant1");
-    private static final TenantId TENANT2 = new TenantId("tenant2");
-    @Mock
-    private DataBroker dataBroker;
-    @Mock
-    private DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> cache;
-    @Mock
-    private ListenerRegistration<EpPolicyTemplateBySgtListenerImpl> listenerRegistration;
-    @Mock
-    private DataTreeModification<EndpointPolicyTemplateBySgt> dataTreeModification;
-    @Mock
-    private DataObjectModification<EndpointPolicyTemplateBySgt> rootNode;
-
-    private final EndpointPolicyTemplateBySgt template1;
-    private final EndpointPolicyTemplateBySgt template2;
-
-    private EpPolicyTemplateBySgtListenerImpl listener;
-
-    public EpPolicyTemplateBySgtListenerImplTest() {
-        this.template1 = new EndpointPolicyTemplateBySgtBuilder()
-                .setSgt(SGT1)
-                .setTenant(TENANT1)
-                .setEndpointGroups(Lists.newArrayList(new EndpointGroupId("epg1"), new EndpointGroupId("epg2")))
-                .setConditions(Lists.newArrayList(new ConditionName("condition1"), new ConditionName("condition2")))
-                .build();
-
-        this.template2 = new EndpointPolicyTemplateBySgtBuilder()
-                .setSgt(SGT1)
-                .setTenant(TENANT2)
-                .setEndpointGroups(Lists.newArrayList(new EndpointGroupId("epg3"), new EndpointGroupId("epg4")))
-                .setConditions(Lists.newArrayList(new ConditionName("condition2"), new ConditionName("condition3")))
-                .build();
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        Mockito.when(dataBroker.registerDataTreeChangeListener(
-                Matchers.<DataTreeIdentifier<EndpointPolicyTemplateBySgt>>any(),
-                Matchers.<EpPolicyTemplateBySgtListenerImpl>any()))
-                .thenReturn(listenerRegistration);
-        listener = new EpPolicyTemplateBySgtListenerImpl(dataBroker, cache);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        Mockito.verifyNoMoreInteractions(cache);
-    }
-
-    @Test
-    public void testOnDataTreeChanged_add() throws Exception {
-        Mockito.when(rootNode.getDataAfter()).thenReturn(template1);
-        Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
-        Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
-
-        listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(cache).add(template1);
-    }
-
-    @Test
-    public void testOnDataTreeChanged_remove() throws Exception {
-        Mockito.when(rootNode.getDataBefore()).thenReturn(template1);
-        Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
-        Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
-
-        listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(cache).invalidate(template1);
-    }
-
-    @Test
-    public void testOnDataTreeChanged_update() throws Exception {
-        Mockito.when(rootNode.getDataBefore()).thenReturn(template1);
-        Mockito.when(rootNode.getDataAfter()).thenReturn(template2);
-        Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
-        Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
-
-        listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(cache).update(template1, template2);
-    }
-
-    @Test
-    public void testClose() throws Exception {
-        Mockito.verify(listenerRegistration, Mockito.never()).close();
-        listener.close();
-        Mockito.verify(listenerRegistration).close();
-        listener.close();
-        Mockito.verify(listenerRegistration, Mockito.times(2)).close();
-    }
-}
\ No newline at end of file
index 3337b078867576dd986a35fd52e92eadd5d2ab68..303bc8c55e448109f66d9f8429266a03bef705f0 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener;
 
 import java.util.Collections;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -66,6 +67,13 @@ public class RendererConfigurationListenerImplTest {
                                         .build()))
                                 .build())
                         .build())
+                .setVersion((long) order)
+                .build();
+    }
+
+    private RendererPolicy createVersion(final int order) {
+        return new RendererPolicyBuilder()
+                .setVersion((long) order)
                 .build();
     }
 
@@ -93,7 +101,7 @@ public class RendererConfigurationListenerImplTest {
         Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
 
         listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(policyManager).syncPolicy(policy1.getConfiguration(), null);
+        Mockito.verify(policyManager).syncPolicy(policy1.getConfiguration(), null, 0);
     }
 
     @Test
@@ -104,18 +112,18 @@ public class RendererConfigurationListenerImplTest {
         Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
 
         listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(policyManager).syncPolicy(policy2.getConfiguration(), policy1.getConfiguration());
+        Mockito.verify(policyManager).syncPolicy(policy2.getConfiguration(), policy1.getConfiguration(), 1);
     }
 
     @Test
     public void testOnDataTreeChanged_remove() throws Exception {
         Mockito.when(rootNode.getDataBefore()).thenReturn(policy2);
-        Mockito.when(rootNode.getDataAfter()).thenReturn(null);
+        Mockito.when(rootNode.getDataAfter()).thenReturn(createVersion(1));
         Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
         Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
 
         listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(policyManager).syncPolicy(null, policy2.getConfiguration());
+        Mockito.verify(policyManager).syncPolicy(null, policy2.getConfiguration(), 1);
     }
 
     @Test
diff --git a/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/NodeManagerTest.java b/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/NodeManagerTest.java
new file mode 100644 (file)
index 0000000..98aec52
--- /dev/null
@@ -0,0 +1,356 @@
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+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.RendererNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import javax.annotation.Nonnull;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+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.when;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connected;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connecting;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.UnableToConnect;
+
+
+public class NodeManagerTest extends CustomDataBrokerTest {
+
+    private final NodeId NODE_NAME = new NodeId("testNode");
+    private final TopologyId TOPOLOGY_ID = new TopologyId("topology-netconf");
+    private final Ipv4Address IPv4_ADDRESS = new Ipv4Address("174.25.75.11");
+    private NodeManager nodeManager;
+    private DataBroker dataBroker;
+
+    @Nonnull
+    @Override
+    public Collection<java.lang.Class<?>> getClassesFromModules() {
+        return Arrays.asList(Renderers.class, NetworkTopology.class, NetconfNode.class);
+    }
+
+    @Before
+    public void init() {
+        dataBroker = getDataBroker();
+        BindingAwareBroker.ProviderContext context = mock(BindingAwareBroker.ProviderContext.class);
+        MountPointService mountPointService = mock(MountPointService.class);
+        when(context.getSALService(any())).thenReturn(mountPointService);
+        nodeManager = new NodeManager(dataBroker, context);
+    }
+
+    @Test
+    public void testRegisterNewNode_connectingCase() throws Exception {
+        Node testNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(testNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    // Create Cases
+
+    @Test
+    public void testRegisterNewNode_connectedCaseNoIpAddress() throws Exception {
+        Node testNode = createNode(Connected, null, NODE_NAME, Capabilities.None);
+        nodeManager.syncNodes(testNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testRegisterNewNode_connectedCaseNullCapabilities() throws Exception {
+        Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.None);
+        nodeManager.syncNodes(testNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testRegisterNewNode_connectedCasePartialCapabilities() throws Exception {
+        Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial);
+        nodeManager.syncNodes(testNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testRegisterNewNode_connectedCaseFullCapabilities() throws Exception {
+        Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(testNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertNotNull(result);
+        assertTrue(result.size() == 1);
+    }
+
+    @Test
+    public void testRegisterNewNode_unableToConnectCase() throws Exception {
+        Node testNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(testNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testUpdateNode_fromConnectingToConnected() throws Exception {
+        Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(oldNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        assertNotNull(result);
+        assertTrue(result.size() == 1);
+    }
+
+    // Update Cases
+
+    @Test
+    public void testUpdateNode_fromConnectingToUnableToConnect() throws Exception {
+        Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        Node newNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(oldNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testUpdateNode_fromConnectedToConnecting() throws Exception {
+        Node oldNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        Node newNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(oldNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertNotNull(result);
+        assertTrue(result.size() == 1);
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testUpdateNode_fromConnectedToUnableToConnect() throws Exception {
+        Node oldNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        Node newNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(oldNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertNotNull(result);
+        assertTrue(result.size() == 1);
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testUpdateNode_fromUnableToConnectToConnecting() throws Exception {
+        Node oldNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        Node newNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(oldNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testUpdateNode_fromUnableToConnectToConnected() throws Exception {
+        Node oldNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(oldNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        assertNotNull(result);
+        assertTrue(result.size() == 1);
+    }
+
+    @Test
+    public void testUpdateNode_advancedCase() throws Exception {
+        Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial);
+        nodeManager.syncNodes(oldNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        // One node is connecting, partial capabilities = empty list
+        assertTrue(result.isEmpty());
+        Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial);
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        // Update 1.: node is connected, still partial capabilities = empty list
+        assertTrue(result.isEmpty());
+        oldNode = newNode;
+        newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        // Update 2.: node is connected, full capabilities = 1 entry in list
+        assertNotNull(result);
+        assertTrue(result.size() == 1);
+        oldNode = newNode;
+        newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.None);
+        nodeManager.syncNodes(newNode, oldNode);
+        result = rendererNodesReader();
+        // Update 3.: node remains connected, but without capabilities = empty list
+        assertTrue(result.isEmpty());
+    }
+
+    // Advanced update Case
+
+    @Test
+    public void testRemoveNode() throws Exception {
+        Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        nodeManager.syncNodes(testNode, null);
+        List<RendererNode> result = rendererNodesReader();
+        assertNotNull(result);
+        assertTrue(result.size() == 1);
+        nodeManager.syncNodes(null, testNode);
+        result = rendererNodesReader();
+        assertTrue(result.isEmpty());
+    }
+
+    // Remove Case
+
+    @Test
+    public void getNodeManagementIpByMountPointIid_absentNode() {
+        NodeId testNodeId = new NodeId(NODE_NAME);
+        InstanceIdentifier mountpointIid = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID)))
+                .child(Node.class, new NodeKey(testNodeId)).build();
+        String ipAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
+        assertNull(ipAddress);
+    }
+
+    @Test
+    public void getNodeManagementIpByMountPointIid_ipV4Case() throws Exception {
+        // Put node
+        Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+        InstanceIdentifier<Node> testNodeIid = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID)))
+                .child(Node.class, new NodeKey(testNode.getNodeId())).build();
+        ReadWriteTransaction rwt = dataBroker.newReadWriteTransaction();
+        rwt.put(LogicalDatastoreType.CONFIGURATION, testNodeIid, testNode, true);
+        rwt.submit().checkedGet();
+        InstanceIdentifier mountpointIid = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID)))
+                .child(Node.class, new NodeKey(NODE_NAME)).build();
+        String result = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
+        assertEquals(IPv4_ADDRESS.getValue(), result);
+    }
+
+    private Node createNode(final NetconfNodeConnectionStatus.ConnectionStatus connectionStatus,
+                            final Ipv4Address ipAddress,
+                            final NodeId nodeName,
+                            final Capabilities choice) {
+        AvailableCapabilities capabilities = null;
+        switch (choice) {
+            case None: {
+                capabilities = emptyCapabilities();
+                break;
+            }
+            case Partial: {
+                capabilities = partialCapabilities();
+                break;
+            }
+            case Full: {
+                capabilities = fullCapabilities();
+            }
+        }
+        // Netconf node
+        NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder();
+        netconfNodeBuilder.setConnectionStatus(connectionStatus)
+                .setAvailableCapabilities(capabilities)
+                .setHost(new Host(new IpAddress(ipAddress)));
+        // Node
+        NodeBuilder nodeBuilder = new NodeBuilder();
+        nodeBuilder.setNodeId(new NodeId(nodeName))
+                .setKey(new NodeKey(new NodeId(nodeName)))
+                .addAugmentation(NetconfNode.class, netconfNodeBuilder.build());
+        return nodeBuilder.build();
+    }
+
+    // Utility methods
+
+    private List<RendererNode> rendererNodesReader() throws Exception {
+        InstanceIdentifier<Renderers> renderersIid =
+                InstanceIdentifier.builder(Renderers.class).build();
+        ReadWriteTransaction rwt = dataBroker.newReadWriteTransaction();
+        CheckedFuture<Optional<Renderers>, ReadFailedException> submitFuture =
+                rwt.read(LogicalDatastoreType.OPERATIONAL, renderersIid);
+        Optional<Renderers> optionalRenderers = submitFuture.checkedGet();
+        if (optionalRenderers.isPresent()) {
+            Renderers renderers = optionalRenderers.get();
+            if (renderers != null && renderers.getRenderer() != null && !renderers.getRenderer().isEmpty()) {
+                RendererNodes writtenNodes = renderers.getRenderer().get(0).getRendererNodes();
+                if (writtenNodes != null) {
+                    return writtenNodes.getRendererNode();
+                }
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    private AvailableCapabilities emptyCapabilities() {
+        AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder();
+        return availableCapabilitiesBuilder.build();
+    }
+
+    private AvailableCapabilities partialCapabilities() {
+        final String c1 = "(urn:ios?revision=2016-03-08)ned";
+        final String c2 = "(http://tail-f.com/yang/common?revision=2015-05-22)tailf-common";
+        final String c3 = "(http://tail-f.com/yang/common?revision=2015-03-19)tailf-cli-extensions";
+        String[] capabilityList = {c1, c2, c3};
+        AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder();
+        availableCapabilitiesBuilder.setAvailableCapability(Arrays.asList(capabilityList));
+        return availableCapabilitiesBuilder.build();
+    }
+
+    private AvailableCapabilities fullCapabilities() {
+        final String c1 = "(urn:ios?revision=2016-03-08)ned";
+        final String c2 = "(http://tail-f.com/yang/common?revision=2015-05-22)tailf-common";
+        final String c3 = "(http://tail-f.com/yang/common?revision=2015-03-19)tailf-cli-extensions";
+        final String c4 = "(http://tail-f.com/yang/common?revision=2013-11-07)tailf-meta-extensions";
+        final String c5 = "(urn:ietf:params:xml:ns:yang:ietf-yang-types?revision=2013-07-15)ietf-yang-types";
+        final String c6 = "(urn:ietf:params:xml:ns:yang:ietf-inet-types?revision=2013-07-15)ietf-inet-types";
+        String[] capabilityList = {c1, c2, c3, c4, c5, c6};
+        AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder();
+        availableCapabilitiesBuilder.setAvailableCapability(Arrays.asList(capabilityList));
+        return availableCapabilitiesBuilder.build();
+    }
+
+    private enum Capabilities {None, Partial, Full}
+}
\ No newline at end of file
diff --git a/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImplTest.java b/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImplTest.java
new file mode 100644 (file)
index 0000000..100ba97
--- /dev/null
@@ -0,0 +1,399 @@
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+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.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import java.util.List;
+
+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.WriteTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.ServiceChainingUtil;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
+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.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
+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.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipationKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.ConfigurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.EndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererEndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererForwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RuleGroupsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
+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.RendererEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.ClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRuleBuilder;
+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.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.AddressEndpointWithLocationAugBuilder;
+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.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({RendererPolicyUtil.class, PolicyManagerUtil.class, SfcProviderServiceForwarderAPI.class})
+public class PolicyManagerImplTest {
+
+    private final String address = "address";
+    private final String connector = "connector";
+    private final SfpName servicePath = new SfpName("service-path");
+    private final RspName renderedPath = new RspName("rendered-path");
+    private final SffName forwarderName = new SffName("service-forwarder");
+    private final ContextId contextId_1 = new ContextId("context-id-1");
+    private final ContextId contextId_2 = new ContextId("context-id-2");
+    private final ContextId contextId_3 = new ContextId("context-id-3");
+    private final ContextId contextId_4 = new ContextId("context-id-4");
+    private final ContractId contractId = new ContractId("contract-id");
+    private final String ipAddress = "192.168.50.1";
+    private final NodeId nodeId = new NodeId("node-id");
+    private final SubjectName subjectName = new SubjectName("subject-name");
+    private final TenantId tenantId = new TenantId("tenant-id");
+    private final TopologyId topologyId = new TopologyId("topology-id");
+    private final ActionDefinitionId chainActionDefinitionId = new ActionDefinitionId("Action-Chain");
+    private final ActionDefinitionId otherActionDefinitionId = new ActionDefinitionId("Action-Other");
+    private final SfName functionName = new SfName("service-function");
+    private PolicyManagerImpl policyManager;
+    private DataBroker mountpoint;
+    private NodeManager nodeManager;
+    private WriteTransaction writeTransaction;
+
+    @Before
+    public void init() {
+        mountpoint = mock(DataBroker.class);
+        writeTransaction = mock(WriteTransaction.class);
+        nodeManager = mock(NodeManager.class);
+        policyManager = new PolicyManagerImpl(mountpoint, nodeManager);
+        when(mountpoint.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+        when(writeTransaction.submit()).thenReturn(Futures.immediateCheckedFuture((Void) null));
+    }
+
+    @Test
+    public void testSyncPolicy_emptyConfiguration() throws Exception {
+        Configuration policyConfiguration = createTestConfiguration(null, null, null, null);
+        ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null, 0);
+        assertTrue((boolean) result.get());
+    }
+
+    @Test
+    public void testSyncPolicy_noEndpointsInConfiguration() throws Exception {
+        RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_1, contextId_2, null);
+        Configuration policyConfiguration = createTestConfiguration(null, Collections.singletonList(rendererEndpoint),
+                null, null);
+        ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null, 0);
+        assertTrue((boolean) result.get());
+    }
+
+    @Test
+    public void testSyncPolicy_noMountPoint() throws Exception {
+        AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+        RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3, null);
+        Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+                Collections.singletonList(rendererEndpoint), null, null);
+
+        AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+        AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, false);
+        stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+        when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(null);
+
+        ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null, 0);
+        assertTrue((boolean) result.get());
+    }
+
+    @Test
+    public void testSyncPolicy_nullSgtTags() throws Exception {
+        AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+        RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3, null);
+        Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+                Collections.singletonList(rendererEndpoint), null, null);
+
+        AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+        AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, false);
+        stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+        when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+        when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+        when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+
+        ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null, 0);
+        assertTrue((boolean) result.get());
+    }
+
+    @Test
+    public void testSyncPolicy_emptyRuleGroup() throws Exception {
+        AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+        RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation =
+                createRuleGroupWithRendererEpParticipation(PROVIDER);
+        RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3,
+                ruleGroupWithParticipation);
+        RuleGroup ruleGroup = createRuleGroup(null);
+        Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+                Collections.singletonList(rendererEndpoint), null, ruleGroup);
+
+        AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+        AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, true);
+        stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+        when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+        when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+        when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+
+        ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null, 0);
+        assertTrue((boolean) result.get());
+    }
+
+    @Test
+    public void testSyncPolicy_noActionDefinition() throws Exception {
+        AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+        RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation =
+                createRuleGroupWithRendererEpParticipation(PROVIDER);
+        RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3,
+                ruleGroupWithParticipation);
+
+        RuleGroup ruleGroup = createRuleGroup(createRule(Out, null));
+        Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+                Collections.singletonList(rendererEndpoint), null, ruleGroup);
+
+        AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+        AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, true);
+        stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+        when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+        when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+        when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+
+        ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null, 0);
+        assertTrue((boolean) result.get());
+    }
+
+    @Test
+    public void testSyncPolicy_otherAction() throws Exception {
+        AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+        RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation =
+                createRuleGroupWithRendererEpParticipation(PROVIDER);
+        RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3,
+                ruleGroupWithParticipation);
+
+        RuleGroup ruleGroup = createRuleGroup(createRule(Out, otherActionDefinitionId));
+        Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+                Collections.singletonList(rendererEndpoint), null, ruleGroup);
+
+        AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+        AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, true);
+        stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+        when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+        when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+        when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+
+        ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null, 0);
+        assertTrue((boolean) result.get());
+    }
+
+    @Test
+    public void testSyncPolicy_asymmetricChain() throws Exception {
+        AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+        RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation =
+                createRuleGroupWithRendererEpParticipation(PROVIDER);
+        RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3,
+                ruleGroupWithParticipation);
+
+        RuleGroup ruleGroup = createRuleGroup(createRule(Out, chainActionDefinitionId));
+        Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+                Collections.singletonList(rendererEndpoint), null, ruleGroup);
+
+        AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+        AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, true);
+        stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+        when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+        when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+        when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+        ServiceFunctionPath sfp = createServiceFunctionPath();
+        stub(method(ServiceChainingUtil.class, "getServicePath")).toReturn(sfp);
+        RenderedServicePath rsp = createRenderedServicePath();
+        stub(method(ServiceChainingUtil.class, "createRenderedPath")).toReturn(rsp);
+        ServiceFunctionForwarder serviceFunctionForwarder = createServiceForwarder();
+        stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder"))
+                .toReturn(serviceFunctionForwarder);
+
+        ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null, 0);
+        assertTrue((boolean) result.get());
+    }
+
+    private ServiceFunctionForwarder createServiceForwarder() {
+        ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder = new ServiceFunctionForwarderBuilder();
+        serviceFunctionForwarderBuilder.setName(new SffName(forwarderName))
+                .setKey(new ServiceFunctionForwarderKey(new SffName(forwarderName)))
+                .setIpMgmtAddress(new IpAddress(new Ipv4Address(ipAddress)));
+        return serviceFunctionForwarderBuilder.build();
+    }
+
+    // Utility methods
+
+    private InstanceIdentifier createMountpointIid() {
+        return InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(topologyId))
+                .child(Node.class, new NodeKey(nodeId)).build();
+    }
+
+    private ResolvedRule createRule(HasDirection.Direction direction, ActionDefinitionId actionDefinitionId) {
+        ResolvedRuleBuilder resolvedRuleBuilder = new ResolvedRuleBuilder();
+        ClassifierBuilder classifierBuilder = new ClassifierBuilder();
+        classifierBuilder.setDirection(direction);
+        ActionBuilder actionBuilder = new ActionBuilder();
+        actionBuilder.setActionDefinitionId(actionDefinitionId);
+        resolvedRuleBuilder.setClassifier(Collections.singletonList(classifierBuilder.build()))
+                .setAction(Collections.singletonList(actionBuilder.build()));
+        return resolvedRuleBuilder.build();
+    }
+
+    private RuleGroupWithRendererEndpointParticipation createRuleGroupWithRendererEpParticipation(final EndpointPolicyParticipation participation) {
+        RuleGroupWithRendererEndpointParticipationBuilder ruleGroupBuilder = new RuleGroupWithRendererEndpointParticipationBuilder();
+        ruleGroupBuilder.setKey(new RuleGroupWithRendererEndpointParticipationKey(contractId, participation, subjectName,
+                tenantId));
+        return ruleGroupBuilder.build();
+    }
+
+    private AbsoluteLocation createAbsoluteLocationExternal(String connector, InstanceIdentifier mountpoint) {
+        ExternalLocationCaseBuilder externalLocationCaseBuilder = new ExternalLocationCaseBuilder();
+        externalLocationCaseBuilder.setExternalNodeConnector(connector)
+                .setExternalNodeMountPoint(mountpoint);
+        AbsoluteLocationBuilder absoluteLocationBuilder = new AbsoluteLocationBuilder();
+        absoluteLocationBuilder.setLocationType(externalLocationCaseBuilder.build());
+        return absoluteLocationBuilder.build();
+    }
+
+    private ServiceFunctionPath createServiceFunctionPath() {
+        ServiceFunctionPathBuilder serviceFunctionPathBuilder = new ServiceFunctionPathBuilder();
+        serviceFunctionPathBuilder.setKey(new ServiceFunctionPathKey(servicePath))
+                .setSymmetric(false);
+        return serviceFunctionPathBuilder.build();
+    }
+
+    private RenderedServicePath createRenderedServicePath() {
+        RenderedServicePathHopBuilder renderedServicePathHopBuilder = new RenderedServicePathHopBuilder();
+        renderedServicePathHopBuilder.setServiceFunctionForwarder(forwarderName);
+        renderedServicePathHopBuilder.setServiceFunctionName(functionName);
+        renderedServicePathHopBuilder.build();
+
+        RenderedServicePathBuilder renderedServicePathBuilder = new RenderedServicePathBuilder();
+        renderedServicePathBuilder.setKey(new RenderedServicePathKey(renderedPath))
+                .setRenderedServicePathHop(Collections.singletonList(renderedServicePathHopBuilder.build()));
+        return renderedServicePathBuilder.build();
+    }
+
+
+    private AddressEndpointWithLocation createAddressEndpointWithLocation(final ContextId contextId,
+                                                                          final AbsoluteLocation location,
+                                                                          boolean augmentation) {
+        AddressEndpointWithLocationAugBuilder augmentationBuilder = new AddressEndpointWithLocationAugBuilder();
+        augmentationBuilder.setSgt(new Sgt(1));
+        AddressEndpointWithLocationBuilder addressEndpointBuilder = new AddressEndpointWithLocationBuilder();
+        addressEndpointBuilder.setKey(new AddressEndpointWithLocationKey(address, IpPrefixType.class,
+                contextId, L2BridgeDomain.class))
+                .setAbsoluteLocation(location);
+        if (augmentation) {
+            addressEndpointBuilder.addAugmentation(AddressEndpointWithLocationAug.class, augmentationBuilder.build());
+        }
+        return addressEndpointBuilder.build();
+    }
+
+    private RendererEndpoint createRendererEndpoint(ContextId contextId_1, ContextId contextId_2,
+                                                    RuleGroupWithRendererEndpointParticipation ruleGroup) {
+        PeerEndpointWithPolicyBuilder peerEndpointWithPolicyBuilder = new PeerEndpointWithPolicyBuilder();
+        peerEndpointWithPolicyBuilder.setKey(new PeerEndpointWithPolicyKey(address, IpPrefixType.class, contextId_1,
+                L2BridgeDomain.class))
+                .setRuleGroupWithRendererEndpointParticipation(Collections.singletonList(ruleGroup));
+        RendererEndpointBuilder rendererEndpointBuilder = new RendererEndpointBuilder();
+        rendererEndpointBuilder.setKey(new RendererEndpointKey(address, IpPrefixType.class, contextId_2,
+                L2BridgeDomain.class))
+                .setPeerEndpointWithPolicy(Collections.singletonList(peerEndpointWithPolicyBuilder.build()));
+        return rendererEndpointBuilder.build();
+    }
+
+    private RuleGroup createRuleGroup(ResolvedRule rule) {
+        RuleGroupBuilder ruleGroupBuilder = new RuleGroupBuilder();
+        ruleGroupBuilder.setKey(new RuleGroupKey(contractId, subjectName, tenantId))
+                .setResolvedRule(Collections.singletonList(rule));
+        return ruleGroupBuilder.build();
+    }
+
+    private Configuration createTestConfiguration(final List<AddressEndpointWithLocation> endpointsWithLocation,
+                                                  final List<RendererEndpoint> rendererEndpoints,
+                                                  final RendererForwarding rendererForwarding,
+                                                  final RuleGroup ruleGroup) {
+        // Set endpoints
+        EndpointsBuilder endpointsBuilder = new EndpointsBuilder();
+        endpointsBuilder.setAddressEndpointWithLocation(endpointsWithLocation);
+        // Set renderer endpoints
+        RendererEndpointsBuilder rendererEndpointsBuilder = new RendererEndpointsBuilder();
+        rendererEndpointsBuilder.setRendererEndpoint(rendererEndpoints);
+        // Set rule group
+        RuleGroupsBuilder ruleGroupsBuilder = new RuleGroupsBuilder();
+        ruleGroupsBuilder.setRuleGroup(Collections.singletonList(ruleGroup));
+        // Build configuration
+        ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
+        configurationBuilder.setEndpoints(endpointsBuilder.build())
+                .setRendererEndpoints(rendererEndpointsBuilder.build())
+                .setRendererForwarding(rendererForwarding)
+                .setRuleGroups(ruleGroupsBuilder.build());
+        return configurationBuilder.build();
+    }
+
+
+}
\ No newline at end of file
index aac65c819f0d80a4d27dc1c4bbfe3119af8a8446..7dd6b67ee31602e10afe44cac6e1673eec1e4384 100644 (file)
@@ -8,12 +8,11 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
 
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -26,11 +25,15 @@ import org.mockito.invocation.InvocationOnMock;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.mockito.stubbing.Answer;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.ConfigurationBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 /**
  * Test for {@link PolicyManagerZipImpl}.
  */
@@ -60,23 +63,23 @@ public class PolicyManagerZipImplTest {
 
     @Test
     public void testSyncPolicy_add() throws Exception {
-        policyManager.syncPolicy(null, configAfter);
+        policyManager.syncPolicy(null, configAfter, 0);
         policyManager.close();
-        Mockito.verify(delegate).syncPolicy(null, configAfter);
+        Mockito.verify(delegate).syncPolicy(null, configAfter, 0);
     }
 
     @Test
     public void testSyncPolicy_update() throws Exception {
-        policyManager.syncPolicy(configBefore, configAfter);
+        policyManager.syncPolicy(configBefore, configAfter, 0);
         policyManager.close();
-        Mockito.verify(delegate).syncPolicy(configBefore, configAfter);
+        Mockito.verify(delegate).syncPolicy(configBefore, configAfter, 0);
     }
 
     @Test
     public void testSyncPolicy_remove() throws Exception {
-        policyManager.syncPolicy(configBefore, null);
+        policyManager.syncPolicy(configBefore, null, 0);
         policyManager.close();
-        Mockito.verify(delegate).syncPolicy(configBefore, null);
+        Mockito.verify(delegate).syncPolicy(configBefore, null, 0);
     }
 
     @Test
@@ -91,7 +94,7 @@ public class PolicyManagerZipImplTest {
         final CountDownLatch latchForFirst = new CountDownLatch(1);
         final CountDownLatch latchForOthers = new CountDownLatch(1);
 
-        Mockito.when(delegate.syncPolicy(Matchers.<Configuration>any(), Matchers.<Configuration>any()))
+        Mockito.when(delegate.syncPolicy(Matchers.<Configuration>any(), Matchers.<Configuration>any(), Matchers.anyLong()))
                 .thenAnswer(new Answer<ListenableFuture<Boolean>>() {
                     @Override
                     public ListenableFuture<Boolean> answer(final InvocationOnMock invocationOnMock) throws Throwable {
@@ -105,19 +108,19 @@ public class PolicyManagerZipImplTest {
                 .thenReturn(Futures.immediateFuture(true));
 
         final List<ListenableFuture<Boolean>> allResults = new ArrayList<>();
-        allResults.add(policyManager.syncPolicy(null, configBefore));
+        allResults.add(policyManager.syncPolicy(null, configBefore, 0));
 
         latchForOthers.await(1, TimeUnit.SECONDS);
-        allResults.add(policyManager.syncPolicy(configBefore, configAfter));
-        allResults.add(policyManager.syncPolicy(configAfter, null));
-        allResults.add(policyManager.syncPolicy(null, configAfter2));
+        allResults.add(policyManager.syncPolicy(configBefore, configAfter, 0));
+        allResults.add(policyManager.syncPolicy(configAfter, null, 0));
+        allResults.add(policyManager.syncPolicy(null, configAfter2, 0));
         latchForFirst.countDown();
 
         Futures.allAsList(allResults).get(1, TimeUnit.SECONDS);
         LOG.info("all configs finished");
         policyManager.close();
         final InOrder inOrder = Mockito.inOrder(delegate);
-        inOrder.verify(delegate).syncPolicy(null, configBefore);
-        inOrder.verify(delegate).syncPolicy(configBefore, configAfter2);
+        inOrder.verify(delegate).syncPolicy(null, configBefore, 0);
+        inOrder.verify(delegate).syncPolicy(configBefore, configAfter2, 0);
     }
 }
\ No newline at end of file
index 810a3f12d82a3a2d51fd10a5e0fdcaa1de1e84e6..af067b529ce388664c6165b596c2c7e2db77ffc9 100644 (file)
@@ -24,6 +24,7 @@ import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 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.writer.NodeWriter;
 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.renderer.RendererNodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
index b189656dbc2aeac982a4f162ea95d85b40e65170..fba4c12a67e2b2d07911d59f3d1fb79e99344c64 100644 (file)
@@ -34,12 +34,15 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev1407
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
 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.yangtools.yang.binding.InstanceIdentifier;
 
+import static org.junit.Assert.assertNotNull;
+
 /**
  * Test for {@link PolicyManagerUtil}.
  */
@@ -65,6 +68,12 @@ public class PolicyManagerUtilTest {
         new OpendaylightSfc().setDataProvider(dataBroker);
     }
 
+    @Test
+    public void testCreateClassMap() {
+        ClassMap cm = PolicyManagerUtil.createClassMap("testName", null);
+        assertNotNull(cm);
+    }
+
     @Test
     public void testGetServicePath() throws Exception {
         final ParameterValue paramValueSfc = new ParameterValueBuilder()
@@ -80,7 +89,7 @@ public class PolicyManagerUtilTest {
         Mockito.when(roTx.read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(ServiceFunctionPaths.class)))
                 .thenReturn(Futures.immediateCheckedFuture(Optional.of(sfPaths)));
 
-        final ServiceFunctionPath servicePath = PolicyManagerUtil.getServicePath(Collections.singletonList(paramValueSfc));
+        final ServiceFunctionPath servicePath = ServiceChainingUtil.getServicePath(Collections.singletonList(paramValueSfc));
         Assert.assertEquals(serviceFunctionPath, servicePath);
     }
 
@@ -93,7 +102,7 @@ public class PolicyManagerUtilTest {
         Mockito.when(roTx.read(Matchers.eq(LogicalDatastoreType.OPERATIONAL), rendererServicePathIICaptor.capture()))
                 .thenReturn(Futures.immediateCheckedFuture(Optional.of(renderedSP)));
 
-        final RenderedServicePath renderedPath = PolicyManagerUtil.createRenderedPath(serviceFunctionPath, tenantId);
+        final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(serviceFunctionPath, tenantId);
         Assert.assertEquals(renderedSP, renderedPath);
         final InstanceIdentifier<RenderedServicePath> ii = rendererServicePathIICaptor.getValue();
         Assert.assertEquals("sfp-name-01tenant-id-01-gbp-rsp", ii.firstKeyOf(RenderedServicePath.class).getName().getValue());
@@ -109,7 +118,7 @@ public class PolicyManagerUtilTest {
                 .thenReturn(Futures.immediateCheckedFuture(Optional.of(renderedServicePath)));
 
 
-        final RenderedServicePath symmetricRenderedPath = PolicyManagerUtil.createSymmetricRenderedPath(
+        final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(
                 serviceFunctionPath, renderedServicePath, tenantId);
         Assert.assertEquals(renderedServicePath, symmetricRenderedPath);
         final InstanceIdentifier<RenderedServicePath> ii = rendererServicePathIICaptor.getValue();
diff --git a/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/ServiceChainingUtilTest.java b/renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/ServiceChainingUtilTest.java
new file mode 100644 (file)
index 0000000..65603aa
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+ * 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.util;
+
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+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;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
+import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
+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.SffName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+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.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+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;
+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.Local;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.LocalBuilder;
+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.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.ServiceFunction;
+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.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+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.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicyBuilder;
+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.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * Test for {@link ServiceChainingUtil}.
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({
+        ServiceChainingUtil.class,
+        SfcProviderServicePathAPI.class,
+        SfcProviderRenderedPathAPI.class,
+        SfcProviderServiceForwarderAPI.class
+})
+public class ServiceChainingUtilTest {
+
+    @Captor
+    private ArgumentCaptor<RspName> rspNameCaptor;
+    @Captor
+    private ArgumentCaptor<SffName> sffNameCaptor;
+    @Captor
+    private ArgumentCaptor<ServiceFunctionPath> sfpCaptor;
+    @Captor
+    private ArgumentCaptor<CreateRenderedPathInput> createRspCaptor;
+    @Captor
+    private ArgumentCaptor<RenderedServicePath> rspCaptor;
+    @Captor
+    private ArgumentCaptor<List<Class>> listClassCaptor;
+    @Mock
+    private PolicyWriter policyWriter;
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private ReadWriteTransaction rwTx;
+
+    @Before
+    public void setUp() throws Exception {
+        final NodeId currentNodeId = new NodeId("unit-node-01");
+        Mockito.when(policyWriter.getCurrentNodeId()).thenReturn(currentNodeId);
+
+        final String managementIpAddress = "1.2.3.5";
+        Mockito.when(policyWriter.getManagementIpAddress()).thenReturn(managementIpAddress);
+
+        Mockito.when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
+    }
+
+    @Test
+    public void testGetServicePath() throws Exception {
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfcPath = createSfp(sfcNameValue, false);
+        final ServiceFunctionPaths sfcPaths = new ServiceFunctionPathsBuilder()
+                .setServiceFunctionPath(Collections.singletonList(sfcPath))
+                .build();
+
+        stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(sfcPaths);
+
+        final ServiceFunctionPath servicePath = ServiceChainingUtil.getServicePath(Lists.newArrayList(
+                createParameterValue("sfc-chain-name", sfcNameValue)
+        ));
+        Assert.assertEquals(sfcPath, servicePath);
+    }
+
+    private ParameterValue createParameterValue(final String name, final String value) {
+        return new ParameterValueBuilder().setName(new ParameterName(name)).setStringValue(value).build();
+    }
+
+    @Test
+    public void testResolveChainAction_full() throws Exception {
+        final PeerEndpointWithPolicy peerEndpoint = createPeerEndpointWithPolicy();
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final Map<PolicyManagerImpl.ActionCase, Action> actionMap = createActionMap();
+        final String classMapName = "unit-class-map-name-01";
+
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfcPath = createSfp(sfcNameValue, false);
+        final ServiceFunctionPaths sfcPaths = new ServiceFunctionPathsBuilder()
+                .setServiceFunctionPath(Collections.singletonList(sfcPath))
+                .build();
+
+        stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(sfcPaths);
+
+        final RenderedServicePath rsp = createRsp("unit-rsp-02");
+        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
+        stub(method(ServiceChainingUtil.class, "setSfcPart")).toReturn(true);
+
+        ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+
+        Mockito.verify(policyWriter).cache(listClassCaptor.capture());
+        Mockito.verifyNoMoreInteractions(policyWriter);
+        Assert.assertEquals(1, listClassCaptor.getValue().size());
+    }
+
+    @Test
+    public void testResolveChainAction_fullSymmetric() throws Exception {
+        final PeerEndpointWithPolicy peerEndpoint = createPeerEndpointWithPolicy();
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final Map<PolicyManagerImpl.ActionCase, Action> actionMap = createActionMap();
+        final String classMapName = "unit-class-map-name-01";
+
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfcPath = createSfp(sfcNameValue, true);
+        final ServiceFunctionPaths sfcPaths = new ServiceFunctionPathsBuilder()
+                .setServiceFunctionPath(Collections.singletonList(sfcPath))
+                .build();
+
+        stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(sfcPaths);
+
+        final RenderedServicePath rsp = createRsp("unit-rsp-02");
+        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
+        stub(method(ServiceChainingUtil.class, "setSfcPart")).toReturn(true);
+
+        ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+
+        Mockito.verify(policyWriter).cache(listClassCaptor.capture());
+        Mockito.verifyNoMoreInteractions(policyWriter);
+        Assert.assertEquals(2, listClassCaptor.getValue().size());
+    }
+
+    @Test
+    public void testResolveChainAction_partial01() throws Exception {
+        final PeerEndpointWithPolicy peerEndpoint = createPeerEndpointWithPolicy();
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final Map<PolicyManagerImpl.ActionCase, Action> actionMap = createActionMap();
+        final String classMapName = "unit-class-map-name-01";
+
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfcPath = createSfp(sfcNameValue, true);
+        final ServiceFunctionPaths sfcPaths = new ServiceFunctionPathsBuilder()
+                .setServiceFunctionPath(Collections.singletonList(sfcPath))
+                .build();
+
+        stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(sfcPaths);
+
+        final RenderedServicePath rsp = createRsp("unit-rsp-02");
+        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
+        stub(method(ServiceChainingUtil.class, "setSfcPart")).toReturn(true);
+        stub(method(ServiceChainingUtil.class, "createSymmetricRenderedPath")).toReturn(null);
+
+        ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    @Test
+    public void testResolveChainAction_partial02() throws Exception {
+        final PeerEndpointWithPolicy peerEndpoint = createPeerEndpointWithPolicy();
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final Map<PolicyManagerImpl.ActionCase, Action> actionMap = createActionMap();
+        final String classMapName = "unit-class-map-name-01";
+
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfcPath = createSfp(sfcNameValue, false);
+        final ServiceFunctionPaths sfcPaths = new ServiceFunctionPathsBuilder()
+                .setServiceFunctionPath(Collections.singletonList(sfcPath))
+                .build();
+
+        stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(sfcPaths);
+
+        final RenderedServicePath rsp = createRsp("unit-rsp-02");
+        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
+        stub(method(ServiceChainingUtil.class, "setSfcPart")).toReturn(false);
+
+        ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    @Test
+    public void testResolveChainAction_partial03() throws Exception {
+        final PeerEndpointWithPolicy peerEndpoint = createPeerEndpointWithPolicy(null);
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final Map<PolicyManagerImpl.ActionCase, Action> actionMap = createActionMap();
+        final String classMapName = "unit-class-map-name-01";
+
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfcPath = createSfp(sfcNameValue, false);
+        final ServiceFunctionPaths sfcPaths = new ServiceFunctionPathsBuilder()
+                .setServiceFunctionPath(Collections.singletonList(sfcPath))
+                .build();
+
+        stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(sfcPaths);
+
+        final RenderedServicePath rsp = createRsp("unit-rsp-02");
+        stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
+
+        ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    @Test
+    public void testResolveChainAction_partial04() throws Exception {
+        final PeerEndpointWithPolicy peerEndpoint = createPeerEndpointWithPolicy(null);
+        final Sgt sourceSgt = new Sgt(1);
+        final Sgt destinationSgt = new Sgt(2);
+        final Map<PolicyManagerImpl.ActionCase, Action> actionMap = createActionMap(false);
+        final String classMapName = "unit-class-map-name-01";
+
+        ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    private Map<PolicyManagerImpl.ActionCase, Action> createActionMap() {
+        return createActionMap(true);
+    }
+
+    private Map<PolicyManagerImpl.ActionCase, Action> createActionMap(final boolean fillParamValue) {
+        final Map<PolicyManagerImpl.ActionCase,Action> actionMap = new HashMap<>();
+        final ActionBuilder actionValue = new ActionBuilder();
+        if (fillParamValue) {
+            actionValue.setParameterValue(Collections.singletonList(new ParameterValueBuilder()
+                    .setName(new ParameterName(ChainActionDefinition.SFC_CHAIN_NAME))
+                    .setStringValue("123")
+                    .build()));
+        }
+        actionMap.put(PolicyManagerImpl.ActionCase.CHAIN, actionValue.build());
+        return actionMap;
+    }
+
+    private PeerEndpointWithPolicy createPeerEndpointWithPolicy() {
+        return createPeerEndpointWithPolicy(new TenantId("unit-tenant-06"));
+    }
+
+    private PeerEndpointWithPolicy createPeerEndpointWithPolicy(final TenantId tenantId) {
+        return new PeerEndpointWithPolicyBuilder()
+                .setRuleGroupWithRendererEndpointParticipation(Collections.singletonList(
+                        new RuleGroupWithRendererEndpointParticipationBuilder()
+                                .setTenantId(tenantId)
+                                .build()
+                ))
+                .build();
+    }
+
+    @Test
+    public void testCreateRenderedPath() throws Exception {
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfp = createSfp(sfcNameValue, false);
+        final TenantId tenantId = new TenantId("unit-tennant-01");
+
+        final RenderedServicePath rsp = createRsp("unit-rsp-01");
+
+        PowerMockito.mockStatic(SfcProviderRenderedPathAPI.class);
+        final SfcProviderRenderedPathAPI api = PowerMockito.mock(SfcProviderRenderedPathAPI.class);
+        PowerMockito.when(api.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(rsp);
+
+        final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(sfp, tenantId);
+
+        Assert.assertEquals("123_plainunit-tennant-01-gbp-rsp", rspNameCaptor.getValue().getValue());
+        Assert.assertEquals(rsp, renderedPath);
+    }
+
+    @Test
+    public void testCreateRenderedPath_notExisting() throws Exception {
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfp = createSfp(sfcNameValue, false);
+        final TenantId tenantId = new TenantId("unit-tennant-01");
+
+        final RenderedServicePath rsp = createRsp("unit-rsp-01");
+
+        PowerMockito.mockStatic(SfcProviderRenderedPathAPI.class);
+        final SfcProviderRenderedPathAPI api = PowerMockito.mock(SfcProviderRenderedPathAPI.class);
+        PowerMockito.when(api.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(null);
+        PowerMockito.when(api.createRenderedServicePathAndState(
+                sfpCaptor.capture(), createRspCaptor.capture()
+        )).thenReturn(rsp);
+
+        final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(sfp, tenantId);
+
+        Assert.assertEquals("123_plainunit-tennant-01-gbp-rsp", rspNameCaptor.getValue().getValue());
+
+        final ServiceFunctionPath serviceFunctionPath = sfpCaptor.getValue();
+        Assert.assertEquals("123_plain", serviceFunctionPath.getName().getValue());
+        Assert.assertFalse(serviceFunctionPath.isSymmetric());
+
+        final CreateRenderedPathInput createRPInput = createRspCaptor.getValue();
+        Assert.assertFalse(createRPInput.isSymmetric());
+        Assert.assertEquals("123_plain", createRPInput.getParentServiceFunctionPath());
+        Assert.assertEquals("123_plainunit-tennant-01-gbp-rsp", createRPInput.getName());
+
+        Assert.assertEquals(rsp, renderedPath);
+    }
+
+    private RenderedServicePath createRsp(final String rspNameValue) {
+        return new RenderedServicePathBuilder()
+                .setName(new RspName(rspNameValue))
+                .setRenderedServicePathHop(Lists.newArrayList(createRspHop("rsp-hop-01-sf")))
+                .build();
+    }
+
+    private RenderedServicePathHop createRspHop(final String sfNameValue) {
+        return new RenderedServicePathHopBuilder()
+                .setServiceFunctionName(new SfName(sfNameValue))
+                .setServiceFunctionForwarder(new SffName(sfNameValue + "+sff"))
+                .build();
+    }
+
+    private ServiceFunctionPath createSfp(final String sfcNameValue, final boolean symmetric) {
+        return new ServiceFunctionPathBuilder()
+                .setServiceChainName(new SfcName(sfcNameValue))
+                .setName(new SfpName(sfcNameValue + "_plain"))
+                .setSymmetric(symmetric)
+                .build();
+    }
+
+    @Test
+    public void testCreateSymmetricRenderedPath() throws Exception {
+        final ServiceFunctionPath sfp = createSfp("unit-sfp-02", false);
+        final RenderedServicePath rsp = createRsp("unit-rsp-02");
+        final TenantId tennantId = new TenantId("tenant-02");
+
+        PowerMockito.mockStatic(SfcProviderRenderedPathAPI.class);
+        final SfcProviderRenderedPathAPI api = PowerMockito.mock(SfcProviderRenderedPathAPI.class);
+        PowerMockito.when(api.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(rsp);
+
+        final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(sfp, rsp, tennantId);
+
+        Assert.assertEquals("unit-sfp-02_plaintenant-02-gbp-rsp-Reverse", rspNameCaptor.getValue().getValue());
+        Assert.assertEquals(rsp, symmetricRenderedPath);
+    }
+
+    @Test
+    public void testCreateSymmetricRenderedPath_notExisting() throws Exception {
+        final ServiceFunctionPath sfp = createSfp("unit-sfp-02", false);
+        final RenderedServicePath rsp = createRsp("unit-rsp-02");
+        final TenantId tennantId = new TenantId("tenant-02");
+
+        PowerMockito.mockStatic(SfcProviderRenderedPathAPI.class);
+        final SfcProviderRenderedPathAPI api = PowerMockito.mock(SfcProviderRenderedPathAPI.class);
+        PowerMockito.when(api.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(null);
+        PowerMockito.when(api.createSymmetricRenderedServicePathAndState(rspCaptor.capture())).thenReturn(rsp);
+
+        final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(sfp, rsp, tennantId);
+
+        Assert.assertEquals("unit-sfp-02_plaintenant-02-gbp-rsp-Reverse", rspNameCaptor.getValue().getValue());
+        Assert.assertEquals(rsp, rspCaptor.getValue());
+        Assert.assertEquals(rsp, symmetricRenderedPath);
+    }
+
+    @Test
+    public void testCheckLocalForwarderPresence() throws Exception {
+        final Local local = new LocalBuilder().build();
+
+        Mockito.when(rwTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), Matchers.<InstanceIdentifier<Local>>any()))
+                .thenReturn(Futures.<Optional<Local>, ReadFailedException>immediateCheckedFuture(Optional.of(local)))
+                .thenReturn(Futures.<Optional<Local>, ReadFailedException>immediateCheckedFuture(Optional.absent()))
+                .thenReturn(Futures.<Optional<Local>, ReadFailedException>immediateFailedCheckedFuture(new ReadFailedException("n/a")));
+
+        Assert.assertTrue(ServiceChainingUtil.checkLocalForwarderPresence(dataBroker));
+        Assert.assertFalse(ServiceChainingUtil.checkLocalForwarderPresence(dataBroker));
+        Assert.assertFalse(ServiceChainingUtil.checkLocalForwarderPresence(dataBroker));
+        Assert.assertFalse(ServiceChainingUtil.checkLocalForwarderPresence(dataBroker));
+    }
+
+    @Test
+    public void testCheckServicePathPresence() throws Exception {
+        final ServiceChain serviceChainOk = new ServiceChainBuilder()
+                .setServicePath(Collections.singletonList(new ServicePathBuilder().build()))
+                .build();
+        final ServiceChain serviceChainBad1 = new ServiceChainBuilder()
+                .setServicePath(Collections.emptyList())
+                .build();
+        final ServiceChain serviceChainBad2 = new ServiceChainBuilder().build();
+
+        Mockito.when(rwTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), Matchers.<InstanceIdentifier<ServiceChain>>any()))
+                .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateCheckedFuture(Optional.of(serviceChainOk)))
+                .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateCheckedFuture(Optional.of(serviceChainBad1)))
+                .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateCheckedFuture(Optional.of(serviceChainBad2)))
+                .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateCheckedFuture(Optional.absent()))
+                .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateFailedCheckedFuture(new ReadFailedException("n/a")));
+
+        Assert.assertFalse(ServiceChainingUtil.checkServicePathPresence(dataBroker));
+        Assert.assertTrue(ServiceChainingUtil.checkServicePathPresence(dataBroker));
+        Assert.assertTrue(ServiceChainingUtil.checkServicePathPresence(dataBroker));
+        Assert.assertTrue(ServiceChainingUtil.checkServicePathPresence(dataBroker));
+        Assert.assertFalse(ServiceChainingUtil.checkServicePathPresence(dataBroker));
+    }
+
+    @Test
+    public void testFindServiceFunctionPath() throws Exception {
+        final String sfcNameValue = "123";
+        final ServiceFunctionPath sfcPath = createSfp(sfcNameValue, false);
+        final ServiceFunctionPaths sfcPaths = new ServiceFunctionPathsBuilder()
+                .setServiceFunctionPath(Collections.singletonList(sfcPath))
+                .build();
+
+        stub(method(SfcProviderServicePathAPI.class, "readAllServiceFunctionPaths")).toReturn(sfcPaths);
+
+        final ServiceFunctionPath servicePath = ServiceChainingUtil.findServiceFunctionPath(new SfcName(sfcNameValue));
+        Assert.assertEquals(sfcPath, servicePath);
+    }
+
+    @Test
+    public void testSetSfcPart_success() throws Exception {
+        final RenderedServicePath rsp = createRsp("unit-rsp-03");
+        final org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder
+                sff = new ServiceFunctionForwarderBuilder()
+                .setName(new SffName("unit-sff-03"))
+                .setIpMgmtAddress(new IpAddress(new Ipv4Address("1.2.3.4")))
+                .build();
+
+        stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
+
+        PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
+        final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
+        PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(sff);
+
+
+        final boolean outcome = ServiceChainingUtil.setSfcPart(rsp, policyWriter);
+
+        Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
+        Assert.assertTrue(outcome);
+
+        Mockito.verify(policyWriter).cache(Matchers.<ServiceFfName>any());
+        Mockito.verify(policyWriter).cache(Matchers.<ServiceChain>any());
+        Mockito.verify(policyWriter).getCurrentNodeId();
+        Mockito.verify(policyWriter).getCurrentMountpoint();
+        Mockito.verify(policyWriter).getManagementIpAddress();
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    @Test
+    public void testSetSfcPart_success_newRsp() throws Exception {
+        final RenderedServicePath rsp = createRsp("unit-rsp-03");
+        final org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder
+                sff = new ServiceFunctionForwarderBuilder()
+                .setName(new SffName("unit-sff-03"))
+                .setIpMgmtAddress(new IpAddress(new Ipv4Address("1.2.3.4")))
+                .build();
+
+        stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(false);
+
+        PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
+        final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
+        PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(sff);
+
+
+        final boolean outcome = ServiceChainingUtil.setSfcPart(rsp, policyWriter);
+
+        Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
+        Assert.assertTrue(outcome);
+
+        Mockito.verify(policyWriter).cache(Matchers.<Local>any());
+        Mockito.verify(policyWriter).cache(Matchers.<ServiceFfName>any());
+        Mockito.verify(policyWriter).cache(Matchers.<ServiceChain>any());
+        Mockito.verify(policyWriter).getCurrentMountpoint();
+        Mockito.verify(policyWriter, Mockito.times(2)).getManagementIpAddress();
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    @Test
+    public void testSetSfcPart_fail01() throws Exception {
+        Assert.assertFalse(ServiceChainingUtil.setSfcPart(null, policyWriter));
+
+        final RenderedServicePathBuilder rspBuilder = new RenderedServicePathBuilder().setName(new RspName("unit-rsp-05"));
+        Assert.assertFalse(ServiceChainingUtil.setSfcPart(rspBuilder.build(), policyWriter));
+
+        rspBuilder.setRenderedServicePathHop(Collections.emptyList());
+        Assert.assertFalse(ServiceChainingUtil.setSfcPart(rspBuilder.build(), policyWriter));
+
+        rspBuilder.setRenderedServicePathHop(Collections.singletonList(null));
+        Assert.assertFalse(ServiceChainingUtil.setSfcPart(rspBuilder.build(), policyWriter));
+
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    @Test
+    public void testSetSfcPart_fail02() throws Exception {
+        final RenderedServicePath rsp = createRsp("unit-rsp-03");
+
+        PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
+        final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
+        PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(null);
+
+        final boolean outcome = ServiceChainingUtil.setSfcPart(rsp, policyWriter);
+
+        Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
+        Assert.assertFalse(outcome);
+
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    @Test
+    public void testSetSfcPart_fail03() throws Exception {
+        final RenderedServicePath rsp = createRsp("unit-rsp-03");
+        final ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder()
+                .setName(new SffName("unit-sff-03"))
+                .setIpMgmtAddress(null);
+
+        stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
+
+        PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
+        final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
+        PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(
+                sffBuilder.build());
+
+        Assert.assertFalse(ServiceChainingUtil.setSfcPart(rsp, policyWriter));
+
+        Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
+
+        Mockito.verify(policyWriter).getCurrentMountpoint();
+        Mockito.verify(policyWriter).getCurrentNodeId();
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+    @Test
+    public void testSetSfcPart_fail04() throws Exception {
+        final RenderedServicePath rsp = createRsp("unit-rsp-03");
+        final ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder()
+                .setName(new SffName("unit-sff-03"))
+                .setIpMgmtAddress(new IpAddress((Ipv4Address) null));
+
+        stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
+
+        PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
+        final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
+        PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(
+                sffBuilder.build());
+
+        Assert.assertFalse(ServiceChainingUtil.setSfcPart(rsp, policyWriter));
+
+        Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
+
+        Mockito.verify(policyWriter).getCurrentMountpoint();
+        Mockito.verify(policyWriter).getCurrentNodeId();
+        Mockito.verifyNoMoreInteractions(policyWriter);
+    }
+
+
+    @Test
+    public void testForwarderTypeChoice() throws Exception {
+        final String sffValue = "unit-xx";
+        final ServiceTypeChoice fwChoice = ServiceChainingUtil.forwarderTypeChoice(sffValue);
+
+        Assert.assertTrue(fwChoice instanceof ServiceFunctionForwarder);
+        final ServiceFunctionForwarder sff = (ServiceFunctionForwarder) fwChoice;
+        Assert.assertEquals(sffValue, sff.getServiceFunctionForwarder());
+    }
+
+    @Test
+    public void testFunctionTypeChoice() throws Exception {
+        final String stcValue = "unit-xx";
+        final ServiceTypeChoice srvTypeChoice = ServiceChainingUtil.functionTypeChoice(stcValue);
+
+        Assert.assertTrue(srvTypeChoice instanceof ServiceFunction);
+        final ServiceFunction stc = (ServiceFunction) srvTypeChoice;
+        Assert.assertEquals(stcValue, stc.getServiceFunction());
+    }
+}
\ No newline at end of file
index e8a91201d30d48ade7d8b5cfcf66fa5342246385..f16ccfc46c06021c05d103274200ea80e60d7989 100644 (file)
       <artifactId>vbd-api</artifactId>
       <version>1.0.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>opendaylight-l2-types</artifactId>
+    </dependency>
 
     <!-- testing dependencies -->
     <dependency>
index cf90406a2971cf72bf9ff25035f4db9ea62944de..0250be51fe2099ce5927f09b98e97d72d87b228b 100644 (file)
@@ -23,8 +23,8 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.RendererPolicyListener;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppEndpointListener;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppNodeListener;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.BridgeDomainManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.VppNodeManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.BridgeDomainManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.ForwardingManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.VppRendererPolicyManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.AllowAction;
@@ -117,7 +117,7 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider {
         EventBus dtoEventBus = new EventBus("DTO events");
         interfaceManager = new InterfaceManager(mountDataProvider, dataBroker, NETCONF_WORKER);
         dtoEventBus.register(interfaceManager);
-        ForwardingManager fwManager = new ForwardingManager(interfaceManager, new BridgeDomainManagerImpl(dataBroker));
+        ForwardingManager fwManager = new ForwardingManager(interfaceManager, new BridgeDomainManagerImpl(dataBroker), dataBroker);
         vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, dataBroker);
         dtoEventBus.register(vppRendererPolicyManager);
 
index 1b8f8b01ce0148a4ffb9a788e84fc8f7d66c80e9..1fd983930e4727e7f20bff318c3c305101d61db8 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.api;
 
 import javax.annotation.Nonnull;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanVni;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 
@@ -23,22 +24,34 @@ public interface BridgeDomainManager {
     /**
      * Creates a bridge domain on VPP node and it also adds tunnels of the bridge domain to VXLAN
      * full mesh topology
-     * 
+     *
      * @param bridgeDomainName name of bridge domain
      * @param vni VXLAN VNI used in full mesh topology for the given bridge domain
-     * @param vppNode VPP node where the bridge domain should be created
+     * @param vppNodeId VPP node where the bridge domain should be created
      * @return {@link ListenableFuture}
      */
-    ListenableFuture<Void> createVxlanBridgeDomainOnVppNode(@Nonnull String bridgeDomainName, @Nonnull VxlanVni vni,
-            NodeId vppNode);
+    ListenableFuture<Void> createVxlanBridgeDomainOnVppNode(@Nonnull String bridgeDomainName, @Nonnull VxlanVni vni, @Nonnull NodeId vppNodeId);
+
+    /**
+     * Creates a bridge domain on VPP node and it also adds tunnels of the bridge domain to VLAN
+     * full mesh topology
+     *
+     * @param bridgeDomainName name of bridge domain
+     * @param vlanId VLAN ID used in full mesh topology for the given bridge domain
+     * @param vppNodeId VPP node where the bridge domain should be created
+     * @return {@link ListenableFuture}
+     */
+
+    ListenableFuture<Void> createVlanBridgeDomainOnVppNode(@Nonnull String bridgeDomainName, @Nonnull VlanId vlanId, @Nonnull NodeId vppNodeId);
 
     /**
      * Removes a bridge domain from VPP node and it also removes tunnels of the bridge domain from
      * VXLAN full mesh topology
-     * 
+     *
      * @param bridgeDomainName name of bridge domain
      * @param vppNode VPP node where the bridge domain should be removed from
      * @return {@link ListenableFuture}
      */
     ListenableFuture<Void> removeBridgeDomainFromVppNode(@Nonnull String bridgeDomainName, NodeId vppNode);
+
 }
index 5fac50bd88e80e3067a2351d81d352530d5ef9c7..cfdd9a8d4a86a5d02447517cb8a2e593cb7a75fd 100644 (file)
@@ -251,6 +251,7 @@ public class InterfaceManager implements AutoCloseable {
 
                 String existingBridgeDomain = resolveBridgeDomain(optIface.get());
                 if (bridgeDomainName.equals(existingBridgeDomain)) {
+                    LOG.debug("Bridge domain {} already exists on interface {}", bridgeDomainName, interfacePath);
                     String nodePath = VppPathMapper.bridgeDomainToRestPath(bridgeDomainName);
                     if (!nodePath.equals(epLoc.getExternalNode())) {
                         vppEndpointLocationProvider.updateExternalNodeLocationForEndpoint(nodePath,
@@ -264,6 +265,7 @@ public class InterfaceManager implements AutoCloseable {
                 L2 l2 = new L2Builder()
                     .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomainName).build()).build();
                 rwTx.merge(LogicalDatastoreType.CONFIGURATION, l2Iid, l2);
+                LOG.debug("Adding bridge domain {} to interface {}", bridgeDomainName, interfacePath);
                 return Futures.transform(rwTx.submit(), new Function<Void, Void>() {
 
                     @Override
@@ -327,6 +329,8 @@ public class InterfaceManager implements AutoCloseable {
 
                 String existingBridgeDomain = resolveBridgeDomain(optIface.get());
                 if (Strings.isNullOrEmpty(existingBridgeDomain)) {
+                    LOG.debug("Bridge domain does not exist therefore it is cosidered as"
+                            + "deleted for interface {}", interfacePath);
                     // bridge domain does not exist on interface so we consider job done
                     vppEndpointLocationProvider.updateExternalNodeLocationForEndpoint(null,
                             epLoc.getExternalNodeMountPoint(), addrEpWithLoc.getKey());
@@ -336,6 +340,7 @@ public class InterfaceManager implements AutoCloseable {
                 InstanceIdentifier<L2> l2Iid =
                         interfaceIid.builder().augmentation(VppInterfaceAugmentation.class).child(L2.class).build();
                 rwTx.delete(LogicalDatastoreType.CONFIGURATION, l2Iid);
+                LOG.debug("Deleting bridge domain from interface {}", interfacePath);
                 return Futures.transform(rwTx.submit(), new Function<Void, Void>() {
 
                     @Override
index 52accca62f54dbbee42e5867aa384b2b6f01a242..b9ddae02fa592f038945bcd03c1455b33ccd3dbf 100644 (file)
@@ -74,12 +74,12 @@ public class VppEndpointLocationProvider implements AutoCloseable {
                 IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER,
                         providerAddressEndpointLocation.getKey()),
                 providerAddressEndpointLocation);
-
+        LOG.debug("Creating location for {}", providerAddressEndpointLocation.getKey());
         Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
 
             @Override
             public void onSuccess(Void result) {
-                LOG.debug("{} provides location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
+                LOG.debug("{} provided location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
                         providerAddressEndpointLocation);
             }
 
@@ -109,11 +109,12 @@ public class VppEndpointLocationProvider implements AutoCloseable {
         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
         wTx.delete(LogicalDatastoreType.CONFIGURATION,
                 IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER, provAddrEpLocKey));
+        LOG.debug("Deleting location for {}", provAddrEpLocKey);
         Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
 
             @Override
             public void onSuccess(Void result) {
-                LOG.debug("{} removes location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(), provAddrEpLocKey);
+                LOG.debug("{} removed location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(), provAddrEpLocKey);
             }
 
             @Override
@@ -144,12 +145,12 @@ public class VppEndpointLocationProvider implements AutoCloseable {
                 IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER,
                         providerAddressEndpointLocation.getKey()),
                 providerAddressEndpointLocation);
-
+        LOG.debug("Updating location for {}", provAddrEpLocKey);
         Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
 
             @Override
             public void onSuccess(Void result) {
-                LOG.debug("{} merges location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
+                LOG.debug("{} merged location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
                         providerAddressEndpointLocation);
             }
 
index 086b51953249c43a10d37a309ed0eeb21fb586d7..7eeb356530e7d5c6015c793669b322c1ed83c469 100644 (file)
@@ -21,7 +21,9 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.NodeOperEvent;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.VppNodeManager;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -34,6 +36,7 @@ import com.google.common.eventbus.EventBus;
 public class VppNodeListener implements DataTreeChangeListener<Node>, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(VppNodeListener.class);
+    private static final TopologyId TOPOLOGY_NETCONF = new TopologyId("topology-netconf");
 
     private final ListenerRegistration<VppNodeListener> listenerRegistration;
     private final VppNodeManager nodeManager;
@@ -44,7 +47,10 @@ public class VppNodeListener implements DataTreeChangeListener<Node>, AutoClosea
         this.eventBus = Preconditions.checkNotNull(eventBus);
         // Register listener
         final DataTreeIdentifier<Node> networkTopologyPath = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
-                InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).child(Node.class).build());
+                InstanceIdentifier.builder(NetworkTopology.class)
+                    .child(Topology.class, new TopologyKey(TOPOLOGY_NETCONF))
+                    .child(Node.class)
+                    .build());
         listenerRegistration =
                 Preconditions.checkNotNull(dataBroker.registerDataTreeChangeListener(networkTopologyPath, this));
         LOG.info("Network-Topology VppNodelistener registered");
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/BridgeDomainManagerImpl.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/BridgeDomainManagerImpl.java
deleted file mode 100644 (file)
index c695be8..0000000
+++ /dev/null
@@ -1,112 +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.vpp.manager;
-
-import java.util.Arrays;
-
-import javax.annotation.Nonnull;
-
-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.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanVni;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyTypesVbridgeAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyTypesVbridgeAugmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.topology.types.VbridgeTopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev160429.TunnelTypeVxlan;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev160429.network.topology.topology.tunnel.parameters.VxlanTunnelParametersBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeBuilder;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-
-public class BridgeDomainManagerImpl implements BridgeDomainManager {
-
-    private static final TopologyId SUPPORTING_TOPOLOGY_NETCONF = new TopologyId("topology-netconf");
-    private static final TopologyTypes VBRIDGE_TOPOLOGY_TYPE = new TopologyTypesBuilder().addAugmentation(
-            TopologyTypesVbridgeAugment.class,
-            new TopologyTypesVbridgeAugmentBuilder().setVbridgeTopology(new VbridgeTopologyBuilder().build()).build())
-        .build();
-    private final DataBroker dataProvder;
-
-    public BridgeDomainManagerImpl(DataBroker dataProvder) {
-        this.dataProvder = Preconditions.checkNotNull(dataProvder);
-    }
-
-    @Override
-    public ListenableFuture<Void> createVxlanBridgeDomainOnVppNode(@Nonnull String bridgeDomainName,
-            @Nonnull VxlanVni vni, NodeId vppNode) {
-        TopologyKey topologyKey = new TopologyKey(new TopologyId(bridgeDomainName));
-        ReadOnlyTransaction rTx = dataProvder.newReadOnlyTransaction();
-        CheckedFuture<Optional<Topology>, ReadFailedException> futureTopology =
-                rTx.read(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getTopologyIid(topologyKey));
-        rTx.close();
-        return Futures.transform(futureTopology, new AsyncFunction<Optional<Topology>, Void>() {
-
-            @Override
-            public ListenableFuture<Void> apply(Optional<Topology> optTopology) throws Exception {
-                WriteTransaction wTx = dataProvder.newWriteOnlyTransaction();
-                if (!optTopology.isPresent()) {
-                    TopologyVbridgeAugment vbridgeAugment =
-                            new TopologyVbridgeAugmentBuilder().setTunnelType(TunnelTypeVxlan.class)
-                                .setArpTermination(false)
-                                .setFlood(true)
-                                .setForward(true)
-                                .setLearn(true)
-                                .setUnknownUnicastFlood(true)
-                                .setTunnelParameters(new VxlanTunnelParametersBuilder().setVni(vni).build())
-                                .build();
-                    Topology topology = new TopologyBuilder().setKey(topologyKey)
-                        .setTopologyTypes(VBRIDGE_TOPOLOGY_TYPE)
-                        .addAugmentation(TopologyVbridgeAugment.class, vbridgeAugment)
-                        .build();
-
-                    wTx.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getTopologyIid(topology.getKey()),
-                            topology, true);
-                }
-                Node node = new NodeBuilder().setNodeId(vppNode)
-                    .setSupportingNode(Arrays.asList(new SupportingNodeBuilder()
-                        .setTopologyRef(SUPPORTING_TOPOLOGY_NETCONF).setNodeRef(vppNode).build()))
-                    .build();
-                wTx.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNodeIid(topologyKey, node.getKey()),
-                        node);
-                return wTx.submit();
-            }
-        });
-    }
-
-    @Override
-    public ListenableFuture<Void> removeBridgeDomainFromVppNode(@Nonnull String bridgeDomainName, NodeId vppNode) {
-        WriteTransaction wTx = dataProvder.newWriteOnlyTransaction();
-        wTx.delete(LogicalDatastoreType.CONFIGURATION,
-                VppIidFactory.getNodeIid(new TopologyKey(new TopologyId(bridgeDomainName)), new NodeKey(vppNode)));
-        return wTx.submit();
-    }
-
-}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImpl.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImpl.java
new file mode 100644 (file)
index 0000000..7449070
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * 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.vpp.policy;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+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.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomainKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.bridge.domain.PhysicalLocationRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanVni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.NodeVbridgeAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyTypesVbridgeAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyTypesVbridgeAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.node.BridgeMember;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.topology.types.VbridgeTopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vlan.rev160429.NodeVbridgeVlanAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vlan.rev160429.NodeVbridgeVlanAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vlan.rev160429.TunnelTypeVlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vlan.rev160429.network.topology.topology.tunnel.parameters.VlanNetworkParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev160429.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev160429.network.topology.topology.tunnel.parameters.VxlanTunnelParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+public class BridgeDomainManagerImpl implements BridgeDomainManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainManagerImpl.class);
+    private static final TopologyId SUPPORTING_TOPOLOGY_NETCONF = new TopologyId("topology-netconf");
+    private static final TopologyTypes VBRIDGE_TOPOLOGY_TYPE = new TopologyTypesBuilder().addAugmentation(
+            TopologyTypesVbridgeAugment.class,
+            new TopologyTypesVbridgeAugmentBuilder().setVbridgeTopology(new VbridgeTopologyBuilder().build()).build())
+        .build();
+    private final DataBroker dataProvder;
+
+    private static final class ListenableFutureSetter<T extends DataObject>
+            implements DataTreeChangeListener<T> {
+
+        private static final Logger LOG = LoggerFactory.getLogger(ListenableFutureSetter.class);
+        private final SettableFuture<Void> future;
+        private final ModificationType modificationForFutureSet;
+        private final DataTreeIdentifier<T> iid;
+        private final ListenerRegistration<ListenableFutureSetter<T>> registeredListener;
+
+        private ListenableFutureSetter(DataBroker dataProvider, SettableFuture<Void> future,
+                DataTreeIdentifier<T> iid, ModificationType modificationForFutureSet) {
+            this.future = Preconditions.checkNotNull(future);
+            Preconditions.checkArgument(!future.isDone());
+            this.modificationForFutureSet = Preconditions.checkNotNull(modificationForFutureSet);
+            this.iid = Preconditions.checkNotNull(iid);
+            registeredListener = dataProvider.registerDataTreeChangeListener(iid, this);
+            LOG.trace("Registered listener for path {}", iid.getRootIdentifier());
+        }
+
+        @Override
+        public void onDataTreeChanged(Collection<DataTreeModification<T>> changes) {
+            changes.forEach(modif -> {
+                DataObjectModification<T> rootNode = modif.getRootNode();
+                ModificationType modificationType = rootNode.getModificationType();
+                if (modificationType == modificationForFutureSet) {
+                    LOG.debug("{} in OPER DS: {}", modificationType.name(), iid.getRootIdentifier());
+                    unregisterOnTrue(future.set(null));
+                }
+            });
+        }
+
+        private void unregisterOnTrue(boolean _true) {
+            if (_true) {
+                LOG.trace("Unregistering listener for path {}", iid.getRootIdentifier());
+                if (registeredListener != null) {
+                    registeredListener.close();
+                }
+            }
+        }
+    }
+
+    public BridgeDomainManagerImpl(DataBroker dataProvder) {
+        this.dataProvder = Preconditions.checkNotNull(dataProvder);
+    }
+
+    @Override
+    public ListenableFuture<Void> createVxlanBridgeDomainOnVppNode(@Nonnull String bridgeDomainName,
+            @Nonnull VxlanVni vni, @Nonnull NodeId vppNodeId) {
+        TopologyVbridgeAugment topoAug = new TopologyVbridgeAugmentBuilder().setTunnelType(TunnelTypeVxlan.class)
+            .setArpTermination(false)
+            .setFlood(true)
+            .setForward(true)
+            .setLearn(true)
+            .setUnknownUnicastFlood(true)
+            .setTunnelParameters(new VxlanTunnelParametersBuilder().setVni(vni).build())
+            .build();
+        return createBridgeDomainOnVppNode(bridgeDomainName, topoAug, createBasicVppNodeBuilder(vppNodeId).build());
+    }
+
+    @Override
+    public ListenableFuture<Void> createVlanBridgeDomainOnVppNode(@Nonnull String bridgeDomainName,
+            @Nonnull VlanId vlanId, @Nonnull NodeId vppNodeId) {
+        TopologyVbridgeAugment topoAug = new TopologyVbridgeAugmentBuilder().setTunnelType(TunnelTypeVlan.class)
+            .setArpTermination(false)
+            .setFlood(true)
+            .setForward(true)
+            .setLearn(true)
+            .setUnknownUnicastFlood(true)
+            .setTunnelParameters(new VlanNetworkParametersBuilder().setVlanId(vlanId).build())
+            .build();
+        InstanceIdentifier<BridgeDomain> bridgeDomainConfigIid = InstanceIdentifier.builder(Config.class)
+            .child(BridgeDomain.class, new BridgeDomainKey(bridgeDomainName))
+            .build();
+        ReadOnlyTransaction rTx = dataProvder.newReadOnlyTransaction();
+        CheckedFuture<Optional<BridgeDomain>, ReadFailedException> futureTopology =
+                rTx.read(LogicalDatastoreType.CONFIGURATION, bridgeDomainConfigIid);
+        rTx.close();
+        return Futures.transform(futureTopology, new AsyncFunction<Optional<BridgeDomain>, Void>() {
+
+            @Override
+            public ListenableFuture<Void> apply(Optional<BridgeDomain> optBridgeDomainConf) throws Exception {
+                if (optBridgeDomainConf.isPresent() && optBridgeDomainConf.get().getPhysicalLocationRef() != null) {
+                    for (PhysicalLocationRef ref : optBridgeDomainConf.get().getPhysicalLocationRef()) {
+                        if (ref.getInterface() != null && ref.getInterface().size() > 0) {
+                            NodeVbridgeVlanAugment vppNodeVlanAug = new NodeVbridgeVlanAugmentBuilder()
+                                .setSuperInterface(ref.getInterface().get(0)).build();
+                            Node vppNode = createBasicVppNodeBuilder(vppNodeId)
+                                .addAugmentation(vppNodeVlanAug.getClass(), vppNodeVlanAug).build();
+                            return createBridgeDomainOnVppNode(bridgeDomainName, topoAug, vppNode);
+                        }
+                    }
+                }
+                return Futures.immediateFailedFuture(
+                        new Throwable("Failed to apply config for VLAN bridge domain " + bridgeDomainName));
+            }
+        });
+    }
+
+    private static NodeBuilder createBasicVppNodeBuilder(NodeId nodeId) {
+        return new NodeBuilder().setNodeId(nodeId).setSupportingNode(Arrays.asList(
+                new SupportingNodeBuilder().setTopologyRef(SUPPORTING_TOPOLOGY_NETCONF).setNodeRef(nodeId).build()));
+    }
+
+    private ListenableFuture<Void> createBridgeDomainOnVppNode(@Nonnull String bridgeDomainName,
+            final TopologyVbridgeAugment vBridgeAug, Node vppNode) {
+        TopologyKey topologyKey = new TopologyKey(new TopologyId(bridgeDomainName));
+        ReadOnlyTransaction rTx = dataProvder.newReadOnlyTransaction();
+        InstanceIdentifier<Topology> topologyIid = VppIidFactory.getTopologyIid(topologyKey);
+        CheckedFuture<Optional<Topology>, ReadFailedException> futureTopology =
+                rTx.read(LogicalDatastoreType.CONFIGURATION, topologyIid);
+        rTx.close();
+        return Futures.transform(futureTopology, new AsyncFunction<Optional<Topology>, Void>() {
+
+            @Override
+            public ListenableFuture<Void> apply(Optional<Topology> optTopology) throws Exception {
+                WriteTransaction wTx = dataProvder.newWriteOnlyTransaction();
+                if (!optTopology.isPresent()) {
+                    Topology topology = new TopologyBuilder().setKey(topologyKey)
+                        .setTopologyTypes(VBRIDGE_TOPOLOGY_TYPE)
+                        .addAugmentation(TopologyVbridgeAugment.class, vBridgeAug)
+                        .build();
+                    wTx.put(LogicalDatastoreType.CONFIGURATION, topologyIid,
+                            topology, true);
+                }
+                InstanceIdentifier<Node> nodeIid = VppIidFactory.getNodeIid(topologyKey, vppNode.getKey());
+                wTx.put(LogicalDatastoreType.CONFIGURATION, nodeIid, vppNode);
+                SettableFuture<Void> future = SettableFuture.create();
+                Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
+
+                    @Override
+                    public void onSuccess(Void result) {
+                        DataTreeIdentifier<BridgeMember> bridgeMemberIid =
+                                new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                                        nodeIid.augmentation(NodeVbridgeAugment.class).child(BridgeMember.class));
+                        LOG.debug("Request create node in topology for VBD was stored to CONF DS. {}", nodeIid);
+                        new ListenableFutureSetter<>(dataProvder, future, bridgeMemberIid,
+                                ModificationType.WRITE);
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        LOG.warn("Request create node in topology for VBD was not stored to CONF DS. {}", nodeIid, t);
+                        future.setException(new Exception("Cannot send request to VBD."));
+                    }
+                });
+                return future;
+            }
+        });
+    }
+
+    @Override
+    public ListenableFuture<Void> removeBridgeDomainFromVppNode(@Nonnull String bridgeDomainName, NodeId vppNode) {
+        WriteTransaction wTx = dataProvder.newWriteOnlyTransaction();
+        InstanceIdentifier<Node> nodeIid =
+                VppIidFactory.getNodeIid(new TopologyKey(new TopologyId(bridgeDomainName)), new NodeKey(vppNode));
+        wTx.delete(LogicalDatastoreType.CONFIGURATION, nodeIid);
+        SettableFuture<Void> future = SettableFuture.create();
+        Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(Void result) {
+                DataTreeIdentifier<BridgeMember> bridgeMemberIid =
+                        new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                                nodeIid.augmentation(NodeVbridgeAugment.class).child(BridgeMember.class));
+                LOG.debug("Request delete node in topology for VBD was stored to CONF DS. {}", nodeIid);
+                new ListenableFutureSetter<>(dataProvder, future, bridgeMemberIid, ModificationType.DELETE);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.warn("Request delete node in topology for VBD was not stored to CONF DS. {}", nodeIid, t);
+                future.setException(new Exception("Cannot send request to VBD."));
+            }
+        });
+        return future;
+    }
+
+}
index 6c5ba8fccc8ba508e18f89fb85e621303f44c370..d42e47d130da3b8b8634112dca6091a5ee42a5f2 100644 (file)
@@ -8,15 +8,23 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.vpp.policy;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+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.renderer.vpp.api.BridgeDomainManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.Containment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.ForwardingContextContainment;
@@ -26,48 +34,112 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VlanNetwork;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomainKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanVni;
 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;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.SetMultimap;
 
-public class ForwardingManager {
+public final class ForwardingManager {
 
     private static final Logger LOG = LoggerFactory.getLogger(ForwardingManager.class);
-
+    @VisibleForTesting
+    static long WAIT_FOR_BD_CREATION = 10; // seconds
+    private long lastVxlanVni = 1L;
+    private final Map<String, VxlanVni> vxlanVniByBridgeDomain = new HashMap<>();
     private final InterfaceManager ifaceManager;
     private final BridgeDomainManager bdManager;
-
-    public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull BridgeDomainManager bdManager) {
+    private final DataBroker dataBroker;
+    public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull BridgeDomainManager bdManager, @Nonnull DataBroker dataBroker) {
         this.ifaceManager = Preconditions.checkNotNull(ifaceManager);
         this.bdManager = Preconditions.checkNotNull(bdManager);
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
     }
 
-    public void createVxlanBridgeDomainsOnNodes(SetMultimap<String, NodeId> vppNodesByBridgeDomain) {
+    public Optional<BridgeDomain> readBridgeDomainConfig(String name) {
+        InstanceIdentifier<BridgeDomain> bdIid = InstanceIdentifier.builder(Config.class)
+            .child(BridgeDomain.class, new BridgeDomainKey(name))
+            .build();
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        return DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, bdIid, rTx);
+    }
+
+    public void createBridgeDomainOnNodes(SetMultimap<String, NodeId> vppNodesByBridgeDomain) {
         for (String bd : vppNodesByBridgeDomain.keySet()) {
+            Optional<BridgeDomain> bdConfig = readBridgeDomainConfig(bd);
             Set<NodeId> vppNodes = vppNodesByBridgeDomain.get(bd);
-            for (NodeId vppNode : vppNodes) {
-                try {
-                    bdManager.createVxlanBridgeDomainOnVppNode(bd, null, vppNode).get();
-                } catch (InterruptedException | ExecutionException e) {
-                    LOG.warn("Bridge domain {} was not created on node {}", bd, vppNode.getValue(), e);
+            if (bdConfig.isPresent()) {
+                if (bdConfig.get().getType().equals(VlanNetwork.class)) {
+                    createVlanBridgeDomains(bd, bdConfig.get().getVlan(), vppNodes);
+                }
+            } else {
+                VxlanVni vxlanVni = vxlanVniByBridgeDomain.get(bd);
+                if (vxlanVni == null) {
+                    vxlanVni = new VxlanVni(lastVxlanVni++);
+                    vxlanVniByBridgeDomain.put(bd, vxlanVni);
                 }
+                createVxlanBridgeDomains(bd, vxlanVni, vppNodes);
+            }
+        }
+    }
+
+    private void createVxlanBridgeDomains(String bd, VxlanVni vni, Set<NodeId> vppNodes) {
+        for (NodeId vppNode : vppNodes) {
+            try {
+                LOG.trace("Creating VXLAN bridge-domain {} on node {} with VNI {}", bd, vppNode.getValue(),
+                        vni);
+                // TODO think about propagating ListenableFuture - timeout set as workaround
+                bdManager.createVxlanBridgeDomainOnVppNode(bd, vni, vppNode).get(WAIT_FOR_BD_CREATION,
+                        TimeUnit.SECONDS);
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.warn("VXLAN Bridge domain {} was not created on node {}", bd, vppNode.getValue(), e);
+            } catch (TimeoutException e) {
+                LOG.warn("Probably, VXLAN Bridge domain {} was not created on node {} because BridgeDomainManager "
+                        + "did not respond by {} seconds.", bd, vppNode.getValue(), WAIT_FOR_BD_CREATION, e);
+            }
+        }
+    }
+
+    private void createVlanBridgeDomains(String bd, VlanId vlanId, Set<NodeId> vppNodes) {
+        for (NodeId vppNode : vppNodes) {
+            try {
+                LOG.trace("Creating VLAN bridge-domain {} on node {} with VLAN ID {}", bd, vppNode.getValue(),
+                        vlanId.getValue());
+                // TODO think about propagating ListenableFuture - timeout set as workaround
+                bdManager.createVlanBridgeDomainOnVppNode(bd, vlanId, vppNode).get(WAIT_FOR_BD_CREATION,
+                        TimeUnit.SECONDS);
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.warn("VLAN Bridge domain {} was not created on node {}", bd, vppNode.getValue(), e);
+            } catch (TimeoutException e) {
+                LOG.warn("Probably, VLAN Bridge domain {} was not created on node {} because BridgeDomainManager "
+                        + "did not respond by {} seconds.", bd, vppNode.getValue(), WAIT_FOR_BD_CREATION, e);
             }
         }
     }
 
-    public void removeVxlanBridgeDomainsOnNodes(SetMultimap<String, NodeId> vppNodesByBridgeDomain) {
+    public void removeBridgeDomainOnNodes(SetMultimap<String, NodeId> vppNodesByBridgeDomain) {
         for (String bd : vppNodesByBridgeDomain.keySet()) {
             Set<NodeId> vppNodes = vppNodesByBridgeDomain.get(bd);
             for (NodeId vppNode : vppNodes) {
                 try {
-                    bdManager.removeBridgeDomainFromVppNode(bd, vppNode).get();
+                    bdManager.removeBridgeDomainFromVppNode(bd, vppNode).get(WAIT_FOR_BD_CREATION,
+                            TimeUnit.SECONDS);
                 } catch (InterruptedException | ExecutionException e) {
                     LOG.warn("Bridge domain {} was not removed from node {}", bd, vppNode.getValue(), e);
+                } catch (TimeoutException e) {
+                    LOG.warn("Probably, bridge domain {} was not removed from node {} because BridgeDomainManager "
+                            + "did not respond by {} seconds.", bd, vppNode.getValue(), WAIT_FOR_BD_CREATION, e);
                 }
             }
         }
@@ -97,6 +169,10 @@ public class ForwardingManager {
                 // TODO add it to the status for renderer manager
                 LOG.warn("Interface was not added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp, e);
             }
+        } else {
+            LOG.debug("Forwarding is not created - Location of renderer endpoint contains "
+                    + "external-node therefore VPP renderer assumes that interface for endpoint is "
+                    + "already assigned in bridge-domain representing external-node. {}", rEp);
         }
     }
 
@@ -116,6 +192,10 @@ public class ForwardingManager {
                 // TODO add it to the status for renderer manager
                 LOG.warn("bridge-domain was not deleted from interface for endpoint {}", rEp, e);
             }
+        } else {
+            LOG.debug("Forwarding is not removed - Location of renderer endpoint does not contain "
+                    + "external-node therefore VPP renderer assumes that interface for endpoint is not "
+                    + "assigned to bridge-domain representing external-node. {}", rEp);
         }
     }
 
index 3d21b6224d31ca2cde306c6c4360faae970c801a..5f9c0cd80f562cc6176ff8c6c22fbc59d6cbec80 100644 (file)
@@ -28,6 +28,7 @@ import org.opendaylight.groupbasedpolicy.util.IidFactory;
 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.renderer.rev151103.renderers.renderer.RendererPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@@ -65,16 +66,16 @@ public class VppRendererPolicyManager {
         RendererPolicyBuilder responseBuilder = new RendererPolicyBuilder();
         switch (event.getDtoModificationType()) {
             case CREATED:
-                LOG.trace("CREATED : {}", event);
+                LOG.trace("CREATED : {}", event.getIid());
                 responseBuilder.setVersion(event.getAfter().get().getVersion());
                 rendererPolicyCreated(event.getAfter().get());
                 break;
             case UPDATED:
-                LOG.trace("UPDATED: {}", event);
+                LOG.trace("UPDATED: {}", event.getIid());
                 RendererPolicy rPolicyBefore = event.getBefore().get();
                 RendererPolicy rPolicyAfter = event.getAfter().get();
                 responseBuilder.setVersion(rPolicyAfter.getVersion());
-                if (!isConfigurationChanged(rPolicyBefore, rPolicyAfter)) {
+                if (rPolicyBefore.getConfiguration() == null && rPolicyAfter.getConfiguration() == null) {
                     LOG.debug("Configuration is not changed only updating config version from {} to {}",
                             rPolicyBefore.getVersion(), rPolicyAfter.getVersion());
                 } else {
@@ -83,7 +84,7 @@ public class VppRendererPolicyManager {
                 }
                 break;
             case DELETED:
-                LOG.trace("DELETED: {}", event);
+                LOG.trace("DELETED: {}", event.getIid());
                 responseBuilder.setVersion(event.getBefore().get().getVersion());
                 rendererPolicyDeleted(event.getBefore().get());
                 break;
@@ -106,13 +107,6 @@ public class VppRendererPolicyManager {
         });
     }
 
-    private boolean isConfigurationChanged(RendererPolicy before, RendererPolicy after) {
-        if (before.getConfiguration() == null && after.getConfiguration() == null) {
-            return false;
-        }
-        return true;
-    }
-
     private void rendererPolicyUpdated(RendererPolicy rPolicyBefore, RendererPolicy rPolicyAfter) {
         PolicyContext policyCtxBefore = new PolicyContext(rPolicyBefore);
         PolicyContext policyCtxAfter = new PolicyContext(rPolicyAfter);
@@ -158,18 +152,40 @@ public class VppRendererPolicyManager {
         ImmutableSet<RendererEndpointKey> rendEpsAfter = policyCtxAfter.getPolicyTable().rowKeySet();
 
         SetView<RendererEndpointKey> removedRendEps = Sets.difference(rendEpsBefore, rendEpsAfter);
+        LOG.trace("Removed renderer endpoints {}", removedRendEps);
         removedRendEps.forEach(rEpKey -> fwManager.removeForwardingForEndpoint(rEpKey, policyCtxBefore));
 
-        fwManager.removeVxlanBridgeDomainsOnNodes(removedVppNodesByL2Fd);
-        fwManager.createVxlanBridgeDomainsOnNodes(createdVppNodesByL2Fd);
+        LOG.trace("Removed bridge domains on nodes {}", removedVppNodesByL2Fd);
+        LOG.trace("Created bridge domains on nodes {}", createdVppNodesByL2Fd);
+        fwManager.removeBridgeDomainOnNodes(removedVppNodesByL2Fd);
+        fwManager.createBridgeDomainOnNodes(createdVppNodesByL2Fd);
 
         SetView<RendererEndpointKey> createdRendEps = Sets.difference(rendEpsAfter, rendEpsBefore);
+        LOG.trace("Created renderer endpoints {}", createdRendEps);
         createdRendEps.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtxAfter));
 
         SetView<RendererEndpointKey> updatedRendEps = Sets.intersection(rendEpsBefore, rendEpsAfter);
-        // TODO think about all cases, but keep it simple for now
-        updatedRendEps.forEach(rEpKey -> fwManager.removeForwardingForEndpoint(rEpKey, policyCtxBefore));
-        updatedRendEps.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtxAfter));
+        LOG.trace("Updated renderer endpoints {}", updatedRendEps);
+        // update forwarding for endpoint
+        updatedRendEps.forEach(rEpKey -> {
+            AddressEndpointWithLocation addrEpWithLocBefore =
+                    policyCtxBefore.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
+            AddressEndpointWithLocation addrEpWithLocAfter =
+                    policyCtxAfter.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
+            if (isLocationChanged(addrEpWithLocBefore, addrEpWithLocAfter)) {
+                LOG.debug("Location is changed in endpoint {}", rEpKey);
+                LOG.trace("\nLocation before: {}\nLocation after: {}", addrEpWithLocBefore.getAbsoluteLocation(),
+                        addrEpWithLocAfter.getAbsoluteLocation());
+                fwManager.removeForwardingForEndpoint(rEpKey, policyCtxBefore);
+                fwManager.createForwardingForEndpoint(rEpKey, policyCtxAfter);
+            }
+        });
+    }
+
+    private static boolean isLocationChanged(AddressEndpointWithLocation before, AddressEndpointWithLocation after) {
+        ExternalLocationCase locationBefore = ForwardingManager.resolveAndValidateLocation(before);
+        ExternalLocationCase locationAfter = ForwardingManager.resolveAndValidateLocation(after);
+        return !locationBefore.equals(locationAfter);
     }
 
     private static MapDifference<String, Collection<NodeId>> createDiffForVppNodesByL2Fd(PolicyContext policyCtxBefore,
@@ -177,7 +193,7 @@ public class VppRendererPolicyManager {
         ImmutableSet<RendererEndpointKey> rendEpsBefore = policyCtxBefore.getPolicyTable().rowKeySet();
         ImmutableSet<RendererEndpointKey> rendEpsAfter = policyCtxAfter.getPolicyTable().rowKeySet();
         SetMultimap<String, NodeId> vppNodesByL2FdBefore = resolveVppNodesByL2Fd(rendEpsBefore, policyCtxBefore);
-        SetMultimap<String, NodeId> vppNodesByL2FdAfter = resolveVppNodesByL2Fd(rendEpsAfter, policyCtxBefore);
+        SetMultimap<String, NodeId> vppNodesByL2FdAfter = resolveVppNodesByL2Fd(rendEpsAfter, policyCtxAfter);
         return Maps.difference(vppNodesByL2FdBefore.asMap(), vppNodesByL2FdAfter.asMap());
     }
 
@@ -186,7 +202,7 @@ public class VppRendererPolicyManager {
         ImmutableSet<RendererEndpointKey> rEpKeys = policyCtx.getPolicyTable().rowKeySet();
 
         SetMultimap<String, NodeId> vppNodesByL2Fd = resolveVppNodesByL2Fd(rEpKeys, policyCtx);
-        fwManager.createVxlanBridgeDomainsOnNodes(vppNodesByL2Fd);
+        fwManager.createBridgeDomainOnNodes(vppNodesByL2Fd);
 
         rEpKeys.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtx));
     }
@@ -198,7 +214,7 @@ public class VppRendererPolicyManager {
         rEpKeys.forEach(rEpKey -> fwManager.removeForwardingForEndpoint(rEpKey, policyCtx));
 
         SetMultimap<String, NodeId> vppNodesByL2Fd = resolveVppNodesByL2Fd(rEpKeys, policyCtx);
-        fwManager.removeVxlanBridgeDomainsOnNodes(vppNodesByL2Fd);
+        fwManager.removeBridgeDomainOnNodes(vppNodesByL2Fd);
     }
 
     private static SetMultimap<String, NodeId> resolveVppNodesByL2Fd(Set<RendererEndpointKey> rEpKeys,
index e15b1d7a85bfe03ccb28bc208c776628a356c4dd..81f2f45346113fa70182e528a9eaf227411c3922 100644 (file)
@@ -13,6 +13,8 @@ module vpp-renderer {
     prefix "vpp-renderer";
 
     import base-endpoint { prefix base-ep; revision-date 2016-04-27; }
+    import network-topology { prefix nt; revision-date 2013-10-21; }
+    import opendaylight-l2-types { prefix l2-types; revision-date "2013-08-27"; }
 
     description
         "This module is a baseline for the group-based policy vpp renderer model.";
@@ -22,6 +24,27 @@ module vpp-renderer {
             "Initial revision.";
     }
 
+    identity network-type-base {
+        description "Base for Network Types.";
+    }
+
+    identity flat-network {
+        description "Flat Provider Network Type";
+        base network-type-base;
+    }
+
+    identity vlan-network {
+        description "VLAN Provider Network Type";
+        base network-type-base;
+    }
+
+    typedef network-type {
+        description "Type of Network.";
+        type identityref {
+            base network-type-base;
+        }
+    }
+
     container config {
         list vpp-endpoint {
             description "Renderer creates/removes interface on VPP node based on given parameters.";
@@ -52,5 +75,38 @@ module vpp-renderer {
                 }
             }
         }
+
+        list bridge-domain {
+            key "id";
+            leaf id {
+                description "Same as in VBD.";
+                type string;
+            }
+            leaf description {
+               type string;
+            }
+            leaf type {
+                mandatory true;
+                type network-type;
+            }
+            leaf vlan {
+                when "type = 'vlan-network'";
+                type l2-types:vlan-id;
+            }
+            list physical-location-ref {
+                description
+                    "Refers to physical interfaces on vpp nodes through which external
+                     nodes belonging to the same bridge-domain can be reached.";
+                key "node-id";
+                leaf node-id {
+                    description "Refers to a VPP node.";
+                    type nt:node-id;
+                }
+                leaf-list interface {
+                    description "Physical interface on the VPP node.";
+                    type string;
+                }
+            }
+        }
     }
 }
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.groupbasedpolicy.renderer.vpp.manager;
+package org.opendaylight.groupbasedpolicy.renderer.vpp.policy;
 
 import java.util.Arrays;
 import java.util.Collection;
@@ -41,7 +41,6 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeBuilder;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
 
 public class BridgeDomainManagerImplTest extends CustomDataBrokerTest {
 
@@ -92,10 +91,8 @@ public class BridgeDomainManagerImplTest extends CustomDataBrokerTest {
     }
 
     @Test
-    public void testCreateVxlanBridgeDomainOnVppNode() {
-        ListenableFuture<Void> registered =
-                bridgeDomainManager.createVxlanBridgeDomainOnVppNode(BRIDGE_DOMAIN_ID, BRIDGE_DOMAIN_VNI, VPP_NODE_ID);
-        Assert.assertTrue(registered.isDone());
+    public void testCreateVxlanBridgeDomainOnVppNode() throws Exception {
+        bridgeDomainManager.createVxlanBridgeDomainOnVppNode(BRIDGE_DOMAIN_ID, BRIDGE_DOMAIN_VNI, VPP_NODE_ID);
 
         Optional<Topology> topologyOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
                 VppIidFactory.getTopologyIid(BASE_TOPOLOGY.getKey()), dataBroker.newReadOnlyTransaction());
@@ -119,9 +116,7 @@ public class BridgeDomainManagerImplTest extends CustomDataBrokerTest {
                 dataBroker.newReadOnlyTransaction());
         Assert.assertTrue(topologyOptional.isPresent());
 
-        ListenableFuture<Void> deleted =
-                bridgeDomainManager.removeBridgeDomainFromVppNode(BRIDGE_DOMAIN_ID, VPP_NODE_ID);
-        Assert.assertTrue(deleted.isDone());
+        bridgeDomainManager.removeBridgeDomainFromVppNode(BRIDGE_DOMAIN_ID, VPP_NODE_ID);
 
         topologyOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
                 VppIidFactory.getNodeIid(new TopologyKey(BASE_TOPOLOGY_ID), new NodeKey(VPP_NODE_ID)),
index 9e79c52baa9430fcf7185e0b38f34142fd529925..25c9db47bf2f604cd059627cad79e2e3f3395398 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.policy;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -28,7 +30,6 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppEndpointLocationProvider;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.BridgeDomainManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
 import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
@@ -69,6 +70,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
 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.PeerEndpointWithPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicyBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupBuilder;
@@ -77,9 +79,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_render
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.bridge.domain.PhysicalLocationRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanVni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.Interconnection;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBased;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains;
@@ -95,6 +99,7 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Strings;
 import com.google.common.util.concurrent.MoreExecutors;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -103,49 +108,37 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
     private static final InstanceIdentifier<RendererPolicy> RENDERER_POLICY_IID =
             IidFactory.rendererIid(VppRenderer.NAME).child(RendererPolicy.class);
     private static final ContextId CTX_ID = new ContextId("ctx");
-    private static final AddressEndpointWithLocationKey CLIENT_EP_KEY =
-            new AddressEndpointWithLocationKey("1.1.1.1", AddressType.class, CTX_ID, ContextType.class);
-    private static final AddressEndpointWithLocationKey WEB_EP_KEY =
-            new AddressEndpointWithLocationKey("2.2.2.2", AddressType.class, CTX_ID, ContextType.class);
     private static final ContextId L2FD_CTX = new ContextId("l2fd");
-    private static final NetworkContainment L2FD_NET_CONT =
-            new NetworkContainmentBuilder().setContainment(new ForwardingContextContainmentBuilder()
-                .setContextType(L2FloodDomain.class).setContextId(L2FD_CTX).build()).build();
-    private final static TopologyKey TOPO_KEY = new TopologyKey(new TopologyId("topo1"));
-    private final static NodeKey NODE_KEY = new NodeKey(new NodeId("node1"));
-    private final static InstanceIdentifier<Node> VPP_NODE_IID = InstanceIdentifier.builder(NetworkTopology.class)
+    private final static TopologyKey TOPO_KEY = new TopologyKey(new TopologyId("topology-netconf"));
+    private final static InstanceIdentifier<Node> VPP_NODE_1_IID = InstanceIdentifier.builder(NetworkTopology.class)
         .child(Topology.class, TOPO_KEY)
-        .child(Node.class, NODE_KEY)
+        .child(Node.class, new NodeKey(new NodeId("node1")))
+        .build();
+    private final static InstanceIdentifier<Node> VPP_NODE_2_IID = InstanceIdentifier.builder(NetworkTopology.class)
+        .child(Topology.class, TOPO_KEY)
+        .child(Node.class, new NodeKey(new NodeId("node2")))
         .build();
-    private static final String IFACE_NAME_CLIENT_EP = "interfaceClient";
-    private static final String NODE_CONNECTOR_CLIENT_EP = VppPathMapper.interfaceToRestPath(IFACE_NAME_CLIENT_EP);
-    private static final String IFACE_NAME_WEB_EP = "interfaceWeb";
-    private static final String NODE_CONNECTOR_WEB_EP = VppPathMapper.interfaceToRestPath(IFACE_NAME_WEB_EP);
     private static final ContractId CONTRACT_ID = new ContractId("contract");
     private static final TenantId TENANT_ID = new TenantId("tenant");
     private static final SubjectName SUBJECT_NAME = new SubjectName("subject");
     private static final RuleName RULE_NAME = new RuleName("rule");
-    private static final RuleGroupWithRendererEndpointParticipation RULE_GROUP_WITH_REND_EP_PART =
+    private static final RuleGroupWithRendererEndpointParticipation RULE_GROUP_WITH_CONSUMER =
             new RuleGroupWithRendererEndpointParticipationBuilder().setContractId(CONTRACT_ID)
                 .setTenantId(TENANT_ID)
                 .setSubjectName(SUBJECT_NAME)
                 .setRendererEndpointParticipation(EndpointPolicyParticipation.CONSUMER)
                 .build();
+    private static final RuleGroupWithRendererEndpointParticipation RULE_GROUP_WITH_PROVIDER =
+            new RuleGroupWithRendererEndpointParticipationBuilder().setContractId(CONTRACT_ID)
+                .setTenantId(TENANT_ID)
+                .setSubjectName(SUBJECT_NAME)
+                .setRendererEndpointParticipation(EndpointPolicyParticipation.PROVIDER)
+                .build();
     private static final RuleGroup RULE_GROUP = new RuleGroupBuilder().setContractId(CONTRACT_ID)
         .setTenantId(TENANT_ID)
         .setSubjectName(SUBJECT_NAME)
         .setResolvedRule(Arrays.asList(new ResolvedRuleBuilder().setName(RULE_NAME).build()))
         .build();
-    // data for InterfaceManager
-    private final static InstanceIdentifier<VppEndpoint> BASIC_VPP_CLIENT_EP_IID =
-            InstanceIdentifier.builder(Config.class)
-                .child(VppEndpoint.class, new VppEndpointKey(CLIENT_EP_KEY.getAddress(), CLIENT_EP_KEY.getAddressType(),
-                        CLIENT_EP_KEY.getContextId(), CLIENT_EP_KEY.getContextType()))
-                .build();
-    private final static InstanceIdentifier<VppEndpoint> BASIC_VPP_WEB_EP_IID = InstanceIdentifier.builder(Config.class)
-        .child(VppEndpoint.class, new VppEndpointKey(WEB_EP_KEY.getAddress(), WEB_EP_KEY.getAddressType(),
-                WEB_EP_KEY.getContextId(), WEB_EP_KEY.getContextType()))
-        .build();
     private final static String SOCKET = "socket";
 
     private MountedDataBrokerProvider mountedDataProviderMock;
@@ -161,49 +154,40 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
     public Collection<Class<?>> getClassesFromModules() {
         return Arrays.asList(Node.class, VppEndpoint.class, Interfaces.class, BridgeDomains.class,
                 LocationProviders.class, L2FloodDomain.class, VxlanVni.class, TopologyVbridgeAugment.class,
-                TunnelTypeVxlan.class);
+                TunnelTypeVxlan.class, PhysicalLocationRef.class);
     }
 
     @Before
     public void init() throws Exception {
+        ForwardingManager.WAIT_FOR_BD_CREATION = 2;
         mountedDataProviderMock = Mockito.mock(MountedDataBrokerProvider.class);
         mountPointDataBroker = getDataBroker();
         setup(); // initialize new data broker for ODL data store
         dataBroker = getDataBroker();
         Mockito.when(mountedDataProviderMock.getDataBrokerForMountPoint(Mockito.any(InstanceIdentifier.class)))
             .thenReturn(Optional.of(mountPointDataBroker));
-        ifaceManager = new InterfaceManager(mountedDataProviderMock, dataBroker, MoreExecutors.newDirectExecutorService());
+        ifaceManager =
+                new InterfaceManager(mountedDataProviderMock, dataBroker, MoreExecutors.newDirectExecutorService());
         bdManager = new BridgeDomainManagerImpl(mountPointDataBroker);
-        fwManager = new ForwardingManager(ifaceManager, bdManager);
+        fwManager = new ForwardingManager(ifaceManager, bdManager, dataBroker);
         vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, dataBroker);
     }
 
     @Test
-    public void testRendererPolicyChanged_createdClient() throws Exception {
-        storeInterfaceFor(CLIENT_EP_KEY, IFACE_NAME_CLIENT_EP, BASIC_VPP_CLIENT_EP_IID);
+    public void testRendererPolicyChanged_created_oneEpPerEpg() throws Exception {
+        String clientIp = "1.1.1.1";
+        String clientIfaceName = "client1";
+        AbsoluteLocation clientLocation = absoluteLocation(VPP_NODE_1_IID, null, clientIfaceName);
+        AddressEndpointWithLocation clientEp = createEndpoint(clientIp, L2FD_CTX.getValue(), clientLocation);
+        String webIp = "2.2.2.2";
+        String webIfaceName = "web1";
+        AbsoluteLocation webLocation = absoluteLocation(VPP_NODE_1_IID, null, webIfaceName);
+        AddressEndpointWithLocation webEp = createEndpoint(webIp, L2FD_CTX.getValue(), webLocation);
 
-        AddressEndpointWithLocation clientEp = new AddressEndpointWithLocationBuilder().setKey(CLIENT_EP_KEY)
-            .setNetworkContainment(L2FD_NET_CONT)
-            .setAbsoluteLocation(absoluteLocation(VPP_NODE_IID, null, NODE_CONNECTOR_CLIENT_EP))
-            .build();
-        AddressEndpointWithLocation webEp = new AddressEndpointWithLocationBuilder().setKey(WEB_EP_KEY)
-            .setNetworkContainment(L2FD_NET_CONT)
-            .setAbsoluteLocation(absoluteLocation(VPP_NODE_IID, null, NODE_CONNECTOR_WEB_EP))
-            .build();
-        Endpoints endpoints =
-                new EndpointsBuilder().setAddressEndpointWithLocation(Arrays.asList(clientEp, webEp)).build();
-        RendererEndpoint rendererEndpoint = new RendererEndpointBuilder()
-            .setKey(KeyFactory.rendererEndpointKey(CLIENT_EP_KEY))
-            .setPeerEndpointWithPolicy(Arrays.asList(new PeerEndpointWithPolicyBuilder()
-                .setKey(KeyFactory.peerEndpointWithPolicyKey(WEB_EP_KEY))
-                .setRuleGroupWithRendererEndpointParticipation(Arrays.asList(RULE_GROUP_WITH_REND_EP_PART))
-                .build()))
-            .build();
-        Configuration configuration = new ConfigurationBuilder().setEndpoints(endpoints)
-            .setRendererEndpoints(
-                    new RendererEndpointsBuilder().setRendererEndpoint(Arrays.asList(rendererEndpoint)).build())
-            .setRuleGroups(new RuleGroupsBuilder().setRuleGroup(Arrays.asList(RULE_GROUP)).build())
-            .build();
+        storeVppEndpoint(clientEp.getKey(), clientIfaceName, createVppEndpointIid(clientEp.getKey()));
+        storeVppEndpoint(webEp.getKey(), webIfaceName, createVppEndpointIid(webEp.getKey()));
+
+        Configuration configuration = createConfiguration(Arrays.asList(clientEp), Arrays.asList(webEp));
         RendererPolicy rendererPolicy =
                 new RendererPolicyBuilder().setVersion(1L).setConfiguration(configuration).build();
         RendererPolicyConfEvent event = new RendererPolicyConfEvent(RENDERER_POLICY_IID, null, rendererPolicy);
@@ -211,17 +195,10 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
         vppRendererPolicyManager.rendererPolicyChanged(event);
 
         // assert state on data store behind mount point
-        ReadOnlyTransaction rTxMount = mountPointDataBroker.newReadOnlyTransaction();
-        Optional<Interface> potentialIface = rTxMount.read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
-            .builder(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME_CLIENT_EP)).build()).get();
-        Assert.assertTrue(potentialIface.isPresent());
-        Interface iface = potentialIface.get();
-        VppInterfaceAugmentation vppIfaceAug = iface.getAugmentation(VppInterfaceAugmentation.class);
-        Assert.assertNotNull(vppIfaceAug);
-        Interconnection interconnection = vppIfaceAug.getL2().getInterconnection();
-        Assert.assertNotNull(interconnection);
-        Assert.assertTrue(interconnection instanceof BridgeBased);
-        Assert.assertEquals(L2FD_CTX.getValue(), ((BridgeBased) interconnection).getBridgeDomain());
+        Interface clientIface = readAndAssertInterface(clientIfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), clientIface);
+        Interface webIface = readAndAssertInterface(webIfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), webIface);
         // assert state on ODL data store
         ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
         Optional<LocationProvider> optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
@@ -230,57 +207,52 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
         Assert.assertTrue(optLocationProvider.isPresent());
         List<ProviderAddressEndpointLocation> epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
         Assert.assertNotNull(epLocs);
-        Assert.assertEquals(1, epLocs.size());
-        Assert.assertEquals(absoluteLocation(VPP_NODE_IID, VppPathMapper.bridgeDomainToRestPath(L2FD_CTX.getValue()),
-                NODE_CONNECTOR_CLIENT_EP), epLocs.get(0).getAbsoluteLocation());
+        Assert.assertEquals(2, epLocs.size());
+        assertProviderAddressEndpointLocation(clientEp.getKey(),
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), clientIfaceName), epLocs);
+        assertProviderAddressEndpointLocation(webEp.getKey(),
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), webIfaceName), epLocs);
     }
 
     @Test
-    public void testRendererPolicyChanged_createdClientAndThenWeb() throws Exception {
-        testRendererPolicyChanged_createdClient();
+    public void testRendererPolicyChanged_update() throws Exception {
+        String client1IfaceName = "client1";
+        AbsoluteLocation client1LocationNodeNull = absoluteLocation(VPP_NODE_1_IID, null, client1IfaceName);
+        AddressEndpointWithLocation client1Ep =
+                createEndpoint("10.0.0.1", L2FD_CTX.getValue(), client1LocationNodeNull);
+        String web1IfaceName = "web1";
+        AbsoluteLocation web1LocationNodeNull = absoluteLocation(VPP_NODE_2_IID, null, web1IfaceName);
+        AddressEndpointWithLocation web1Ep = createEndpoint("20.0.0.1", L2FD_CTX.getValue(), web1LocationNodeNull);
+        String client2IfaceName = "client2";
+        AbsoluteLocation client2LocationNodeNull = absoluteLocation(VPP_NODE_1_IID, null, client2IfaceName);
+        AddressEndpointWithLocation client2Ep =
+                createEndpoint("10.0.0.2", L2FD_CTX.getValue(), client2LocationNodeNull);
+        String web2IfaceName = "web2";
+        AbsoluteLocation web2LocationNodeNull = absoluteLocation(VPP_NODE_2_IID, null, web2IfaceName);
+        AddressEndpointWithLocation web2Ep = createEndpoint("20.0.0.2", L2FD_CTX.getValue(), web2LocationNodeNull);
 
-        storeInterfaceFor(WEB_EP_KEY, IFACE_NAME_WEB_EP, BASIC_VPP_WEB_EP_IID);
+        storeVppEndpoint(client1Ep.getKey(), client1IfaceName, createVppEndpointIid(client1Ep.getKey()));
+        storeVppEndpoint(web1Ep.getKey(), web1IfaceName, createVppEndpointIid(web1Ep.getKey()));
+        storeVppEndpoint(client2Ep.getKey(), client2IfaceName, createVppEndpointIid(client2Ep.getKey()));
+        storeVppEndpoint(web2Ep.getKey(), web2IfaceName, createVppEndpointIid(web2Ep.getKey()));
 
-        AddressEndpointWithLocation webEp = new AddressEndpointWithLocationBuilder().setKey(WEB_EP_KEY)
-            .setNetworkContainment(L2FD_NET_CONT)
-            .setAbsoluteLocation(absoluteLocation(VPP_NODE_IID, null, NODE_CONNECTOR_WEB_EP))
-            .build();
-        AddressEndpointWithLocation clientEp = new AddressEndpointWithLocationBuilder().setKey(CLIENT_EP_KEY)
-            .setNetworkContainment(L2FD_NET_CONT)
-            .setAbsoluteLocation(absoluteLocation(VPP_NODE_IID, null, NODE_CONNECTOR_CLIENT_EP))
-            .build();
-        Endpoints endpoints =
-                new EndpointsBuilder().setAddressEndpointWithLocation(Arrays.asList(webEp, clientEp)).build();
-        RendererEndpoint rendererEndpoint = new RendererEndpointBuilder()
-            .setKey(KeyFactory.rendererEndpointKey(WEB_EP_KEY))
-            .setPeerEndpointWithPolicy(Arrays.asList(new PeerEndpointWithPolicyBuilder()
-                .setKey(KeyFactory.peerEndpointWithPolicyKey(CLIENT_EP_KEY))
-                .setRuleGroupWithRendererEndpointParticipation(Arrays.asList(RULE_GROUP_WITH_REND_EP_PART))
-                .build()))
-            .build();
-        Configuration configuration = new ConfigurationBuilder().setEndpoints(endpoints)
-            .setRendererEndpoints(
-                    new RendererEndpointsBuilder().setRendererEndpoint(Arrays.asList(rendererEndpoint)).build())
-            .setRuleGroups(new RuleGroupsBuilder().setRuleGroup(Arrays.asList(RULE_GROUP)).build())
-            .build();
+        Configuration configuration =
+                createConfiguration(Arrays.asList(client1Ep, client2Ep), Arrays.asList(web1Ep, web2Ep));
         RendererPolicy rendererPolicy =
                 new RendererPolicyBuilder().setVersion(1L).setConfiguration(configuration).build();
         RendererPolicyConfEvent event = new RendererPolicyConfEvent(RENDERER_POLICY_IID, null, rendererPolicy);
 
         vppRendererPolicyManager.rendererPolicyChanged(event);
 
-        // assert state on data store behind mount point
-        ReadOnlyTransaction rTxMount = mountPointDataBroker.newReadOnlyTransaction();
-        Optional<Interface> potentialIface = rTxMount.read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
-            .builder(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME_WEB_EP)).build()).get();
-        Assert.assertTrue(potentialIface.isPresent());
-        Interface iface = potentialIface.get();
-        VppInterfaceAugmentation vppIfaceAug = iface.getAugmentation(VppInterfaceAugmentation.class);
-        Assert.assertNotNull(vppIfaceAug);
-        Interconnection interconnection = vppIfaceAug.getL2().getInterconnection();
-        Assert.assertNotNull(interconnection);
-        Assert.assertTrue(interconnection instanceof BridgeBased);
-        Assert.assertEquals(L2FD_CTX.getValue(), ((BridgeBased) interconnection).getBridgeDomain());
+        // assert state on data store behind mount point ######################################
+        Interface client1Iface = readAndAssertInterface(client1IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), client1Iface);
+        Interface web1Iface = readAndAssertInterface(web1IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), web1Iface);
+        Interface client2Iface = readAndAssertInterface(client2IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), client2Iface);
+        Interface web2Iface = readAndAssertInterface(web2IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), web2Iface);
         // assert state on ODL data store
         ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
         Optional<LocationProvider> optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
@@ -289,46 +261,227 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
         Assert.assertTrue(optLocationProvider.isPresent());
         List<ProviderAddressEndpointLocation> epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
         Assert.assertNotNull(epLocs);
-        Assert.assertEquals(2, epLocs.size());
-        if (epLocs.get(0).getAddress().equals(CLIENT_EP_KEY.getAddress())) {
-            Assert.assertEquals(absoluteLocation(VPP_NODE_IID,
-                    VppPathMapper.bridgeDomainToRestPath(L2FD_CTX.getValue()), NODE_CONNECTOR_CLIENT_EP),
-                    epLocs.get(0).getAbsoluteLocation());
-            Assert.assertEquals(absoluteLocation(VPP_NODE_IID,
-                    VppPathMapper.bridgeDomainToRestPath(L2FD_CTX.getValue()), NODE_CONNECTOR_WEB_EP),
-                    epLocs.get(1).getAbsoluteLocation());
+        Assert.assertEquals(4, epLocs.size());
+        assertProviderAddressEndpointLocation(client1Ep.getKey(),
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), client1IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(web1Ep.getKey(),
+                absoluteLocation(VPP_NODE_2_IID, L2FD_CTX.getValue(), web1IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(client2Ep.getKey(),
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), client2IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(web2Ep.getKey(),
+                absoluteLocation(VPP_NODE_2_IID, L2FD_CTX.getValue(), web2IfaceName), epLocs);
+        // #####################################################################################
+
+        AbsoluteLocation client1Location =
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), client1IfaceName);
+        AbsoluteLocation web1Location =
+                absoluteLocation(VPP_NODE_2_IID, L2FD_CTX.getValue(), web1IfaceName);
+        AbsoluteLocation web2Location =
+                absoluteLocation(VPP_NODE_2_IID, L2FD_CTX.getValue(), web2IfaceName);
+        configuration = createConfiguration(
+                Arrays.asList(
+                        new AddressEndpointWithLocationBuilder(client1Ep).setAbsoluteLocation(client1Location).build(),
+                        new AddressEndpointWithLocationBuilder(client2Ep).setAbsoluteLocation(client2LocationNodeNull)
+                            .build()),
+                Arrays.asList(new AddressEndpointWithLocationBuilder(web1Ep).setAbsoluteLocation(web1Location).build(),
+                        new AddressEndpointWithLocationBuilder(web2Ep).setAbsoluteLocation(web2Location).build()));
+        RendererPolicy rendererPolicy2 =
+                new RendererPolicyBuilder().setVersion(2L).setConfiguration(configuration).build();
+        RendererPolicyConfEvent event2 =
+                new RendererPolicyConfEvent(RENDERER_POLICY_IID, rendererPolicy, rendererPolicy2);
+
+        vppRendererPolicyManager.rendererPolicyChanged(event2);
+
+        // assert state on data store behind mount point ######################################
+        client1Iface = readAndAssertInterface(client1IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), client1Iface);
+        web1Iface = readAndAssertInterface(web1IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), web1Iface);
+        client2Iface = readAndAssertInterface(client2IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), client2Iface);
+        web2Iface = readAndAssertInterface(web2IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), web2Iface);
+        // assert state on ODL data store
+        rTx = dataBroker.newReadOnlyTransaction();
+        optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
+            .get();
+        Assert.assertTrue(optLocationProvider.isPresent());
+        epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
+        Assert.assertNotNull(epLocs);
+        Assert.assertEquals(4, epLocs.size());
+        assertProviderAddressEndpointLocation(client1Ep.getKey(),
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), client1IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(web1Ep.getKey(),
+                absoluteLocation(VPP_NODE_2_IID, L2FD_CTX.getValue(), web1IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(client2Ep.getKey(),
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), client2IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(web2Ep.getKey(),
+                absoluteLocation(VPP_NODE_2_IID, L2FD_CTX.getValue(), web2IfaceName), epLocs);
+        // #####################################################################################
+
+        AbsoluteLocation client2Location =
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), client2IfaceName);
+        configuration = createConfiguration(
+                Arrays.asList(new AddressEndpointWithLocationBuilder(client1Ep).setAbsoluteLocation(client1Location)
+                    .build(),
+                        new AddressEndpointWithLocationBuilder(client2Ep).setAbsoluteLocation(client2Location).build()),
+                Arrays.asList(new AddressEndpointWithLocationBuilder(web1Ep).setAbsoluteLocation(web1Location).build(),
+                        new AddressEndpointWithLocationBuilder(web2Ep).setAbsoluteLocation(web2Location).build()));
+        RendererPolicy rendererPolicy3 =
+                new RendererPolicyBuilder().setVersion(3L).setConfiguration(configuration).build();
+        RendererPolicyConfEvent event3 =
+                new RendererPolicyConfEvent(RENDERER_POLICY_IID, rendererPolicy2, rendererPolicy3);
+
+        vppRendererPolicyManager.rendererPolicyChanged(event3);
+
+        // assert state on data store behind mount point ######################################
+        client1Iface = readAndAssertInterface(client1IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), client1Iface);
+        web1Iface = readAndAssertInterface(web1IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), web1Iface);
+        client2Iface = readAndAssertInterface(client2IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), client2Iface);
+        web2Iface = readAndAssertInterface(web2IfaceName);
+        assertBridgeDomainOnInterface(L2FD_CTX.getValue(), web2Iface);
+        // assert state on ODL data store
+        rTx = dataBroker.newReadOnlyTransaction();
+        optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
+            .get();
+        Assert.assertTrue(optLocationProvider.isPresent());
+        epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
+        Assert.assertNotNull(epLocs);
+        Assert.assertEquals(4, epLocs.size());
+        assertProviderAddressEndpointLocation(client1Ep.getKey(),
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), client1IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(web1Ep.getKey(),
+                absoluteLocation(VPP_NODE_2_IID, L2FD_CTX.getValue(), web1IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(client2Ep.getKey(),
+                absoluteLocation(VPP_NODE_1_IID, L2FD_CTX.getValue(), client2IfaceName), epLocs);
+        assertProviderAddressEndpointLocation(web2Ep.getKey(),
+                absoluteLocation(VPP_NODE_2_IID, L2FD_CTX.getValue(), web2IfaceName), epLocs);
+        // #####################################################################################
+    }
+
+    private static AbsoluteLocation absoluteLocation(InstanceIdentifier<?> mountPoint, String nodeName,
+            String nodeConnectorName) {
+        ExternalLocationCaseBuilder extLocBuilder =
+                new ExternalLocationCaseBuilder().setExternalNodeMountPoint(mountPoint);
+        if (!Strings.isNullOrEmpty(nodeName)) {
+            extLocBuilder.setExternalNode(VppPathMapper.bridgeDomainToRestPath(nodeName));
+        }
+        if (!Strings.isNullOrEmpty(nodeConnectorName)) {
+            extLocBuilder.setExternalNodeConnector(VppPathMapper.interfaceToRestPath(nodeConnectorName));
+        }
+        return new AbsoluteLocationBuilder().setLocationType(extLocBuilder.build()).build();
+    }
+
+    private AddressEndpointWithLocation createEndpoint(String ip, String l2FdIdAsNetCont,
+            AbsoluteLocation absoluteLocation) {
+        AddressEndpointWithLocationKey key =
+                new AddressEndpointWithLocationKey(ip, AddressType.class, CTX_ID, ContextType.class);
+        NetworkContainment networkContainment =
+                new NetworkContainmentBuilder().setContainment(new ForwardingContextContainmentBuilder()
+                    .setContextType(L2FloodDomain.class).setContextId(new ContextId(l2FdIdAsNetCont)).build()).build();
+        return new AddressEndpointWithLocationBuilder().setKey(key)
+            .setNetworkContainment(networkContainment)
+            .setAbsoluteLocation(absoluteLocation)
+            .build();
+    }
+
+    private InstanceIdentifier<VppEndpoint> createVppEndpointIid(AddressEndpointWithLocationKey key) {
+        return InstanceIdentifier.builder(Config.class)
+            .child(VppEndpoint.class, new VppEndpointKey(key.getAddress(), key.getAddressType(), key.getContextId(),
+                    key.getContextType()))
+            .build();
+    }
+
+    private Configuration createConfiguration(List<AddressEndpointWithLocation> consumers,
+            List<AddressEndpointWithLocation> providers) {
+        List<AddressEndpointWithLocation> eps =
+                Stream.concat(consumers.stream(), providers.stream()).collect(Collectors.toList());
+        Endpoints endpoints = new EndpointsBuilder().setAddressEndpointWithLocation(eps).build();
+        List<RendererEndpoint> consumersAsRendererEps = consumers.stream().map(cons -> {
+            List<PeerEndpointWithPolicy> peers = providers.stream()
+                .map(web -> new PeerEndpointWithPolicyBuilder()
+                    .setKey(KeyFactory.peerEndpointWithPolicyKey(web.getKey()))
+                    .setRuleGroupWithRendererEndpointParticipation(Arrays.asList(RULE_GROUP_WITH_CONSUMER))
+                    .build())
+                .collect(Collectors.toList());
+            return new RendererEndpointBuilder().setKey(KeyFactory.rendererEndpointKey(cons.getKey()))
+                .setPeerEndpointWithPolicy(peers)
+                .build();
+        }).collect(Collectors.toList());
+        List<RendererEndpoint> providersAsRendererEps = providers.stream().map(prov -> {
+            List<PeerEndpointWithPolicy> peers = consumers.stream()
+                .map(client -> new PeerEndpointWithPolicyBuilder()
+                    .setKey(KeyFactory.peerEndpointWithPolicyKey(client.getKey()))
+                    .setRuleGroupWithRendererEndpointParticipation(Arrays.asList(RULE_GROUP_WITH_PROVIDER))
+                    .build())
+                .collect(Collectors.toList());
+            return new RendererEndpointBuilder().setKey(KeyFactory.rendererEndpointKey(prov.getKey()))
+                .setPeerEndpointWithPolicy(peers)
+                .build();
+        }).collect(Collectors.toList());
+        List<RendererEndpoint> rendererEps = Stream
+            .concat(consumersAsRendererEps.stream(), providersAsRendererEps.stream()).collect(Collectors.toList());
+        return new ConfigurationBuilder().setEndpoints(endpoints)
+            .setRendererEndpoints(new RendererEndpointsBuilder().setRendererEndpoint(rendererEps).build())
+            .setRuleGroups(new RuleGroupsBuilder().setRuleGroup(Arrays.asList(RULE_GROUP)).build())
+            .build();
+    }
+
+    private void assertProviderAddressEndpointLocation(AddressEndpointWithLocationKey expectedEpKey,
+            AbsoluteLocation expectedEpLoc, List<ProviderAddressEndpointLocation> providerEpLocs) {
+        List<ProviderAddressEndpointLocation> expectedProvEpLoc =
+                providerEpLocs.stream()
+                    .filter(provEpLoc -> provEpLoc.getKey()
+                        .equals(KeyFactory.providerAddressEndpointLocationKey(expectedEpKey)))
+                    .collect(Collectors.toList());
+        Assert.assertFalse(expectedProvEpLoc.isEmpty());
+        Assert.assertEquals(1, expectedProvEpLoc.size());
+        Assert.assertEquals(expectedEpLoc, expectedProvEpLoc.get(0).getAbsoluteLocation());
+    }
+
+    private Interface readAndAssertInterface(String expectedInterface) throws Exception {
+        ReadOnlyTransaction rTxMount = mountPointDataBroker.newReadOnlyTransaction();
+        Optional<Interface> potentialIface = rTxMount.read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
+            .builder(Interfaces.class).child(Interface.class, new InterfaceKey(expectedInterface)).build()).get();
+        Assert.assertTrue(potentialIface.isPresent());
+        return potentialIface.get();
+    }
+
+    private static void assertBridgeDomainOnInterface(String expectedBridgeDomain, Interface actualIface) {
+        VppInterfaceAugmentation vppIfaceAug = actualIface.getAugmentation(VppInterfaceAugmentation.class);
+        Assert.assertNotNull(vppIfaceAug);
+        if (!Strings.isNullOrEmpty(expectedBridgeDomain)) {
+            Interconnection interconnection = vppIfaceAug.getL2().getInterconnection();
+            Assert.assertNotNull(interconnection);
+            Assert.assertTrue(interconnection instanceof BridgeBased);
+            Assert.assertEquals(expectedBridgeDomain, ((BridgeBased) interconnection).getBridgeDomain());
         } else {
-            Assert.assertEquals(absoluteLocation(VPP_NODE_IID,
-                    VppPathMapper.bridgeDomainToRestPath(L2FD_CTX.getValue()), NODE_CONNECTOR_CLIENT_EP),
-                    epLocs.get(1).getAbsoluteLocation());
-            Assert.assertEquals(absoluteLocation(VPP_NODE_IID,
-                    VppPathMapper.bridgeDomainToRestPath(L2FD_CTX.getValue()), NODE_CONNECTOR_WEB_EP),
-                    epLocs.get(0).getAbsoluteLocation());
+            if (vppIfaceAug != null) {
+                L2 l2 = vppIfaceAug.getL2();
+                if (l2 != null) {
+                    Assert.assertNull(l2.getInterconnection());
+                }
+            }
         }
     }
 
-    private void storeInterfaceFor(AddressEndpointWithLocationKey epKey, String ifaceName,
+    private void storeVppEndpoint(AddressEndpointWithLocationKey epKey, String ifaceName,
             InstanceIdentifier<VppEndpoint> vppEpIid) {
         VppEndpoint vhostEp = new VppEndpointBuilder().setAddress(epKey.getAddress())
             .setAddressType(epKey.getAddressType())
             .setContextId(epKey.getContextId())
             .setContextType(epKey.getContextType())
             .setVppInterfaceName(ifaceName)
-            .setVppNodePath(VPP_NODE_IID)
+            .setVppNodePath(VPP_NODE_1_IID)
             .setInterfaceTypeChoice(new VhostUserCaseBuilder().setSocket(SOCKET).build())
             .build();
         VppEndpointConfEvent vppEpEvent = new VppEndpointConfEvent(vppEpIid, null, vhostEp);
         ifaceManager.vppEndpointChanged(vppEpEvent);
     }
 
-    private static AbsoluteLocation absoluteLocation(InstanceIdentifier<?> mountPoint, String node,
-            String nodeConnector) {
-        return new AbsoluteLocationBuilder()
-            .setLocationType(new ExternalLocationCaseBuilder().setExternalNodeMountPoint(mountPoint)
-                .setExternalNode(node)
-                .setExternalNodeConnector(nodeConnector)
-                .build())
-            .build();
-    }
-
 }
index 9cb592bcbec01a92d157c3d01d92c022d16c9dff..0f2d59bb85c49c3c688a4821427d08b506035d69 100755 (executable)
                         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
                         <name>binding-rpc-broker</name>
                     </rpc-registry>
+                    <domain-specific-registry>
+                        <type xmlns:gbp="urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy">
+                            gbp:domain-specific-registry
+                        </type>
+                        <name>domain-specific-registry</name>
+                    </domain-specific-registry>
                 </module>
             </modules>
         </data>
index 8a78441ec48b4ae9480c6db3ac622bafb052994b..c7560b6755464135fb95b49331a0dd9b0a6c1948 100644 (file)
@@ -30,6 +30,7 @@ public class SxpMapperProviderModule extends org.opendaylight.controller.config.
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return new SxpMapperProviderImpl(getDataBrokerDependency(), getRpcRegistryDependency());
+        return new SxpMapperProviderImpl(getDataBrokerDependency(), getRpcRegistryDependency(),
+                getDomainSpecificRegistryDependency());
     }
 }
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/ReadableAsyncByKey.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/ReadableAsyncByKey.java
new file mode 100644 (file)
index 0000000..b594de0
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.sxp.mapper.api;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import javax.annotation.Nonnull;
+
+/**
+ * Purpose: simple asynchronous search interface allowing for custom key and returning list of values
+ *
+ * @param <X> special key type
+ * @param <V> value type
+ */
+public interface ReadableAsyncByKey<X, V> {
+
+    /**
+     * @param specialKey custom key to search by
+     * @return list of found values
+     */
+    ListenableFuture<Collection<V>> readBy(@Nonnull X specialKey);
+}
index fc46e6d179e229f0bf60d3b6aab87972c6dd23f4..1e3406608e2a2a627a1e4c996cbf1220e216ed4a 100644 (file)
@@ -5,14 +5,14 @@
  * 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.sxp.mapper.api;
 
-import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Collection;
 import javax.annotation.Nonnull;
 
 /**
- * Purpose: simple asynchronous search interface allowing for custom key and returning list of values
+ * Purpose: simple search interface allowing for custom key and returning list of values
  *
  * @param <X> special key type
  * @param <V> value type
@@ -23,5 +23,5 @@ public interface ReadableByKey<X, V> {
      * @param specialKey custom key to search by
      * @return list of found values
      */
-    ListenableFuture<Collection<V>> readBy(@Nonnull X specialKey);
+    Collection<V> readBy(@Nonnull X specialKey);
 }
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpEndpointAugmentorImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpEndpointAugmentorImpl.java
new file mode 100644 (file)
index 0000000..deee5ab
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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.sxp.mapper.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.Map.Entry;
+import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EpPolicyTemplateValueKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EpPolicyTemplateValueKeyFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.ContainmentEndpointWithLocation;
+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.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.AddressEndpointWithLocationAugBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+public class SxpEndpointAugmentorImpl implements EndpointAugmentor {
+
+    private final ReadableByKey<EpPolicyTemplateValueKey, EndpointPolicyTemplateBySgt> epPolicyTemplateDao;
+    private final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory;
+
+    public SxpEndpointAugmentorImpl(final ReadableByKey<EpPolicyTemplateValueKey, EndpointPolicyTemplateBySgt> epPolicyTemplateDao,
+                                   final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory) {
+        this.epPolicyTemplateKeyFactory = Preconditions.checkNotNull(epPolicyTemplateKeyFactory, "epPolicyTemplateKeyFactory can not be null");
+        this.epPolicyTemplateDao = Preconditions.checkNotNull(epPolicyTemplateDao, "epPolicyTemplateDao can not be null");
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<AddressEndpoint>>, Augmentation<AddressEndpoint>> buildAddressEndpointAugmentation(
+            AddressEndpointReg input) {
+        return null;
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<ContainmentEndpoint>>, Augmentation<ContainmentEndpoint>> buildContainmentEndpointAugmentation(
+            ContainmentEndpointReg input) {
+        return null;
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<AddressEndpointWithLocation>>, Augmentation<AddressEndpointWithLocation>> buildAddressEndpointWithLocationAugmentation(
+            AddressEndpoint input) {
+        final EpPolicyTemplateValueKey templateValueKey = epPolicyTemplateKeyFactory.createKey(
+                input.getTenant(), input.getEndpointGroup(), input.getCondition());
+
+        final Collection<EndpointPolicyTemplateBySgt> epPolicyTemplates = epPolicyTemplateDao.readBy(templateValueKey);
+        final Entry<Class<? extends Augmentation<AddressEndpointWithLocation>>, Augmentation<AddressEndpointWithLocation>> entry;
+
+        if (epPolicyTemplates.isEmpty()) {
+            entry = null;
+        } else {
+            //TODO: cover case when multiple templates found
+            final Augmentation<AddressEndpointWithLocation> addressEndpointWithLocationAug =
+                    new AddressEndpointWithLocationAugBuilder()
+                            .setSgt(Iterables.getFirst(epPolicyTemplates, null).getSgt())
+                            .build();
+            entry = new AbstractMap.SimpleEntry<>(AddressEndpointWithLocationAug.class, addressEndpointWithLocationAug);
+        }
+
+        return entry;
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<ContainmentEndpointWithLocation>>, Augmentation<ContainmentEndpointWithLocation>> buildContainmentEndpointWithLocationAugmentation(
+            ContainmentEndpoint input) {
+        return null;
+    }
+
+}
index 8cd816c87f50d1cc55b6991f48841060a8583368..5edfd0c772888c31074e1026f6b7b281265d6edc 100644 (file)
@@ -10,18 +10,21 @@ package org.opendaylight.groupbasedpolicy.sxp.mapper.impl;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.api.DomainSpecificRegistry;
+import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EPForwardingTemplateDaoImpl;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EPPolicyTemplateDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EpPolicyTemplateValueKeyFactory;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.MasterDatabaseBindingDaoImpl;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.SimpleCachedDaoEPForwardingTemplateImpl;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.SimpleCachedDaoImpl;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen.EPForwardingTemplateListenerImpl;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen.EPPolicyTemplateListenerImpl;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen.MasterDatabaseBindingListenerImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.EPTemplateUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
@@ -38,17 +41,17 @@ public class SxpMapperProviderImpl implements AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(SxpMapperProviderImpl.class);
 
-    private final DataBroker dataBrokerDependency;
-    private final RpcProviderRegistry rpcRegistryDependency;
     private final MasterDatabaseBindingListenerImpl sxpDatabaseListener;
     private final SxpMapperReactor sxpMapperReactor;
     private final EPTemplateListener epPolicyTemplateListener;
     private final EPTemplateListener epForwardingTemplateListener;
+    private final DomainSpecificRegistry domainSpecificRegistry;
+    private final EndpointAugmentor sxpEndpointAugmentor;
 
-    public SxpMapperProviderImpl(final DataBroker dataBroker, final RpcProviderRegistry rpcRegistryDependency) {
+    public SxpMapperProviderImpl(final DataBroker dataBroker, final RpcProviderRegistry rpcRegistryDependency,
+            final DomainSpecificRegistry domainSpecificRegistry) {
         LOG.info("starting SxmMapper ..");
-        this.dataBrokerDependency = dataBroker;
-        this.rpcRegistryDependency = rpcRegistryDependency;
+        this.domainSpecificRegistry = domainSpecificRegistry;
 
         final BaseEndpointService endpointService = rpcRegistryDependency.getRpcService(BaseEndpointService.class);
         sxpMapperReactor = new SxpMapperReactorImpl(endpointService, dataBroker);
@@ -58,7 +61,9 @@ public class SxpMapperProviderImpl implements AutoCloseable {
                 new SimpleCachedDaoEPForwardingTemplateImpl();
         final SimpleCachedDao<IpPrefix, MasterDatabaseBinding> masterDBBindingCachedDao = new SimpleCachedDaoImpl<>();
 
-        final DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateDao = new EPPolicyTemplateDaoImpl(dataBroker, epPolicyTemplateCachedDao);
+        final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory = new EpPolicyTemplateValueKeyFactory(
+                EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering());
+        final EPPolicyTemplateDaoImpl epPolicyTemplateDao = new EPPolicyTemplateDaoImpl(dataBroker, epPolicyTemplateCachedDao, epPolicyTemplateKeyFactory);
         final EPForwardingTemplateDaoImpl epForwardingTemplateDao = new EPForwardingTemplateDaoImpl(dataBroker,
                 epForwardingTemplateCachedDao);
         final  MasterDatabaseBindingDaoImpl masterDBBindingDao = new MasterDatabaseBindingDaoImpl(dataBroker, masterDBBindingCachedDao);
@@ -69,6 +74,8 @@ public class SxpMapperProviderImpl implements AutoCloseable {
                 masterDBBindingDao, epForwardingTemplateDao);
         epForwardingTemplateListener = new EPForwardingTemplateListenerImpl(dataBroker, sxpMapperReactor, epForwardingTemplateCachedDao,
                 masterDBBindingDao, epPolicyTemplateDao);
+        sxpEndpointAugmentor = new SxpEndpointAugmentorImpl(epPolicyTemplateDao, epPolicyTemplateKeyFactory);
+        domainSpecificRegistry.getEndpointAugmentorRegistry().register(sxpEndpointAugmentor);
         LOG.info("started SxmMapper");
     }
 
@@ -78,5 +85,6 @@ public class SxpMapperProviderImpl implements AutoCloseable {
         sxpDatabaseListener.close();
         epPolicyTemplateListener.close();
         epForwardingTemplateListener.close();
+        domainSpecificRegistry.getEndpointAugmentorRegistry().unregister(sxpEndpointAugmentor);
     }
 }
index 5723fae84ff91eee4214bb3c34d0c3e5298ae4a8..0fc67a517cbeefdf95c3c8b2fba01e6ce58d82f1 100644 (file)
@@ -8,8 +8,14 @@
 
 package org.opendaylight.groupbasedpolicy.sxp.mapper.impl;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Collections;
-
 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;
@@ -41,14 +47,6 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-import com.google.common.util.concurrent.ListenableFuture;
-
 /**
  * Purpose: exclusively processes sxp master database changes and EGP templates changes
  */
@@ -78,18 +76,17 @@ public class SxpMapperReactorImpl implements SxpMapperReactor {
             .setNetworkDomainType(epForwardingTemplate.getNetworkContainment().getNetworkDomainType())
             .setNetworkDomainId(epForwardingTemplate.getNetworkContainment().getNetworkDomainId())
             .build())
-            .build();
-        final RegisterEndpointInput epInput = new RegisterEndpointInputBuilder()
-                .setAddressEndpointReg(Collections.singletonList(new AddressEndpointRegBuilder()
-                        .setAddressType(IpPrefixType.class)
-                        .setAddress(address.getValue())
-                        .setContextType(L3Context.class)
-                        .setContextId(epForwardingTemplate.getL3Context())
-                        .setNetworkContainment(networkContainment)
-                        .setCondition(epPolicyTemplate.getConditions())
-                        .setTenant(epPolicyTemplate.getTenant())
-                        .setEndpointGroup(epPolicyTemplate.getEndpointGroups())
-                        .build()))
+                    .build();
+        final RegisterEndpointInput epInput = new RegisterEndpointInputBuilder().setAddressEndpointReg(
+                Collections.singletonList(new AddressEndpointRegBuilder().setAddressType(IpPrefixType.class)
+                    .setAddress(address.getValue())
+                    .setContextType(L3Context.class)
+                    .setContextId(epForwardingTemplate.getL3Context())
+                    .setNetworkContainment(networkContainment)
+                    .setCondition(epPolicyTemplate.getConditions())
+                    .setTenant(epPolicyTemplate.getTenant())
+                    .setEndpointGroup(epPolicyTemplate.getEndpointGroups())
+                    .build()))
                 .build();
                 epForwardingTemplate.getL3Context();
 
index 5e20b7e4ef94ea68706510f02c381b445c4c1d26..dbbc3cceac2d5b95b54f93811f66f4d3e0ee30f4 100644 (file)
@@ -9,9 +9,13 @@ package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collection;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -20,6 +24,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
@@ -30,17 +35,21 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 /**
  * Purpose: general dao for EndPoint templates
  */
-public class EPPolicyTemplateDaoImpl implements DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> {
+public class EPPolicyTemplateDaoImpl implements DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt>,
+        ReadableByKey<EpPolicyTemplateValueKey, EndpointPolicyTemplateBySgt> {
 
     private static final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> READ_FUTURE_ABSENT = Futures.immediateFuture(Optional.absent());
 
     private final DataBroker dataBroker;
     private final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao;
+    private final EpPolicyTemplateValueKeyFactory keyFactory;
 
     public EPPolicyTemplateDaoImpl(final DataBroker dataBroker,
-                                   final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao) {
+                                   final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao,
+                                   final EpPolicyTemplateValueKeyFactory keyFactory) {
         this.dataBroker = dataBroker;
         this.cachedDao = cachedDao;
+        this.keyFactory = keyFactory;
     }
 
     @Override
@@ -62,7 +71,7 @@ public class EPPolicyTemplateDaoImpl implements DSAsyncDao<Sgt, EndpointPolicyTe
                 @Override
                 public Optional<EndpointPolicyTemplateBySgt> apply(@Nullable final Optional<EndpointPolicyTemplateBySgt> input) {
                     if (input.isPresent()) {
-                        cachedDao.update(key, input.get());
+                        cachedDao.update(key, keyFactory.sortValueKeyLists(input.get()));
                     }
                     return input;
                 }
@@ -79,4 +88,18 @@ public class EPPolicyTemplateDaoImpl implements DSAsyncDao<Sgt, EndpointPolicyTe
         return cachedDao.find(key);
     }
 
+    @Override
+    public Collection<EndpointPolicyTemplateBySgt> readBy(@Nonnull final EpPolicyTemplateValueKey specialKey) {
+        final Predicate<EpPolicyTemplateValueKey> templateValuePredicate = Predicates.equalTo(specialKey);
+        final Collection<EndpointPolicyTemplateBySgt> foundTemplates = new ArrayList<>();
+
+        for (EndpointPolicyTemplateBySgt epPolicyTemplate : cachedDao.values()) {
+            final EpPolicyTemplateValueKey templateValueKey = keyFactory.createKeyWithDefaultOrdering(epPolicyTemplate);
+            if (templateValuePredicate.apply(templateValueKey)) {
+                foundTemplates.add(epPolicyTemplate);
+            }
+        }
+
+        return foundTemplates;
+    }
 }
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache;
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
 
 import java.util.List;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
@@ -18,19 +18,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 /**
  * Purpose: composite key holcer for {@link EndpointPolicyTemplateBySgt}
  */
-public class EpPolicyTemplateCacheKey {
+public class EpPolicyTemplateValueKey {
 
     private final TenantId tenantId;
     private final List<EndpointGroupId> epgId;
     private final List<ConditionName> conditionName;
 
-    public EpPolicyTemplateCacheKey(final TenantId tenantId, final List<EndpointGroupId> epgId, final List<ConditionName> conditionName) {
+    public EpPolicyTemplateValueKey(final TenantId tenantId, final List<EndpointGroupId> epgId, final List<ConditionName> conditionName) {
         this.tenantId = tenantId;
         this.epgId = epgId;
         this.conditionName = conditionName;
     }
 
-    public EpPolicyTemplateCacheKey(AddressEndpointWithLocation endpoint) {
+    public EpPolicyTemplateValueKey(AddressEndpointWithLocation endpoint) {
         this(endpoint.getTenant(), endpoint.getEndpointGroup(), endpoint.getCondition());
     }
 
@@ -51,7 +51,7 @@ public class EpPolicyTemplateCacheKey {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
 
-        final EpPolicyTemplateCacheKey that = (EpPolicyTemplateCacheKey) o;
+        final EpPolicyTemplateValueKey that = (EpPolicyTemplateValueKey) o;
 
         if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false;
         if (epgId != null ? !epgId.equals(that.epgId) : that.epgId != null) return false;
@@ -6,38 +6,52 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache;
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
 
 import com.google.common.collect.Ordering;
 import java.util.Collections;
+import java.util.List;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
 
 /**
  * Purpose: create cache keys with ordered lists inside
  */
-public class EpPolicyTemplateCacheKeyFactory {
+public class EpPolicyTemplateValueKeyFactory {
     private final Ordering<EndpointGroupId> epgIdOrdering;
     private final Ordering<ConditionName> conditionOrdering;
 
-    public EpPolicyTemplateCacheKeyFactory(final Ordering<EndpointGroupId> epgIdOrdering,
+    public EpPolicyTemplateValueKeyFactory(final Ordering<EndpointGroupId> epgIdOrdering,
                                            final Ordering<ConditionName> conditionOrdering) {
         this.epgIdOrdering = epgIdOrdering;
         this.conditionOrdering = conditionOrdering;
     }
 
-    public EpPolicyTemplateCacheKey createKey(final EndpointPolicyTemplateBySgt newSource) {
-        Collections.sort(newSource.getEndpointGroups(), epgIdOrdering);
-        Collections.sort(newSource.getConditions(), conditionOrdering);
+    public EndpointPolicyTemplateBySgt sortValueKeyLists(final EndpointPolicyTemplateBySgt template) {
+        if (template.getEndpointGroups() != null) {
+            Collections.sort(template.getEndpointGroups(), epgIdOrdering);
+        }
+        if (template.getConditions() != null) {
+            Collections.sort(template.getConditions(), conditionOrdering);
+        }
+        return template;
+    }
 
-        return new EpPolicyTemplateCacheKey(
+    public EpPolicyTemplateValueKey createKeyWithDefaultOrdering(final EndpointPolicyTemplateBySgt newSource) {
+        return new EpPolicyTemplateValueKey(
                 newSource.getTenant(), newSource.getEndpointGroups(), newSource.getConditions());
     }
 
-    public EpPolicyTemplateCacheKey createKey(final EpPolicyTemplateCacheKey existingKey) {
+    public EpPolicyTemplateValueKey sortValueKeyLists(final EpPolicyTemplateValueKey existingKey) {
         Collections.sort(existingKey.getEpgId(), epgIdOrdering);
         Collections.sort(existingKey.getConditionName(), conditionOrdering);
         return existingKey;
     }
+
+    public EpPolicyTemplateValueKey createKey(final TenantId tenant, final List<EndpointGroupId> endpointGroup,
+                                              final List<ConditionName> condition) {
+        return sortValueKeyLists(new EpPolicyTemplateValueKey(tenant, endpointGroup, condition));
+    }
 }
index 22fcf2df3cfa038501ccfea99299903367797923..e45c71a6a14a54e92983ece462616ec07d6c36f9 100644 (file)
@@ -15,6 +15,7 @@ import com.google.common.util.concurrent.ListenableFuture;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -23,13 +24,16 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.MasterDatabaseBindingListener;
-import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableAsyncByKey;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.MasterDatabaseFields;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpDatabasesFields;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -40,7 +44,7 @@ import org.slf4j.LoggerFactory;
  * Purpose: general dao for EndPoint templates
  */
 public class MasterDatabaseBindingDaoImpl implements DSAsyncDao<IpPrefix, MasterDatabaseBinding>,
-        ReadableByKey<Sgt, MasterDatabaseBinding> {
+        ReadableAsyncByKey<Sgt, MasterDatabaseBinding> {
 
     private static final Logger LOG = LoggerFactory.getLogger(MasterDatabaseBindingDaoImpl.class);
     private static final ListenableFuture<Optional<MasterDatabaseBinding>> READ_FUTURE_ABSENT = Futures.immediateFuture(Optional.absent());
@@ -90,22 +94,29 @@ public class MasterDatabaseBindingDaoImpl implements DSAsyncDao<IpPrefix, Master
                     cachedDao.invalidateCache();
 
                     for (Node node : input.get().getNode()) {
-                        final SxpNodeIdentity sxpNodeIdentity = node.getAugmentation(SxpNodeIdentity.class);
-                        if (sxpNodeIdentity != null) {
-                            final List<MasterDatabaseBinding> masterDBBindings = sxpNodeIdentity.getMasterDatabase().getMasterDatabaseBinding();
-                            if (masterDBBindings != null) {
-                                for (MasterDatabaseBinding masterDBItem : masterDBBindings) {
-                                    // update all
-                                    final MasterDatabaseBinding previousValue = cachedDao.update(
-                                            masterDBItem.getIpPrefix(), masterDBItem);
-                                    if (previousValue != null) {
-                                        LOG.warn("updated key already obtained: [node:{}, sgt:{}]",
-                                                node.getNodeId().getValue(),
-                                                masterDBItem.getSecurityGroupTag());
+                        java.util.Optional.ofNullable(node.getAugmentation(SxpNodeIdentity.class))
+                                .map(SxpNodeIdentity::getSxpDomains)
+                                .map(SxpDomains::getSxpDomain)
+                                .ifPresent((sxpDomain) -> {
+                                    final List<MasterDatabaseBinding> masterDBBindings = sxpDomain.stream()
+                                            .map(SxpDatabasesFields::getMasterDatabase)
+                                            .filter(masterDb -> masterDb != null)
+                                            .map(MasterDatabaseFields::getMasterDatabaseBinding)
+                                            .filter(binding -> binding != null)
+                                            .flatMap(Collection::stream)
+                                            .collect(Collectors.toList());
+
+                                    for (MasterDatabaseBinding masterDBItem : masterDBBindings) {
+                                        // update all
+                                        final MasterDatabaseBinding
+                                                previousValue =
+                                                cachedDao.update(masterDBItem.getIpPrefix(), masterDBItem);
+                                        if (previousValue != null) {
+                                            LOG.warn("updated key already obtained: [node:{}, sgt:{}]",
+                                                    node.getNodeId().getValue(), masterDBItem.getSecurityGroupTag());
+                                        }
                                     }
-                                }
-                            }
-                        }
+                                });
                     }
                 } else {
                     LOG.warn("failed to update cache of SxpMasterDB - no data");
index 62df7ed3458f2a058ada0f055ffc7770c050b958..3f9b3918f6dd9e7d768ca0b04d46fe3c85bd51c8 100644 (file)
@@ -25,7 +25,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
-import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableAsyncByKey;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.EPTemplateUtil;
@@ -58,13 +58,13 @@ public class EPPolicyTemplateListenerImpl implements EPTemplateListener<Endpoint
     private final InstanceIdentifier<EndpointPolicyTemplateBySgt> templatePath;
     private final SxpMapperReactor sxpMapperReactor;
     private final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> templateCachedDao;
-    private final ReadableByKey<Sgt, MasterDatabaseBinding> masterDBBindingDao;
+    private final ReadableAsyncByKey<Sgt, MasterDatabaseBinding> masterDBBindingDao;
     private final DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao;
 
     public EPPolicyTemplateListenerImpl(final DataBroker dataBroker,
                                         final SxpMapperReactor sxpMapperReactor,
                                         final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> templateCachedDao,
-                                        final ReadableByKey<Sgt, MasterDatabaseBinding> masterDBBindingDao,
+                                        final ReadableAsyncByKey<Sgt, MasterDatabaseBinding> masterDBBindingDao,
                                         final DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao) {
         this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor);
         this.templateCachedDao = Preconditions.checkNotNull(templateCachedDao);
index 76d726c0eeab6d7674ea66cc385890370a0511a3..6df2c7a028437696648d24b86c40889dc1d72f66 100644 (file)
@@ -33,6 +33,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -76,6 +78,8 @@ public class MasterDatabaseBindingListenerImpl implements MasterDatabaseBindingL
         sxpDbPath = MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH
                 .child(Node.class)
                 .augmentation(SxpNodeIdentity.class)
+                .child(SxpDomains.class)
+                .child(SxpDomain.class)
                 .child(MasterDatabase.class)
                 .child(MasterDatabaseBinding.class);
 
index 65d665f1cd6ee41e26d6e7fb7a39eabc763baad3..c7b165dae632845a10d83508ec2430568d38788a 100644 (file)
@@ -8,7 +8,9 @@
 package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util;
 
 import com.google.common.base.Function;
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Optional;
+import com.google.common.collect.Ordering;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.ArrayList;
@@ -19,6 +21,8 @@ import org.apache.commons.lang3.tuple.MutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.commons.net.util.SubnetUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
 
@@ -28,6 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 public final class EPTemplateUtil {
 
     public static final String FULL_IPV4_MASK_SUFFIX = "/32";
+    private static final Comparable EMPTY_COMPARABLE = "";
 
     private EPTemplateUtil() {
         throw new IllegalAccessError("constructing util class");
@@ -101,6 +106,32 @@ public final class EPTemplateUtil {
         });
     }
 
+    public static Ordering<EndpointGroupId> createEndpointGroupIdOrdering() {
+        return Ordering.natural().onResultOf(new Function<EndpointGroupId, Comparable>() {
+            @Nullable
+            @Override
+            public Comparable apply(@Nullable final EndpointGroupId input) {
+                if (input == null) {
+                    return EMPTY_COMPARABLE;
+                }
+                return MoreObjects.firstNonNull(input.getValue(), EMPTY_COMPARABLE);
+            }
+        });
+    }
+
+    public static Ordering<ConditionName> createConditionNameOrdering() {
+        return Ordering.natural().onResultOf(new Function<ConditionName, Comparable>() {
+            @Nullable
+            @Override
+            public Comparable apply(@Nullable final ConditionName input) {
+                if (input == null) {
+                    return EMPTY_COMPARABLE;
+                }
+                return MoreObjects.firstNonNull(input.getValue(), EMPTY_COMPARABLE);
+            }
+        });
+    }
+
     public static class OptionalMutablePair<L, R> extends MutablePair<Optional<L>, Optional<R>> {
         public OptionalMutablePair() {
             super(Optional.absent(), Optional.absent());
index 2d84ac8443e8c4bf5c28e1a1d4df8daec47e99b1..8373d9fdb79a2dfebf92fd6ada46ed8c20d28021 100644 (file)
@@ -13,6 +13,7 @@ module sxp-mapper-cfg {
 
     import config { prefix config; revision-date 2013-04-05; }
     import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+    import groupbasedpolicy-cfg {prefix gbpcfg; revision-date 2015-11-06; }
 
     description
         "This module contains the base YANG definitions for
@@ -54,6 +55,15 @@ module sxp-mapper-cfg {
                     }
                 }
             }
+            //Domain specific registry
+            container domain-specific-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity gbpcfg:domain-specific-registry;
+                    }
+                }
+            }
         }
     }
 }
index 9252cae337e902177df8f9fedd5996261dae7c95..c9578e45cf5dfa413085f819ef9189096f18c9aa 100644 (file)
@@ -15,6 +15,9 @@ module sxp-mapper-model {
     import gbp-common { prefix gbp-common; revision-date 2014-04-21; }
     import ietf-inet-types { prefix inet; revision-date 2010-09-24; }
     import forwarding { prefix forwarding; revision-date 2016-04-27; }
+    import base-endpoint { prefix base-edpoint; revision-date 2016-04-27; }
+    import yang-ext { prefix ext; revision-date 2013-07-09; }
+    import renderer { prefix renderer; revision-date 2015-11-03; }
 
     description
         "This module contains the YANG definitions for
@@ -77,4 +80,17 @@ module sxp-mapper-model {
             }
         }
     }
+
+    grouping sxp-sgt {
+        description "SGT leaf dedicated for endpoint-rpc, endpoint container and renderer configuration
+            (attach by augmentation)";
+        leaf sgt {
+            type sxp-database:sgt;
+        }
+    }
+
+    augment "renderer:renderers/renderer:renderer/renderer:renderer-policy/renderer:configuration/renderer:endpoints/renderer:address-endpoint-with-location" {
+        ext:augment-identifier "address-endpoint-with-location-aug";
+        uses sxp-sgt;
+    }
 }
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpEndpointAugmentorImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpEndpointAugmentorImplTest.java
new file mode 100644 (file)
index 0000000..9e5b33d
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * 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.sxp.mapper.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EpPolicyTemplateValueKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EpPolicyTemplateValueKeyFactory;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.EPTemplateUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+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.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Test for {@link SxpEndpointAugmentorImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SxpEndpointAugmentorImplTest {
+
+    @Mock
+    private ReadableByKey<EpPolicyTemplateValueKey, EndpointPolicyTemplateBySgt> epPolicyDao;
+    @Spy
+    private EpPolicyTemplateValueKeyFactory keyFactory = new EpPolicyTemplateValueKeyFactory(
+            EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering());
+    @Captor
+    private ArgumentCaptor<EpPolicyTemplateValueKey> keyCapt;
+
+    private SxpEndpointAugmentorImpl augmetor;
+
+    @Before
+    public void setUp() throws Exception {
+        augmetor = new SxpEndpointAugmentorImpl(epPolicyDao, keyFactory);
+    }
+
+    @Test
+    public void testBuildAddressEndpointWithLocationAugmentation() throws Exception {
+        final TenantId tenantId = new TenantId("tn1");
+        final AddressEndpoint endpoint = new AddressEndpointBuilder()
+                .setTenant(tenantId)
+                .setCondition(buildConditions(new String[]{"cn2", "cn1"}))
+                .setEndpointGroup(buildEndpointGroupIds(new String[]{"epg2", "epg1"}))
+                .build();
+
+        Mockito.doCallRealMethod().when(keyFactory).sortValueKeyLists(Matchers.<EndpointPolicyTemplateBySgt>any());
+        final List<ConditionName> conditions = buildConditions(new String[]{"cn1", "cn2"});
+        final List<EndpointGroupId> endpointGroupIds = buildEndpointGroupIds(new String[]{"epg1", "epg2"});
+        final EndpointPolicyTemplateBySgt epPolicyTemplate = new EndpointPolicyTemplateBySgtBuilder()
+                .setTenant(tenantId)
+                .setEndpointGroups(endpointGroupIds)
+                .setConditions(conditions)
+                .setSgt(new Sgt(42))
+                .build();
+
+        Mockito.when(epPolicyDao.readBy(keyCapt.capture())).thenReturn(Collections.singletonList(epPolicyTemplate));
+
+        final Map.Entry<Class<? extends Augmentation<AddressEndpointWithLocation>>, Augmentation<AddressEndpointWithLocation>>
+                augmentationEntry = augmetor.buildAddressEndpointWithLocationAugmentation(endpoint);
+
+        Assert.assertEquals(AddressEndpointWithLocationAug.class, augmentationEntry.getKey());
+        Assert.assertTrue(DataObject.class.isAssignableFrom(augmentationEntry.getValue().getClass()));
+        Assert.assertEquals(AddressEndpointWithLocationAug.class, ((DataObject) augmentationEntry.getValue()).getImplementedInterface());
+        Assert.assertEquals(42, ((AddressEndpointWithLocationAug) augmentationEntry.getValue()).getSgt().getValue().intValue());
+
+        final EpPolicyTemplateValueKey keyValue = keyCapt.getValue();
+        Assert.assertEquals(tenantId, keyValue.getTenantId());
+        Assert.assertEquals(endpointGroupIds, keyValue.getEpgId());
+        Assert.assertEquals(conditions, keyValue.getConditionName());
+    }
+
+    private static List<EndpointGroupId> buildEndpointGroupIds(final String[] names) {
+        final List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
+        for (String epgId : names) {
+            endpointGroupIds.add(new EndpointGroupId(epgId));
+        }
+        return endpointGroupIds;
+    }
+
+    private static List<ConditionName> buildConditions(final String[] names) {
+        final List<ConditionName> conditions = new ArrayList<>();
+        for (String condition : names) {
+            conditions.add(new ConditionName(condition));
+        }
+        return conditions;
+    }
+
+    @Test
+    public void testBuildAddressEndpointAugmentation() throws Exception {
+        final AddressEndpointReg endpoint = new AddressEndpointRegBuilder().build();
+        Assert.assertNull(augmetor.buildAddressEndpointAugmentation(endpoint));
+    }
+
+    @Test
+    public void testBuildContainmentEndpointAugmentation() throws Exception {
+        final ContainmentEndpointReg endpoint = new ContainmentEndpointRegBuilder().build();
+        Assert.assertNull(augmetor.buildContainmentEndpointAugmentation(endpoint));
+    }
+
+    @Test
+    public void testBuildContainmentEndpointWithLocationAugmentation() throws Exception {
+        final ContainmentEndpoint endpoint = new ContainmentEndpointBuilder().build();
+        Assert.assertNull(augmetor.buildContainmentEndpointWithLocationAugmentation(endpoint));
+    }
+}
\ No newline at end of file
index 6dc1bb3449ce7ff7a2e8b903bacbde2405318a73..42a3a6c1a965250ea8d00b69dfda8360f0b7a259 100644 (file)
@@ -8,22 +8,34 @@
 package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.InOrder;
 import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.Spy;
 import org.mockito.runners.MockitoJUnitRunner;
 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.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.EPTemplateUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.SxpMapper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
@@ -46,6 +58,13 @@ public class EPPolicyTemplateDaoImplTest {
     private SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao;
     @Mock
     private ReadOnlyTransaction rTx;
+    @Spy
+    private EpPolicyTemplateValueKeyFactory keyFactory = new EpPolicyTemplateValueKeyFactory(
+            EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering());
+    @Captor
+    ArgumentCaptor<Sgt> sgtCapt;
+    @Captor
+    ArgumentCaptor<EndpointPolicyTemplateBySgt> epPolicyTemplateCapt;
 
     private EPPolicyTemplateDaoImpl dao;
 
@@ -57,7 +76,7 @@ public class EPPolicyTemplateDaoImplTest {
 
     @Before
     public void setUp() throws Exception {
-        dao = new EPPolicyTemplateDaoImpl(dataBroker, cachedDao);
+        dao = new EPPolicyTemplateDaoImpl(dataBroker, cachedDao, keyFactory);
     }
 
     @Test
@@ -95,6 +114,7 @@ public class EPPolicyTemplateDaoImplTest {
                 Matchers.<InstanceIdentifier<EndpointPolicyTemplateBySgt>>any())).thenReturn(
                 Futures.<Optional<EndpointPolicyTemplateBySgt>, ReadFailedException>immediateCheckedFuture(
                         Optional.of(EP_POLICY_TEMPLATE_VALUE)));
+        Mockito.doCallRealMethod().when(keyFactory).sortValueKeyLists(Matchers.<EndpointPolicyTemplateBySgt>any());
 
         final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> read = dao.read(KEY_1);
         Assert.assertTrue(read.isDone());
@@ -115,4 +135,81 @@ public class EPPolicyTemplateDaoImplTest {
         final InstanceIdentifier<EndpointPolicyTemplateBySgt> readPath = dao.buildReadPath(KEY_1);
         Assert.assertEquals(expectedPath, readPath);
     }
+
+    @Test
+    public void testReadBy_single() throws Exception {
+        final EpPolicyTemplateValueKey key = new EpPolicyTemplateValueKey(new TenantId("tn1"),
+                buildEndpointGroupIds(new String[]{"epg1", "epg2"}),
+                buildConditions(new String[]{"cn1", "cn2"}));
+
+        Mockito.doCallRealMethod().when(keyFactory).createKeyWithDefaultOrdering(Matchers.<EndpointPolicyTemplateBySgt>any());
+
+        Mockito.when(cachedDao.values()).thenReturn(Lists.newArrayList(
+                createEpPolicytemplate(new Sgt(1), new String[]{"cn2", "cn1"}, new String[]{"epg1", "epg2"}, "tn1"),
+                createEpPolicytemplate(new Sgt(2), new String[]{"cn1", "cn2"}, new String[]{"epg2", "epg1"}, "tn1"),
+                createEpPolicytemplate(new Sgt(3), new String[]{"cn2", "cn1"}, new String[]{"epg2", "epg1"}, "tn1"),
+                createEpPolicytemplate(new Sgt(4), new String[]{"cn1", "cn2"}, new String[]{"epg1", "epg2"}, "tn1")
+        ));
+
+        final Collection<EndpointPolicyTemplateBySgt> policyTemplates = dao.readBy(key);
+        Assert.assertEquals(1, policyTemplates.size());
+        Assert.assertEquals(4, Iterables.getFirst(policyTemplates, null).getSgt().getValue().intValue());
+    }
+
+    @Test
+    public void testRead_unsortedLists() throws Exception {
+        final EndpointPolicyTemplateBySgt epPolicytemplateUnsorted = createEpPolicytemplate(new Sgt(1),
+                new String[]{"cn2", "cn1"}, new String[]{"epg2", "epg1"}, "tn1");
+
+        Mockito.doCallRealMethod().when(keyFactory).createKeyWithDefaultOrdering(Matchers.<EndpointPolicyTemplateBySgt>any());
+
+        Mockito.when(cachedDao.find(Matchers.<Sgt>any())).thenReturn(
+                Optional.<EndpointPolicyTemplateBySgt>absent());
+        Mockito.when(cachedDao.isEmpty()).thenReturn(true);
+        Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
+
+        Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
+                Matchers.<InstanceIdentifier<EndpointPolicyTemplateBySgt>>any())).thenReturn(
+                Futures.<Optional<EndpointPolicyTemplateBySgt>, ReadFailedException>immediateCheckedFuture(
+                        Optional.of(epPolicytemplateUnsorted)));
+
+        dao.read(new Sgt(1));
+
+        Mockito.verify(cachedDao).update(sgtCapt.capture(), epPolicyTemplateCapt.capture());
+        Mockito.verify(cachedDao).find(sgtCapt.capture());
+
+        Assert.assertEquals(1, sgtCapt.getValue().getValue().intValue());
+        final EndpointPolicyTemplateBySgt template = epPolicyTemplateCapt.getValue();
+        Assert.assertEquals(1, template.getSgt().getValue().intValue());
+        Assert.assertEquals("tn1", template.getTenant().getValue());
+        Assert.assertEquals(buildEndpointGroupIds(new String[]{"epg1", "epg2"}), template.getEndpointGroups());
+        Assert.assertEquals(buildConditions(new String[]{"cn1", "cn2"}), template.getConditions());
+    }
+
+
+    private EndpointPolicyTemplateBySgt createEpPolicytemplate(final Sgt sgt, final String[] conditionNames,
+                                                               final String[] epgIds, final String tenant) {
+        return new EndpointPolicyTemplateBySgtBuilder()
+                .setSgt(sgt)
+                .setEndpointGroups(buildEndpointGroupIds(epgIds))
+                .setConditions(buildConditions(conditionNames))
+                .setTenant(new TenantId(tenant))
+                .build();
+    }
+
+    private static List<EndpointGroupId> buildEndpointGroupIds(final String[] names) {
+        final List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
+        for (String epgId : names) {
+            endpointGroupIds.add(new EndpointGroupId(epgId));
+        }
+        return endpointGroupIds;
+    }
+
+    private static List<ConditionName> buildConditions(final String[] names) {
+        final List<ConditionName> conditions = new ArrayList<>();
+        for (String condition : names) {
+            conditions.add(new ConditionName(condition));
+        }
+        return conditions;
+    }
 }
\ No newline at end of file
index f0d4c8df68ab57141f886b0a6e26347d8cd3cf96..171709bebf17788a277f9362a58e6ba2fc9eff52 100644 (file)
@@ -35,6 +35,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.mast
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomainsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
@@ -74,8 +76,13 @@ public class MasterDatabaseBindingDaoImplTest {
                 .setNode(Lists.newArrayList(new NodeBuilder()
                         .setNodeId(new NodeId("utNodeId"))
                         .addAugmentation(SxpNodeIdentity.class, new SxpNodeIdentityBuilder()
-                                .setMasterDatabase(new MasterDatabaseBuilder()
-                                        .setMasterDatabaseBinding(Lists.newArrayList(MASTER_DB_BINDING_VALUE))
+                                .setSxpDomains(new SxpDomainsBuilder()
+                                        .setSxpDomain(Collections.singletonList(new SxpDomainBuilder()
+                                                .setDomainName("global")
+                                                .setMasterDatabase(new MasterDatabaseBuilder()
+                                                        .setMasterDatabaseBinding(Lists.newArrayList(MASTER_DB_BINDING_VALUE))
+                                                        .build())
+                                                .build()))
                                         .build())
                                 .build())
                         .build()))
index 36a57a0625e7bbc1f9217874f814c27f04697ecb..f2bcc1bd5cc1caf9e52923e99dcac438dcd5ded1 100644 (file)
@@ -27,7 +27,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
-import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableAsyncByKey;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
@@ -69,7 +69,7 @@ public class EPPolicyTemplateListenerImplTest {
     @Mock
     private DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao;
     @Mock
-    private ReadableByKey<Sgt, MasterDatabaseBinding> masterDBDao;
+    private ReadableAsyncByKey<Sgt, MasterDatabaseBinding> masterDBDao;
     @Mock
     private ListenerRegistration<? extends EPTemplateListener> listenerRegistration;
     @Mock
index 6fe38dbbf9bb2f7352282516692521f1a2ed7830..435cf4d8686f0f187e4ed93800678a4d1e8cbc1a 100644 (file)
@@ -40,6 +40,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.mast
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@@ -59,6 +62,8 @@ public class MasterDatabaseBindingListenerImplTest {
             MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH
                     .child(Node.class, new NodeKey(new NodeId("utNodeId")))
                     .augmentation(SxpNodeIdentity.class)
+                    .child(SxpDomains.class)
+                    .child(SxpDomain.class, new SxpDomainKey("global"))
                     .child(MasterDatabase.class)
                     .child(MasterDatabaseBinding.class, new MasterDatabaseBindingKey(IP_PREFIX));
     private static final DataTreeIdentifier<MasterDatabaseBinding> MASTER_DB_BINDING_TREE_PATH =