Merge "resolved-policy view - initial commit"
authorMartin Sunal <msunal@cisco.com>
Wed, 15 Jun 2016 15:54:31 +0000 (15:54 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 15 Jun 2016 15:54:31 +0000 (15:54 +0000)
177 files changed:
.gitignore
artifacts/pom.xml
domain-extensions/l2-l3/pom.xml [new file with mode: 0644]
domain-extensions/l2-l3/src/main/config/default-config.xml [new file with mode: 0644]
domain-extensions/l2-l3/src/main/java/org/opendaylight/controller/config/yang/config/domain_extension/l2_l3/impl/L2L3DomainExtensionModule.java [new file with mode: 0644]
domain-extensions/l2-l3/src/main/java/org/opendaylight/controller/config/yang/config/domain_extension/l2_l3/impl/L2L3DomainExtensionModuleFactory.java [new file with mode: 0644]
domain-extensions/l2-l3/src/main/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/L2L3NetworkDomainAugmentor.java [new file with mode: 0644]
domain-extensions/l2-l3/src/main/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/util/L2L3IidFactory.java [new file with mode: 0644]
domain-extensions/l2-l3/src/main/yang/l2-l3-domain-extension-cfg.yang [new file with mode: 0644]
domain-extensions/l2-l3/src/main/yang/l2-l3-forwarding.yang [moved from groupbasedpolicy/src/main/yang/model/l2-l3-forwarding.yang with 100% similarity]
domain-extensions/l2-l3/src/test/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/L2L3NetworkDomainAugmentorTest.java [new file with mode: 0644]
domain-extensions/l2-l3/src/test/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/util/L2L3IidFactoryTest.java [new file with mode: 0644]
domain-extensions/pom.xml [new file with mode: 0644]
features/pom.xml
features/src/main/features/features.xml
groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/DomainSpecificRegistryModule.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/api/EndpointAugmentor.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/api/NetworkDomainAugmentor.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/forwarding/NetworkDomainAugmentorRegistryImpl.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/location/resolver/LocationResolver.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/DtoEquivalenceUtils.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointInfo.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointLocationInfo.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererConfigurationBuilder.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererManager.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererUtils.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/resolver/ForwardingResolver.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/NetUtils.java
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointServiceImplTest.java
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/location/resolver/LocationResolverTest.java
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/RendererManagerDataBrokerTest.java
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/RendererManagerTest.java
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/TestDataFactory.java
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/util/IidFactoryTest.java
location-providers/ne-location-provider/pom.xml
location-providers/ne-location-provider/src/main/java/org/opendaylight/groupbasedpolicy/ne/location/provider/NeLocationProvider.java
location-providers/ne-location-provider/src/test/java/org/opendaylight/groupbasedpolicy/ne/location/provider/NeLocationProviderTest.java
neutron-mapper/pom.xml
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/NeutronMapper.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronNetworkAware.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/NeutronRouterAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/NetworkUtils.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/PortUtils.java
neutron-mapper/src/main/yang/neutron-provider-topology.yang [new file with mode: 0644]
neutron-mapper/src/main/yang/odl-external-reference.yang [new file with mode: 0644]
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/infrastructure/NetworkClientTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/infrastructure/NetworkServiceTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java [new file with mode: 0644]
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronRouterAwareDataStoreTest.java [new file with mode: 0644]
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/test/CustomDataBrokerTest.java [moved from neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/GbpDataBrokerTest.java with 60% similarity]
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperAssert.java [new file with mode: 0644]
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperDataBrokerTest.java [new file with mode: 0644]
neutron-vpp-mapper/pom.xml [new file with mode: 0644]
neutron-vpp-mapper/src/main/config/default-config.xml [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/controller/config/yang/config/neutron_vpp_mapper/impl/NeutronVppMapperModule.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/controller/config/yang/config/neutron_vpp_mapper/impl/NeutronVppMapperModuleFactory.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/NeutronVppMapper.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/SocketInfo.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/BaseEndpointByPortListener.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/MappingProvider.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NeutronListener.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java [new file with mode: 0644]
neutron-vpp-mapper/src/main/yang/neutron-vpp-mapper-impl.yang [new file with mode: 0644]
neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NeutronListenerTest.java [new file with mode: 0644]
neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandlerTest.java [new file with mode: 0644]
neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/TestUtils.java [new file with mode: 0644]
pom.xml
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasContractManagerListener.java
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointManagerListener.java
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasPolicyManager.java
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasSubnetManagerListener.java
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasTenantManagerListener.java
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasContractManagerListenerCovrgTest.java [new file with mode: 0644]
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointAugCovrgTest.java [new file with mode: 0644]
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointManagerListenerCovrgTest.java [new file with mode: 0644]
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasIidFactoryTest.java [new file with mode: 0644]
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasPolicyManagerCovrgTest.java [new file with mode: 0644]
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasPolicyManagerTest.java
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasRendererCovrgTest.java [new file with mode: 0644]
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasSubnetManagerListenerCovrgTest.java [new file with mode: 0644]
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasTenantManagerListenerCovrgTest.java [new file with mode: 0644]
renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/test/DataChangeListenerTester.java [new file with mode: 0644]
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/listener/IosXeCapableNodeListenerImpl.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/util/NodeWriter.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/Action.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/ChainAction.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/Classifier.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/EtherTypeClassifier.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/IpProtoClassifier.java [new file with mode: 0644]
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/IosXeCapableNodeListenerImplTest.java
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/NodeWriterTest.java
renderers/ofoverlay/pom.xml
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/OFStatisticsManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ReadGbpFlowCacheTask.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ResolvedPolicyClassifierListener.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SFlowRTConnection.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/SFlowQueryParams.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/arp/ArpTaskerTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/arp/ArpUtilsTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/EndpointManagerListenerTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/EndpointManagerTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayAugTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayContextListenerTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayL3ContextListenerTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayL3NatAugTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/equivalence/BucketsEquivalenceTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/equivalence/GroupEquivalenceTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientResponseTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/OFStatisticsManagerTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ProcessDataTaskTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ReadGbpFlowCacheTaskTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ResolvedPolicyClassifierListenerTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SFlowRTConnectionTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SflowClientSettingsListenerTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/test/TransactionMockUtils.java [new file with mode: 0644]
renderers/vpp/pom.xml
renderers/vpp/src/main/config/default-config.xml
renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/GbpVppProviderModule.java [moved from renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppProviderModule.java with 58% similarity]
renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/GbpVppProviderModuleFactory.java [moved from renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppProviderModuleFactory.java with 77% similarity]
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 [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/AbstractInterfaceCommand.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ConfigCommand.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/DtoChangeEvent.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/NodeOperEvent.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/RendererPolicyConfEvent.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/VppEndpointConfEvent.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppEndpointLocationProvider.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapper.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/RendererPolicyListener.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppEndpointListener.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppNodeListener.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/BridgeDomainManagerImpl.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/VppNodeManager.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/PolicyContext.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/RendererResolvedPolicy.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ResolvedRuleGroup.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/Action.java [new file with mode: 0755]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/AllowAction.java [new file with mode: 0755]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/Classifier.java [new file with mode: 0755]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/EtherTypeClassifier.java [new file with mode: 0755]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/IpProtoClassifier.java [new file with mode: 0755]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/General.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/KeyFactory.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/MountedDataBrokerProvider.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppNodeWriter.java [new file with mode: 0644]
renderers/vpp/src/main/yang/vpp-provider-impl.yang
renderers/vpp/src/main/yang/vpp-renderer.yang [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/CustomDataBrokerTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/VppRendererDataBrokerTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommandTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/DtoChangeEventTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/NodeOperEventTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/VppEndpointConfEventTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManagerTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapperTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppEndpointListenerTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/BridgeDomainManagerImplTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/VppManagerDataStoreTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppNodeWriterTest.java [new file with mode: 0644]
renderers/vpp/src/test/resources/log4j.xml [new file with mode: 0644]
sxp-mapper/pom.xml

index 83e2e32876bf1e33ac94223a952a6ac138d7238f..c48935d447beb761c34ecf6c100be0e6d4bfc60f 100644 (file)
@@ -25,3 +25,4 @@ maven-metadata-local.xml
 .DS_Store
 *.ipr
 *.iws
+*.log
\ No newline at end of file
index 93101c44ab947e5ec7cc320946cdc5611e4539d8..e6d732605682328b74caf012dd78a94f58a3e422 100755 (executable)
         <artifactId>groupbasedpolicy</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>l2-l3-domain-extension</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <dependency>
         <groupId>${project.groupId}</groupId>
         <artifactId>ofoverlay-renderer</artifactId>
         <artifactId>neutron-mapper</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>neutron-vpp-mapper</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <dependency>
         <groupId>${project.groupId}</groupId>
         <artifactId>neutron-ovsdb</artifactId>
         <type>xml</type>
         <classifier>config</classifier>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.groupbasedpolicy</groupId>
+        <artifactId>l2-l3-domain-extension</artifactId>
+        <version>${project.version}</version>
+        <type>xml</type>
+        <classifier>config</classifier>
+      </dependency>
       <dependency>
         <groupId>${project.groupId}</groupId>
         <artifactId>ofoverlay-renderer</artifactId>
         <type>xml</type>
         <classifier>config</classifier>
       </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>neutron-vpp-mapper</artifactId>
+        <version>${project.version}</version>
+        <type>xml</type>
+        <classifier>config</classifier>
+      </dependency>
       <dependency>
         <groupId>${project.groupId}</groupId>
         <artifactId>neutron-ovsdb</artifactId>
diff --git a/domain-extensions/l2-l3/pom.xml b/domain-extensions/l2-l3/pom.xml
new file mode 100644 (file)
index 0000000..61da72d
--- /dev/null
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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 -->
+<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.groupbasedpolicy</groupId>
+    <artifactId>groupbasedpolicy-domain-extensions</artifactId>
+    <version>0.4.0-SNAPSHOT</version>
+    <relativePath>../</relativePath>
+  </parent>
+
+  <artifactId>l2-l3-domain-extension</artifactId>
+  <packaging>bundle</packaging>
+
+  <dependencies>
+    <!-- testing dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>groupbasedpolicy</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <!-- project build -->
+  <build>
+    <!-- We use the maven-resources-plugin to copy a class from the groupbasepolicy
+      bundle that we need in order to run some unit tests in the renderer (classes
+      in the test directory aren't packaged in bundles, and instead of keeping
+      separate copies, we just copy the file(s) needed in order to run the test). -->
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package>
+              org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.*,
+              org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util
+            </Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/domain-extensions/l2-l3/src/main/config/default-config.xml b/domain-extensions/l2-l3/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..ffeaa62
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<snapshot>
+    <configuration>
+        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:l2l3="urn:opendaylight:params:xml:ns:yang:controller:config:domain_extension:l2_l3:impl">
+                        l2l3:l2-l3-domain-extension-impl
+                    </type>
+                    <name>l2-l3-domain-extension-impl</name>
+
+                    <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>
+
+    </configuration>
+
+    <required-capabilities>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:domain_extension:l2_l3:impl?module=l2-l3-domain-extension-cfg&amp;revision=2016-05-25</capability>
+    </required-capabilities>
+
+</snapshot>
diff --git a/domain-extensions/l2-l3/src/main/java/org/opendaylight/controller/config/yang/config/domain_extension/l2_l3/impl/L2L3DomainExtensionModule.java b/domain-extensions/l2-l3/src/main/java/org/opendaylight/controller/config/yang/config/domain_extension/l2_l3/impl/L2L3DomainExtensionModule.java
new file mode 100644 (file)
index 0000000..80534ec
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.controller.config.yang.config.domain_extension.l2_l3.impl;
+
+import org.opendaylight.groupbasedpolicy.api.DomainSpecificRegistry;
+import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.L2L3NetworkDomainAugmentor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class L2L3DomainExtensionModule extends org.opendaylight.controller.config.yang.config.domain_extension.l2_l3.impl.AbstractL2L3DomainExtensionModule {
+
+    private static final Logger LOG = LoggerFactory.getLogger(L2L3DomainExtensionModule.class);
+
+    public L2L3DomainExtensionModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public L2L3DomainExtensionModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.domain_extension.l2_l3.impl.L2L3DomainExtensionModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        DomainSpecificRegistry domainSpecificRegistry = getDomainSpecificRegistryDependency();
+        Preconditions.checkNotNull(domainSpecificRegistry);
+        L2L3NetworkDomainAugmentor l2l3NetworkDomainAugmentor =
+                new L2L3NetworkDomainAugmentor(domainSpecificRegistry.getNetworkDomainAugmentorRegistry());
+        LOG.info("{} successfully started.", L2L3DomainExtensionModule.class.getCanonicalName());
+        return l2l3NetworkDomainAugmentor;
+    }
+
+}
diff --git a/domain-extensions/l2-l3/src/main/java/org/opendaylight/controller/config/yang/config/domain_extension/l2_l3/impl/L2L3DomainExtensionModuleFactory.java b/domain-extensions/l2-l3/src/main/java/org/opendaylight/controller/config/yang/config/domain_extension/l2_l3/impl/L2L3DomainExtensionModuleFactory.java
new file mode 100644 (file)
index 0000000..61bfa02
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.controller.config.yang.config.domain_extension.l2_l3.impl;
+public class L2L3DomainExtensionModuleFactory extends org.opendaylight.controller.config.yang.config.domain_extension.l2_l3.impl.AbstractL2L3DomainExtensionModuleFactory {
+
+}
diff --git a/domain-extensions/l2-l3/src/main/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/L2L3NetworkDomainAugmentor.java b/domain-extensions/l2-l3/src/main/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/L2L3NetworkDomainAugmentor.java
new file mode 100644 (file)
index 0000000..9b8fe27
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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.domain_extension.l2_l3;
+
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.Map.Entry;
+
+import org.opendaylight.groupbasedpolicy.api.NetworkDomainAugmentor;
+import org.opendaylight.groupbasedpolicy.api.NetworkDomainAugmentorRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRendererBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+import com.google.common.base.Preconditions;
+
+public class L2L3NetworkDomainAugmentor implements NetworkDomainAugmentor, AutoCloseable {
+
+    private final NetworkDomainAugmentorRegistry networkDomainAugmentorRegistry;
+
+    public L2L3NetworkDomainAugmentor(NetworkDomainAugmentorRegistry networkDomainAugmentorRegistry) {
+        this.networkDomainAugmentorRegistry = Preconditions.checkNotNull(networkDomainAugmentorRegistry);
+        this.networkDomainAugmentorRegistry.register(this);
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<RendererNetworkDomain>>, Augmentation<RendererNetworkDomain>> buildRendererNetworkDomainAugmentation(
+            NetworkDomain input) {
+        SubnetAugmentForwarding subnetForwarding = input.getAugmentation(SubnetAugmentForwarding.class);
+        if (subnetForwarding == null) {
+            return null;
+        }
+        return new SimpleImmutableEntry<>(SubnetAugmentRenderer.class,
+                new SubnetAugmentRendererBuilder(subnetForwarding).build());
+    }
+
+    @Override
+    public void close() throws Exception {
+        networkDomainAugmentorRegistry.unregister(this);
+    }
+
+}
diff --git a/domain-extensions/l2-l3/src/main/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/util/L2L3IidFactory.java b/domain-extensions/l2-l3/src/main/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/util/L2L3IidFactory.java
new file mode 100644 (file)
index 0000000..99f7a59
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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.domain_extension.l2_l3.util;
+
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
+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.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class L2L3IidFactory {
+
+    public static InstanceIdentifier<NetworkDomain> subnetIid(TenantId tenantId, NetworkDomainId id) {
+        NetworkDomainKey domainKey = new NetworkDomainKey(id, Subnet.class);
+        return IidFactory.forwardingByTenantIid(tenantId).child(NetworkDomain.class, domainKey);
+    }
+
+    public static InstanceIdentifier<ForwardingContext> l2FloodDomainIid(TenantId tenantId, ContextId id) {
+        ForwardingContextKey domainKey = new ForwardingContextKey(id, L2FloodDomain.class);
+        return IidFactory.forwardingByTenantIid(tenantId).child(ForwardingContext.class, domainKey);
+    }
+
+    public static InstanceIdentifier<ForwardingContext> l2BridgeDomainIid(TenantId tenantId, ContextId id) {
+        ForwardingContextKey domainKey = new ForwardingContextKey(id, L2BridgeDomain.class);
+        return IidFactory.forwardingByTenantIid(tenantId).child(ForwardingContext.class, domainKey);
+    }
+
+    public static InstanceIdentifier<ForwardingContext> l3ContextIid(TenantId tenantId, ContextId id) {
+        ForwardingContextKey domainKey = new ForwardingContextKey(id, L3Context.class);
+        return IidFactory.forwardingByTenantIid(tenantId).child(ForwardingContext.class, domainKey);
+    }
+
+}
diff --git a/domain-extensions/l2-l3/src/main/yang/l2-l3-domain-extension-cfg.yang b/domain-extensions/l2-l3/src/main/yang/l2-l3-domain-extension-cfg.yang
new file mode 100644 (file)
index 0000000..548197b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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
+ */
+
+module l2-l3-domain-extension-cfg {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:domain_extension:l2_l3:impl";
+    prefix "gbpcfg";
+
+    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
+          l2-l3 domain exstension implementation.";
+
+    revision "2016-05-25" {
+        description
+            "Initial revision.";
+    }
+
+    identity l2-l3-domain-extension-impl {
+        base "config:module-type";
+
+        config:java-name-prefix L2L3DomainExtension;
+    }
+
+    // Augments the 'configuration' choice node under modules/module.
+    augment "/config:modules/config:module/config:configuration" {
+        case l2-l3-domain-extension-impl {
+            when "/config:modules/config:module/config:type = 'l2-l3-domain-extension-impl'";
+
+            // DomainSpecificRegistry service
+            container domain-specific-registry {
+                uses config:service-ref {
+                    refine type {
+                        config:required-identity gbpcfg:domain-specific-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/domain-extensions/l2-l3/src/test/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/L2L3NetworkDomainAugmentorTest.java b/domain-extensions/l2-l3/src/test/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/L2L3NetworkDomainAugmentorTest.java
new file mode 100644 (file)
index 0000000..ba08683
--- /dev/null
@@ -0,0 +1,115 @@
+package org.opendaylight.groupbasedpolicy.domain_extension.l2_l3;
+
+import java.util.Arrays;
+import java.util.Map.Entry;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.groupbasedpolicy.api.NetworkDomainAugmentorRegistry;
+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.IpPrefix;
+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.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwardingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.GatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+@RunWith(MockitoJUnitRunner.class)
+public class L2L3NetworkDomainAugmentorTest {
+
+    private static final IpPrefix IP_PREFIX = new IpPrefix(new Ipv4Prefix("1.1.1.1/24"));
+    private static final IpPrefix IP_PREFIX_2 = new IpPrefix(new Ipv4Prefix("2.2.2.2/24"));
+    private static final IpAddress IP_ADDRESS = new IpAddress(new Ipv4Address("1.1.1.1"));
+    private static final IpAddress IP_ADDRESS_2 = new IpAddress(new Ipv4Address("2.2.2.2"));
+    private static final NetworkDomainId NET_DOMAIN = new NetworkDomainId("netDomain1");
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+    @Mock
+    private NetworkDomainAugmentorRegistry networkDomainAugmentorRegistry;
+
+    private L2L3NetworkDomainAugmentor l2l3Augmentor;
+
+    @Before
+    public void init() {
+        l2l3Augmentor = new L2L3NetworkDomainAugmentor(networkDomainAugmentorRegistry);
+    }
+
+    @Test
+    public void testConstructor() {
+        L2L3NetworkDomainAugmentor l2l3NetworkDomainAugmentor =
+                new L2L3NetworkDomainAugmentor(networkDomainAugmentorRegistry);
+        Mockito.verify(networkDomainAugmentorRegistry).register(Mockito.eq(l2l3NetworkDomainAugmentor));
+    }
+
+    @Test
+    public void testConstructor_npe_exception() {
+        exception.expect(NullPointerException.class);
+        new L2L3NetworkDomainAugmentor(null);
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        l2l3Augmentor.close();
+        Mockito.verify(networkDomainAugmentorRegistry).register(Mockito.eq(l2l3Augmentor));
+    }
+
+    @Test
+    public void testBuildRendererNetworkDomainAugmentation() {
+        Gateways gateways = new GatewaysBuilder().setGateway(IP_ADDRESS)
+            .setPrefixes(Arrays.asList(new PrefixesBuilder().setPrefix(IP_PREFIX_2).build()))
+            .build();
+        SubnetAugmentForwarding subnetAugmentForwarding =
+                new SubnetAugmentForwardingBuilder().setSubnet(new SubnetBuilder().setIpPrefix(IP_PREFIX)
+                    .setGateways(Arrays.asList(gateways))
+                    .setVirtualRouterIp(IP_ADDRESS_2)
+                    .build()).build();
+        NetworkDomain networkDomain = new NetworkDomainBuilder()
+            .setNetworkDomainType(
+                    org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.NetworkDomain.class)
+            .setNetworkDomainId(NET_DOMAIN)
+            .addAugmentation(SubnetAugmentForwarding.class, subnetAugmentForwarding)
+            .build();
+
+        Entry<Class<? extends Augmentation<RendererNetworkDomain>>, Augmentation<RendererNetworkDomain>> rendererNetworkDomainAugmentation =
+                l2l3Augmentor.buildRendererNetworkDomainAugmentation(networkDomain);
+
+        Assert.assertNotNull(rendererNetworkDomainAugmentation);
+        Assert.assertEquals(SubnetAugmentRenderer.class, rendererNetworkDomainAugmentation.getKey());
+        Augmentation<RendererNetworkDomain> rendererNetDomainAug = rendererNetworkDomainAugmentation.getValue();
+        Assert.assertTrue(rendererNetDomainAug instanceof SubnetAugmentRenderer);
+        SubnetAugmentRenderer subnetAugmentRenderer = (SubnetAugmentRenderer) rendererNetDomainAug;
+        Assert.assertEquals(subnetAugmentForwarding.getSubnet(), subnetAugmentRenderer.getSubnet());
+    }
+
+    @Test
+    public void testBuildRendererNetworkDomainAugmentation_nullAugmentation() {
+        NetworkDomain networkDomain = new NetworkDomainBuilder()
+            .setNetworkDomainType(
+                    org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.NetworkDomain.class)
+            .setNetworkDomainId(NET_DOMAIN)
+            .build();
+
+        Entry<Class<? extends Augmentation<RendererNetworkDomain>>, Augmentation<RendererNetworkDomain>> rendererNetworkDomainAugmentation =
+                l2l3Augmentor.buildRendererNetworkDomainAugmentation(networkDomain);
+
+        Assert.assertNull(rendererNetworkDomainAugmentation);
+    }
+
+}
diff --git a/domain-extensions/l2-l3/src/test/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/util/L2L3IidFactoryTest.java b/domain-extensions/l2-l3/src/test/java/org/opendaylight/groupbasedpolicy/domain_extension/l2_l3/util/L2L3IidFactoryTest.java
new file mode 100644 (file)
index 0000000..4edb0f8
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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.domain_extension.l2_l3.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class L2L3IidFactoryTest {
+
+    private static final TenantId TENANT_ID = new TenantId("t1");
+    private static final ContextId CONTEXT_ID = new ContextId("ctx1");
+
+    @Test
+    public void testL2FloodDomainIid() {
+        InstanceIdentifier<ForwardingContext> identifier = L2L3IidFactory.l2FloodDomainIid(TENANT_ID, CONTEXT_ID);
+        Assert.assertEquals(CONTEXT_ID, InstanceIdentifier.keyOf(identifier).getContextId());
+        Assert.assertEquals(TENANT_ID, identifier.firstKeyOf(ForwardingByTenant.class).getTenantId());
+    }
+
+    @Test
+    public void testL2BridgeDomainIid() {
+        InstanceIdentifier<ForwardingContext> identifier = L2L3IidFactory.l2BridgeDomainIid(TENANT_ID, CONTEXT_ID);
+        Assert.assertEquals(CONTEXT_ID, InstanceIdentifier.keyOf(identifier).getContextId());
+        Assert.assertEquals(TENANT_ID, identifier.firstKeyOf(ForwardingByTenant.class).getTenantId());
+    }
+
+    @Test
+    public void testL3ContextIid() {
+        InstanceIdentifier<ForwardingContext> identifier = L2L3IidFactory.l3ContextIid(TENANT_ID, CONTEXT_ID);
+        Assert.assertEquals(CONTEXT_ID, InstanceIdentifier.keyOf(identifier).getContextId());
+        Assert.assertEquals(TENANT_ID, identifier.firstKeyOf(ForwardingByTenant.class).getTenantId());
+    }
+
+    @Test
+    public void testSubnetIid() {
+        InstanceIdentifier<NetworkDomain> identifier = L2L3IidFactory.subnetIid(TENANT_ID, CONTEXT_ID);
+        Assert.assertEquals(TENANT_ID, identifier.firstKeyOf(ForwardingByTenant.class).getTenantId());
+        Assert.assertEquals(CONTEXT_ID, identifier.firstKeyOf(NetworkDomain.class).getNetworkDomainId());
+    }
+}
diff --git a/domain-extensions/pom.xml b/domain-extensions/pom.xml
new file mode 100644 (file)
index 0000000..24650ba
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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 -->
+<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.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <groupId>org.opendaylight.groupbasedpolicy</groupId>
+  <artifactId>groupbasedpolicy-domain-extensions</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>l2-l3</module>
+  </modules>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>groupbasedpolicy</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
index fd26227806d5ed27910986c5e15db3232981aa47..2bb1d8c3d1573b8439648479c72f0ee6eeacb57b 100755 (executable)
@@ -38,6 +38,7 @@
     <config.configfile.directory>etc/opendaylight/karaf</config.configfile.directory>
     <sxp.version>1.3.0-SNAPSHOT</sxp.version>
     <netconf.version>1.1.0-SNAPSHOT</netconf.version>
+    <vbd.version>1.0.0-SNAPSHOT</vbd.version>
   </properties>
 
   <dependencyManagement>
         <scope>import</scope>
         <type>pom</type>
       </dependency>
+
+      <!-- honeycomb/VBD -->
+      <dependency>
+        <groupId>org.opendaylight.honeycomb.vbd</groupId>
+        <artifactId>vbd-artifacts</artifactId>
+        <version>${vbd.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
       <classifier>features</classifier>
     </dependency>
 
+    <!-- honeycomb/VBD -->
+    <dependency>
+      <groupId>org.opendaylight.honeycomb.vbd</groupId>
+      <artifactId>vbd-features</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+    </dependency>
+
     <!-- GBP -->
     <dependency>
       <groupId>commons-net</groupId>
       <groupId>org.opendaylight.groupbasedpolicy</groupId>
       <artifactId>groupbasedpolicy</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>l2-l3-domain-extension</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.groupbasedpolicy</groupId>
       <artifactId>ofoverlay-renderer</artifactId>
       <groupId>org.opendaylight.groupbasedpolicy</groupId>
       <artifactId>neutron-mapper</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>neutron-vpp-mapper</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.groupbasedpolicy</groupId>
       <artifactId>neutron-ovsdb</artifactId>
       <type>xml</type>
       <classifier>config</classifier>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>l2-l3-domain-extension</artifactId>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.groupbasedpolicy</groupId>
       <artifactId>ofoverlay-renderer</artifactId>
       <type>xml</type>
       <classifier>config</classifier>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>neutron-vpp-mapper</artifactId>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.groupbasedpolicy</groupId>
       <artifactId>neutron-ovsdb</artifactId>
       <classifier>config</classifier>
     </dependency>
   </dependencies>
-</project>
\ No newline at end of file
+</project>
index 0177b8b1d56d2f5484f7511ba7f8eb5725d0a3ea..bc6072c93a88d34a4c28c8d1c92161dbb404c043 100755 (executable)
@@ -35,6 +35,8 @@
     <repository>mvn:org.opendaylight.sxp/features/${sxp.version}/xml/features</repository>
     <!-- Repos needed by iosxe renderer -->
     <repository>mvn:org.opendaylight.netconf/features-netconf-connector/${netconf.version}/xml/features</repository>
+    <!-- Repos needed by vpp renderer -->
+    <repository>mvn:org.opendaylight.honeycomb.vbd/vbd-features/${vbd.version}/xml/features</repository>
 
     <!-- The common GBP components -->
     <feature name='odl-groupbasedpolicy-base' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: Base Copmonents'>
     <feature name='odl-groupbasedpolicy-neutronmapper' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: Neutron Mapper mapps neutron APIs to GBP APIs '>
         <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>
     </feature>
 
     -->
     <feature name='odl-groupbasedpolicy-vpp' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: VPP renderer '>
         <feature version="${project.version}">odl-groupbasedpolicy-base</feature>
+        <feature version="${netconf.version}">odl-netconf-topology</feature>
+        <feature version="${vbd.version}">odl-vbd-api</feature>
+        <bundle>mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/vpp-renderer/{{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-vpp-renderer.xml">mvn:org.opendaylight.groupbasedpolicy/vpp-renderer/{{VERSION}}/xml/config</configfile>
     </feature>
 
+    <!--
+        The Neutron-VPP provider
+    -->
+    <feature name='odl-groupbasedpolicy-neutron-vpp-mapper' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: Neutron Mapper mapps neutron APIs to GBP APIs '>
+        <feature version="${project.version}">odl-groupbasedpolicy-neutronmapper</feature>
+        <feature version="${project.version}">odl-groupbasedpolicy-vpp</feature>
+        <bundle>mvn:org.opendaylight.groupbasedpolicy/neutron-vpp-mapper/{{VERSION}}</bundle>
+        <configfile finalname="${config.configfile.directory}/15-neutron-vpp-mapper.xml">mvn:org.opendaylight.groupbasedpolicy/neutron-vpp-mapper/{{VERSION}}/xml/config</configfile>
+    </feature>
+
     <!--
          The UI Backend
     -->
     <feature name='odl-groupbasedpolicy-sxp-mapper' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: sxp-mapper'>
         <feature version="${project.version}">odl-groupbasedpolicy-base</feature>
         <feature version="${sxp.version}">odl-sxp-core</feature>
+        <bundle>mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}</bundle>
         <bundle>mvn:commons-net/commons-net/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/sxp-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-groupbasedpolicy-sxp-mapper.xml">mvn:org.opendaylight.groupbasedpolicy/sxp-mapper/{{VERSION}}/xml/config</configfile>
     </feature>
 
     -->
     <feature name='odl-groupbasedpolicy-ne-location-provider' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: NE location provider'>
         <feature version="${project.version}">odl-groupbasedpolicy-base</feature>
+        <bundle>mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/ne-location-provider/{{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-ne-location-provider.xml">mvn:org.opendaylight.groupbasedpolicy/ne-location-provider/{{VERSION}}/xml/config</configfile>
     </feature>
 
     <!--
        IOS-XE renderer
-   -->
+    -->
     <feature name='odl-groupbasedpolicy-ios-xe' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: ios-xe renderer'>
         <feature version="${project.version}">odl-groupbasedpolicy-base</feature>
         <feature version="${sfc.version}">odl-sfc-provider</feature>
         <feature version="${sxp.version}">odl-sxp-core</feature>
         <feature version="${netconf.version}">odl-netconf-topology</feature>
+        <bundle>mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/sxp-mapper/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/ios-xe-renderer/{{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-groupbasedpolicy-ios-xe-renderer.xml">mvn:org.opendaylight.groupbasedpolicy/ios-xe-renderer/{{VERSION}}/xml/config</configfile>
     </feature>
 </features>
index b237883b130a88c4813d17c1c631b8be871e2bac..aed35222d879e73b715cb21fb64e603ce03f2e01 100644 (file)
@@ -57,7 +57,7 @@ public class DomainSpecificRegistryModule extends org.opendaylight.controller.co
             endpointAugmentorRegistryImpl = new EndpointAugmentorRegistryImpl();
             netDomainAugmentorRegistryImpl = new NetworkDomainAugmentorRegistryImpl();
             baseEndpointServiceImpl = new BaseEndpointServiceImpl(dataProvider, rpcRegistry, endpointAugmentorRegistryImpl);
-            rendererManager = new RendererManager(dataProvider, netDomainAugmentorRegistryImpl);
+            rendererManager = new RendererManager(dataProvider, netDomainAugmentorRegistryImpl, endpointAugmentorRegistryImpl);
         }
 
         @Override
index 3a901cc82e9b8f0e371a5572b8477e8978880162..cc8167fba533c5a02bfe803811c3f7ecbd5793a4 100644 (file)
@@ -17,6 +17,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.ContainmentEndpointWithLocation;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import java.util.Map;
 
@@ -35,7 +36,7 @@ public interface EndpointAugmentor {
      */
     @Nullable
     Map.Entry<Class<? extends Augmentation<AddressEndpoint>>, Augmentation<AddressEndpoint>> buildAddressEndpointAugmentation(
-            AddressEndpointReg input);
+            @Nonnull AddressEndpointReg input);
 
     /**
      * Creates pair of {@link ContainmentEndpoint} augmentation. Augmentation is domain specific.
@@ -48,7 +49,7 @@ public interface EndpointAugmentor {
      */
     @Nullable
     Map.Entry<Class<? extends Augmentation<ContainmentEndpoint>>, Augmentation<ContainmentEndpoint>> buildContainmentEndpointAugmentation(
-            ContainmentEndpointReg input);
+            @Nonnull ContainmentEndpointReg input);
 
     /**
      * Creates pair of {@link AddressEndpointWithLocation} augmentation. Augmentation is domain
@@ -60,7 +61,7 @@ public interface EndpointAugmentor {
      */
     @Nullable
     Map.Entry<Class<? extends Augmentation<AddressEndpointWithLocation>>, Augmentation<AddressEndpointWithLocation>> buildAddressEndpointWithLocationAugmentation(
-            AddressEndpoint input);
+            @Nonnull AddressEndpoint input);
 
     /**
      * Creates pair of {@link ContainmentEndpointWithLocation} augmentation. Augmentation is domain
@@ -72,5 +73,5 @@ public interface EndpointAugmentor {
      */
     @Nullable
     Map.Entry<Class<? extends Augmentation<ContainmentEndpointWithLocation>>, Augmentation<ContainmentEndpointWithLocation>> buildContainmentEndpointWithLocationAugmentation(
-            ContainmentEndpoint input);
+            @Nonnull ContainmentEndpoint input);
 }
index 0c7931616596e06fa9e0a9230af1aaf21cbcd147..86febdad1c0782b0cee8d7a71a105647fd362c27 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.groupbasedpolicy.api;
 
 import java.util.Map;
 
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
@@ -31,6 +32,6 @@ public interface NetworkDomainAugmentor {
      */
     @Nullable
     Map.Entry<Class<? extends Augmentation<RendererNetworkDomain>>, Augmentation<RendererNetworkDomain>> buildRendererNetworkDomainAugmentation(
-            NetworkDomain input);
+            @Nonnull NetworkDomain input);
 
 }
index 9c9cf04a4d68c9e7bc1c9ed986310f4e8b5a11ba..5e38d7e99d14a31b82a89e83cc1ba8ee03e0642c 100644 (file)
@@ -36,7 +36,7 @@ public class NetworkDomainAugmentorRegistryImpl implements NetworkDomainAugmento
         }
     }
 
-    public Set<NetworkDomainAugmentor> getEndpointAugmentors() {
+    public Set<NetworkDomainAugmentor> getNetworkDomainAugmentors() {
         return augmentors;
     }
 
index dfbf4d0678238af6ec101c9afc6b74e18a300585..32addda168cc937f7be85c97956e07f453dfb007 100644 (file)
@@ -22,6 +22,7 @@ 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.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocationBuilder;
@@ -54,7 +55,7 @@ public class LocationResolver implements DataTreeChangeListener<LocationProvider
         this.dataBroker = dataBroker;
         this.realLocations = new HashMap<>();
         this.listenerRegistation = dataBroker.registerDataTreeChangeListener(
-                new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
                         InstanceIdentifier.builder(LocationProviders.class).child(LocationProvider.class).build()),
                 this);
     }
@@ -87,7 +88,8 @@ public class LocationResolver implements DataTreeChangeListener<LocationProvider
                     break;
                 }
             }
-            wtx.submit();
+            LOG.debug("Writing endpoint location changes to DS");
+            DataStoreHelper.submitToDs(wtx);
         }
     }
 
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/DtoEquivalenceUtils.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/DtoEquivalenceUtils.java
new file mode 100644 (file)
index 0000000..be65d9f
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * 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;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.annotation.Nullable;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.CommonEndpointFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
+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.AddressEndpointKey;
+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.ContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.RelativeLocations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
+
+import com.google.common.base.Equivalence;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.MapDifference;
+import com.google.common.collect.Maps;
+
+class DtoEquivalenceUtils {
+
+    private static final Function<ForwardingByTenant, TenantId> FORWARDING_BY_TENANT_TO_TENANT_ID =
+            new Function<ForwardingByTenant, TenantId>() {
+
+                @Override
+                public TenantId apply(ForwardingByTenant input) {
+                    return input.getTenantId();
+                }
+            };
+    private static final Equivalence<AddressEndpoint> ADDR_EP_EQ = new Equivalence<AddressEndpoint>() {
+
+        @Override
+        protected boolean doEquivalent(AddressEndpoint a, AddressEndpoint b) {
+            if (!Objects.equals(a.getKey(), b.getKey())) {
+                return false;
+            }
+            if (!Objects.equals(a.getParentEndpointChoice(), b.getParentEndpointChoice())) {
+                return false;
+            }
+            if (!equalsDtoLists(a.getChildEndpoint(), b.getChildEndpoint())) {
+                return false;
+            }
+            if (!equalsCommonEndpointFields(a, b)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        protected int doHash(AddressEndpoint t) {
+            return t.hashCode();
+        }
+    };
+
+    private static final Equivalence<ContainmentEndpoint> CONT_EP_EQ = new Equivalence<ContainmentEndpoint>() {
+
+        @Override
+        protected boolean doEquivalent(ContainmentEndpoint a, ContainmentEndpoint b) {
+            if (!Objects.equals(a.getKey(), b.getKey())) {
+                return false;
+            }
+            if (!equalsDtoLists(a.getChildEndpoint(), b.getChildEndpoint())) {
+                return false;
+            }
+            if (!equalsCommonEndpointFields(a, b)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        protected int doHash(ContainmentEndpoint t) {
+            return t.hashCode();
+        }
+    };
+
+    private static final Equivalence<AddressEndpointLocation> ADDR_EP_LOC_EQ =
+            new Equivalence<AddressEndpointLocation>() {
+
+                @Override
+                protected boolean doEquivalent(AddressEndpointLocation a, AddressEndpointLocation b) {
+                    if (!Objects.equals(a.getKey(), b.getKey())) {
+                        return false;
+                    }
+                    if (!Objects.equals(a.getAbsoluteLocation(), b.getAbsoluteLocation())) {
+                        return false;
+                    }
+                    if (!equalsRelativeLocations(a.getRelativeLocations(), b.getRelativeLocations())) {
+                        return false;
+                    }
+                    return true;
+                }
+
+                @Override
+                protected int doHash(AddressEndpointLocation t) {
+                    return t.hashCode();
+                }
+            };
+
+    private static final Equivalence<ContainmentEndpointLocation> CONT_EP_LOC_EQ =
+            new Equivalence<ContainmentEndpointLocation>() {
+
+                @Override
+                protected boolean doEquivalent(ContainmentEndpointLocation a, ContainmentEndpointLocation b) {
+                    if (!Objects.equals(a.getKey(), b.getKey())) {
+                        return false;
+                    }
+                    if (!equalsRelativeLocations(a.getRelativeLocations(), b.getRelativeLocations())) {
+                        return false;
+                    }
+                    return true;
+                }
+
+                @Override
+                protected int doHash(ContainmentEndpointLocation t) {
+                    return t.hashCode();
+                }
+            };
+
+    private static final Equivalence<ForwardingByTenant> FWD_BY_TENANT_EQ = new Equivalence<ForwardingByTenant>() {
+
+        @Override
+        protected boolean doEquivalent(ForwardingByTenant x, ForwardingByTenant y) {
+            if (!Objects.equals(x.getKey(), y.getKey())) {
+                return false;
+            }
+            if (!equalsDtoLists(x.getForwardingContext(), y.getForwardingContext())) {
+                return false;
+            }
+            if (!equalsDtoLists(x.getNetworkDomain(), y.getNetworkDomain())) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        protected int doHash(ForwardingByTenant t) {
+            return t.hashCode();
+        }
+    };
+
+    private DtoEquivalenceUtils() {}
+
+    static boolean equalsAddressEpByKey(@Nullable Map<AddressEndpointKey, AddressEndpoint> o1,
+            @Nullable Map<AddressEndpointKey, AddressEndpoint> o2) {
+        return equalsDtoMapsByEquivalence(o1, o2, ADDR_EP_EQ);
+    }
+
+    static boolean equalsContainmentEpByKey(@Nullable Map<ContainmentEndpointKey, ContainmentEndpoint> o1,
+            @Nullable Map<ContainmentEndpointKey, ContainmentEndpoint> o2) {
+        return equalsDtoMapsByEquivalence(o1, o2, CONT_EP_EQ);
+    }
+
+    static boolean equalsAddrEpLocByAddrEpKey(Map<AddressEndpointKey, AddressEndpointLocation> o1,
+            Map<AddressEndpointKey, AddressEndpointLocation> o2) {
+        return equalsDtoMapsByEquivalence(o1, o2, ADDR_EP_LOC_EQ);
+    }
+
+    static boolean equalsContEpLocByContEpKey(Map<ContainmentEndpointKey, ContainmentEndpointLocation> o1,
+            Map<ContainmentEndpointKey, ContainmentEndpointLocation> o2) {
+        return equalsDtoMapsByEquivalence(o1, o2, CONT_EP_LOC_EQ);
+    }
+
+    static boolean equalsForwarding(@Nullable Forwarding a, @Nullable Forwarding b) {
+        if ((a == null && b != null) || (a != null && b == null)) {
+            return false;
+        }
+        if (a == null && b == null) {
+            return true;
+        }
+        return equalsForwardingByTenantLists(a.getForwardingByTenant(), b.getForwardingByTenant());
+    }
+
+    private static boolean equalsCommonEndpointFields(CommonEndpointFields a, CommonEndpointFields b) {
+        if (!Objects.equals(a.getNetworkContainment(), b.getNetworkContainment())) {
+            return false;
+        }
+        if (!Objects.equals(a.getTenant(), b.getTenant())) {
+            return false;
+        }
+        if (!Objects.equals(a.getTimestamp(), b.getTimestamp())) {
+            return false;
+        }
+        if (!equalsDtoLists(a.getCondition(), b.getCondition())) {
+            return false;
+        }
+        if (!equalsDtoLists(a.getEndpointGroup(), b.getEndpointGroup())) {
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean equalsRelativeLocations(RelativeLocations a, RelativeLocations b) {
+        if ((a == null && b != null) || (a != null && b == null)) {
+            return false;
+        }
+        if (a == null && b == null) {
+            return true;
+        }
+        if (!equalsDtoLists(a.getExternalLocation(), b.getExternalLocation())) {
+            return false;
+        }
+        if (!equalsDtoLists(a.getInternalLocation(), b.getInternalLocation())) {
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean equalsForwardingByTenantLists(List<ForwardingByTenant> a, List<ForwardingByTenant> b) {
+        if ((a == null && b != null) || (a != null && b == null)) {
+            return false;
+        }
+        if (a == null && b == null) {
+            return true;
+        }
+        if (a.size() != b.size()) {
+            return false;
+        }
+        ImmutableMap<TenantId, ForwardingByTenant> aMap = Maps.uniqueIndex(a, FORWARDING_BY_TENANT_TO_TENANT_ID);
+        ImmutableMap<TenantId, ForwardingByTenant> bMap = Maps.uniqueIndex(b, FORWARDING_BY_TENANT_TO_TENANT_ID);
+        return equalsDtoMapsByEquivalence(aMap, bMap, FWD_BY_TENANT_EQ);
+    }
+
+    private static <K, V> boolean equalsDtoMapsByEquivalence(@Nullable Map<K, V> o1, @Nullable Map<K, V> o2,
+            Equivalence<V> eq) {
+        if ((o1 == null && o2 != null) || (o1 != null && o2 == null)) {
+            return false;
+        }
+        if (o1 == null && o2 == null) {
+            return true;
+        }
+        if (o1.size() != o2.size()) {
+            return false;
+        }
+        MapDifference<K, V> diff = Maps.difference(o1, o2, eq);
+        if (!diff.entriesOnlyOnLeft().isEmpty() || !diff.entriesOnlyOnRight().isEmpty()) {
+            return false;
+        }
+        if (!diff.entriesDiffering().isEmpty()) {
+            return false;
+        }
+        return true;
+    }
+
+    private static <T> boolean equalsDtoLists(@Nullable List<T> a, @Nullable List<T> b) {
+        if ((a == null && b != null) || (a != null && b == null)) {
+            return false;
+        }
+        if (a == null && b == null) {
+            return true;
+        }
+        return a.size() == b.size() && a.containsAll(b);
+    }
+}
index b8ef7c0426aaa95fab5340de92dea4c9177eff36..c25db15fd5b19b46d4ccbf4c5d74d5845e1711ad 100644 (file)
@@ -99,4 +99,40 @@ public class EndpointInfo {
         return containmentEpsByEpg.get(epg);
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((addressEpByKey == null) ? 0 : addressEpByKey.hashCode());
+        result = prime * result + ((containmentEpByKey == null) ? 0 : containmentEpByKey.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        EndpointInfo other = (EndpointInfo) obj;
+        if (addressEpByKey == null) {
+            if (other.addressEpByKey != null)
+                return false;
+        } else if (!DtoEquivalenceUtils.equalsAddressEpByKey(addressEpByKey, other.addressEpByKey))
+            return false;
+        if (containmentEpByKey == null) {
+            if (other.containmentEpByKey != null)
+                return false;
+        } else if (!DtoEquivalenceUtils.equalsContainmentEpByKey(containmentEpByKey, other.containmentEpByKey))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "EndpointInfo [addressEpByKey=" + addressEpByKey + ", containmentEpByKey=" + containmentEpByKey + "]";
+    }
+
 }
index a961e1efff9f4332f1fb46a54e8921fef9309e9d..426a09f560041a1fd0f0528c9afc7e7d172d1e6e 100644 (file)
@@ -34,41 +34,42 @@ import com.google.common.collect.ImmutableSet;
 public class EndpointLocationInfo {
 
     private final ImmutableMultimap<InstanceIdentifier<?>, AddressEndpointLocation> endpointsByAbsNodeLocation;
-    private final ImmutableMap<AddressEndpointKey, AddressEndpointLocation> adrEpLocByAdrEpKey;
-    private final ImmutableMap<ContainmentEndpointKey, ContainmentEndpointLocation> contEpLocBycontEpKey;
+    private final ImmutableMap<AddressEndpointKey, AddressEndpointLocation> addrEpLocByAddrEpKey;
+    private final ImmutableMap<ContainmentEndpointKey, ContainmentEndpointLocation> contEpLocByContEpKey;
 
     public EndpointLocationInfo(EndpointLocations epLocations) {
         List<AddressEndpointLocation> addressEndpointLocations = epLocations.getAddressEndpointLocation();
-        endpointsByAbsNodeLocation = EndpointLocationUtils.resolveEndpointsByAbsoluteNodeLocation(addressEndpointLocations);
+        endpointsByAbsNodeLocation =
+                EndpointLocationUtils.resolveEndpointsByAbsoluteNodeLocation(addressEndpointLocations);
         if (addressEndpointLocations == null) {
-            adrEpLocByAdrEpKey = ImmutableMap.of();
+            addrEpLocByAddrEpKey = ImmutableMap.of();
         } else {
             com.google.common.collect.ImmutableMap.Builder<AddressEndpointKey, AddressEndpointLocation> adrEpLocByAdrEpKeyBuilder =
                     ImmutableMap.builder();
             for (AddressEndpointLocation adrEpLoc : addressEndpointLocations) {
                 adrEpLocByAdrEpKeyBuilder.put(toAdrEpKey(adrEpLoc.getKey()), adrEpLoc);
             }
-            adrEpLocByAdrEpKey = adrEpLocByAdrEpKeyBuilder.build();
+            addrEpLocByAddrEpKey = adrEpLocByAdrEpKeyBuilder.build();
         }
         List<ContainmentEndpointLocation> containmentEndpointLocations = epLocations.getContainmentEndpointLocation();
         if (containmentEndpointLocations == null) {
-            contEpLocBycontEpKey = ImmutableMap.of();
+            contEpLocByContEpKey = ImmutableMap.of();
         } else {
             com.google.common.collect.ImmutableMap.Builder<ContainmentEndpointKey, ContainmentEndpointLocation> contEpLocBycontEpKeyBuilder =
                     ImmutableMap.builder();
             for (ContainmentEndpointLocation contEpLoc : containmentEndpointLocations) {
                 contEpLocBycontEpKeyBuilder.put(toContEpKey(contEpLoc.getKey()), contEpLoc);
             }
-            contEpLocBycontEpKey = contEpLocBycontEpKeyBuilder.build();
+            contEpLocByContEpKey = contEpLocBycontEpKeyBuilder.build();
         }
     }
 
     public Optional<AddressEndpointLocation> getAdressEndpointLocation(AddressEndpointKey epKey) {
-        return Optional.fromNullable(adrEpLocByAdrEpKey.get(epKey));
+        return Optional.fromNullable(addrEpLocByAddrEpKey.get(epKey));
     }
 
     public Optional<ContainmentEndpointLocation> getContainmentEndpointLocation(ContainmentEndpointKey contEpKey) {
-        return Optional.fromNullable(contEpLocBycontEpKey.get(contEpKey));
+        return Optional.fromNullable(contEpLocByContEpKey.get(contEpKey));
     }
 
     private AddressEndpointKey toAdrEpKey(AddressEndpointLocationKey adrEpLocKey) {
@@ -84,21 +85,22 @@ public class EndpointLocationInfo {
         return endpointsByAbsNodeLocation.keySet();
     }
 
-    public ImmutableSet<AddressEndpointKey> getAddressEpsWithAbsoluteNodeLocation(InstanceIdentifier<?> realNodeLocation) {
+    public ImmutableSet<AddressEndpointKey> getAddressEpsWithAbsoluteNodeLocation(
+            InstanceIdentifier<?> realNodeLocation) {
         return FluentIterable.from(endpointsByAbsNodeLocation.get(realNodeLocation))
-                .transform(new Function<AddressEndpointLocation, AddressEndpointKey>() {
-
-                    @Override
-                    public AddressEndpointKey apply(AddressEndpointLocation epLoc) {
-                        return new AddressEndpointKey(epLoc.getAddress(),
-                                epLoc.getAddressType(), epLoc.getContextId(), epLoc.getContextType());
-                    }
-                })
-                .toSet();
+            .transform(new Function<AddressEndpointLocation, AddressEndpointKey>() {
+
+                @Override
+                public AddressEndpointKey apply(AddressEndpointLocation epLoc) {
+                    return new AddressEndpointKey(epLoc.getAddress(), epLoc.getAddressType(), epLoc.getContextId(),
+                            epLoc.getContextType());
+                }
+            })
+            .toSet();
     }
 
-    public boolean hasRealLocation(AddressEndpointKey adrEpKey) {
-        AddressEndpointLocation adrEpLoc = adrEpLocByAdrEpKey.get(adrEpKey);
+    public boolean hasAbsoluteLocation(AddressEndpointKey adrEpKey) {
+        AddressEndpointLocation adrEpLoc = addrEpLocByAddrEpKey.get(adrEpKey);
         if (adrEpLoc == null) {
             return false;
         }
@@ -114,7 +116,7 @@ public class EndpointLocationInfo {
     }
 
     public boolean hasRelativeLocation(AddressEndpointKey adrEpKey) {
-        AddressEndpointLocation adrEpLoc = adrEpLocByAdrEpKey.get(adrEpKey);
+        AddressEndpointLocation adrEpLoc = addrEpLocByAddrEpKey.get(adrEpKey);
         if (adrEpLoc == null) {
             return false;
         }
@@ -130,7 +132,7 @@ public class EndpointLocationInfo {
     }
 
     public boolean hasRelativeLocation(ContainmentEndpointKey contEpKey) {
-        ContainmentEndpointLocation contEpLoc = contEpLocBycontEpKey.get(contEpKey);
+        ContainmentEndpointLocation contEpLoc = contEpLocByContEpKey.get(contEpKey);
         if (contEpLoc == null) {
             return false;
         }
@@ -145,4 +147,41 @@ public class EndpointLocationInfo {
         return true;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((addrEpLocByAddrEpKey == null) ? 0 : addrEpLocByAddrEpKey.hashCode());
+        result = prime * result + ((contEpLocByContEpKey == null) ? 0 : contEpLocByContEpKey.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        EndpointLocationInfo other = (EndpointLocationInfo) obj;
+        if (addrEpLocByAddrEpKey == null) {
+            if (other.addrEpLocByAddrEpKey != null)
+                return false;
+        } else if (!DtoEquivalenceUtils.equalsAddrEpLocByAddrEpKey(addrEpLocByAddrEpKey, other.addrEpLocByAddrEpKey))
+            return false;
+        if (contEpLocByContEpKey == null) {
+            if (other.contEpLocByContEpKey != null)
+                return false;
+        } else if (!DtoEquivalenceUtils.equalsContEpLocByContEpKey(contEpLocByContEpKey, other.contEpLocByContEpKey))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "EndpointLocationInfo [adrEpLocByAdrEpKey=" + addrEpLocByAddrEpKey + ", contEpLocBycontEpKey="
+                + contEpLocByContEpKey + "]";
+    }
+
 }
index f23160eeb864877a6d8141fbf4e29044b0f5cf95..33908b4b1422bb399939d032d11f0ca1e73dcadd 100644 (file)
@@ -20,6 +20,7 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor;
 import org.opendaylight.groupbasedpolicy.api.NetworkDomainAugmentor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
@@ -271,11 +272,11 @@ public class RendererConfigurationBuilder {
     }
 
     public Endpoints buildEndoints(EndpointInfo epInfo, EndpointLocationInfo epLocInfo,
-            Map<InstanceIdentifier<?>, RendererName> rendererByNode) {
+            Map<InstanceIdentifier<?>, RendererName> rendererByNode, Set<EndpointAugmentor> augmentors) {
         List<AddressEndpointWithLocation> epsWithLoc =
-                resolveEpsWithLoc(getAddressEndpointKeys(), epInfo, epLocInfo, rendererByNode);
+                resolveEpsWithLoc(getAddressEndpointKeys(), epInfo, epLocInfo, rendererByNode, augmentors);
         List<ContainmentEndpointWithLocation> contEpsWithLoc =
-                resolveContEpsWithLoc(getContainmentEndpointKeys(), epInfo, epLocInfo);
+                resolveContEpsWithLoc(getContainmentEndpointKeys(), epInfo, epLocInfo, augmentors);
         return new EndpointsBuilder().setAddressEndpointWithLocation(epsWithLoc)
             .setContainmentEndpointWithLocation(contEpsWithLoc)
             .build();
@@ -283,7 +284,7 @@ public class RendererConfigurationBuilder {
 
     private static List<AddressEndpointWithLocation> resolveEpsWithLoc(Set<AddressEndpointKey> epKeys,
             EndpointInfo epInfo, EndpointLocationInfo epLocInfo,
-            Map<InstanceIdentifier<?>, RendererName> rendererByNode) {
+            Map<InstanceIdentifier<?>, RendererName> rendererByNode, Set<EndpointAugmentor> augmentors) {
         List<AddressEndpointWithLocation> result = new ArrayList<>();
         for (AddressEndpointKey epKey : epKeys) {
             Optional<AddressEndpoint> potentialEp = epInfo.getEndpoint(epKey);
@@ -291,7 +292,7 @@ public class RendererConfigurationBuilder {
             Optional<AddressEndpointLocation> potentionalEpLoc = epLocInfo.getAdressEndpointLocation(epKey);
             Preconditions.checkArgument(potentionalEpLoc.isPresent());
             RendererName rendererName = resolveRendererName(potentionalEpLoc.get(), rendererByNode);
-            result.add(createEpWithLoc(potentialEp.get(), potentionalEpLoc.get(), rendererName));
+            result.add(createEpWithLoc(potentialEp.get(), potentionalEpLoc.get(), rendererName, augmentors));
         }
         return result;
     }
@@ -306,8 +307,9 @@ public class RendererConfigurationBuilder {
     }
 
     private static AddressEndpointWithLocation createEpWithLoc(AddressEndpoint ep, AddressEndpointLocation epLoc,
-            RendererName rendererName) {
-        return new AddressEndpointWithLocationBuilder().setAddress(ep.getAddress())
+            RendererName rendererName, Set<EndpointAugmentor> augmentors) {
+        AddressEndpointWithLocationBuilder addrEpWithLoc = new AddressEndpointWithLocationBuilder()
+            .setAddress(ep.getAddress())
             .setAddressType(ep.getAddressType())
             .setContextId(ep.getContextId())
             .setContextType(ep.getContextType())
@@ -320,12 +322,19 @@ public class RendererConfigurationBuilder {
             .setTimestamp(ep.getTimestamp())
             .setAbsoluteLocation(epLoc.getAbsoluteLocation())
             .setRelativeLocations(epLoc.getRelativeLocations())
-            .setRendererName(rendererName)
-            .build();
+            .setRendererName(rendererName);
+        for (EndpointAugmentor augmentor : augmentors) {
+            Entry<Class<? extends Augmentation<AddressEndpointWithLocation>>, Augmentation<AddressEndpointWithLocation>> addrEpWithLocAug =
+                    augmentor.buildAddressEndpointWithLocationAugmentation(ep);
+            if (addrEpWithLocAug != null) {
+                addrEpWithLoc.addAugmentation(addrEpWithLocAug.getKey(), addrEpWithLocAug.getValue());
+            }
+        }
+        return addrEpWithLoc.build();
     }
 
     private static List<ContainmentEndpointWithLocation> resolveContEpsWithLoc(Set<ContainmentEndpointKey> contEpKeys,
-            EndpointInfo epInfo, EndpointLocationInfo epLocInfo) {
+            EndpointInfo epInfo, EndpointLocationInfo epLocInfo, Set<EndpointAugmentor> augmentors) {
         List<ContainmentEndpointWithLocation> result = new ArrayList<>();
         for (ContainmentEndpointKey contEpKey : contEpKeys) {
             Optional<ContainmentEndpoint> potentialContEp = epInfo.getContainmentEndpoint(contEpKey);
@@ -333,14 +342,15 @@ public class RendererConfigurationBuilder {
             Optional<ContainmentEndpointLocation> potentialContEpLoc =
                     epLocInfo.getContainmentEndpointLocation(contEpKey);
             Preconditions.checkArgument(potentialContEpLoc.isPresent());
-            result.add(createContEpWithLoc(potentialContEp.get(), potentialContEpLoc.get()));
+            result.add(createContEpWithLoc(potentialContEp.get(), potentialContEpLoc.get(), augmentors));
         }
         return result;
     }
 
     private static ContainmentEndpointWithLocation createContEpWithLoc(ContainmentEndpoint contEp,
-            ContainmentEndpointLocation contEpLoc) {
-        return new ContainmentEndpointWithLocationBuilder().setContextId(contEp.getContextId())
+            ContainmentEndpointLocation contEpLoc, Set<EndpointAugmentor> augmentors) {
+        ContainmentEndpointWithLocationBuilder contEpWithLoc = new ContainmentEndpointWithLocationBuilder()
+            .setContextId(contEp.getContextId())
             .setContextType(contEp.getContextType())
             .setTenant(contEp.getTenant())
             .setChildEndpoint(contEp.getChildEndpoint())
@@ -348,8 +358,15 @@ public class RendererConfigurationBuilder {
             .setCondition(contEp.getCondition())
             .setNetworkContainment(contEp.getNetworkContainment())
             .setTimestamp(contEp.getTimestamp())
-            .setRelativeLocations(contEpLoc.getRelativeLocations())
-            .build();
+            .setRelativeLocations(contEpLoc.getRelativeLocations());
+        for (EndpointAugmentor augmentor : augmentors) {
+            Entry<Class<? extends Augmentation<ContainmentEndpointWithLocation>>, Augmentation<ContainmentEndpointWithLocation>> contEpWithLocAug =
+                    augmentor.buildContainmentEndpointWithLocationAugmentation(contEp);
+            if (contEpWithLocAug != null) {
+                contEpWithLoc.addAugmentation(contEpWithLocAug.getKey(), contEpWithLocAug.getValue());
+            }
+        }
+        return contEpWithLoc.build();
     }
 
     public RuleGroups buildRuluGroups(ResolvedPolicyInfo policyInfo) {
index 16b68886cf0c4bd655c39bbae6c313126a82831f..772d0583c33285a653a17b2b1e9ad561b0ba44ce 100644 (file)
@@ -23,6 +23,7 @@ import javax.annotation.Nullable;
 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.base_endpoint.EndpointAugmentorRegistryImpl;
 import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey;
 import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
 import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey;
@@ -85,12 +86,11 @@ public class RendererManager implements AutoCloseable {
 
     private final DataBroker dataProvider;
     private final NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry;
+    private final EndpointAugmentorRegistryImpl epAugmentorRegistry;
     private final Set<RendererName> processingRenderers = new HashSet<>();
-    private Map<InstanceIdentifier<?>, RendererName> rendererByNode = new HashMap<>();
-    private ResolvedPolicyInfo policyInfo;
-    private EndpointInfo epInfo;
-    private EndpointLocationInfo epLocInfo;
-    private Forwarding forwarding;
+    private InputState currentState = new InputState();
+    private InputState configuredState;
+    private boolean currentVersionHasConfig = false;
 
     private final EndpointsListener endpointsListener;
     private final EndpointLocationsListener endpointLocationsListener;
@@ -98,9 +98,95 @@ public class RendererManager implements AutoCloseable {
     private final ForwardingListener forwardingListener;
     private final RenderersListener renderersListener;
 
-    public RendererManager(DataBroker dataProvider, NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry) {
+    private static final class InputState {
+
+        private ResolvedPolicyInfo policyInfo;
+        private EndpointInfo epInfo;
+        private EndpointLocationInfo epLocInfo;
+        private Forwarding forwarding;
+        private Map<InstanceIdentifier<?>, RendererName> rendererByNode = new HashMap<>();
+
+        private boolean isValid() {
+            if (rendererByNode.isEmpty() || policyInfo == null || epInfo == null || epLocInfo == null
+                    || forwarding == null) {
+                return false;
+            }
+            return true;
+        }
+
+        private InputState createCopy() {
+            InputState copy = new InputState();
+            copy.policyInfo = this.policyInfo;
+            copy.epInfo = this.epInfo;
+            copy.epLocInfo = this.epLocInfo;
+            copy.forwarding = this.forwarding;
+            copy.rendererByNode = ImmutableMap.copyOf(rendererByNode);
+            return copy;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((epInfo == null) ? 0 : epInfo.hashCode());
+            result = prime * result + ((epLocInfo == null) ? 0 : epLocInfo.hashCode());
+            result = prime * result + ((forwarding == null) ? 0 : forwarding.hashCode());
+            result = prime * result + ((policyInfo == null) ? 0 : policyInfo.hashCode());
+            result = prime * result + ((rendererByNode == null) ? 0 : rendererByNode.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            InputState other = (InputState) obj;
+            if (epInfo == null) {
+                if (other.epInfo != null)
+                    return false;
+            } else if (!epInfo.equals(other.epInfo))
+                return false;
+            if (epLocInfo == null) {
+                if (other.epLocInfo != null)
+                    return false;
+            } else if (!epLocInfo.equals(other.epLocInfo))
+                return false;
+            if (forwarding == null) {
+                if (other.forwarding != null)
+                    return false;
+            } else if (!DtoEquivalenceUtils.equalsForwarding(forwarding, other.forwarding))
+                return false;
+            if (policyInfo == null) {
+                if (other.policyInfo != null)
+                    return false;
+            } else if (!policyInfo.equals(other.policyInfo))
+                return false;
+            if (rendererByNode == null) {
+                if (other.rendererByNode != null)
+                    return false;
+            } else if (!rendererByNode.equals(other.rendererByNode))
+                return false;
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "InputState [policyInfo=" + policyInfo + ", epInfo=" + epInfo + ", epLocInfo=" + epLocInfo
+                    + ", forwarding=" + forwarding + ", rendererByNode=" + rendererByNode + ", isValid()=" + isValid()
+                    + "]";
+        }
+
+    }
+
+    public RendererManager(DataBroker dataProvider, NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry,
+            EndpointAugmentorRegistryImpl epAugmentorRegistry) {
         this.dataProvider = checkNotNull(dataProvider);
         this.netDomainAugmentorRegistry = checkNotNull(netDomainAugmentorRegistry);
+        this.epAugmentorRegistry = checkNotNull(epAugmentorRegistry);
         endpointsListener = new EndpointsListener(this, dataProvider);
         endpointLocationsListener = new EndpointLocationsListener(this, dataProvider);
         resolvedPoliciesListener = new ResolvedPoliciesListener(this, dataProvider);
@@ -109,37 +195,35 @@ public class RendererManager implements AutoCloseable {
     }
 
     public synchronized void endpointsUpdated(final Endpoints endpoints) {
-        epInfo = new EndpointInfo(endpoints);
+        currentState.epInfo = new EndpointInfo(endpoints);
         processState();
     }
 
     public synchronized void endpointLocationsUpdated(final EndpointLocations epLocations) {
-        epLocInfo = new EndpointLocationInfo(epLocations);
+        currentState.epLocInfo = new EndpointLocationInfo(epLocations);
         processState();
     }
 
     public synchronized void resolvedPoliciesUpdated(final ResolvedPolicies resolvedPolicies) {
-        policyInfo = new ResolvedPolicyInfo(resolvedPolicies);
+        currentState.policyInfo = new ResolvedPolicyInfo(resolvedPolicies);
         processState();
     }
 
     public synchronized void forwardingUpdated(final Forwarding forwarding) {
-        this.forwarding = forwarding;
+        currentState.forwarding = forwarding;
         processState();
     }
 
     public synchronized void renderersUpdated(final Renderers renderersCont) {
         ImmutableMultimap<InstanceIdentifier<?>, RendererName> renderersByNode =
                 RendererUtils.resolveRenderersByNodes(renderersCont.getRenderer());
-        rendererByNode = new HashMap<>();
+        currentState.rendererByNode = new HashMap<>();
         for (InstanceIdentifier<?> nodePath : renderersByNode.keySet()) {
             ImmutableCollection<RendererName> renderers = renderersByNode.get(nodePath);
             // only first renderer is used
-            rendererByNode.put(nodePath, renderers.asList().get(0));
+            currentState.rendererByNode.put(nodePath, renderers.asList().get(0));
         }
-        if (processingRenderers.isEmpty()) {
-            processState();
-        } else {
+        if (!processingRenderers.isEmpty()) {
             LOG.debug("Waiting for renderers. Version {} needs to be processed by renderers: {}", version,
                     processingRenderers);
             ImmutableMap<RendererName, Renderer> rendererByName =
@@ -161,6 +245,7 @@ public class RendererManager implements AutoCloseable {
                 }
             }
         }
+        processState();
     }
 
     private void processState() {
@@ -169,56 +254,76 @@ public class RendererManager implements AutoCloseable {
                     processingRenderers);
             return;
         }
-        if (rendererByNode.values().isEmpty()) {
+        if (currentState.equals(configuredState)) {
+            LOG.trace("Nothing was changed in config for renderers {}", currentState);
             return;
         }
-
-        version++;
-        Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = createRendererConfigBuilders();
-        List<Renderer> renderers = new ArrayList<>();
-        Set<RendererName> rendererNames = new HashSet<>(rendererByNode.values());
+        Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName =
+                createRendererConfigBuilders();
+        Set<RendererName> rendererNames = new HashSet<>(currentState.rendererByNode.values());
+        boolean newVersionHasConfig = false;
+        Map<RendererName, Optional<Configuration>> configsByRendererName = new HashMap<>();
         for (RendererName rendererName : rendererNames) {
             RendererConfigurationBuilder rendererPolicyBuilder = rendererConfigBuilderByRendererName.get(rendererName);
             Optional<Configuration> potentialConfig = createConfiguration(rendererPolicyBuilder);
-            RendererPolicy rendererPolicy = null;
             if (potentialConfig.isPresent()) {
-                LOG.debug("Created configuration for renderer with version {}", rendererName.getValue(), version);
-                rendererPolicy =
-                        new RendererPolicyBuilder().setVersion(version).setConfiguration(potentialConfig.get()).build();
+                newVersionHasConfig = true;
+            }
+            configsByRendererName.put(rendererName, potentialConfig);
+        }
+        if (newVersionHasConfig || currentVersionHasConfig) {
+            version++;
+            if (!writeRenderersConfigs(configsByRendererName)) {
+                LOG.warn("Version {} was not dispatched successfully. Previous version is valid until next update.",
+                        version);
+                for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
+                    processingRenderers.remove(rendererName);
+                }
+                version--;
+                return;
             } else {
-                rendererPolicy =
-                        new RendererPolicyBuilder().setVersion(version).build();
+                currentVersionHasConfig = newVersionHasConfig;
+                configuredState = currentState.createCopy();
+            }
+        }
+    }
+
+    private boolean writeRenderersConfigs(Map<RendererName, Optional<Configuration>> configsByRendererName) {
+        List<Renderer> renderers = new ArrayList<>();
+        for (RendererName rendererName : configsByRendererName.keySet()) {
+            RendererPolicy rendererPolicy = null;
+            if (configsByRendererName.get(rendererName).isPresent()) {
+                rendererPolicy = new RendererPolicyBuilder().setVersion(version)
+                    .setConfiguration(configsByRendererName.get(rendererName).get())
+                    .build();
+
+            } else {
+                rendererPolicy = new RendererPolicyBuilder().setVersion(version).build();
             }
             renderers.add(new RendererBuilder().setName(rendererName).setRendererPolicy(rendererPolicy).build());
             processingRenderers.add(rendererName);
+            LOG.debug("Created configuration for renderer {} with version {}", rendererName.getValue(), version);
         }
         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
         wTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Renderers.class),
                 new RenderersBuilder().setRenderer(renderers).build());
-        if (!DataStoreHelper.submitToDs(wTx)) {
-            LOG.warn("Version {} was not dispatched successfully. Previous version is valid till next update.",
-                    version);
-            for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
-                processingRenderers.remove(rendererName);
-            }
-            version--;
-        }
+        return DataStoreHelper.submitToDs(wTx);
     }
 
     /**
      * Entry is added to the result map only if:<br>
      * 1. There is at least one Address EP with absolute location
      * 2. There is a renderer responsible for that EP
-     * 
+     *
      * @return
      */
     private Map<RendererName, RendererConfigurationBuilder> createRendererConfigBuilders() {
-        if (!isStateValid()) {
+        if (!currentState.isValid()) {
             return Collections.emptyMap();
         }
         Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = new HashMap<>();
-        for (InstanceIdentifier<?> absEpLocation : epLocInfo.getAllAbsoluteNodeLocations()) {
-            RendererName rendererName = rendererByNode.get(absEpLocation);
+        for (InstanceIdentifier<?> absEpLocation : currentState.epLocInfo.getAllAbsoluteNodeLocations()) {
+            RendererName rendererName = currentState.rendererByNode.get(absEpLocation);
             if (rendererName == null) {
                 LOG.trace("Renderer does not exist for EP with location: {}", absEpLocation);
                 continue;
@@ -228,8 +333,9 @@ public class RendererManager implements AutoCloseable {
                 rendererConfigBuilder = new RendererConfigurationBuilder();
                 rendererConfigBuilderByRendererName.put(rendererName, rendererConfigBuilder);
             }
-            for (AddressEndpointKey rendererAdrEpKey : epLocInfo.getAddressEpsWithAbsoluteNodeLocation(absEpLocation)) {
-                Optional<AddressEndpoint> potentialAddressEp = epInfo.getEndpoint(rendererAdrEpKey);
+            for (AddressEndpointKey rendererAdrEpKey : currentState.epLocInfo
+                .getAddressEpsWithAbsoluteNodeLocation(absEpLocation)) {
+                Optional<AddressEndpoint> potentialAddressEp = currentState.epInfo.getEndpoint(rendererAdrEpKey);
                 if (!potentialAddressEp.isPresent()) {
                     LOG.trace("Endpoint does not exist but has location: {}", rendererAdrEpKey);
                     continue;
@@ -241,14 +347,6 @@ public class RendererManager implements AutoCloseable {
         return rendererConfigBuilderByRendererName;
     }
 
-    private boolean isStateValid() {
-        if (rendererByNode.isEmpty() || policyInfo == null || epInfo == null || epLocInfo == null
-                || forwarding == null) {
-            return false;
-        }
-        return true;
-    }
-
     private Optional<Configuration> createConfiguration(@Nullable RendererConfigurationBuilder rendererPolicyBuilder) {
         if (rendererPolicyBuilder == null) {
             return Optional.absent();
@@ -261,14 +359,15 @@ public class RendererManager implements AutoCloseable {
         configBuilder.setRendererEndpoints(rendererEndpoints);
 
         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints endpoints =
-                rendererPolicyBuilder.buildEndoints(epInfo, epLocInfo, rendererByNode);
+                rendererPolicyBuilder.buildEndoints(currentState.epInfo, currentState.epLocInfo,
+                        currentState.rendererByNode, epAugmentorRegistry.getEndpointAugmentors());
         configBuilder.setEndpoints(endpoints);
 
-        RuleGroups ruleGroups = rendererPolicyBuilder.buildRuluGroups(policyInfo);
+        RuleGroups ruleGroups = rendererPolicyBuilder.buildRuluGroups(currentState.policyInfo);
         configBuilder.setRuleGroups(ruleGroups);
 
-        RendererForwarding rendererForwarding = rendererPolicyBuilder.buildRendererForwarding(forwarding,
-                netDomainAugmentorRegistry.getEndpointAugmentors());
+        RendererForwarding rendererForwarding = rendererPolicyBuilder.buildRendererForwarding(currentState.forwarding,
+                netDomainAugmentorRegistry.getNetworkDomainAugmentors());
         configBuilder.setRendererForwarding(rendererForwarding);
 
         return Optional.of(configBuilder.build());
@@ -288,25 +387,29 @@ public class RendererManager implements AutoCloseable {
         Set<EpgKeyDto> rendererEpgs = toEpgKeys(rendererAdrEp.getEndpointGroup(), rendererAdrEp.getTenant());
         RendererEndpointKey rendererEpKey = AddressEndpointUtils.toRendererEpKey(rendererAdrEp.getKey());
         for (EpgKeyDto rendererEpg : rendererEpgs) {
-            ImmutableSet<ConsEpgKey> consPeerEpgs = policyInfo.findConsumerPeers(rendererEpg);
+            ImmutableSet<ConsEpgKey> consPeerEpgs = currentState.policyInfo.findConsumerPeers(rendererEpg);
             for (ConsEpgKey consPeerEpg : consPeerEpgs) {
-                Optional<ResolvedPolicy> potentialPolicy = policyInfo.findPolicy(consPeerEpg, rendererEpg);
+                Optional<ResolvedPolicy> potentialPolicy = currentState.policyInfo.findPolicy(consPeerEpg, rendererEpg);
                 ResolvedPolicy policy = potentialPolicy.get();
-                ImmutableSet<AddressEndpointKey> consPeerAdrEps = epInfo.findAddressEpsWithEpg(consPeerEpg);
+                ImmutableSet<AddressEndpointKey> consPeerAdrEps =
+                        currentState.epInfo.findAddressEpsWithEpg(consPeerEpg);
                 resolveRendererPolicyBetweenEpAndPeers(rendererEpKey, consPeerAdrEps, policy,
                         EndpointPolicyParticipation.PROVIDER, rendererPolicyBuilder);
-                ImmutableSet<ContainmentEndpointKey> consPeerContEps = epInfo.findContainmentEpsWithEpg(consPeerEpg);
+                ImmutableSet<ContainmentEndpointKey> consPeerContEps =
+                        currentState.epInfo.findContainmentEpsWithEpg(consPeerEpg);
                 resolveRendererPolicyBetweenEpAndContPeers(rendererEpKey, consPeerContEps, policy,
                         EndpointPolicyParticipation.PROVIDER, rendererPolicyBuilder);
             }
-            ImmutableSet<ProvEpgKey> provPeerEpgs = policyInfo.findProviderPeers(rendererEpg);
+            ImmutableSet<ProvEpgKey> provPeerEpgs = currentState.policyInfo.findProviderPeers(rendererEpg);
             for (ProvEpgKey provPeerEpg : provPeerEpgs) {
-                Optional<ResolvedPolicy> potentialPolicy = policyInfo.findPolicy(rendererEpg, provPeerEpg);
+                Optional<ResolvedPolicy> potentialPolicy = currentState.policyInfo.findPolicy(rendererEpg, provPeerEpg);
                 ResolvedPolicy policy = potentialPolicy.get();
-                ImmutableSet<AddressEndpointKey> provPeerAdrEps = epInfo.findAddressEpsWithEpg(provPeerEpg);
+                ImmutableSet<AddressEndpointKey> provPeerAdrEps =
+                        currentState.epInfo.findAddressEpsWithEpg(provPeerEpg);
                 resolveRendererPolicyBetweenEpAndPeers(rendererEpKey, provPeerAdrEps, policy,
                         EndpointPolicyParticipation.CONSUMER, rendererPolicyBuilder);
-                ImmutableSet<ContainmentEndpointKey> provPeerContEps = epInfo.findContainmentEpsWithEpg(provPeerEpg);
+                ImmutableSet<ContainmentEndpointKey> provPeerContEps =
+                        currentState.epInfo.findContainmentEpsWithEpg(provPeerEpg);
                 resolveRendererPolicyBetweenEpAndContPeers(rendererEpKey, provPeerContEps, policy,
                         EndpointPolicyParticipation.CONSUMER, rendererPolicyBuilder);
             }
@@ -324,7 +427,7 @@ public class RendererManager implements AutoCloseable {
         for (ContainmentEndpointKey peerContEpKey : peerContEps) {
             ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
             if (eig != null) { // peers are in EIG
-                if (!epLocInfo.hasRelativeLocation(peerContEpKey)) {
+                if (!currentState.epLocInfo.hasRelativeLocation(peerContEpKey)) {
                     LOG.debug("EIG Containment Peer does not have relative location therefore it is ignored: {}",
                             peerContEpKey);
                     continue;
@@ -355,9 +458,12 @@ public class RendererManager implements AutoCloseable {
             return;
         }
         for (AddressEndpointKey peerAdrEpKey : peerAdrEps) {
+            if (isSameKeys(rendererEpKey, peerAdrEpKey)) {
+                continue;
+            }
             ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
             if (eig != null) {
-                if (!epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
+                if (!currentState.epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
                     LOG.debug("EIG Peer does not have relative location therefore it is ignored: {}", peerAdrEpKey);
                     continue;
                 }
@@ -371,8 +477,8 @@ public class RendererManager implements AutoCloseable {
                     }
                 }
             } else {
-                if (!epLocInfo.hasRealLocation(peerAdrEpKey)) {
-                    LOG.debug("Peer does not have real location therefore it is ignored: {}", peerAdrEpKey);
+                if (!currentState.epLocInfo.hasAbsoluteLocation(peerAdrEpKey)) {
+                    LOG.debug("Peer does not have absolute location therefore it is ignored: {}", peerAdrEpKey);
                     continue;
                 }
                 PeerEndpointKey peerEpKey = AddressEndpointUtils.toPeerEpKey(peerAdrEpKey);
@@ -399,6 +505,16 @@ public class RendererManager implements AutoCloseable {
         return false;
     }
 
+    private boolean isSameKeys(RendererEndpointKey rendererEpKey, AddressEndpointKey peerAdrEpKey) {
+        if (rendererEpKey.getAddress().equals(peerAdrEpKey.getAddress())
+                && rendererEpKey.getAddressType().equals(peerAdrEpKey.getAddressType())
+                && rendererEpKey.getContextId().equals(peerAdrEpKey.getContextId())
+                && rendererEpKey.getContextType().equals(peerAdrEpKey.getContextType())) {
+            return true;
+        }
+        return false;
+    }
+
     private Set<EpgKeyDto> toEpgKeys(List<EndpointGroupId> epgIds, TenantId tenantId) {
         return FluentIterable.from(epgIds).transform(new Function<EndpointGroupId, EpgKeyDto>() {
 
index 08cec8c6e8f14bdb208f6c229a34f6db907a7410..fc24581ed421cb70ad953f7aadcdfcd52899c298 100644 (file)
@@ -32,6 +32,9 @@ public class RendererUtils {
         }
         Builder<InstanceIdentifier<?>, RendererName> renderersByNodeBuilder = ImmutableMultimap.builder();
         for (Renderer renderer : renderers) {
+            if (renderer.getRendererNodes() == null) {
+                continue;
+            }
             List<RendererNode> rendererNodes = renderer.getRendererNodes().getRendererNode();
             if (rendererNodes == null) {
                 continue;
index 4d8877efa9b0de2d4f915e57e01b73e60e050891..08ae9bcce078f0f99956e61fa08e04d01e1c508a 100644 (file)
@@ -10,9 +10,11 @@ package org.opendaylight.groupbasedpolicy.resolver;
 
 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.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -23,6 +25,8 @@ public class ForwardingResolver extends DataTreeChangeHandler<ForwardingByTenant
 
     public ForwardingResolver(DataBroker dataProvider) {
         super(dataProvider);
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                InstanceIdentifier.builder(Forwarding.class).child(ForwardingByTenant.class).build()));
     }
 
     @Override
index 9faabd823a0f2539e103561468ee57c9b0985686..b9a85bd55394bac5cfc88f24e9f19f145f9d4ecf 100644 (file)
@@ -39,7 +39,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
@@ -58,19 +57,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_l
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProviderKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2BridgeDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenantKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
@@ -124,7 +115,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecord;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecordKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 
 public class IidFactory {
 
@@ -258,31 +248,6 @@ public class IidFactory {
             .build();
     }
 
-    public static InstanceIdentifier<NetworkDomain> subnetIid(TenantId tenantId, NetworkDomainId id) {
-        NetworkDomainKey domainKey = new NetworkDomainKey(id, Subnet.class);
-        return createForwardingByTenantIidBuilder(tenantId).child(NetworkDomain.class, domainKey).build();
-    }
-
-    public static InstanceIdentifier<ForwardingContext> l2FloodDomainIid(TenantId tenantId, ContextId id) {
-        ForwardingContextKey domainKey = new ForwardingContextKey(id, L2FloodDomain.class);
-        return createForwardingByTenantIidBuilder(tenantId).child(ForwardingContext.class, domainKey).build();
-    }
-
-    public static InstanceIdentifier<ForwardingContext> l2BridgeDomainIid(TenantId tenantId, ContextId id) {
-        ForwardingContextKey domainKey = new ForwardingContextKey(id, L2BridgeDomain.class);
-        return createForwardingByTenantIidBuilder(tenantId).child(ForwardingContext.class, domainKey).build();
-    }
-
-    public static InstanceIdentifier<ForwardingContext> l3ContextIid(TenantId tenantId, ContextId id) {
-        ForwardingContextKey domainKey = new ForwardingContextKey(id, L3Context.class);
-        return createForwardingByTenantIidBuilder(tenantId).child(ForwardingContext.class, domainKey).build();
-    }
-
-    private static InstanceIdentifierBuilder<ForwardingByTenant> createForwardingByTenantIidBuilder(TenantId tenantId) {
-        return InstanceIdentifier.builder(Forwarding.class).child(ForwardingByTenant.class,
-                new ForwardingByTenantKey(tenantId));
-    }
-
     @Deprecated
     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain> l2FloodDomainIid(TenantId tenantId,
             L2FloodDomainId l2FloodDomainId) {
@@ -499,12 +464,22 @@ public class IidFactory {
                 .build();
     }
 
-    public static InstanceIdentifier<ProviderAddressEndpointLocation> providerAddressEndpointLocationIid(String provider,
-            Class<? extends AddressType> addrType, String addr, Class<? extends ContextType> cType,
+    public static InstanceIdentifier<ProviderAddressEndpointLocation> providerAddressEndpointLocationIid(
+            String provider, Class<? extends AddressType> addrType, String addr, Class<? extends ContextType> cType,
             ContextId containment) {
+        return providerAddressEndpointLocationIid(new ProviderName(provider),
+                new ProviderAddressEndpointLocationKey(addr, addrType, containment, cType));
+    }
+
+    public static InstanceIdentifier<ProviderAddressEndpointLocation> providerAddressEndpointLocationIid(
+            ProviderName provider, ProviderAddressEndpointLocationKey providerAddressEndpointLocationKey) {
+        return locationProviderIid(provider).child(ProviderAddressEndpointLocation.class,
+                providerAddressEndpointLocationKey);
+    }
+
+    public static InstanceIdentifier<LocationProvider> locationProviderIid(ProviderName provider) {
         return InstanceIdentifier.builder(LocationProviders.class)
-                .child(LocationProvider.class, new LocationProviderKey(new ProviderName(provider)))
-            .child(ProviderAddressEndpointLocation.class, new ProviderAddressEndpointLocationKey(addr, addrType, containment, cType))
+            .child(LocationProvider.class, new LocationProviderKey(provider))
             .build();
     }
 
index a650f11fbb1a8a66ba203f93effafe43c3875ead..36152ac498dd7cdbb58e66718a614ca3b062ac7b 100644 (file)
@@ -99,8 +99,8 @@ public final class NetUtils {
         if (prefix1.getIpv4Prefix() != null && prefix2.getIpv4Prefix() != null) {
             SubnetUtils fromPrefix1 = new SubnetUtils(prefix1.getIpv4Prefix().getValue());
             SubnetUtils fromPrefix2 = new SubnetUtils(prefix2.getIpv4Prefix().getValue());
-            if (fromPrefix1.getInfo().isInRange(fromPrefix2.getInfo().getHighAddress())
-                    && fromPrefix2.getInfo().isInRange(fromPrefix1.getInfo().getHighAddress())) {
+            if (fromPrefix1.getInfo().getNetworkAddress().equals(fromPrefix2.getInfo().getNetworkAddress())
+                    && fromPrefix1.getInfo().getNetmask().equals(fromPrefix2.getInfo().getNetmask())) {
                 return true;
             }
         } else if (prefix1.getIpv6Prefix() != null && prefix2.getIpv6Prefix() != null) {
index 9e0abe80e6e21eb7246079f1363cfff28564590a..522d149aa8480f5186e8532c7959348480582af5 100644 (file)
@@ -58,11 +58,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
 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.L2FloodDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.NetworkDomain;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
 import com.google.common.base.Optional;
@@ -77,27 +75,26 @@ public class BaseEndpointServiceImplTest extends CustomDataBrokerTest {
     private static final String CONTEXT_ID = "testContext";
     private static final long timestamp = 1234567890L;
     private static final NetworkDomainContainment networkDomainContainment = new NetworkDomainContainmentBuilder()
-        .setNetworkDomainId(new NetworkDomainId(DOMAIN)).setNetworkDomainType(Subnet.class).build();
+        .setNetworkDomainId(new NetworkDomainId(DOMAIN)).setNetworkDomainType(NetworkDomain.class).build();
     private static final ParentEndpoint BASE_L3_PARENT = new ParentEndpointBuilder().setAddress(IP_ADDRESS)
-        .setAddressType(IpPrefixType.class)
+        .setAddressType(AddressType.class)
         .setContextId(new ContextId(CONTEXT_ID))
-        .setContextType(L3Context.class)
+        .setContextType(ContextType.class)
         .build();
     private static final ChildEndpoint BASE_L2_CHILD = new ChildEndpointBuilder().setAddress(MAC_ADDRESS)
-        .setAddressType(MacAddressType.class)
+        .setAddressType(AddressType.class)
         .setContextId(new ContextId(CONTEXT_ID))
-        .setContextType(L2FloodDomain.class)
+        .setContextType(ContextType.class)
         .build();
     private static final ParentContainmentEndpoint BASE_CONT_PARENT = new ParentContainmentEndpointBuilder()
-        .setContextId(new ContextId(CONTEXT_ID)).setContextType(L2FloodDomain.class).build();
+        .setContextId(new ContextId(CONTEXT_ID)).setContextType(ContextType.class).build();
 
     private DataBroker dataProvider;
     private BaseEndpointServiceImpl baseEndpointRpcRegistry;
 
     @Override
     public Collection<Class<?>> getClassesFromModules() {
-        return ImmutableList.of(Endpoints.class, AddressEndpoints.class, ContainmentEndpoints.class,
-                MacAddressType.class, IpPrefixType.class);
+        return ImmutableList.of(Endpoints.class, AddressEndpoints.class, ContainmentEndpoints.class);
     }
 
     @Before
@@ -410,10 +407,10 @@ public class BaseEndpointServiceImplTest extends CustomDataBrokerTest {
     private AddressEndpointBuilder createBaseL2EpBuilder() {
         return new AddressEndpointBuilder().setTimestamp(timestamp)
             .setContextId(new ContextId(CONTEXT_ID))
-            .setContextType(L2FloodDomain.class)
+            .setContextType(ContextType.class)
             .setTenant(new TenantId(TENANT))
             .setAddress(MAC_ADDRESS)
-            .setAddressType(MacAddressType.class)
+            .setAddressType(AddressType.class)
             .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build())
             .setTimestamp(timestamp);
     }
@@ -421,10 +418,10 @@ public class BaseEndpointServiceImplTest extends CustomDataBrokerTest {
     private AddressEndpointBuilder createBaseL3EpBuilder() {
         return new AddressEndpointBuilder().setTimestamp(timestamp)
             .setContextId(new ContextId(CONTEXT_ID))
-            .setContextType(L3Context.class)
+            .setContextType(ContextType.class)
             .setTenant(new TenantId(TENANT))
             .setAddress(IP_ADDRESS)
-            .setAddressType(IpPrefixType.class)
+            .setAddressType(AddressType.class)
             .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build())
             .setTimestamp(timestamp);
     }
@@ -432,7 +429,7 @@ public class BaseEndpointServiceImplTest extends CustomDataBrokerTest {
     private ContainmentEndpointBuilder createBaseContEpBuilder() {
         return new ContainmentEndpointBuilder().setTimestamp(timestamp)
             .setContextId(new ContextId(CONTEXT_ID))
-            .setContextType(L2FloodDomain.class)
+            .setContextType(ContextType.class)
             .setTenant(new TenantId(TENANT))
             .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build());
     }
index 7e8c5ef351cd38021cb178c855e5c1722ede732f..890e9f012a69cc97b52b12a9ce1c30bc400393a0 100644 (file)
@@ -42,8 +42,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_l
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderContainmentEndpointLocationBuilder;
-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.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -84,12 +84,11 @@ public class LocationResolverTest extends CustomDataBrokerTest {
 
     @Override
     public Collection<Class<?>> getClassesFromModules() {
-        return ImmutableList.<Class<?>>of(LocationProvider.class, Nodes.class, L3Context.class,
-                EndpointLocations.class);
+        return ImmutableList.<Class<?>>of(LocationProvider.class, Nodes.class, EndpointLocations.class);
     }
 
     @Test
-    public void test_LocationProviderWrite() throws Exception {
+    public void testOnDataTreeChanged_write() throws Exception {
         AbsoluteLocation absoluteLocation =
                 new AbsoluteLocationBuilder().setLocationType(new InternalLocationCaseBuilder()
                     .setInternalNode(nodeIid1).setInternalNodeConnector(connectorIid).build()).build();
@@ -101,14 +100,14 @@ public class LocationResolverTest extends CustomDataBrokerTest {
         LocationProvider provider = new LocationProviderBuilder().setProvider(new ProviderName(PROVIDER_NAME))
             .setProviderAddressEndpointLocation(
                     Collections.singletonList(new ProviderAddressEndpointLocationBuilder()
-                        .setKey(new ProviderAddressEndpointLocationKey(ADDRESS, IpPrefixType.class, contextId,
-                                L3Context.class))
+                        .setKey(new ProviderAddressEndpointLocationKey(ADDRESS, AddressType.class, contextId,
+                                ContextType.class))
                         .setAbsoluteLocation(absoluteLocation)
                         .setRelativeLocations(relativeLocations)
                         .build()))
             .setProviderContainmentEndpointLocation(
                     Collections.singletonList(new ProviderContainmentEndpointLocationBuilder().setContextId(contextId)
-                        .setContextType(L3Context.class)
+                        .setContextType(ContextType.class)
                         .setRelativeLocations(relativeLocations)
                         .build()))
             .build();
@@ -116,7 +115,7 @@ public class LocationResolverTest extends CustomDataBrokerTest {
             .child(LocationProvider.class, provider.getKey())
             .build();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
-        wtx.put(LogicalDatastoreType.OPERATIONAL, iid, provider);
+        wtx.put(LogicalDatastoreType.CONFIGURATION, iid, provider);
         wtx.submit().get();
 
         ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
@@ -126,19 +125,19 @@ public class LocationResolverTest extends CustomDataBrokerTest {
         EndpointLocations readLocations = read.get();
         assertNotNull(readLocations.getAddressEndpointLocation());
         assertEquals(1, readLocations.getAddressEndpointLocation().size());
-        assertEquals(new AddressEndpointLocationKey(ADDRESS, IpPrefixType.class, contextId, L3Context.class),
+        assertEquals(new AddressEndpointLocationKey(ADDRESS, AddressType.class, contextId, ContextType.class),
                 readLocations.getAddressEndpointLocation().get(0).getKey());
         assertEquals(absoluteLocation, readLocations.getAddressEndpointLocation().get(0).getAbsoluteLocation());
         assertNotNull(readLocations.getContainmentEndpointLocation());
         assertEquals(1, readLocations.getContainmentEndpointLocation().size());
-        assertEquals(new ContainmentEndpointLocationKey(contextId, L3Context.class),
+        assertEquals(new ContainmentEndpointLocationKey(contextId, ContextType.class),
                 readLocations.getContainmentEndpointLocation().get(0).getKey());
         assertEquals(relativeLocations, readLocations.getContainmentEndpointLocation().get(0).getRelativeLocations());
     }
 
     @Test
-    public void test_LocationProviderOverWrite() throws Exception {
-        test_LocationProviderWrite();
+    public void testOnDataTreeChanged_overWrite() throws Exception {
+        testOnDataTreeChanged_write();
         AbsoluteLocation absoluteLocation =
                 new AbsoluteLocationBuilder().setLocationType(new InternalLocationCaseBuilder()
                     .setInternalNode(nodeIid2).setInternalNodeConnector(connectorIid).build()).build();
@@ -150,14 +149,14 @@ public class LocationResolverTest extends CustomDataBrokerTest {
         LocationProvider provider = new LocationProviderBuilder().setProvider(new ProviderName(PROVIDER_NAME))
             .setProviderAddressEndpointLocation(
                     Collections.singletonList(new ProviderAddressEndpointLocationBuilder()
-                        .setKey(new ProviderAddressEndpointLocationKey(ADDRESS, IpPrefixType.class, contextId,
-                                L3Context.class))
+                        .setKey(new ProviderAddressEndpointLocationKey(ADDRESS, AddressType.class, contextId,
+                                ContextType.class))
                         .setAbsoluteLocation(absoluteLocation)
                         .setRelativeLocations(relativeLocations)
                         .build()))
             .setProviderContainmentEndpointLocation(
                     Collections.singletonList(new ProviderContainmentEndpointLocationBuilder().setContextId(contextId)
-                        .setContextType(L3Context.class)
+                        .setContextType(ContextType.class)
                         .setRelativeLocations(relativeLocations)
                         .build()))
             .build();
@@ -165,7 +164,7 @@ public class LocationResolverTest extends CustomDataBrokerTest {
             .child(LocationProvider.class, provider.getKey())
             .build();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
-        wtx.put(LogicalDatastoreType.OPERATIONAL, iid, provider);
+        wtx.put(LogicalDatastoreType.CONFIGURATION, iid, provider);
         wtx.submit().get();
 
         ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
@@ -175,24 +174,24 @@ public class LocationResolverTest extends CustomDataBrokerTest {
         EndpointLocations readLocations = read.get();
         assertNotNull(readLocations.getAddressEndpointLocation());
         assertEquals(1, readLocations.getAddressEndpointLocation().size());
-        assertEquals(new AddressEndpointLocationKey(ADDRESS, IpPrefixType.class, contextId, L3Context.class),
+        assertEquals(new AddressEndpointLocationKey(ADDRESS, AddressType.class, contextId, ContextType.class),
                 readLocations.getAddressEndpointLocation().get(0).getKey());
         assertEquals(absoluteLocation, readLocations.getAddressEndpointLocation().get(0).getAbsoluteLocation());
         assertNotNull(readLocations.getContainmentEndpointLocation());
         assertEquals(1, readLocations.getContainmentEndpointLocation().size());
-        assertEquals(new ContainmentEndpointLocationKey(contextId, L3Context.class),
+        assertEquals(new ContainmentEndpointLocationKey(contextId, ContextType.class),
                 readLocations.getContainmentEndpointLocation().get(0).getKey());
         assertEquals(relativeLocations, readLocations.getContainmentEndpointLocation().get(0).getRelativeLocations());
     }
 
     @Test
-    public void test_LocationProviderDelete() throws Exception {
-        test_LocationProviderWrite();
+    public void testOnDataTreeChanged_delete() throws Exception {
+        testOnDataTreeChanged_write();
         InstanceIdentifier<LocationProvider> iid = InstanceIdentifier.builder(LocationProviders.class)
             .child(LocationProvider.class, new LocationProviderKey(new ProviderName(PROVIDER_NAME)))
             .build();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
-        wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+        wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
         wtx.submit().get();
 
         ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
@@ -218,19 +217,19 @@ public class LocationResolverTest extends CustomDataBrokerTest {
     }
 
     @Test
-    public void test_LocationProviderModify() throws Exception {
-        test_LocationProviderWrite();
+    public void testOnDataTreeChanged_modify() throws Exception {
+        testOnDataTreeChanged_write();
         AbsoluteLocation absoluteLocation =
                 new AbsoluteLocationBuilder().setLocationType(new InternalLocationCaseBuilder()
                     .setInternalNode(nodeIid2).setInternalNodeConnector(connectorIid).build()).build();
         InstanceIdentifier<AbsoluteLocation> iid = InstanceIdentifier.builder(LocationProviders.class)
             .child(LocationProvider.class, new LocationProviderKey(new ProviderName(PROVIDER_NAME)))
             .child(ProviderAddressEndpointLocation.class,
-                    new ProviderAddressEndpointLocationKey(ADDRESS, IpPrefixType.class, contextId, L3Context.class))
+                    new ProviderAddressEndpointLocationKey(ADDRESS, AddressType.class, contextId, ContextType.class))
             .child(AbsoluteLocation.class)
             .build();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
-        wtx.put(LogicalDatastoreType.OPERATIONAL, iid, absoluteLocation);
+        wtx.put(LogicalDatastoreType.CONFIGURATION, iid, absoluteLocation);
         wtx.submit().get();
 
         ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
@@ -240,7 +239,7 @@ public class LocationResolverTest extends CustomDataBrokerTest {
         EndpointLocations readLocations = read.get();
         assertNotNull(readLocations.getAddressEndpointLocation());
         assertEquals(1, readLocations.getAddressEndpointLocation().size());
-        assertEquals(new AddressEndpointLocationKey(ADDRESS, IpPrefixType.class, contextId, L3Context.class),
+        assertEquals(new AddressEndpointLocationKey(ADDRESS, AddressType.class, contextId, ContextType.class),
                 readLocations.getAddressEndpointLocation().get(0).getKey());
         assertEquals(absoluteLocation, readLocations.getAddressEndpointLocation().get(0).getAbsoluteLocation());
     }
index 1c6c9b14ec51bacf2187b99334f840732919df5c..c6e209c2e9537d8e2a94ac729e7c257062cbca84 100644 (file)
@@ -23,6 +23,7 @@ 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.groupbasedpolicy.base_endpoint.EndpointAugmentorRegistryImpl;
 import org.opendaylight.groupbasedpolicy.forwarding.NetworkDomainAugmentorRegistryImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocationsBuilder;
@@ -43,6 +44,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ForwardingBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenantBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder;
@@ -96,6 +98,8 @@ public class RendererManagerDataBrokerTest {
     @Mock
     private NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry;
     @Mock
+    private EndpointAugmentorRegistryImpl epAugmentorRegistry;
+    @Mock
     private WriteTransaction wTx;
     @Mock
     private CheckedFuture<Void, TransactionCommitFailedException> submitFuture;
@@ -106,8 +110,9 @@ public class RendererManagerDataBrokerTest {
     public void init() {
         Mockito.when(dataProvider.newWriteOnlyTransaction()).thenReturn(wTx);
         Mockito.when(wTx.submit()).thenReturn(submitFuture);
-        Mockito.when(netDomainAugmentorRegistry.getEndpointAugmentors()).thenReturn(Collections.emptySet());
-        rendererManager = new RendererManager(dataProvider, netDomainAugmentorRegistry);
+        Mockito.when(netDomainAugmentorRegistry.getNetworkDomainAugmentors()).thenReturn(Collections.emptySet());
+        Mockito.when(epAugmentorRegistry.getEndpointAugmentors()).thenReturn(Collections.emptySet());
+        rendererManager = new RendererManager(dataProvider, netDomainAugmentorRegistry, epAugmentorRegistry);
         RendererManager.resetVersion();
     }
 
@@ -143,7 +148,7 @@ public class RendererManagerDataBrokerTest {
                 .setForwardingByTenant(
                         Arrays.asList(new ForwardingByTenantBuilder().setTenantId(TestDataFactory.TENANT_ID)
                             .setForwardingContext(Arrays.asList(new ForwardingContextBuilder()
-                                .setContextType(TestDataFactory.DummyContextType.class)
+                                .setContextType(ContextType.class)
                                 .setContextId(TestDataFactory.CTX_1)
                                 .build()))
                             .build()))
@@ -244,7 +249,7 @@ public class RendererManagerDataBrokerTest {
                 .setForwardingByTenant(
                         Arrays.asList(new ForwardingByTenantBuilder().setTenantId(TestDataFactory.TENANT_ID)
                             .setForwardingContext(Arrays.asList(new ForwardingContextBuilder()
-                                .setContextType(TestDataFactory.DummyContextType.class)
+                                .setContextType(ContextType.class)
                                 .setContextId(TestDataFactory.CTX_1)
                                 .build()))
                             .build()))
@@ -327,7 +332,7 @@ public class RendererManagerDataBrokerTest {
                 .setForwardingByTenant(
                         Arrays.asList(new ForwardingByTenantBuilder().setTenantId(TestDataFactory.TENANT_ID)
                             .setForwardingContext(Arrays.asList(new ForwardingContextBuilder()
-                                .setContextType(TestDataFactory.DummyContextType.class)
+                                .setContextType(ContextType.class)
                                 .setContextId(TestDataFactory.CTX_1)
                                 .build()))
                             .build()))
index 0aa8a2574bd150447d0e11b70cdf08fd8da852b7..84973e308ad827d047e7a2d6c026154976100904 100644 (file)
@@ -22,6 +22,7 @@ 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.groupbasedpolicy.base_endpoint.EndpointAugmentorRegistryImpl;
 import org.opendaylight.groupbasedpolicy.forwarding.NetworkDomainAugmentorRegistryImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocationsBuilder;
@@ -75,13 +76,16 @@ public class RendererManagerTest {
     private DataBroker dataProvider;
     @Mock
     private NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry;
+    @Mock
+    private EndpointAugmentorRegistryImpl epAugmentorRegistry;
 
     private RendererManager rendererManager;
 
     @Before
     public void init() {
-        Mockito.when(netDomainAugmentorRegistry.getEndpointAugmentors()).thenReturn(Collections.emptySet());
-        rendererManager = new RendererManager(dataProvider, netDomainAugmentorRegistry);
+        Mockito.when(netDomainAugmentorRegistry.getNetworkDomainAugmentors()).thenReturn(Collections.emptySet());
+        Mockito.when(epAugmentorRegistry.getEndpointAugmentors()).thenReturn(Collections.emptySet());
+        rendererManager = new RendererManager(dataProvider, netDomainAugmentorRegistry, epAugmentorRegistry);
     }
 
     /**
index b4e88128cf4da14c09e5af77fb4b4449a8e8cff5..2640ae036f14b8e39663fc3d37d0528ffaa30e6f 100644 (file)
@@ -82,25 +82,25 @@ public class TestDataFactory {
     }
 
     public static AddressEndpointBuilder defaultAdrEp(String address, EndpointGroupId... epgs) {
-        return new AddressEndpointBuilder().setContextType(DummyContextType.class)
+        return new AddressEndpointBuilder().setContextType(ContextType.class)
             .setContextId(CTX_1)
-            .setAddressType(DummyAddressType.class)
+            .setAddressType(AddressType.class)
             .setAddress(address)
             .setTenant(TENANT_ID)
             .setEndpointGroup(Arrays.asList(epgs))
             .setNetworkContainment(
                     new NetworkContainmentBuilder().setContainment(new ForwardingContextContainmentBuilder()
-                        .setContextType(DummyContextType.class).setContextId(CTX_1).build()).build());
+                        .setContextType(ContextType.class).setContextId(CTX_1).build()).build());
     }
 
     public static ContainmentEndpointBuilder defaultContEp(EndpointGroupId... epgs) {
-        return new ContainmentEndpointBuilder().setContextType(DummyContextType.class)
+        return new ContainmentEndpointBuilder().setContextType(ContextType.class)
             .setContextId(CTX_1)
             .setTenant(TENANT_ID)
             .setEndpointGroup(Arrays.asList(epgs))
             .setNetworkContainment(
                     new NetworkContainmentBuilder().setContainment(new ForwardingContextContainmentBuilder()
-                        .setContextType(DummyContextType.class).setContextId(CTX_1).build()).build());
+                        .setContextType(ContextType.class).setContextId(CTX_1).build()).build());
     }
 
     public static ResolvedRuleBuilder defaultResolvedRule(RuleName ruleName) {
@@ -135,8 +135,4 @@ public class TestDataFactory {
             .setPolicyRuleGroupWithEndpointConstraints(ImmutableList.of(blueRuleGrpWithoutCons));
     }
 
-    public static abstract class DummyContextType extends ContextType {
-    };
-    public static abstract class DummyAddressType extends AddressType {
-    };
 }
index 8e3a656bb1ee026ab2dc38991a3ec25cad4a36dc..c369767bbbb15f4eaad648ee8771a55f532e9b8a 100755 (executable)
@@ -13,7 +13,6 @@ import static org.mockito.Mockito.mock;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.Mockito;
 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.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
@@ -39,13 +38,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
@@ -53,10 +50,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
@@ -95,7 +91,6 @@ public class IidFactoryTest {
 
     private final String LOCATION_PROVIDER_NAME = "location-provider";
     private final String IP_ADDRESS = "192.68.50.71";
-    private final String IP_PREFIX = "192.168.50.0/24";
     private final String L3_CONTEXT_ID = "l3Context";
     private final String CONNECTOR = "connector";
 
@@ -224,14 +219,6 @@ public class IidFactoryTest {
         Assert.assertEquals(tenantId, identifier.firstKeyOf(Tenant.class).getId());
     }
 
-    @Test
-    public void testL2FloodDomainIid() {
-        ContextId id = mock(ContextId.class);
-        InstanceIdentifier<ForwardingContext> identifier = IidFactory.l2FloodDomainIid(tenantId, id);
-        Assert.assertEquals(id, InstanceIdentifier.keyOf(identifier).getContextId());
-        Assert.assertEquals(tenantId, identifier.firstKeyOf(ForwardingByTenant.class).getTenantId());
-    }
-
     @Test
     public void testL2FloodDomainIid_tenantApi() {
         L2FloodDomainId l2FloodDomainId = mock(L2FloodDomainId.class);
@@ -240,14 +227,6 @@ public class IidFactoryTest {
         Assert.assertEquals(tenantId, identifier.firstKeyOf(Tenant.class).getId());
     }
 
-    @Test
-    public void testL2BridgeDomainIid() {
-        ContextId id = mock(ContextId.class);
-        InstanceIdentifier<ForwardingContext> identifier = IidFactory.l2BridgeDomainIid(tenantId, id);
-        Assert.assertEquals(id, InstanceIdentifier.keyOf(identifier).getContextId());
-        Assert.assertEquals(tenantId, identifier.firstKeyOf(ForwardingByTenant.class).getTenantId());
-    }
-
     @Test
     public void testL2BridgeDomainIid_tenantApi() {
         L2BridgeDomainId l2BridgeDomainId = mock(L2BridgeDomainId.class);
@@ -256,14 +235,6 @@ public class IidFactoryTest {
         Assert.assertEquals(tenantId, identifier.firstKeyOf(Tenant.class).getId());
     }
 
-    @Test
-    public void testL3ContextIid() {
-        ContextId id = mock(ContextId.class);
-        InstanceIdentifier<ForwardingContext> identifier = IidFactory.l3ContextIid(tenantId, id);
-        Assert.assertEquals(id, InstanceIdentifier.keyOf(identifier).getContextId());
-        Assert.assertEquals(tenantId, identifier.firstKeyOf(ForwardingByTenant.class).getTenantId());
-    }
-
     @Test
     public void testL3ContextIid_tenantApi() {
         L3ContextId l3ContextId = mock(L3ContextId.class);
@@ -272,6 +243,12 @@ public class IidFactoryTest {
         Assert.assertEquals(tenantId, identifier.firstKeyOf(Tenant.class).getId());
     }
 
+    @Test
+    public void testForwardingByTenantIid() {
+        InstanceIdentifier<ForwardingByTenant> forwardingByTenantIid = IidFactory.forwardingByTenantIid(tenantId);
+        Assert.assertEquals(tenantId, forwardingByTenantIid.firstKeyOf(ForwardingByTenant.class).getTenantId());
+    }
+
     @Test
     public void testEndpointIid() {
         L2BridgeDomainId l2Context = mock(L2BridgeDomainId.class);
@@ -315,14 +292,6 @@ public class IidFactoryTest {
         Assert.assertNotNull(identifier);
     }
 
-    @Test
-    public void testSubnetIid() {
-        NetworkDomainId id = mock(NetworkDomainId.class);
-        InstanceIdentifier<NetworkDomain> identifier = IidFactory.subnetIid(tenantId, id);
-        Assert.assertEquals(tenantId, identifier.firstKeyOf(ForwardingByTenant.class).getTenantId());
-        Assert.assertEquals(id, identifier.firstKeyOf(NetworkDomain.class).getNetworkDomainId());
-    }
-
     @Test
     public void testSubnetIid_tenantApi() {
         SubnetId subnetId = mock(SubnetId.class);
@@ -396,19 +365,16 @@ public class IidFactoryTest {
     }
 
     @Test
-    public void  testeExternalImplicitGroupIid(){
-        InstanceIdentifier<ExternalImplicitGroup>
-                identifier = IidFactory.externalImplicitGroupIid(tenantId, epgId);
+    public void testeExternalImplicitGroupIid() {
+        InstanceIdentifier<ExternalImplicitGroup> identifier = IidFactory.externalImplicitGroupIid(tenantId, epgId);
         Assert.assertEquals(epgId, identifier.firstKeyOf(ExternalImplicitGroup.class).getId());
     }
 
     @Test
     public void testProviderAddressEndpointLocationIid() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
-        InstanceIdentifier<ProviderAddressEndpointLocation> identifier = IidFactory
-            .providerAddressEndpointLocationIid(LOCATION_PROVIDER_NAME, IpPrefixType.class, IP_ADDRESS,
-                    org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                    l3Context);
+        InstanceIdentifier<ProviderAddressEndpointLocation> identifier = IidFactory.providerAddressEndpointLocationIid(
+                LOCATION_PROVIDER_NAME, AddressType.class, IP_ADDRESS, ContextType.class, l3Context);
         Assert.assertEquals(LOCATION_PROVIDER_NAME,
                 identifier.firstKeyOf(LocationProvider.class).getProvider().getValue());
         Assert.assertEquals(IP_ADDRESS, identifier.firstKeyOf(ProviderAddressEndpointLocation.class).getAddress());
@@ -418,15 +384,11 @@ public class IidFactoryTest {
     @Test
     public void testAddressEndpointIid() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
-        InstanceIdentifier<AddressEndpoint> identifier =
-                IidFactory.addressEndpointIid(new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, l3Context,
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class
-                        ));
-        Assert.assertEquals(IpPrefixType.class, identifier.firstKeyOf(AddressEndpoint.class).getAddressType());
+        InstanceIdentifier<AddressEndpoint> identifier = IidFactory.addressEndpointIid(
+                new AddressEndpointKey(IP_ADDRESS, AddressType.class, l3Context, ContextType.class));
+        Assert.assertEquals(AddressType.class, identifier.firstKeyOf(AddressEndpoint.class).getAddressType());
         Assert.assertEquals(IP_ADDRESS, identifier.firstKeyOf(AddressEndpoint.class).getAddress());
-        Assert.assertEquals(
-                org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                identifier.firstKeyOf(AddressEndpoint.class).getContextType());
+        Assert.assertEquals(ContextType.class, identifier.firstKeyOf(AddressEndpoint.class).getContextType());
         Assert.assertEquals(l3Context, identifier.firstKeyOf(AddressEndpoint.class).getContextId());
     }
 
@@ -434,14 +396,12 @@ public class IidFactoryTest {
     public void testAddressEndpointLocationIid() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
         AddressEndpointLocationKey addrEndpointLocationKey =
-                new AddressEndpointLocationKey(IP_ADDRESS, IpPrefixType.class, l3Context,
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class);
-        InstanceIdentifier<AddressEndpointLocation> iid = IidFactory.addressEndpointLocationIid(addrEndpointLocationKey);
-        Assert.assertEquals(IpPrefixType.class, iid.firstKeyOf(AddressEndpointLocation.class).getAddressType());
+                new AddressEndpointLocationKey(IP_ADDRESS, AddressType.class, l3Context, ContextType.class);
+        InstanceIdentifier<AddressEndpointLocation> iid =
+                IidFactory.addressEndpointLocationIid(addrEndpointLocationKey);
+        Assert.assertEquals(AddressType.class, iid.firstKeyOf(AddressEndpointLocation.class).getAddressType());
         Assert.assertEquals(IP_ADDRESS, iid.firstKeyOf(AddressEndpointLocation.class).getAddress());
-        Assert.assertEquals(
-                org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                iid.firstKeyOf(AddressEndpointLocation.class).getContextType());
+        Assert.assertEquals(ContextType.class, iid.firstKeyOf(AddressEndpointLocation.class).getContextType());
         Assert.assertEquals(l3Context, iid.firstKeyOf(AddressEndpointLocation.class).getContextId());
     }
 
@@ -449,12 +409,10 @@ public class IidFactoryTest {
     public void testContainmentEndpointLocationIid() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
         ContainmentEndpointLocationKey contEndpointLocationKey =
-                new ContainmentEndpointLocationKey(l3Context,
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class);
-        InstanceIdentifier<ContainmentEndpointLocation> iid = IidFactory.containmentEndpointLocationIid(contEndpointLocationKey);
-        Assert.assertEquals(
-                org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                iid.firstKeyOf(ContainmentEndpointLocation.class).getContextType());
+                new ContainmentEndpointLocationKey(l3Context, ContextType.class);
+        InstanceIdentifier<ContainmentEndpointLocation> iid =
+                IidFactory.containmentEndpointLocationIid(contEndpointLocationKey);
+        Assert.assertEquals(ContextType.class, iid.firstKeyOf(ContainmentEndpointLocation.class).getContextType());
         Assert.assertEquals(l3Context, iid.firstKeyOf(ContainmentEndpointLocation.class).getContextId());
     }
 
@@ -462,15 +420,13 @@ public class IidFactoryTest {
     public void internalLocationIid_AddrEndpoint() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
         AddressEndpointLocationKey addrEndpointLocationKey =
-                new AddressEndpointLocationKey(IP_ADDRESS, IpPrefixType.class, l3Context,
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class);
+                new AddressEndpointLocationKey(IP_ADDRESS, AddressType.class, l3Context, ContextType.class);
         InternalLocationKey internalLocationKey = new InternalLocationKey(nodeIid, connectorIid);
-        InstanceIdentifier<InternalLocation> iid = IidFactory.internalLocationIid(addrEndpointLocationKey, internalLocationKey);
-        Assert.assertEquals(IpPrefixType.class, iid.firstKeyOf(AddressEndpointLocation.class).getAddressType());
+        InstanceIdentifier<InternalLocation> iid =
+                IidFactory.internalLocationIid(addrEndpointLocationKey, internalLocationKey);
+        Assert.assertEquals(AddressType.class, iid.firstKeyOf(AddressEndpointLocation.class).getAddressType());
         Assert.assertEquals(IP_ADDRESS, iid.firstKeyOf(AddressEndpointLocation.class).getAddress());
-        Assert.assertEquals(
-                org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                iid.firstKeyOf(AddressEndpointLocation.class).getContextType());
+        Assert.assertEquals(ContextType.class, iid.firstKeyOf(AddressEndpointLocation.class).getContextType());
         Assert.assertEquals(l3Context, iid.firstKeyOf(AddressEndpointLocation.class).getContextId());
         Assert.assertEquals(nodeIid, iid.firstKeyOf(InternalLocation.class).getInternalNode());
         Assert.assertEquals(connectorIid, iid.firstKeyOf(InternalLocation.class).getInternalNodeConnector());
@@ -480,13 +436,11 @@ public class IidFactoryTest {
     public void internalLocationIid_ContEndpoint() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
         ContainmentEndpointLocationKey contEndpointLocationKey =
-                new ContainmentEndpointLocationKey(l3Context,
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class);
+                new ContainmentEndpointLocationKey(l3Context, ContextType.class);
         InternalLocationKey internalLocationKey = new InternalLocationKey(nodeIid, connectorIid);
-        InstanceIdentifier<InternalLocation> iid = IidFactory.internalLocationIid(contEndpointLocationKey, internalLocationKey);
-        Assert.assertEquals(
-                org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                iid.firstKeyOf(ContainmentEndpointLocation.class).getContextType());
+        InstanceIdentifier<InternalLocation> iid =
+                IidFactory.internalLocationIid(contEndpointLocationKey, internalLocationKey);
+        Assert.assertEquals(ContextType.class, iid.firstKeyOf(ContainmentEndpointLocation.class).getContextType());
         Assert.assertEquals(l3Context, iid.firstKeyOf(ContainmentEndpointLocation.class).getContextId());
         Assert.assertEquals(nodeIid, iid.firstKeyOf(InternalLocation.class).getInternalNode());
         Assert.assertEquals(connectorIid, iid.firstKeyOf(InternalLocation.class).getInternalNodeConnector());
@@ -496,15 +450,13 @@ public class IidFactoryTest {
     public void externalLocationIid_AddrEndpoint() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
         AddressEndpointLocationKey addrEndpointLocationKey =
-                new AddressEndpointLocationKey(IP_ADDRESS, IpPrefixType.class, l3Context,
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class);
+                new AddressEndpointLocationKey(IP_ADDRESS, AddressType.class, l3Context, ContextType.class);
         ExternalLocationKey externalLocationKey = new ExternalLocationKey(CONNECTOR, nodeIid);
-        InstanceIdentifier<ExternalLocation> iid = IidFactory.externalLocationIid(addrEndpointLocationKey, externalLocationKey);
-        Assert.assertEquals(IpPrefixType.class, iid.firstKeyOf(AddressEndpointLocation.class).getAddressType());
+        InstanceIdentifier<ExternalLocation> iid =
+                IidFactory.externalLocationIid(addrEndpointLocationKey, externalLocationKey);
+        Assert.assertEquals(AddressType.class, iid.firstKeyOf(AddressEndpointLocation.class).getAddressType());
         Assert.assertEquals(IP_ADDRESS, iid.firstKeyOf(AddressEndpointLocation.class).getAddress());
-        Assert.assertEquals(
-                org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                iid.firstKeyOf(AddressEndpointLocation.class).getContextType());
+        Assert.assertEquals(ContextType.class, iid.firstKeyOf(AddressEndpointLocation.class).getContextType());
         Assert.assertEquals(l3Context, iid.firstKeyOf(AddressEndpointLocation.class).getContextId());
         Assert.assertEquals(CONNECTOR, iid.firstKeyOf(ExternalLocation.class).getExternalNodeConnector());
         Assert.assertEquals(nodeIid, iid.firstKeyOf(ExternalLocation.class).getExternalNodeMountPoint());
@@ -514,13 +466,11 @@ public class IidFactoryTest {
     public void externalLocationIid_ContEndpoint() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
         ContainmentEndpointLocationKey addrEndpointLocationKey =
-                new ContainmentEndpointLocationKey(l3Context,
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class);
+                new ContainmentEndpointLocationKey(l3Context, ContextType.class);
         ExternalLocationKey externalLocationKey = new ExternalLocationKey(CONNECTOR, nodeIid);
-        InstanceIdentifier<ExternalLocation> iid = IidFactory.externalLocationIid(addrEndpointLocationKey, externalLocationKey);
-        Assert.assertEquals(
-                org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                iid.firstKeyOf(ContainmentEndpointLocation.class).getContextType());
+        InstanceIdentifier<ExternalLocation> iid =
+                IidFactory.externalLocationIid(addrEndpointLocationKey, externalLocationKey);
+        Assert.assertEquals(ContextType.class, iid.firstKeyOf(ContainmentEndpointLocation.class).getContextType());
         Assert.assertEquals(l3Context, iid.firstKeyOf(ContainmentEndpointLocation.class).getContextId());
         Assert.assertEquals(CONNECTOR, iid.firstKeyOf(ExternalLocation.class).getExternalNodeConnector());
         Assert.assertEquals(nodeIid, iid.firstKeyOf(ExternalLocation.class).getExternalNodeMountPoint());
@@ -530,14 +480,11 @@ public class IidFactoryTest {
     public void absoluteLocationIid() {
         ContextId l3Context = new ContextId(L3_CONTEXT_ID);
         AddressEndpointLocationKey addrEndpointLocationKey =
-                new AddressEndpointLocationKey(IP_ADDRESS, IpPrefixType.class, l3Context,
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class);
+                new AddressEndpointLocationKey(IP_ADDRESS, AddressType.class, l3Context, ContextType.class);
         InstanceIdentifier<AbsoluteLocation> iid = IidFactory.absoluteLocationIid(addrEndpointLocationKey);
-        Assert.assertEquals(IpPrefixType.class, iid.firstKeyOf(AddressEndpointLocation.class).getAddressType());
+        Assert.assertEquals(AddressType.class, iid.firstKeyOf(AddressEndpointLocation.class).getAddressType());
         Assert.assertEquals(IP_ADDRESS, iid.firstKeyOf(AddressEndpointLocation.class).getAddress());
-        Assert.assertEquals(
-                org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
-                iid.firstKeyOf(AddressEndpointLocation.class).getContextType());
+        Assert.assertEquals(ContextType.class, iid.firstKeyOf(AddressEndpointLocation.class).getContextType());
         Assert.assertEquals(l3Context, iid.firstKeyOf(AddressEndpointLocation.class).getContextId());
     }
 }
index befc7a10cb487ab146b757efce741ab8177e4075..7465e0724502f35b9889dfefbc79d37017878f0f 100644 (file)
   <packaging>bundle</packaging>
 
   <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>l2-l3-domain-extension</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <!-- testing dependencies -->
     <dependency>
       <groupId>junit</groupId>
index e20046df8dca04e571fe7e3858c088fecc3719dd..29583bf1779af387a3ab6cbdd3d820cfd4aeff17 100644 (file)
@@ -22,13 +22,14 @@ 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.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.groupbasedpolicy.util.NetUtils;
 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.endpoints.address.endpoints.AddressEndpoint;
 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.InternalLocationCaseBuilder;
+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.endpoint.network.elements.rev160407.NetworkElements;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElementsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.NetworkElement;
@@ -73,11 +74,12 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
     }
 
     public synchronized void onEndpointsChange(Collection<DataTreeModification<AddressEndpoint>> changes) {
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
         for (DataTreeModification<AddressEndpoint> change : changes) {
             switch (change.getRootNode().getModificationType()) {
                 case DELETE: {
                     AddressEndpoint endpoint = change.getRootNode().getDataBefore();
-                    removeLocationForEndpoint(endpoint);
+                    removeLocationForEndpoint(endpoint, wtx);
                     this.endpoints.remove(endpoint);
                     break;
                 }
@@ -89,7 +91,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                         break;
                     }
                     endpoint = change.getRootNode().getDataAfter();
-                    createLocationForEndpoint(endpoint);
+                    createLocationForEndpoint(endpoint, wtx);
                     this.endpoints.add(endpoint);
                     break;
                 }
@@ -100,9 +102,10 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 }
             }
         }
+        DataStoreHelper.submitToDs(wtx);
     }
 
-    private void createLocationForEndpoint(AddressEndpoint endpoint) {
+    private void createLocationForEndpoint(AddressEndpoint endpoint, WriteTransaction wtx) {
         for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
             for (Interface iface : nullToEmpty(ne.getInterface())) {
                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
@@ -110,14 +113,12 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                             && endpoint.getContextId().equals(en.getL3ContextId())
                             && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
                                 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
-                        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
                         InstanceIdentifier<AbsoluteLocation> iid = IidFactory
                             .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
                                     endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
                             .child(AbsoluteLocation.class);
-                        wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(ne.getIid(), iface.getIid()),
+                        wtx.put(LogicalDatastoreType.CONFIGURATION, iid, createRealLocation(ne.getIid(), iface.getIid()),
                                 true);
-                        wtx.submit();
                         LOG.debug("New location created for endpoint {}", endpoint);
                         return;
                     }
@@ -126,7 +127,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
         }
     }
 
-    private void removeLocationForEndpoint(AddressEndpoint endpoint) {
+    private void removeLocationForEndpoint(AddressEndpoint endpoint, WriteTransaction wtx) {
         for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
             for (Interface iface : nullToEmpty(ne.getInterface())) {
                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
@@ -134,13 +135,11 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                             && endpoint.getContextId().equals(en.getL3ContextId())
                             && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
                                 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
-                        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
                         InstanceIdentifier<AbsoluteLocation> iid = IidFactory
                             .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
                                     endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
                             .child(AbsoluteLocation.class);
-                        wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
-                        wtx.submit();
+                        wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
                         LOG.debug("Location deleted for endpoint {}", endpoint);
                         return;
                     }
@@ -151,6 +150,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
 
     @Override
     public synchronized void onDataTreeChanged(Collection<DataTreeModification<NetworkElements>> changes) {
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
         for (DataTreeModification<NetworkElements> change : changes) {
             switch (change.getRootNode().getModificationType()) {
                 case DELETE: {
@@ -158,7 +158,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                     for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
                         for (Interface iface : nullToEmpty(ne.getInterface())) {
                             for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                                processDeletedEN(en);
+                                processDeletedEN(en, wtx);
                             }
                         }
                     }
@@ -172,7 +172,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                         for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
                             for (Interface iface : nullToEmpty(ne.getInterface())) {
                                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                                    processDeletedEN(en);
+                                    processDeletedEN(en, wtx);
                                 }
                             }
                         }
@@ -181,7 +181,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                     for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
                         for (Interface iface : nullToEmpty(ne.getInterface())) {
                             for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                                processCreatedEN(en, ne.getIid(), iface.getIid());
+                                processCreatedEN(en, ne.getIid(), iface.getIid(), wtx);
                             }
                         }
                     }
@@ -193,12 +193,13 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                     List<DataObjectModification<NetworkElement>> modifiedNetworkElements =
                             getModifiedNetworkElements(change.getRootNode());
                     for (DataObjectModification<NetworkElement> netElement : modifiedNetworkElements) {
-                        processNetworkElementChange(netElement);
+                        processNetworkElementChange(netElement, wtx);
                     }
                     break;
                 }
             }
         }
+        DataStoreHelper.submitToDs(wtx);
     }
 
     private List<DataObjectModification<NetworkElement>> getModifiedNetworkElements(
@@ -217,13 +218,13 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
         return nes;
     }
 
-    private void processNetworkElementChange(DataObjectModification<NetworkElement> netElement) {
+    private void processNetworkElementChange(DataObjectModification<NetworkElement> netElement, WriteTransaction wtx) {
         switch (netElement.getModificationType()) {
             case DELETE: {
                 NetworkElement ne = netElement.getDataBefore();
                 for (Interface iface : nullToEmpty(ne.getInterface())) {
                     for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                        processDeletedEN(en);
+                        processDeletedEN(en, wtx);
                     }
                 }
                 networkElements.getNetworkElement().remove(ne);
@@ -235,7 +236,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 if (ne != null) {
                     for (Interface iface : nullToEmpty(ne.getInterface())) {
                         for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                            processDeletedEN(en);
+                            processDeletedEN(en, wtx);
                         }
                     }
                     networkElements.getNetworkElement().remove(ne);
@@ -243,7 +244,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 ne = netElement.getDataAfter();
                 for (Interface iface : nullToEmpty(ne.getInterface())) {
                     for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                        processCreatedEN(en, ne.getIid(), iface.getIid());
+                        processCreatedEN(en, ne.getIid(), iface.getIid(), wtx);
                     }
                 }
                 networkElements.getNetworkElement().add(ne);
@@ -253,7 +254,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
             case SUBTREE_MODIFIED: {
                 List<DataObjectModification<Interface>> modifiedInterfaces = getModifiedInterfaces(netElement);
                 for (DataObjectModification<Interface> modifiedInterface : modifiedInterfaces) {
-                    processInterfaceChange(modifiedInterface, netElement.getDataBefore());
+                    processInterfaceChange(modifiedInterface, netElement.getDataBefore(), wtx);
                 }
                 break;
             }
@@ -277,12 +278,12 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
     }
 
     private void processInterfaceChange(DataObjectModification<Interface> modifiedInterface,
-            NetworkElement nodeBefore) {
+            NetworkElement nodeBefore, WriteTransaction wtx) {
         switch (modifiedInterface.getModificationType()) {
             case DELETE: {
                 Interface iface = modifiedInterface.getDataBefore();
                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                    processDeletedEN(en);
+                    processDeletedEN(en, wtx);
                 }
                 int nodeIndex = getIndexOf(nodeBefore);
                 networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
@@ -294,13 +295,13 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 int nodeIndex = getIndexOf(nodeBefore);
                 if (iface != null) {
                     for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                        processDeletedEN(en);
+                        processDeletedEN(en, wtx);
                     }
                     networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
                 }
                 iface = modifiedInterface.getDataAfter();
                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                    processCreatedEN(en, nodeBefore.getIid(), iface.getIid());
+                    processCreatedEN(en, nodeBefore.getIid(), iface.getIid(), wtx);
                 }
                 networkElements.getNetworkElement().get(nodeIndex).getInterface().add(iface);
                 LOG.debug("Created new Interface {}", modifiedInterface.getDataAfter());
@@ -310,7 +311,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 List<DataObjectModification<EndpointNetwork>> modifiedENs =
                         getModifiedEndpointNetworks(modifiedInterface);
                 for (DataObjectModification<EndpointNetwork> modifiedEN : modifiedENs) {
-                    processEndpointNetworkChange(modifiedEN, nodeBefore, modifiedInterface.getDataBefore());
+                    processEndpointNetworkChange(modifiedEN, nodeBefore, modifiedInterface.getDataBefore(), wtx);
                 }
                 break;
             }
@@ -334,10 +335,10 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
     }
 
     private void processEndpointNetworkChange(DataObjectModification<EndpointNetwork> modifiedEN,
-            NetworkElement nodeBefore, Interface ifaceBefore) {
+            NetworkElement nodeBefore, Interface ifaceBefore, WriteTransaction wtx) {
         switch (modifiedEN.getModificationType()) {
             case DELETE: {
-                processDeletedEN(modifiedEN.getDataBefore());
+                processDeletedEN(modifiedEN.getDataBefore(), wtx);
                 int nodeIndex = getIndexOf(nodeBefore);
                 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
                 networkElements.getNetworkElement()
@@ -350,7 +351,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 break;
             }
             case WRITE: {
-                processCreatedEN(modifiedEN.getDataAfter(), nodeBefore.getIid(), ifaceBefore.getIid());
+                processCreatedEN(modifiedEN.getDataAfter(), nodeBefore.getIid(), ifaceBefore.getIid(), wtx);
                 int nodeIndex = getIndexOf(nodeBefore);
                 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
                 networkElements.getNetworkElement()
@@ -370,8 +371,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
     }
 
     private void processCreatedEN(EndpointNetwork en, InstanceIdentifier<?> nodeIID,
-            InstanceIdentifier<?> connectorIID) {
-        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+            InstanceIdentifier<?> connectorIID, WriteTransaction wtx) {
         for (AddressEndpoint endpoint : endpoints) {
             if (endpoint.getContextType().isAssignableFrom(L3Context.class)
                     && endpoint.getContextId().equals(en.getL3ContextId())
@@ -381,16 +381,14 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                     .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
                             endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
                     .child(AbsoluteLocation.class);
-                wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(nodeIID, connectorIID), true);
-                wtx.submit();
+                wtx.put(LogicalDatastoreType.CONFIGURATION, iid, createRealLocation(nodeIID, connectorIID), true);
                 LOG.debug("New location created for endpoint {}", endpoint);
                 return;
             }
         }
     }
 
-    private void processDeletedEN(EndpointNetwork en) {
-        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+    private void processDeletedEN(EndpointNetwork en, WriteTransaction wtx) {
         for (AddressEndpoint endpoint : endpoints) {
             if (endpoint.getContextType().isAssignableFrom(L3Context.class)
                     && endpoint.getContextId().equals(en.getL3ContextId())
@@ -400,8 +398,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                     .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
                             endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
                     .child(AbsoluteLocation.class);
-                wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
-                wtx.submit();
+                wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
                 LOG.debug("Location deleted for endpoint {}", endpoint);
                 return;
             }
@@ -410,7 +407,8 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
 
     private AbsoluteLocation createRealLocation(InstanceIdentifier<?> node, InstanceIdentifier<?> iface) {
         return new AbsoluteLocationBuilder()
-            .setLocationType(new InternalLocationCaseBuilder().setInternalNode(node).setInternalNodeConnector(iface).build()).build();
+            .setLocationType(new ExternalLocationCaseBuilder().setExternalNodeMountPoint(node)
+                    .setExternalNodeConnector(iface.toString()).build()).build();
     }
 
     private <T> List<T> nullToEmpty(@Nullable List<T> list) {
index 8f61ea2bf088f7f56baf6dfd95aca6927051179c..08c0053d7cce17d6d4a7623733175f53f51d92fe 100644 (file)
@@ -35,7 +35,6 @@ import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
 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.NetworkContainmentBuilder;
@@ -44,6 +43,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo
 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.address.endpoints.AddressEndpointKey;
+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.ContextId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElements;
@@ -57,6 +58,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.n
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetwork;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetworkBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetworkKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProvidersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.ProviderName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProviderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationBuilder;
 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.L3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
@@ -80,8 +86,8 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
     private DataBroker dataBroker;
     private NeLocationProvider neProvider;
     private String L3_CONTEXT_ID = "l3Context";
-    private String IPv4_HOST_ADDRESS_1 = "192.168.50.71";
-    private String IPv4_HOST_ADDRESS_2 = "192.168.50.72";
+    private String IPv4_HOST_ADDRESS_1 = "192.168.50.71/24";
+    private String IPv4_HOST_ADDRESS_2 = "192.168.50.72/24";
     private String IPv4_NETWORK_ADDRESS_1 = "192.168.50.0/24";
     private String IPv4_NETWORK_ADDRESS_2 = "192.168.51.0/24";
     private String NODE_ID_1 = "node1";
@@ -91,7 +97,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Override
     public Collection<Class<?>> getClassesFromModules() {
-        return ImmutableList.<Class<?>>of(NetworkElements.class, EndpointLocations.class, Endpoints.class, L3Context.class, Nodes.class);
+        return ImmutableList.<Class<?>>of(NetworkElements.class, LocationProviders.class, Endpoints.class, L3Context.class, Nodes.class);
     }
 
     @Before
@@ -135,8 +141,23 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_AddressEndpointWrite_NoNE_NoOverwrite() throws Exception {
-        AddressEndpoint endpoint =
-                createAddressEndpoint(IPv4_HOST_ADDRESS_1, IpPrefixType.class, L3_CONTEXT_ID, L3Context.class);
+        AddressEndpoint endpoint = writeBaseAddrEndpoint();
+        List<AddressEndpoint> endpoints = neProvider.getEndpoints();
+        assertEquals(1, endpoints.size());
+        assertEquals(endpoint, endpoints.get(0));
+        verifyEmptyLocations();
+    }
+
+    @Test
+    public void test_AddressEndpointWrite_NoNE_Overwrite() throws Exception {
+        writeBaseAddrEndpoint();
+        NetworkContainment nc = new NetworkContainmentBuilder()
+                .setContainment(new NetworkDomainContainmentBuilder().setNetworkDomainId(new NetworkDomainId(L3_CONTEXT_ID)).build())
+                        .build();
+        AddressEndpoint endpoint = new AddressEndpointBuilder().setKey(
+                new AddressEndpointKey(IPv4_HOST_ADDRESS_1, IpPrefixType.class, new ContextId(L3_CONTEXT_ID), L3Context.class))
+                .setNetworkContainment(nc)
+                .build();
         InstanceIdentifier<AddressEndpoint> iid = IidFactory.addressEndpointIid(endpoint.getKey());
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
         wtx.put(LogicalDatastoreType.OPERATIONAL, iid, endpoint, true);
@@ -148,8 +169,8 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
     }
 
     @Test
-    public void test_AddressEndpointWrite_NoNE_Overwrite() throws Exception {
-        test_AddressEndpointWrite_NoNE_NoOverwrite();
+    public void test_AddressEndpointModified_NoNE() throws Exception {
+        writeBaseAddrEndpoint();
         NetworkContainment nc = new NetworkContainmentBuilder()
         .setContainment(new NetworkDomainContainmentBuilder().setNetworkDomainId(new NetworkDomainId(L3_CONTEXT_ID)).build())
                 .build();
@@ -172,7 +193,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_EndpointsDelete_NoNE() throws Exception {
-        test_AddressEndpointWrite_NoNE_NoOverwrite();
+        writeBaseAddrEndpoint();
         InstanceIdentifier<Endpoints> iid = InstanceIdentifier.builder(Endpoints.class)
                 .build();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
@@ -185,7 +206,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_EndpointsModify_NoNE() throws Exception {
-        test_AddressEndpointWrite_NoNE_NoOverwrite();
+        writeBaseAddrEndpoint();
         InstanceIdentifier<Endpoints> iid = InstanceIdentifier.builder(Endpoints.class)
                 .build();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
@@ -198,11 +219,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_NetworkElementsWrite_NoEP_NoOverwrite() throws Exception {
-        NetworkElements nes = createNetworkElements(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_1);
-        InstanceIdentifier<NetworkElements> iid = InstanceIdentifier.builder(NetworkElements.class).build();
-        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
-        wtx.put(LogicalDatastoreType.CONFIGURATION, iid, nes);
-        wtx.submit().get();
+        NetworkElements nes = writeBaseNetworkElements();
         NetworkElements networkElements = neProvider.getNetworkElements();
         assertEquals(nes, networkElements);
         verifyEmptyLocations();
@@ -210,7 +227,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_NetworkElementsWrite_NoEP_Overwrite() throws Exception {
-        test_NetworkElementsWrite_NoEP_NoOverwrite();
+        writeBaseNetworkElements();
         NetworkElements nes = createNetworkElements(NODE_ID_2, CONNECTOR_ID_2, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_1);
         InstanceIdentifier<NetworkElements> iid = InstanceIdentifier.builder(NetworkElements.class).build();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
@@ -223,7 +240,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_NetworkElementWrite_NoEP_Overwrite() throws Exception {
-        test_NetworkElementsWrite_NoEP_NoOverwrite();
+        writeBaseNetworkElements();
         NetworkElement ne = createNetworkElement(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_2);
         InstanceIdentifier<NetworkElement> iid = InstanceIdentifier.builder(NetworkElements.class)
             .child(NetworkElement.class, new NetworkElementKey(ne.getKey()))
@@ -240,7 +257,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_InterfaceWrite_NoEP_Overwrite() throws Exception {
-        test_NetworkElementsWrite_NoEP_NoOverwrite();
+        writeBaseNetworkElements();
         Interface iface = createInterface(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_2);
         InstanceIdentifier<Interface> iid = InstanceIdentifier.builder(NetworkElements.class)
             .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
@@ -260,7 +277,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_EndpointNetworkChange_NoEP() throws Exception {
-        test_NetworkElementsWrite_NoEP_NoOverwrite();
+        writeBaseNetworkElements();
         EndpointNetwork en = createEndpointNetwork(L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_2);
         InstanceIdentifier<EndpointNetwork> iid = InstanceIdentifier.builder(NetworkElements.class)
             .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
@@ -291,7 +308,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_NetworkElementsDelete() throws Exception {
-        test_NetworkElementsWrite_NoEP_NoOverwrite();
+        writeBaseNetworkElements();
         InstanceIdentifier<NetworkElements> iid = InstanceIdentifier.builder(NetworkElements.class).build();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
         wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
@@ -303,7 +320,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_NetworkElementDelete() throws Exception {
-        test_NetworkElementsWrite_NoEP_NoOverwrite();
+        writeBaseNetworkElements();
         InstanceIdentifier<NetworkElement> iid = InstanceIdentifier.builder(NetworkElements.class)
             .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
             .build();
@@ -318,7 +335,7 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     @Test
     public void test_InterfaceDelete() throws Exception {
-        test_NetworkElementsWrite_NoEP_NoOverwrite();
+        writeBaseNetworkElements();
         InstanceIdentifier<Interface> iid = InstanceIdentifier.builder(NetworkElements.class)
             .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
             .child(Interface.class, new InterfaceKey(createInterfaceIid(NODE_ID_1, CONNECTOR_ID_1)))
@@ -334,6 +351,158 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
         verifyEmptyLocations();
     }
 
+    @Test
+    public void test_CreateLocationForAddrEndpoint_EndpointWriteFirst() throws Exception {
+        AddressEndpoint endpoint =
+                createAddressEndpoint(IPv4_HOST_ADDRESS_1, IpPrefixType.class, L3_CONTEXT_ID, L3Context.class);
+        InstanceIdentifier<AddressEndpoint> iid = IidFactory.addressEndpointIid(endpoint.getKey());
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        wtx.put(LogicalDatastoreType.OPERATIONAL, iid, endpoint, true);
+        wtx.submit().get();
+
+        NetworkElements nes = createNetworkElements(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_1);
+        InstanceIdentifier<NetworkElements> neIid = InstanceIdentifier.builder(NetworkElements.class).build();
+        wtx = dataBroker.newWriteOnlyTransaction();
+        wtx.put(LogicalDatastoreType.CONFIGURATION, neIid, nes);
+        wtx.submit().get();
+
+        ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
+        InstanceIdentifier<LocationProviders> locationIid = InstanceIdentifier.builder(LocationProviders.class).build();
+        CheckedFuture<Optional<LocationProviders>, ReadFailedException> read =
+                rtx.read(LogicalDatastoreType.CONFIGURATION, locationIid);
+        assertTrue(read.get().isPresent());
+        rtx.close();
+        LocationProviders locations = read.get().get();
+        LocationProviders locationReference =
+                new LocationProvidersBuilder()
+                    .setLocationProvider(Collections.singletonList(new LocationProviderBuilder()
+                            .setProvider(new ProviderName(NeLocationProvider.NE_LOCATION_PROVIDER_NAME))
+                            .setProviderAddressEndpointLocation(Collections.singletonList(
+                                    new ProviderAddressEndpointLocationBuilder()
+                                    .setAddress(IPv4_HOST_ADDRESS_1)
+                                    .setAddressType(IpPrefixType.class)
+                                    .setContextId(new ContextId(L3_CONTEXT_ID))
+                                    .setContextType(L3Context.class)
+                                    .setAbsoluteLocation(new AbsoluteLocationBuilder()
+                                            .setLocationType(new ExternalLocationCaseBuilder()
+                                                    .setExternalNodeMountPoint(createNetworkElementIid(NODE_ID_1))
+                                                    .setExternalNodeConnector(createInterfaceIid(
+                                                            NODE_ID_1, CONNECTOR_ID_1).toString())
+                                                    .build())
+                                            .build())
+                                    .build()))
+                            .build()))
+                    .build();
+        assertEquals(locationReference, locations);
+    }
+
+    @Test
+    public void test_CreateLocationForAddrEndpoint_NEWriteFirst() throws Exception {
+        NetworkElements nes = createNetworkElements(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_1);
+        InstanceIdentifier<NetworkElements> neIid = InstanceIdentifier.builder(NetworkElements.class).build();
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        wtx.put(LogicalDatastoreType.CONFIGURATION, neIid, nes);
+
+        AddressEndpoint endpoint =
+                createAddressEndpoint(IPv4_HOST_ADDRESS_1, IpPrefixType.class, L3_CONTEXT_ID, L3Context.class);
+        InstanceIdentifier<AddressEndpoint> iid = IidFactory.addressEndpointIid(endpoint.getKey());
+        wtx.put(LogicalDatastoreType.OPERATIONAL, iid, endpoint, true);
+        wtx.submit().get();
+
+        ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
+        InstanceIdentifier<LocationProviders> locationIid = InstanceIdentifier.builder(LocationProviders.class).build();
+        CheckedFuture<Optional<LocationProviders>, ReadFailedException> read =
+                rtx.read(LogicalDatastoreType.CONFIGURATION, locationIid);
+        assertTrue(read.get().isPresent());
+        rtx.close();
+        LocationProviders locations = read.get().get();
+        LocationProviders locationReference =
+                new LocationProvidersBuilder()
+                    .setLocationProvider(Collections.singletonList(new LocationProviderBuilder()
+                            .setProvider(new ProviderName(NeLocationProvider.NE_LOCATION_PROVIDER_NAME))
+                            .setProviderAddressEndpointLocation(Collections.singletonList(
+                                    new ProviderAddressEndpointLocationBuilder()
+                                    .setAddress(IPv4_HOST_ADDRESS_1)
+                                    .setAddressType(IpPrefixType.class)
+                                    .setContextId(new ContextId(L3_CONTEXT_ID))
+                                    .setContextType(L3Context.class)
+                                    .setAbsoluteLocation(new AbsoluteLocationBuilder()
+                                            .setLocationType(new ExternalLocationCaseBuilder()
+                                                    .setExternalNodeMountPoint(createNetworkElementIid(NODE_ID_1))
+                                                    .setExternalNodeConnector(createInterfaceIid(
+                                                            NODE_ID_1, CONNECTOR_ID_1).toString())
+                                                    .build())
+                                            .build())
+                                    .build()))
+                            .build()))
+                    .build();
+        assertEquals(locationReference, locations);
+    }
+
+    @Test
+    public void test_CreateLocationForAddrEndpoint_SimultaneousWrite() throws Exception {
+        NetworkElements nes = createNetworkElements(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_1);
+        InstanceIdentifier<NetworkElements> neIid = InstanceIdentifier.builder(NetworkElements.class).build();
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        wtx.put(LogicalDatastoreType.CONFIGURATION, neIid, nes);
+        wtx.submit().get();
+
+        AddressEndpoint endpoint =
+                createAddressEndpoint(IPv4_HOST_ADDRESS_1, IpPrefixType.class, L3_CONTEXT_ID, L3Context.class);
+        InstanceIdentifier<AddressEndpoint> iid = IidFactory.addressEndpointIid(endpoint.getKey());
+        wtx = dataBroker.newWriteOnlyTransaction();
+        wtx.put(LogicalDatastoreType.OPERATIONAL, iid, endpoint, true);
+        wtx.submit().get();
+
+        ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
+        InstanceIdentifier<LocationProviders> locationIid = InstanceIdentifier.builder(LocationProviders.class).build();
+        CheckedFuture<Optional<LocationProviders>, ReadFailedException> read =
+                rtx.read(LogicalDatastoreType.CONFIGURATION, locationIid);
+        assertTrue(read.get().isPresent());
+        rtx.close();
+        LocationProviders locations = read.get().get();
+        LocationProviders locationReference =
+                new LocationProvidersBuilder()
+                    .setLocationProvider(Collections.singletonList(new LocationProviderBuilder()
+                            .setProvider(new ProviderName(NeLocationProvider.NE_LOCATION_PROVIDER_NAME))
+                            .setProviderAddressEndpointLocation(Collections.singletonList(
+                                    new ProviderAddressEndpointLocationBuilder()
+                                    .setAddress(IPv4_HOST_ADDRESS_1)
+                                    .setAddressType(IpPrefixType.class)
+                                    .setContextId(new ContextId(L3_CONTEXT_ID))
+                                    .setContextType(L3Context.class)
+                                    .setAbsoluteLocation(new AbsoluteLocationBuilder()
+                                            .setLocationType(new ExternalLocationCaseBuilder()
+                                                    .setExternalNodeMountPoint(createNetworkElementIid(NODE_ID_1))
+                                                    .setExternalNodeConnector(createInterfaceIid(
+                                                            NODE_ID_1, CONNECTOR_ID_1).toString())
+                                                    .build())
+                                            .build())
+                                    .build()))
+                            .build()))
+                    .build();
+        assertEquals(locationReference, locations);
+    }
+
+    private AddressEndpoint writeBaseAddrEndpoint () throws Exception {
+        AddressEndpoint endpoint =
+                createAddressEndpoint(IPv4_HOST_ADDRESS_1, IpPrefixType.class, L3_CONTEXT_ID, L3Context.class);
+        InstanceIdentifier<AddressEndpoint> iid = IidFactory.addressEndpointIid(endpoint.getKey());
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        wtx.put(LogicalDatastoreType.OPERATIONAL, iid, endpoint, true);
+        wtx.submit().get();
+        return endpoint;
+    }
+
+    private NetworkElements writeBaseNetworkElements () throws Exception {
+        NetworkElements nes = createNetworkElements(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_1);
+        InstanceIdentifier<NetworkElements> iid = InstanceIdentifier.builder(NetworkElements.class).build();
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        wtx.put(LogicalDatastoreType.CONFIGURATION, iid, nes);
+        wtx.submit().get();
+        return nes;
+    }
+
     private AddressEndpoint createAddressEndpoint(String ipAddr, Class<? extends AddressType> addrType,
             String context, Class<? extends ContextType> cType) {
         return new AddressEndpointBuilder().setAddress(ipAddr).setAddressType(addrType)
@@ -376,8 +545,8 @@ public class NeLocationProviderTest extends CustomDataBrokerTest {
 
     private void verifyEmptyLocations() throws Exception {
         ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
-        InstanceIdentifier<EndpointLocations> locationIid = InstanceIdentifier.builder(EndpointLocations.class).build();
-        CheckedFuture<Optional<EndpointLocations>, ReadFailedException> read =
+        InstanceIdentifier<LocationProviders> locationIid = InstanceIdentifier.builder(LocationProviders.class).build();
+        CheckedFuture<Optional<LocationProviders>, ReadFailedException> read =
                 rtx.read(LogicalDatastoreType.OPERATIONAL, locationIid);
         assertFalse(read.get().isPresent());
         rtx.close();
index a0d0e82730a65df208fd22d3db45832c78bc473c..4b3b291ddbcca314a59dcfc97adae71d85b33471 100644 (file)
@@ -28,8 +28,9 @@
     <!-- project specific dependencies -->
     <dependency>
       <groupId>${project.groupId}</groupId>
-      <artifactId>groupbasedpolicy</artifactId>
+      <artifactId>l2-l3-domain-extension</artifactId>
       <version>${project.version}</version>
+      <type>bundle</type>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.neutron</groupId>
       <groupId>org.opendaylight.mdsal.model</groupId>
       <artifactId>ietf-yang-types-20130715</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>opendaylight-l2-types</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-topology</artifactId>
+    </dependency>
   </dependencies>
 
  <build>
index bfa6523e33a787bc515b3bd209f4a81de05f6145..3309e03e65bfe23516c642a9dedb2212ae84eb8d 100644 (file)
@@ -69,22 +69,22 @@ 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("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
+        .setId(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("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
+        .setId(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("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
+        .setId(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("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
+        .setId(new Uuid("17517202-2408-11e6-b67b-9e71128cae77"))
         .setDirection(DirectionEgress.class)
         .setEthertype(EthertypeV6.class)
         .setSecurityGroupId(MappingUtils.EIG_UUID);
index 045e9624c648d1982d9cf19eac0468c703482823..8c42a7454f0d4ab0dfadea217bba9589d6cc8897 100644 (file)
@@ -16,6 +16,7 @@ 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.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService;
@@ -93,9 +94,9 @@ public class NeutronNetworkAware implements NeutronAware<Network> {
                 MappingUtils.createParent(ctxId, MappingUtils.L2_BRDIGE_DOMAIN));
         ForwardingContext l2Fd = fwdCtxBuilder.build();
 
-        rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, ctxId), l3Context, true);
-        rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, ctxId), l2Bd, true);
-        rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2FloodDomainIid(tenantId, ctxId), l2Fd, true);
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l3ContextIid(tenantId, ctxId), l3Context, true);
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, ctxId), l2Bd, true);
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2FloodDomainIid(tenantId, ctxId), l2Fd, true);
 
         createTenantNetworkDomains(network, tenantId, rwTx);
 
@@ -185,19 +186,19 @@ public class NeutronNetworkAware implements NeutronAware<Network> {
         TenantId tenantId = new TenantId(network.getTenantId().getValue());
         ContextId id = new ContextId(network.getUuid().getValue());
         Optional<ForwardingContext> potentialL2Fd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.l2FloodDomainIid(tenantId, id), rwTx);
+                L2L3IidFactory.l2FloodDomainIid(tenantId, id), rwTx);
         if (!potentialL2Fd.isPresent()) {
             LOG.warn("Illegal state - l2-flood-domain {} does not exist.", id.getValue());
             return;
         }
         Optional<ForwardingContext> potentialL2Bd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.l2BridgeDomainIid(tenantId, id), rwTx);
+                L2L3IidFactory.l2BridgeDomainIid(tenantId, id), rwTx);
         if (!potentialL2Bd.isPresent()) {
             LOG.warn("Illegal state - l2-bridge-domain {} does not exist.", id.getValue());
             return;
         }
         Optional<ForwardingContext> potentialL3Ctx = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.l3ContextIid(tenantId, id), rwTx);
+                L2L3IidFactory.l3ContextIid(tenantId, id), rwTx);
         if (!potentialL3Ctx.isPresent()) {
             LOG.warn("Illegal state - l3-context {} does not exist.", id.getValue());
             return;
index f7a891d9320dcf3b193289eba7ebf8d5998a612a..7bd5b1c188da01723a24ddf35ff5e13e61c28459 100644 (file)
@@ -18,6 +18,7 @@ import javax.annotation.Nullable;
 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.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
@@ -128,11 +129,11 @@ public class NeutronPortAware implements NeutronAware<Port> {
                 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
                 .setParent(MappingUtils.createParent(routerL3Context, MappingUtils.L3_CONTEXT))
                 .build();
-            rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd);
+            rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
             // set virtual router IP for subnet
             NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(
                     routerPortSubnet, portIpWithSubnet.getIpAddress());
-            rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
+            rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
 
             // does the same for tenant forwarding domains
             processTenantForwarding(routerPortSubnet, routerL3Context, portIpWithSubnet, tenantId, rwTx);
@@ -164,7 +165,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
 
             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
             registerBaseEndpointAndStoreMapping(
-                    ImmutableList.<AddressEndpointReg>of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx);
+                    ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx);
             registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
             DataStoreHelper.submitToDs(rwTx);
         } else if (PortUtils.isNormalPort(port)) {
@@ -221,7 +222,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
             TenantId tenantId, ReadWriteTransaction rwTx) {
         L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
         L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(new L3ContextId(routerL3Context)).build();
-        rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd);
+        rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
         // set virtual router IP for subnet
         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet subnet = NeutronSubnetAware.createTenantSubnet(
                 routerPortSubnet, portIpWithSubnet.getIpAddress());
@@ -526,9 +527,9 @@ public class NeutronPortAware implements NeutronAware<Port> {
                 .setParent(MappingUtils.createParent(l3Context, MappingUtils.L3_CONTEXT))
                 .build();
             rwTx.merge(LogicalDatastoreType.CONFIGURATION,
-                    IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx);
+                    L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx);
             NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, null);
-            rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()),
+            rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()),
                     subnet);
             DataStoreHelper.submitToDs(rwTx);
         } else if (PortUtils.isDhcpPort(port)) {
index 0b0199d9ecd6ea375df98216f309718c020a580f..96d95bcdc1b88d9c070a485e15003081a360e09e 100644 (file)
@@ -18,6 +18,7 @@ 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.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
@@ -88,7 +89,7 @@ public class NeutronRouterAware implements NeutronAware<Router> {
 
         ContextId routerl3ContextId = new ContextId(router.getUuid().getValue());
         TenantId tenantId = new TenantId(router.getTenantId().getValue());
-        InstanceIdentifier<ForwardingContext> routerL3CtxIid = IidFactory.l3ContextIid(tenantId, routerl3ContextId);
+        InstanceIdentifier<ForwardingContext> routerL3CtxIid = L2L3IidFactory.l3ContextIid(tenantId, routerl3ContextId);
         ForwardingContextBuilder fwdCtxBuilder = new ForwardingContextBuilder();
         Name routerName = null;
         if (!Strings.isNullOrEmpty(router.getName())) {
@@ -117,7 +118,7 @@ public class NeutronRouterAware implements NeutronAware<Router> {
             l3ContextBuilder.setName(name);
         }
         L3Context l3Context = l3ContextBuilder.setId(l3ContextId).build();
-        wTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context);
+        wTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context, true);
     }
 
     @Override
@@ -168,14 +169,14 @@ public class NeutronRouterAware implements NeutronAware<Router> {
             addNeutronExtGwGbpMapping(routerL3CtxId, gatewayIp, rwTx);
             NetworkDomain subnetDomain = createSubnetWithVirtualRouterIp(gatewayIp, new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId()
                 .getValue()));
-            rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()),
+            rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()),
                     subnetDomain);
             ContextId l2BdId = new ContextId(potentialSubnet.get().getNetworkId().getValue());
             Optional<ForwardingContext> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
-                    IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
+                    L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
             if (!optBd.isPresent()) {
                 LOG.warn(
-                        "Could not read L2-Bridge-Domain {} Modifiaction of it's parent to L3-Context of router {} aborted.",
+                        "Could not read L2-Bridge-Domain {}. Modification of its parent to L3-Context of router {} aborted.",
                         l2BdId, newRouter.getUuid());
                 rwTx.cancel();
                 return;
@@ -183,7 +184,7 @@ public class NeutronRouterAware implements NeutronAware<Router> {
             ForwardingContext l2BdWithGw = new ForwardingContextBuilder(optBd.get())
             .setParent(MappingUtils.createParent(routerL3CtxId, MappingUtils.L3_CONTEXT))
             .build();
-            rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
+            rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
                     l2BdWithGw);
         }
         updateTenantForwarding(newNeutron, oldRouter, newRouter, new L3ContextId(routerL3CtxId), tenantId, rwTx);
@@ -223,7 +224,7 @@ public class NeutronRouterAware implements NeutronAware<Router> {
              l3Context = optL3Context.get();
          } else { // add L3 context if missing
              l3Context = createL3CtxFromRouter(newRouter);
-             rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context);
+             rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context, true);
          }
 
          if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) {
@@ -256,8 +257,9 @@ public class NeutronRouterAware implements NeutronAware<Router> {
                  return;
              }
              IpAddress gatewayIp =  potentialSubnet.get().getGatewayIp();
+             NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue());
              boolean registeredExternalGateway = epRegistrator.registerL3EpAsExternalGateway(tenantId, gatewayIp,
-                     l3ContextId, new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue()));
+                     l3ContextId, networkContainment);
              if (!registeredExternalGateway) {
                  LOG.warn("Could not add L3Prefix as gateway of default route. Gateway port {}", gwPort);
                  rwTx.cancel();
@@ -284,7 +286,7 @@ public class NeutronRouterAware implements NeutronAware<Router> {
                      IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
              if (!optBd.isPresent()) {
                  LOG.warn(
-                         "Could not read L2-Bridge-Domain {} Modifiaction of it's parent to L3-Context of router {} aborted.",
+                         "Could not read L2-Bridge-Domain {}. Modification of its parent to L3-Context of router {} aborted.",
                          l2BdId, newRouter.getUuid());
                  rwTx.cancel();
                  return;
index adf9442f14e3666e28066637c99b4be39ee8b743..2c3037439cd4914dfd243b9e3c86ae57106d1164 100644 (file)
@@ -12,6 +12,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 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.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
@@ -97,7 +98,7 @@ public class NeutronSubnetAware implements
             subnetDomain = createSubnet(neutronSubnet, null);
         }
         processTenantSubnet(neutronSubnet, networkOfSubnet, tenantId, rwTx);
-        rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain, true);
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain, true);
         DataStoreHelper.submitToDs(rwTx);
     }
 
@@ -186,7 +187,7 @@ public class NeutronSubnetAware implements
         NetworkDomainId subnetId = new NetworkDomainId(neutronSubnet.getUuid().getValue());
         TenantId tenantId = new TenantId(neutronSubnet.getTenantId().getValue());
         Optional<NetworkDomain> potentialSubnetDomain = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.subnetIid(tenantId, subnetId), rwTx);
+                L2L3IidFactory.subnetIid(tenantId, subnetId), rwTx);
         if (!potentialSubnetDomain.isPresent()) {
             LOG.warn("Illegal state - subnet network domain {} does not exist.", subnetId.getValue());
             rwTx.cancel();
index bbf671ac7708e29bad74d56c92344e14151c6674..237f105d0af7e2698defa2313898aef92bee3772 100644 (file)
@@ -64,7 +64,7 @@ public class NetworkUtils {
         if (external == null) {
             return false;
         }
-        return true;
+        return external;
     }
 
     public static @Nonnull String getPhysicalNetwork(Network network) {
index 3ef29b5c15570312f33c5113fb774f755975f2e1..debe75422e14f2062beced50167483f88c5c1296 100644 (file)
@@ -24,10 +24,10 @@ import com.google.common.base.Optional;
 
 public class PortUtils {
 
-    private static final String DEVICE_OWNER_DHCP = "network:dhcp";
-    private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
-    private static final String DEVICE_OWNER_ROUTER_GATEWAY = "network:router_gateway";
-    private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
+    public static final String DEVICE_OWNER_DHCP = "network:dhcp";
+    public static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
+    public static final String DEVICE_OWNER_ROUTER_GATEWAY = "network:router_gateway";
+    public static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
 
     public static Optional<Port> findPort(Uuid uuid, @Nullable Ports ports) {
         if (ports == null || ports.getPort() == null) {
diff --git a/neutron-mapper/src/main/yang/neutron-provider-topology.yang b/neutron-mapper/src/main/yang/neutron-provider-topology.yang
new file mode 100644 (file)
index 0000000..9b9f67b
--- /dev/null
@@ -0,0 +1,99 @@
+module neutron-provider-topology {
+    // vi: set et smarttab sw=4 tabstop=4:
+
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:neutron:provider:topology";
+    prefix "neutron-provider";
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Wojciech Dec <wdec@cisco.com>";
+
+    description
+        "Base model describing a Neutron network physical provider network, and
+        and mappings to a device's physical interfaces.
+
+        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";
+
+    revision "2016-06-06" {
+        description "Initial cut";
+    }
+
+    import network-topology { prefix nt; revision-date 2013-10-21; }
+    import neutron-networks { prefix neutron-netw; revision-date "2015-07-12"; }
+    import opendaylight-l2-types { prefix l2-types; revision-date "2013-08-27"; }
+    import odl-external-reference { prefix extref; }
+    import yang-ext { prefix ext; revision-date "2013-07-09"; }
+
+    augment "/nt:network-topology/nt:topology/nt:topology-types" {
+        ext:augment-identifier "topology-types-neutron-provider-augment";
+        container neutron-provider-topology {
+            presence "Indicates a Neutron Physical Provider topology";
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology" {
+        ext:augment-identifier "topology-neutron-provider-augment";
+        when "./nt:topology-types/neutron-provider-topology";
+
+        leaf physical-provider-type {
+            description "Technology used by the physical provider net";
+            type neutron-netw:network-type;
+        }
+
+        choice provider-parameters {
+            container vlan {
+                description "Used to check or assign vlan values";
+                when "../type = neutron-netw:provider-type-vlan";
+                container vlan-range {
+                    leaf start {
+                        description "Lowest VLAN";
+                        type l2-types:vlan-id;
+                    }
+                    leaf end {
+                        type l2-types:vlan-id;
+                        must "current() >= ../start"{}
+                    }
+                }
+            }
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node/nt:termination-point" {
+        ext:augment-identifier "termination-neutron-provider-augment";
+        when "./nt:topology-types/neutron-provider-topology";
+
+        choice interface-type {
+            container physical-interface {
+                description
+                    "Reference to physical ethernet interface that need to be added
+                     into the provider bridge. This interface is a direct system interface
+                     reference configured by the user prior to the device
+                     being attached.";
+
+                leaf interface-name {
+                    type string;
+                    mandatory true;
+                }
+            }
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:link" {
+        when "../nt:topology-types/neutron-provider-topology";
+        ext:augment-identifier "link-neutron-provider-augment";
+        leaf physical-interface {
+            description
+                "Reference to the network element interface.
+
+                This reference needs to be resolved against the supporting
+                node's operational data store.";
+            config false;
+            type extref:external-reference;
+        }
+    }
+}
diff --git a/neutron-mapper/src/main/yang/odl-external-reference.yang b/neutron-mapper/src/main/yang/odl-external-reference.yang
new file mode 100644 (file)
index 0000000..e82bfe2
--- /dev/null
@@ -0,0 +1,41 @@
+module odl-external-reference {
+    // vi: set et smarttab sw=4 tabstop=4:
+
+    yang-version 1;
+    // FIXME: this mode should go to OpenDaylight/mdsal
+    namespace "urn:opendaylight:params:xml:ns:yang:external:reference";
+    prefix "extref";
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Robert Varga <rovarga@cisco.com>";
+
+    description
+        "Model defining the base type for external references for use instead
+        of an instance-identifier, which does not allow referencing entities
+        unknown in the model (due to imports, etc.).
+
+        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";
+
+    revision "2016-01-29" {
+        description "Initial model";
+    }
+
+    typedef external-reference {
+        description "Reference to a YANG-modeled node which resides outside
+            of this system. The format must use module names as namespace
+            prefixes -- in a similar fashion RESTCONF does. The reference
+            is evaluated from the root of the external system.
+
+            This data type does not hold the coordinates of the external
+            system, nor does it specify which data store on the external
+            system should be used to satisfy the reference. This information
+            should be described in the model which instantiates a leaf of
+            this type.";
+        type string;
+    }
+}
index 819c083d8e5f9b867ba33215d0806c459eb2009a..b94caec29ad839f83e98a2a9d1edc14a5d7a188e 100644 (file)
@@ -7,14 +7,14 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.test.GbpDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.PolicyAssert;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelectorBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelectorKey;
 
-public class NetworkClientTest extends GbpDataBrokerTest {
+public class NetworkClientTest extends NeutronMapperDataBrokerTest {
 
     private final String tenantID = "00000000-0000-0000-0000-000000000001";
     private final SelectorName selector = new SelectorName("dummy-selector");
index 625c1f81c9a8a18cff103d770e39c9feb4459341..7d2e18a404b10e27b8a648aaae23cde3a06c9442 100644 (file)
@@ -9,7 +9,7 @@ import java.util.Set;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.test.GbpDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.PolicyAssert;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
@@ -19,7 +19,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
 
-public class NetworkServiceTest extends GbpDataBrokerTest {
+public class NetworkServiceTest extends NeutronMapperDataBrokerTest {
 
     // dhcp
     private static final SubjectName DHCP_SUBJECT_NAME = new SubjectName("ALLOW_DHCP");
diff --git a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java
new file mode 100644 (file)
index 0000000..a5d1f4d
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * 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.neutron.mapper.mapping;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.PortsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.SubnetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder;
+
+public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest {
+
+    private final Uuid tenantUuid = new Uuid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
+    private final Uuid portUuid = new Uuid("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb");
+    private final Uuid subnetUuid = new Uuid("cccccccc-cccc-cccc-cccc-cccccccccccc");
+    private final Uuid networkUuid = new Uuid("dddddddd-dddd-dddd-dddd-dddddddddddd");
+    private final Uuid uuidReserved3 = new Uuid("dddddddd-dddd-dddd-dddd-ddddddddddd3");
+
+    private DataBroker dataBroker;
+    private NeutronPortAware portAware;
+    private EndpointRegistrator epRegistrator;
+    private Neutron neutron;
+
+    @Before
+    public void init() {
+        dataBroker = getDataBroker();
+        neutron = mock(Neutron.class);
+        epRegistrator = mock(EndpointRegistrator.class);
+        when(epRegistrator.registerEndpoint(any(RegisterEndpointInput.class))).thenReturn(true);
+        when(epRegistrator.registerEndpoint(
+                any(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput.class)))
+                    .thenReturn(true);
+        when(epRegistrator.unregisterEndpoint(any(UnregisterEndpointInput.class))).thenReturn(true);
+        when(epRegistrator.unregisterEndpoint(
+                any(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput.class)))
+                    .thenReturn(true);
+
+        portAware = new NeutronPortAware(dataBroker, epRegistrator);
+    }
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Test
+    public void testConstructor_invalidArgument() throws NullPointerException {
+        thrown.expect(NullPointerException.class);
+        new NeutronPortAware(null, null);
+    }
+
+    @Test
+    public void test_createAndDeleteDhcpPort() {
+        IpAddress ipAddress = new IpAddress(new Ipv4Address("10.0.0.2"));
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps portIpWithSubnet = createFixedIps(ipAddress);
+        Port port = newBasePort().setDeviceOwner(PortUtils.DEVICE_OWNER_DHCP)
+            .setFixedIps(ImmutableList.of(portIpWithSubnet))
+            .build();
+        portAware.onCreated(port, neutron);
+        NeutronMapperAssert.assertPortExists(dataBroker, port.getUuid());
+
+        portAware.onDeleted(port, neutron, neutron);
+        NeutronMapperAssert.assertPortNotExists(dataBroker, port.getUuid());
+    }
+
+    @Test
+    public void test_createDhcpPort_noFixedIps() {
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        Port port = newBasePort().setDeviceOwner(PortUtils.DEVICE_OWNER_DHCP).build();
+        portAware.onCreated(port, neutron);
+        NeutronMapperAssert.assertPortNotExists(dataBroker, port.getUuid());
+    }
+
+    @Test
+    public void test_createAndDeleteNormalPort() throws Exception {
+        IpAddress ipAddress = new IpAddress(new Ipv4Address("10.0.0.2"));
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps portIpWithSubnet = createFixedIps(ipAddress);
+        Port port = newBasePort().setDeviceOwner("owner for normal port")
+            .setFixedIps(ImmutableList.of(portIpWithSubnet))
+            .build();
+        portAware.onCreated(port, neutron);
+        NeutronMapperAssert.assertPortExists(dataBroker, port.getUuid());
+
+        portAware.onDeleted(port, neutron, neutron);
+        NeutronMapperAssert.assertPortNotExists(dataBroker, port.getUuid());
+    }
+
+    @Test
+    public void test_createAndUpdateNormalPort() {
+        IpAddress ipAddress = new IpAddress(new Ipv4Address("10.0.0.2"));
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps portIpWithSubnet = createFixedIps(ipAddress);
+        Port port = newBasePort().setDeviceOwner("owner for normal port")
+            .setFixedIps(ImmutableList.of(portIpWithSubnet))
+            .build();
+        portAware.onCreated(port, neutron);
+        NeutronMapperAssert.assertPortExists(dataBroker, port.getUuid());
+
+        Port newPort = new PortBuilder(port).setName("updatedName").build();
+        portAware.onUpdated(port, newPort, neutron, neutron);
+        NeutronMapperAssert.assertPortExists(dataBroker, port.getUuid());
+    }
+
+    @Test
+    public void test_createNormalPort_noFixedIps() {
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        Port port = newBasePort().setDeviceOwner("owner for normal port").build();
+        portAware.onCreated(port, neutron);
+        NeutronMapperAssert.assertPortExists(dataBroker, port.getUuid());
+    }
+
+    @Test
+    public void test_createAndDeleteRouterInterfacePort() {
+        IpAddress ipAddress = new IpAddress(new Ipv4Address("10.0.0.2"));
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps portIpWithSubnet = createFixedIps(ipAddress);
+        Port neutronPort1 = new PortBuilder().setTenantId(new Uuid(tenantUuid))
+            .setFixedIps(ImmutableList.of(portIpWithSubnet))
+            .setName("portName1")
+            .setUuid(portUuid)
+            .setDeviceId("deviceId")
+            .setFixedIps(ImmutableList.of(portIpWithSubnet))
+            .setNetworkId(networkUuid)
+            .setMacAddress("00:00:00:00:35:02")
+            .build();
+        Port neutronPort2 = new PortBuilder().setTenantId(new Uuid(tenantUuid))
+            .setFixedIps(ImmutableList.of(portIpWithSubnet))
+            .setName("portName2")
+            .setUuid(portUuid)
+            .setDeviceId("deviceId")
+            .setDeviceOwner(PortUtils.DEVICE_OWNER_DHCP)
+            .setFixedIps(ImmutableList.of(portIpWithSubnet))
+            .setNetworkId(networkUuid)
+            .setMacAddress("00:00:00:00:35:02")
+            .build();
+        Ports neutronPorts = new PortsBuilder().setPort(ImmutableList.of(neutronPort1, neutronPort2)).build();
+        when(neutron.getPorts()).thenReturn(neutronPorts);
+
+        Subnet subnet = subnets.getSubnet().get(0);
+        Port port = newBasePort().setDeviceOwner(PortUtils.DEVICE_OWNER_ROUTER_IFACE)
+            .setFixedIps(ImmutableList.of(portIpWithSubnet))
+            .build();
+        portAware.onCreated(port, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, ipAddress);
+
+        portAware.onDeleted(port, neutron, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, ipAddress);
+        NeutronMapperAssert.assertPortNotExists(dataBroker, port.getUuid());
+    }
+
+    @Test
+    public void test_createRouterInterfacePort_noFixedIps() {
+        IpAddress ipAddress = new IpAddress(new Ipv4Address("10.0.0.2"));
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        Subnet subnet = subnets.getSubnet().get(0);
+        Port port = newBasePort().setDeviceOwner(PortUtils.DEVICE_OWNER_ROUTER_IFACE).build();
+        portAware.onCreated(port, neutron);
+        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, port, subnet, ipAddress);
+    }
+
+    @Test
+    public void test_createAndDeleteRouterGatewayPort() {
+        Port port = new PortBuilder().setUuid(portUuid).setDeviceOwner(PortUtils.DEVICE_OWNER_ROUTER_GATEWAY).build();
+        portAware.onCreated(port, neutron);
+        portAware.onDeleted(port, neutron, neutron);
+        // no op
+    }
+
+    @Test
+    public void test_createAndDeleteFloatingIpPort() {
+        Port port = new PortBuilder().setUuid(portUuid).setDeviceOwner(PortUtils.DEVICE_OWNER_FLOATING_IP).build();
+        portAware.onCreated(port, neutron);
+        portAware.onDeleted(port, neutron, neutron);
+        // no op
+    }
+
+    private PortBuilder newBasePort() {
+        List<Uuid> secGroups = ImmutableList.of(uuidReserved3);
+        return new PortBuilder().setTenantId(new Uuid(tenantUuid))
+            .setSecurityGroups(secGroups)
+            .setName("portName")
+            .setUuid(portUuid)
+            .setDeviceId("deviceId")
+            .setNetworkId(networkUuid)
+            .setMacAddress("00:00:00:00:35:02");
+    }
+
+    private Subnets createSubnets() {
+        Subnet subnet = new SubnetBuilder().setTenantId(tenantUuid)
+            .setUuid(subnetUuid)
+            .setName("subnetName")
+            .setNetworkId(networkUuid)
+            .setCidr("10.0.0.0/24")
+            .build();
+        return new SubnetsBuilder().setSubnet(ImmutableList.of(subnet)).build();
+    }
+
+    private FixedIps createFixedIps(IpAddress ipAddress) {
+        return new FixedIpsBuilder().setSubnetId(subnetUuid).setIpAddress(ipAddress).build();
+    }
+
+}
diff --git a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronRouterAwareDataStoreTest.java b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronRouterAwareDataStoreTest.java
new file mode 100644 (file)
index 0000000..f7fb730
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * 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.neutron.mapper.mapping;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+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.neutron.mapper.EndpointRegistrator;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
+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;
+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.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.PortsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.SubnetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class NeutronRouterAwareDataStoreTest extends NeutronMapperDataBrokerTest {
+
+    private final Uuid tenantUuid = new Uuid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
+    private final Uuid routerUuid = new Uuid("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb");
+    private final Uuid newRouterUuid = new Uuid("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbb2");
+    private final Uuid subnetUuid = new Uuid("cccccccc-cccc-cccc-cccc-cccccccccccc");
+    private final Uuid networkUuid = new Uuid("dddddddd-dddd-dddd-dddd-dddddddddddd");
+    private final Uuid gatewayPortUuid = new Uuid("dddddddd-dddd-dddd-dddd-ddddddddddd1");
+    private final IpAddress ipAddress = new IpAddress(new Ipv4Address("10.0.0.2"));
+
+    private DataBroker dataBroker;
+    private NeutronRouterAware routerAware;
+    private EndpointRegistrator epRegistrator;
+    private EndpointService epService;
+    private BaseEndpointService baseEpService;
+    private Neutron neutron;
+    private Future<RpcResult<Void>> futureRpcResult;
+    private Future<RpcResult<Void>> futureRpcFail;
+    private RpcResult<Void> rpcResult;
+    private RpcResult<Void> rpcFail;
+    private NeutronNetworkAware networkAware;
+    private Network network;
+
+    @Before
+    public void init() throws ExecutionException, InterruptedException {
+        futureRpcResult = mock(Future.class);
+        futureRpcFail = mock(Future.class);
+        rpcResult = mock(RpcResult.class);
+        rpcFail = mock(RpcResult.class);
+        when(rpcResult.isSuccessful()).thenReturn(true);
+        when(rpcFail.isSuccessful()).thenReturn(false);
+        dataBroker = getDataBroker();
+        neutron = mock(Neutron.class);
+        epService = mock(EndpointService.class);
+        baseEpService = mock(BaseEndpointService.class);
+        when(futureRpcResult.get()).thenReturn(rpcResult);
+        when(futureRpcFail.get()).thenReturn(rpcFail);
+        when(epService.registerEndpoint(
+                any(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput.class)))
+                    .thenReturn(futureRpcResult);
+        when(epService.registerL3PrefixEndpoint(
+                any(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput.class)))
+                    .thenReturn(futureRpcResult);
+        when(baseEpService.registerEndpoint(
+                any(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput.class)))
+                    .thenReturn(futureRpcResult);
+        epRegistrator = new EndpointRegistrator(epService, baseEpService);
+
+        networkAware = new NeutronNetworkAware(dataBroker);
+        network = new NetworkBuilder().setTenantId(tenantUuid).setUuid(networkUuid).setName("networkName").build();
+
+        routerAware = new NeutronRouterAware(dataBroker, epRegistrator);
+    }
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Test
+    public void testConstructor_invalidArgument() throws NullPointerException {
+        thrown.expect(NullPointerException.class);
+        new NeutronRouterAware(null, null);
+    }
+
+    @Test
+    public void testOnCreated() {
+        Router router = new RouterBuilder().setTenantId(tenantUuid).setName("routerName").setUuid(routerUuid).build();
+
+        routerAware.onCreated(router, neutron);
+
+        assertRouterExists(router);
+    }
+
+    @Test
+    public void testOnCreated_incorrectName() {
+        Router router = new RouterBuilder().setTenantId(tenantUuid).setName("123").setUuid(routerUuid).build();
+
+        routerAware.onCreated(router, neutron);
+
+        assertRouterExists(router);
+    }
+
+    @Test
+    public void testOnUpdated() {
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).setSubnetId(subnetUuid).build();
+        Port port = new PortBuilder().setUuid(gatewayPortUuid).setFixedIps(ImmutableList.of(fixedIps)).build();
+        Ports ports = new PortsBuilder().setPort(ImmutableList.of(port)).build();
+        when(neutron.getPorts()).thenReturn(ports);
+
+        Router oldRouter =
+                new RouterBuilder().setTenantId(tenantUuid).setName("oldRouterName").setUuid(routerUuid).build();
+        Router newRouter = new RouterBuilder().setTenantId(tenantUuid)
+            .setName("newRouterName")
+            .setUuid(newRouterUuid)
+            .setGatewayPortId(gatewayPortUuid)
+            .build();
+
+        networkAware.onCreated(network, neutron);
+
+        assertRouterNotExists(oldRouter);
+
+        routerAware.onCreated(oldRouter, neutron);
+
+        assertRouterExists(oldRouter);
+        assertRouterNotExists(newRouter);
+
+        routerAware.onUpdated(oldRouter, newRouter, neutron, neutron);
+
+        assertRouterExists(oldRouter);
+        assertRouterExists(newRouter);
+    }
+
+    @Test
+    public void testOnUpdated_GatewayPortNotFound() {
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).setSubnetId(subnetUuid).build();
+        Port port = new PortBuilder().setUuid(new Uuid("dddddddd-dddd-dddd-dddd-000000000000"))
+            .setFixedIps(ImmutableList.of(fixedIps))
+            .build();
+        Ports ports = new PortsBuilder().setPort(ImmutableList.of(port)).build();
+        when(neutron.getPorts()).thenReturn(ports);
+
+        Router oldRouter =
+                new RouterBuilder().setTenantId(tenantUuid).setName("oldRouterName").setUuid(routerUuid).build();
+        Router newRouter = new RouterBuilder().setTenantId(tenantUuid)
+            .setName("newRouterName")
+            .setUuid(newRouterUuid)
+            .setGatewayPortId(gatewayPortUuid)
+            .build();
+
+        routerAware.onCreated(oldRouter, neutron);
+        routerAware.onUpdated(oldRouter, newRouter, neutron, neutron);
+
+        assertRouterNotExists(newRouter);
+    }
+
+    @Test
+    public void testOnUpdated_noIps() {
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        Port port = new PortBuilder().setUuid(gatewayPortUuid).build();
+        Ports ports = new PortsBuilder().setPort(ImmutableList.of(port)).build();
+        when(neutron.getPorts()).thenReturn(ports);
+
+        Router oldRouter =
+                new RouterBuilder().setTenantId(tenantUuid).setName("oldRouterName").setUuid(routerUuid).build();
+        Router newRouter = new RouterBuilder().setTenantId(tenantUuid)
+            .setName("newRouterName")
+            .setUuid(newRouterUuid)
+            .setGatewayPortId(gatewayPortUuid)
+            .build();
+
+        routerAware.onCreated(oldRouter, neutron);
+        routerAware.onUpdated(oldRouter, newRouter, neutron, neutron);
+
+        assertRouterNotExists(newRouter);
+    }
+
+    @Test
+    public void testOnUpdated_noSubnet() {
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).build();
+        Port port = new PortBuilder().setUuid(gatewayPortUuid).setFixedIps(ImmutableList.of(fixedIps)).build();
+        Ports ports = new PortsBuilder().setPort(ImmutableList.of(port)).build();
+        when(neutron.getPorts()).thenReturn(ports);
+
+        Router oldRouter =
+                new RouterBuilder().setTenantId(tenantUuid).setName("oldRouterName").setUuid(routerUuid).build();
+        Router newRouter = new RouterBuilder().setTenantId(tenantUuid)
+            .setName("newRouterName")
+            .setUuid(newRouterUuid)
+            .setGatewayPortId(gatewayPortUuid)
+            .build();
+
+        routerAware.onCreated(oldRouter, neutron);
+        routerAware.onUpdated(oldRouter, newRouter, neutron, neutron);
+
+        assertRouterNotExists(newRouter);
+    }
+
+    @Test
+    public void testOnUpdated_ExtGatewayNotRegistered() {
+        when(baseEpService.registerEndpoint(
+                any(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput.class)))
+                    .thenReturn(futureRpcFail);
+
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).setSubnetId(subnetUuid).build();
+        Port port = new PortBuilder().setUuid(gatewayPortUuid).setFixedIps(ImmutableList.of(fixedIps)).build();
+        Ports ports = new PortsBuilder().setPort(ImmutableList.of(port)).build();
+        when(neutron.getPorts()).thenReturn(ports);
+
+        Router oldRouter =
+                new RouterBuilder().setTenantId(tenantUuid).setName("oldRouterName").setUuid(routerUuid).build();
+        Router newRouter = new RouterBuilder().setTenantId(tenantUuid)
+            .setName("newRouterName")
+            .setUuid(newRouterUuid)
+            .setGatewayPortId(gatewayPortUuid)
+            .build();
+
+        routerAware.onCreated(oldRouter, neutron);
+        routerAware.onUpdated(oldRouter, newRouter, neutron, neutron);
+
+        assertRouterNotExists(newRouter);
+    }
+
+    @Test
+    public void testOnUpdated_noL2BridgeDomain() {
+        Subnets subnets = createSubnets();
+        when(neutron.getSubnets()).thenReturn(subnets);
+
+        FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).setSubnetId(subnetUuid).build();
+        Port port = new PortBuilder().setUuid(gatewayPortUuid).setFixedIps(ImmutableList.of(fixedIps)).build();
+        Ports ports = new PortsBuilder().setPort(ImmutableList.of(port)).build();
+        when(neutron.getPorts()).thenReturn(ports);
+
+        Router oldRouter =
+                new RouterBuilder().setTenantId(tenantUuid).setName("oldRouterName").setUuid(routerUuid).build();
+        Router newRouter = new RouterBuilder().setTenantId(tenantUuid)
+            .setName("newRouterName")
+            .setUuid(newRouterUuid)
+            .setGatewayPortId(gatewayPortUuid)
+            .build();
+
+        routerAware.onCreated(oldRouter, neutron);
+        routerAware.onUpdated(oldRouter, newRouter, neutron, neutron);
+
+        assertRouterNotExists(newRouter);
+    }
+
+    @Test
+    public void testOnDeleted() {
+        Router router =
+                new RouterBuilder().setTenantId(tenantUuid).setName("oldRouterName").setUuid(routerUuid).build();
+
+        routerAware.onCreated(router, neutron);
+        routerAware.onDeleted(router, neutron, neutron);
+        // no op
+    }
+
+    private Subnets createSubnets() {
+        Subnet subnet = new SubnetBuilder().setTenantId(tenantUuid)
+            .setUuid(subnetUuid)
+            .setName("subnetName")
+            .setNetworkId(networkUuid)
+            .setGatewayIp(ipAddress)
+            .setCidr("10.0.0.0/24")
+            .build();
+        return new SubnetsBuilder().setSubnet(ImmutableList.of(subnet)).build();
+    }
+
+    private void assertRouterExists(Router router) {
+        Optional<L3Context> opt = getL3ContextOptional(router);
+        if (opt.isPresent()) {
+            assertEquals(router.getUuid().getValue(), opt.get().getId().getValue());
+        } else {
+            fail("no router in DS, Uuid:" + router.getUuid());
+        }
+    }
+
+    private void assertRouterNotExists(Router router) {
+        Optional<L3Context> opt = getL3ContextOptional(router);
+        if (opt.isPresent()) {
+            assertNotEquals(router.getUuid().getValue(), opt.get().getId().getValue());
+        }
+    }
+
+    private Optional<L3Context> getL3ContextOptional(Router router) {
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        TenantId tenantId = new TenantId(router.getTenantId().getValue());
+        ContextId routerL3CtxId = new ContextId(router.getUuid().getValue());
+        L3ContextId l3ContextId = new L3ContextId(routerL3CtxId);
+        InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId);
+        return DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l3ContextIid, rTx);
+    }
+
+}
index 64f083958037018ae01d50089355c576a87ca59b..90fc4ad67c3301dd81dfb21ab6a082ca0dfc3e12 100644 (file)
@@ -1,30 +1,50 @@
-package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+/*
+ * 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
+ */
 
-import static org.junit.Assert.fail;
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
 
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSecurityGroupAware;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.test.GbpDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronEntityFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.PolicyAssert;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+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.policy.rev140421.tenants.tenant.policy.EndpointGroup.IntraGroupPolicy;
 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;
 
-public class NeutronSecurityGroupAwareDataStoreTest extends GbpDataBrokerTest {
+public class NeutronSecurityGroupAwareDataStoreTest extends NeutronMapperDataBrokerTest {
 
-    @Test
-    public void testAddAndDeleteNeutronSecurityGroup_noSecurityRules() throws Exception {
-        DataBroker dataBroker = getDataBroker();
-        NeutronSecurityGroupAware groupAware = new NeutronSecurityGroupAware(dataBroker);
+    private final String tenantId = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
+    private final String secGroupId1 = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb";
+    private final String secGroupId2 = "cccccccc-cccc-cccc-cccc-cccccccccccc";
+
+    private DataBroker dataBroker;
+    private NeutronSecurityGroupAware groupAware;
+    private SecurityGroup secGroup1;
+    private SecurityGroup secGroup2;
 
-        final String tenantId = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
-        final String secGroupId1 = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb";
-        final String secGroupId2 = "cccccccc-cccc-cccc-cccc-cccccccccccc";
+    @Before
+    public void init() {
+        dataBroker = getDataBroker();
+        groupAware = new NeutronSecurityGroupAware(dataBroker);
 
-        SecurityGroup secGroup1 = NeutronEntityFactory.securityGroup(secGroupId1, tenantId);
-        SecurityGroup secGroup2 = NeutronEntityFactory.securityGroup(secGroupId2, tenantId);
+        secGroup1 = NeutronEntityFactory.securityGroup(secGroupId1, tenantId);
+        secGroup2 = NeutronEntityFactory.securityGroup(secGroupId2, tenantId);
+    }
 
+    @Test
+    public void testAddAndDeleteNeutronSecurityGroup_noSecurityRules() throws Exception {
         groupAware.onCreated(secGroup1, null);
 
         PolicyAssert.assertTenantExists(dataBroker, tenantId);
@@ -72,14 +92,49 @@ public class NeutronSecurityGroupAwareDataStoreTest extends GbpDataBrokerTest {
         PolicyAssert.assertEndpointGroupCount(dataBroker, tenantId, 0);
     }
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Test
-    public void testConstructor_invalidArgument() throws Exception {
-        try {
-            new NeutronSecurityGroupAware(null);
-            fail(NullPointerException.class.getName() + " expected");
-        } catch (NullPointerException e) {
-            // do nothing
-        }
+    public void testConstructor_invalidArgument() throws NullPointerException {
+        thrown.expect(NullPointerException.class);
+        new NeutronSecurityGroupAware(null);
+    }
+
+    @Test
+    public void testAddNeutronSecurityGroup_ExternalImplicitGroup() throws Exception {
+        String uuid = MappingUtils.EIG_UUID.getValue();
+        SecurityGroup secGroupA = new SecurityGroupBuilder().setUuid(new Uuid(uuid))
+            .setTenantId(new Uuid(tenantId))
+            .setName("correctName")
+            .setDescription("correct description")
+            .build();
+        groupAware.onCreated(secGroupA, null);
+
+        PolicyAssert.assertEndpointGroupExists(dataBroker, tenantId, uuid);
+    }
+
+    @Test
+    public void testAddNeutronSecurityGroup_incorrectNameDescription() throws Exception {
+        String uuid = "dddddddd-dddd-dddd-dddd-dddddddddddd";
+        String longDescription = StringUtils.repeat("a", 4100);
+        SecurityGroup secGroupA = new SecurityGroupBuilder().setUuid(new Uuid(uuid))
+            .setTenantId(new Uuid(tenantId))
+            .setName("123")
+            .setDescription(longDescription)
+            .build();
+        groupAware.onCreated(secGroupA, null);
+
+        PolicyAssert.assertEndpointGroupExists(dataBroker, tenantId, uuid);
+    }
+
+    @Test
+    public void testOnDelete_NonExistingSecGroup() throws Exception {
+        PolicyAssert.assertEndpointGroupNotExists(dataBroker, tenantId, secGroupId2);
+
+        groupAware.onDeleted(secGroup2, null, null);
+
+        PolicyAssert.assertEndpointGroupNotExists(dataBroker, tenantId, secGroupId2);
     }
 
 }
index d3a4ad13e5788b966765d3ddb3aa8952ff6386a8..9d3c199983760401578353d2a6f9e83dee45ea4d 100644 (file)
@@ -11,7 +11,7 @@ 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.groupbasedpolicy.neutron.mapper.test.ConfigDataStoreReader;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.test.GbpDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronEntityFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.PolicyAssert;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
@@ -46,7 +46,7 @@ import com.google.common.collect.ImmutableSet;
  * datastore
  */
 
-public class NeutronSecurityRuleAwareDataStoreTest extends GbpDataBrokerTest {
+public class NeutronSecurityRuleAwareDataStoreTest extends NeutronMapperDataBrokerTest {
 
     @Test
     public final void testAddNeutronSecurityRule_rulesWithRemoteIpPrefix() throws Exception {
index e77e2937ff3e9378f164b943b54a054b2e0a3002..d824e8a5e050338f4fa5fb6ff558fdf184cc17fe 100644 (file)
@@ -11,7 +11,7 @@ import java.util.List;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.ConfigDataStoreReader;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.test.GbpDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronEntityFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.PolicyAssert;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
@@ -29,7 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712
 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;
 
-public class NeutronSecurityRuleAwareTest extends GbpDataBrokerTest {
+public class NeutronSecurityRuleAwareTest extends NeutronMapperDataBrokerTest {
 
     private static final String RULE_ID = "00000000-0000-0000-0000-000000000001";
     private static final String RULE_TENANT_ID = "00000000-0000-0000-0000-000000000002";
similarity index 60%
rename from neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/GbpDataBrokerTest.java
rename to neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/CustomDataBrokerTest.java
index 0a446aea882fb73406745944af228853c2d8d998..f13748b29662c49915a838aa196c723935be129c 100644 (file)
@@ -1,31 +1,49 @@
+/*
+ * Copyright (c) 2015 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.neutron.mapper.test;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import javax.annotation.Nonnull;
 import java.io.IOException;
+import java.util.Collection;
 
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
 import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
-
 /**
  * Loads only modules of GBP and it's dependencies for data broker.
- * <br>Therefore this implementation is faster than {@link AbstractDataBrokerTest}
+ * <br>
+ * Therefore this implementation is faster than {@link AbstractDataBrokerTest}
  */
-public class GbpDataBrokerTest extends AbstractDataBrokerTest {
+public abstract class CustomDataBrokerTest extends AbstractDataBrokerTest {
 
     @Override
     protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
         Builder<YangModuleInfo> moduleInfoSet = ImmutableSet.<YangModuleInfo>builder();
-        loadModuleInfos(Tenant.class, moduleInfoSet);
+        for (Class<?> clazz : getClassesFromModules()) {
+            loadModuleInfos(clazz, moduleInfoSet);
+        }
         return moduleInfoSet.build();
     }
 
-    public static void loadModuleInfos(Class<?> clazzFromModule, Builder<YangModuleInfo> moduleInfoSet) throws Exception {
+    /**
+     * @return a class from every yang module which needs to be loaded. Cannot return {@code null}
+     *         or empty collection.
+     */
+    public abstract @Nonnull Collection<Class<?>> getClassesFromModules();
+
+    public static void loadModuleInfos(Class<?> clazzFromModule, Builder<YangModuleInfo> moduleInfoSet)
+            throws Exception {
         YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(clazzFromModule);
         checkState(moduleInfo != null, "Module Info for %s is not available.", clazzFromModule);
         collectYangModuleInfo(moduleInfo, moduleInfoSet);
diff --git a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperAssert.java b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperAssert.java
new file mode 100644 (file)
index 0000000..5a2bd0c
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.neutron.mapper.test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Optional;
+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.domain_extension.l2_l3.util.L2L3IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSubnetAware;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+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.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NeutronMapperAssert {
+
+    // asserts for port
+
+    public static void assertPortExists(DataBroker dataBroker, Uuid portUuid) {
+        Optional<EndpointByPort> portOptional = getEndpointByPortOptional(dataBroker, portUuid);
+        assertTrue(portOptional.isPresent());
+    }
+
+    public static void assertPortNotExists(DataBroker dataBroker, Uuid portUuid) {
+        Optional<EndpointByPort> portOptional = getEndpointByPortOptional(dataBroker, portUuid);
+        assertFalse(portOptional.isPresent());
+    }
+
+    private static Optional<EndpointByPort> getEndpointByPortOptional(DataBroker dataBroker, Uuid portUuid) {
+        UniqueId portId = new UniqueId(portUuid.getValue());
+        InstanceIdentifier<EndpointByPort> iid = NeutronGbpIidFactory.endpointByPortIid(portId);
+        Optional<EndpointByPort> portOptional;
+        try (ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction()) {
+            portOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, iid, rTx);
+        }
+        return portOptional;
+    }
+
+    public static void assertNetworkDomainExists(DataBroker dataBroker, Port port, Subnet subnet, IpAddress ipAddress) {
+        Optional<NetworkDomain> portOptional =
+                getNetworkDomainOptional(dataBroker, port.getTenantId(), ipAddress, subnet);
+        assertTrue(portOptional.isPresent());
+    }
+
+    public static void assertNetworkDomainNotExists(DataBroker dataBroker, Port port, Subnet subnet,
+            IpAddress ipAddress) {
+        Optional<NetworkDomain> portOptional =
+                getNetworkDomainOptional(dataBroker, port.getTenantId(), ipAddress, subnet);
+        assertFalse(portOptional.isPresent());
+    }
+
+    private static Optional<NetworkDomain> getNetworkDomainOptional(DataBroker dataBroker, Uuid tenantUuid,
+            IpAddress ipAddress, Subnet subnet) {
+        InstanceIdentifier<NetworkDomain> iid;
+        NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(subnet, ipAddress);
+        TenantId tenantId = new TenantId(tenantUuid.getValue());
+        iid = L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId());
+        Optional<NetworkDomain> optional;
+        try (ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction()) {
+            optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
+        }
+        return optional;
+    }
+
+}
diff --git a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperDataBrokerTest.java b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperDataBrokerTest.java
new file mode 100644 (file)
index 0000000..c0ea1a2
--- /dev/null
@@ -0,0 +1,25 @@
+package org.opendaylight.groupbasedpolicy.neutron.mapper.test;
+
+import java.util.Collection;
+
+import com.google.common.collect.ImmutableList;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.Mappings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+
+/**
+ * Loads only modules of GBP and it's dependencies for data broker.
+ * <br>
+ * Therefore this implementation is faster than {@link AbstractDataBrokerTest}
+ */
+public class NeutronMapperDataBrokerTest extends CustomDataBrokerTest {
+
+    @Override
+    public Collection<Class<?>> getClassesFromModules() {
+        return ImmutableList.<Class<?>>of(Tenants.class, Forwarding.class, SubnetAugmentForwarding.class,
+                Mappings.class);
+    }
+
+}
diff --git a/neutron-vpp-mapper/pom.xml b/neutron-vpp-mapper/pom.xml
new file mode 100644 (file)
index 0000000..3159e24
--- /dev/null
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!-- Copyright (c) 2015 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 -->
+<project
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+  xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <groupId>org.opendaylight.groupbasedpolicy</groupId>
+  <artifactId>neutron-vpp-mapper</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <neutron.version>0.7.0-SNAPSHOT</neutron.version>
+  </properties>
+
+  <dependencies>
+    <!-- project specific dependencies -->
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>groupbasedpolicy</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <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>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-topology</artifactId>
+    </dependency>
+    <!-- testing dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-yang-types-20130715</artifactId>
+    </dependency>
+  </dependencies>
+
+ <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+         <!--   <Export-Package>
+            </Export-Package> -->
+            <Import-Package>*</Import-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/neutron-vpp-mapper/src/main/config/default-config.xml b/neutron-vpp-mapper/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..2a196a5
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 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
+-->
+<snapshot>
+    <configuration>
+        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:neutron-vpp-mapper="urn:opendaylight:params:xml:ns:yang:controller:config:neutron-vpp-mapper:impl">
+                        neutron-vpp-mapper:neutron-vpp-mapper-impl
+                    </type>
+                    <name>neutron-vpp-mapper-impl</name>
+                    <rpc-registry>
+                        <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>
+                    <data-broker>
+                      <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                      <name>binding-data-broker</name>
+                    </data-broker>
+                </module>
+            </modules>
+        </data>
+    </configuration>
+    <required-capabilities>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:neutron-vpp-mapper:impl?module=neutron-vpp-mapper-impl&amp;revision=2016-04-25</capability>
+    </required-capabilities>
+</snapshot>
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/controller/config/yang/config/neutron_vpp_mapper/impl/NeutronVppMapperModule.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/controller/config/yang/config/neutron_vpp_mapper/impl/NeutronVppMapperModule.java
new file mode 100644 (file)
index 0000000..e8a60b4
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.controller.config.yang.config.neutron_vpp_mapper.impl;
+
+import org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.NeutronVppMapper;
+
+public class NeutronVppMapperModule extends org.opendaylight.controller.config.yang.config.neutron_vpp_mapper.impl.AbstractNeutronVppMapperModule {
+    public NeutronVppMapperModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public NeutronVppMapperModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.neutron_vpp_mapper.impl.NeutronVppMapperModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        String vhostSocketPath = getVhostSocketPath();
+        String vhostSocketPrefix = getVhostSocketPrefix();
+        NeutronVppMapper neutronVppMapper = new NeutronVppMapper(vhostSocketPath, vhostSocketPrefix, getDataBrokerDependency());
+        return neutronVppMapper;
+    }
+
+}
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/controller/config/yang/config/neutron_vpp_mapper/impl/NeutronVppMapperModuleFactory.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/controller/config/yang/config/neutron_vpp_mapper/impl/NeutronVppMapperModuleFactory.java
new file mode 100644 (file)
index 0000000..d0d74ac
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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
+ */
+/*
+* Generated file
+*
+* Generated from: yang module name: neutron-vpp-mapper-impl yang module local name: neutron-vpp-mapper-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon May 02 12:30:34 CEST 2016
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.neutron_vpp_mapper.impl;
+public class NeutronVppMapperModuleFactory extends org.opendaylight.controller.config.yang.config.neutron_vpp_mapper.impl.AbstractNeutronVppMapperModuleFactory {
+
+}
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/NeutronVppMapper.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/NeutronVppMapper.java
new file mode 100644 (file)
index 0000000..c491156
--- /dev/null
@@ -0,0 +1,31 @@
+/*\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;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.processors.NeutronListener;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class NeutronVppMapper implements AutoCloseable {\r
+\r
+    NeutronListener neutronListener;\r
+    private static final Logger LOG = LoggerFactory.getLogger(NeutronVppMapper.class);\r
+\r
+    public NeutronVppMapper(String socketPath, String socketPrefix, DataBroker dataBroker) {\r
+        SocketInfo socketInfo = new SocketInfo(socketPath, socketPrefix);\r
+        neutronListener = new NeutronListener(dataBroker, socketInfo);\r
+        LOG.info("Neutron VPP started!");\r
+    }\r
+\r
+    @Override\r
+    public void close() throws Exception {\r
+        neutronListener.close();\r
+    }\r
+}\r
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/SocketInfo.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/SocketInfo.java
new file mode 100644 (file)
index 0000000..3c07060
--- /dev/null
@@ -0,0 +1,59 @@
+/*\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;\r
+\r
+public class SocketInfo {\r
+\r
+    private String socketPath;\r
+    private String socketPrefix;\r
+\r
+    public SocketInfo(String socketPath, String socketPrefix) {\r
+        this.socketPath = socketPath;\r
+        this.socketPrefix = socketPrefix;\r
+    }\r
+\r
+    public String getSocketPath() {\r
+        return socketPath;\r
+    }\r
+\r
+    public String getSocketPrefix() {\r
+        return socketPrefix;\r
+    }\r
+\r
+    @Override\r
+    public int hashCode() {\r
+        final int prime = 31;\r
+        int result = 1;\r
+        result = prime * result + ((socketPath == null) ? 0 : socketPath.hashCode());\r
+        result = prime * result + ((socketPrefix == null) ? 0 : socketPrefix.hashCode());\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if (this == obj)\r
+            return true;\r
+        if (obj == null)\r
+            return false;\r
+        if (getClass() != obj.getClass())\r
+            return false;\r
+        SocketInfo other = (SocketInfo) obj;\r
+        if (socketPath == null) {\r
+            if (other.socketPath != null)\r
+                return false;\r
+        } else if (!socketPath.equals(other.socketPath))\r
+            return false;\r
+        if (socketPrefix == null) {\r
+            if (other.socketPrefix != null)\r
+                return false;\r
+        } else if (!socketPrefix.equals(other.socketPrefix))\r
+            return false;\r
+        return true;\r
+    }\r
+}\r
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/BaseEndpointByPortListener.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/BaseEndpointByPortListener.java
new file mode 100644 (file)
index 0000000..0b6b084
--- /dev/null
@@ -0,0 +1,78 @@
+/*\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 org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;\r
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.Mappings;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.GbpByNeutronMappings;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.BaseEndpointsByPorts;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;\r
+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
+        MappingProvider<Port> {\r
+\r
+    private final PortHandler portHandler;\r
+\r
+    protected BaseEndpointByPortListener(PortHandler portHandler, DataBroker dataProvider) {\r
+        super(dataProvider);\r
+        this.portHandler = portHandler;\r
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,\r
+                InstanceIdentifier.builder(Mappings.class)\r
+                    .child(GbpByNeutronMappings.class)\r
+                    .child(BaseEndpointsByPorts.class)\r
+                    .child(BaseEndpointByPort.class)\r
+                    .build()));\r
+    }\r
+\r
+    @Override\r
+    public InstanceIdentifier<Port> getNeutronDtoIid() {\r
+        return portHandler.createWildcartedPortIid();\r
+    }\r
+\r
+    @Override\r
+    public void processCreatedNeutronDto(Port port) {\r
+        portHandler.processCreated(port);\r
+    }\r
+\r
+    @Override\r
+    public void processUpdatedNeutronDto(Port original, Port delta) {\r
+        portHandler.processUpdated(original, delta);\r
+    }\r
+\r
+    @Override\r
+    public void processDeletedNeutronDto(Port port) {\r
+        // handled by BaseEndpointByPort removal\r
+    }\r
+\r
+    @Override\r
+    protected void onWrite(DataObjectModification<BaseEndpointByPort> rootNode,\r
+            InstanceIdentifier<BaseEndpointByPort> rootIdentifier) {\r
+        if (rootNode.getDataBefore() == null) {\r
+            portHandler.processCreated(rootNode.getDataAfter());\r
+        }\r
+    }\r
+\r
+    @Override\r
+    protected void onDelete(DataObjectModification<BaseEndpointByPort> rootNode,\r
+            InstanceIdentifier<BaseEndpointByPort> rootIdentifier) {\r
+        portHandler.processDeleted(rootNode.getDataBefore());\r
+    }\r
+\r
+    @Override\r
+    protected void onSubtreeModified(DataObjectModification<BaseEndpointByPort> rootNode,\r
+            InstanceIdentifier<BaseEndpointByPort> rootIdentifier) {\r
+        // update should not happen\r
+    }\r
+}\r
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/MappingProvider.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/MappingProvider.java
new file mode 100644 (file)
index 0000000..fb8b685
--- /dev/null
@@ -0,0 +1,23 @@
+/*\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 org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+\r
+interface MappingProvider<T extends DataObject> {\r
+\r
+    InstanceIdentifier<T> getNeutronDtoIid();\r
+\r
+    void processCreatedNeutronDto(T t);\r
+\r
+    void processUpdatedNeutronDto(T original, T delta);\r
+\r
+    void processDeletedNeutronDto(T t);\r
+}\r
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NeutronListener.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NeutronListener.java
new file mode 100644 (file)
index 0000000..353120c
--- /dev/null
@@ -0,0 +1,134 @@
+/*\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.io.Closeable;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.LinkedHashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+import java.util.concurrent.ExecutionException;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;\r
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;\r
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;\r
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;\r
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.SocketInfo;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;\r
+import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.google.common.annotations.VisibleForTesting;\r
+import com.google.common.collect.Iterators;\r
+import com.google.common.collect.PeekingIterator;\r
+\r
+public class NeutronListener implements DataTreeChangeListener<Neutron>, Closeable {\r
+\r
+    private static final Logger LOG = LoggerFactory.getLogger(NeutronListener.class);\r
+\r
+    private final Set<MappingProvider<? extends DataObject>> dataChangeProviders = new LinkedHashSet<>();\r
+    protected ListenerRegistration<NeutronListener> registeredListener;\r
+\r
+    public NeutronListener(DataBroker dataBroker, SocketInfo socketInfo) {\r
+        registerHandlersAndListeners(dataBroker, socketInfo);\r
+        registeredListener = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(\r
+                LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(Neutron.class).build()), this);\r
+    }\r
+\r
+    private void registerHandlersAndListeners(DataBroker dataBroker, SocketInfo socketInfo) {\r
+        PortHandler portHandler = new PortHandler(dataBroker, socketInfo);\r
+        dataChangeProviders.add(new BaseEndpointByPortListener(portHandler, dataBroker));\r
+    }\r
+\r
+    @Override\r
+    public void onDataTreeChanged(Collection<DataTreeModification<Neutron>> changes) {\r
+        for (DataTreeModification<Neutron> change : changes) {\r
+            DataObjectModification<Neutron> rootNode = change.getRootNode();\r
+            for (MappingProvider<? extends DataObject> provider : dataChangeProviders) {\r
+                for (DataObjectModification<? extends DataObject> modDto : findModifiedData(provider, rootNode)) {\r
+                    try {\r
+                        processChangedData(modDto, modDto.getModificationType(), provider);\r
+                    } catch (InterruptedException | ExecutionException e) {\r
+                        LOG.error("Failed to process {} modification of node: {}. {}", modDto.getModificationType(),\r
+                                modDto.getIdentifier(), e.getStackTrace());\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    List<DataObjectModification<? extends DataObject>> findModifiedData(MappingProvider<? extends DataObject> provider,\r
+            DataObjectModification<Neutron> rootNode) {\r
+        List<DataObjectModification<? extends DataObject>> modDtos = new ArrayList<>();\r
+        PeekingIterator<PathArgument> pathArgs = Iterators.peekingIterator(provider.getNeutronDtoIid()\r
+            .getPathArguments()\r
+            .iterator());\r
+        DataObjectModification<? extends DataObject> modifDto = rootNode;\r
+        while (pathArgs.hasNext()) {\r
+            pathArgs.next();\r
+            for (DataObjectModification<? extends DataObject> childDto : modifDto.getModifiedChildren()) {\r
+                if (pathArgs.hasNext() && childDto.getDataType().equals(pathArgs.peek().getType())) {\r
+                    if (childDto.getDataType().equals(provider.getNeutronDtoIid().getTargetType())) {\r
+                        modDtos.add(childDto);\r
+                    } else {\r
+                        modifDto = childDto;\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return modDtos;\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    <T extends DataObject> void processChangedData(DataObjectModification<?> dto, ModificationType m,\r
+            MappingProvider<T> processor) throws InterruptedException, ExecutionException {\r
+        switch (m) {\r
+            case WRITE: {\r
+                if (dto.getDataBefore() != null) {\r
+                    processor.processUpdatedNeutronDto((T) dto.getDataBefore(), (T) dto.getDataAfter());\r
+                } else {\r
+                    processor.processCreatedNeutronDto((T) dto.getDataAfter());\r
+                }\r
+                break;\r
+            }\r
+            case SUBTREE_MODIFIED: {\r
+                processor.processUpdatedNeutronDto((T) dto.getDataBefore(), (T) dto.getDataAfter());\r
+                break;\r
+            }\r
+            case DELETE: {\r
+                processor.processDeletedNeutronDto((T) dto.getDataBefore());\r
+                break;\r
+            }\r
+        }\r
+    }\r
+\r
+    @VisibleForTesting\r
+    void clearDataChangeProviders() {\r
+        dataChangeProviders.clear();\r
+    }\r
+\r
+    @VisibleForTesting\r
+    <T extends DataObject> void addDataChangeProvider(MappingProvider<T> t) {\r
+        dataChangeProviders.add(t);\r
+    }\r
+\r
+    @Override\r
+    public void close() {\r
+        registeredListener.close();\r
+    }\r
+}\r
diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java
new file mode 100644 (file)
index 0000000..5bce99c
--- /dev/null
@@ -0,0 +1,222 @@
+/*\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 org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;\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.ReadTransaction;\r
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;\r
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;\r
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;\r
+import org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.SocketInfo;\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.common.rev140421.UniqueId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.Mappings;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.GbpByNeutronMappings;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.BaseEndpointsByPorts;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPortKey;\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.config.VppEndpoint;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCaseBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;\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.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.NetworkTopology;\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.network.topology.topology.Node;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.google.common.annotations.VisibleForTesting;\r
+import com.google.common.base.Optional;\r
+\r
+public class PortHandler implements TransactionChainListener {\r
+\r
+    private static final Logger LOG = LoggerFactory.getLogger(MappingProvider.class);\r
+\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
+    DataBroker dataBroker;\r
+    SocketInfo socketInfo;\r
+\r
+    PortHandler(DataBroker dataBroker, SocketInfo socketInfo) {\r
+        this.dataBroker = dataBroker;\r
+        this.socketInfo = socketInfo;\r
+        transactionChain = this.dataBroker.createTransactionChain(this);\r
+    }\r
+\r
+    void processCreated(Port port) {\r
+        ReadTransaction rTx = dataBroker.newReadOnlyTransaction();\r
+        Optional<BaseEndpointByPort> optBaseEpByPort = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,\r
+                createBaseEpByPortIid(port.getUuid()), rTx);\r
+        if (!optBaseEpByPort.isPresent()) {\r
+            return;\r
+        }\r
+        processCreatedData(port, optBaseEpByPort.get());\r
+    }\r
+\r
+    void processCreated(BaseEndpointByPort bebp) {\r
+        ReadTransaction rTx = dataBroker.newReadOnlyTransaction();\r
+        Optional<Port> optPort = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                createPortIid(bebp.getPortId()), rTx);\r
+        if (!optPort.isPresent()) {\r
+            return;\r
+        }\r
+        processCreatedData(optPort.get(), bebp);\r
+    }\r
+\r
+    @VisibleForTesting\r
+    void processCreatedData(Port port, BaseEndpointByPort bebp) {\r
+        if (isValidVhostUser(port)) {\r
+            VppEndpoint vppEp = buildVhostUserEndpoint(port, bebp);\r
+            writeVppEndpoint(createVppEndpointIid(vppEp.getKey()), vppEp);\r
+            LOG.debug("Created vpp-endpoint {}", vppEp);\r
+        }\r
+    }\r
+\r
+    private boolean isValidVhostUser(Port port) {\r
+        PortBindingExtension portBindingExt = port.getAugmentation(PortBindingExtension.class);\r
+        if (portBindingExt != null) {\r
+            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
+                }\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+\r
+    void processUpdated(Port original, Port delta) {\r
+        if (isValidVhostUser(original)) {\r
+            ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
+            Optional<BaseEndpointByPort> optBebp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,\r
+                    createBaseEpByPortIid(original.getUuid()), rTx);\r
+            rTx.close();\r
+            if (!optBebp.isPresent()) {\r
+                return;\r
+            }\r
+            processDeleted(optBebp.get());\r
+        }\r
+        processCreated(delta);\r
+    }\r
+\r
+    void processDeleted(BaseEndpointByPort bebp) {\r
+        VppEndpointKey vppEpKey = new VppEndpointKey(bebp.getAddress(), bebp.getAddressType(), bebp.getContextId(),\r
+                bebp.getContextType());\r
+        InstanceIdentifier<VppEndpoint> vppEpIid = createVppEndpointIid(vppEpKey);\r
+        ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();\r
+        Optional<VppEndpoint> readVppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, vppEpIid, rTx);\r
+        rTx.close();\r
+        if (readVppEp.isPresent()) {\r
+            writeVppEndpoint(vppEpIid, null);\r
+            LOG.debug("Deleted vpp-endpoint {}", vppEpKey);\r
+        }\r
+    }\r
+\r
+    private void writeVppEndpoint(InstanceIdentifier<VppEndpoint> vppEpIid, VppEndpoint vppEp) {\r
+        WriteTransaction wTx = transactionChain.newWriteOnlyTransaction();\r
+        if (vppEp != null) {\r
+            wTx.put(LogicalDatastoreType.CONFIGURATION, vppEpIid, vppEp, true);\r
+        } else {\r
+            wTx.delete(LogicalDatastoreType.CONFIGURATION, vppEpIid);\r
+        }\r
+        try {\r
+            wTx.submit().checkedGet();\r
+        } catch (TransactionCommitFailedException e) {\r
+            LOG.error("Transaction chain commit failed. {}", e);\r
+            transactionChain.close();\r
+            transactionChain = dataBroker.createTransactionChain(this);\r
+        }\r
+    }\r
+\r
+    @VisibleForTesting\r
+    VppEndpoint buildVhostUserEndpoint(Port port, BaseEndpointByPort bebp) {\r
+        PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);\r
+        String socket = socketInfo.getSocketPath() + socketInfo.getSocketPrefix() + bebp.getPortId().getValue();\r
+        return new VppEndpointBuilder().setDescription("neutron port")\r
+            .setContextId(bebp.getContextId())\r
+            .setContextType(bebp.getContextType())\r
+            .setAddress(bebp.getAddress())\r
+            .setInterfaceTypeChoice(new VhostUserCaseBuilder().setSocket(socket).build())\r
+            .setAddressType(bebp.getAddressType())\r
+            .setVppInterfaceName(bebp.getPortId().getValue())\r
+            .setVppNodePath(createNodeIid(new NodeId(portBinding.getHostId())))\r
+            .build();\r
+    }\r
+\r
+    private InstanceIdentifier<Node> createNodeIid(NodeId nodeId) {\r
+        return InstanceIdentifier.builder(NetworkTopology.class)\r
+            .child(Topology.class, new TopologyKey(new TopologyId(NETCONF_TOPOLOGY_ID)))\r
+            .child(Node.class, new NodeKey(nodeId))\r
+            .build();\r
+    }\r
+\r
+    private InstanceIdentifier<VppEndpoint> createVppEndpointIid(VppEndpointKey vppEpKey) {\r
+        return InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, vppEpKey).build();\r
+    }\r
+\r
+    private InstanceIdentifier<BaseEndpointByPort> createBaseEpByPortIid(Uuid uuid) {\r
+        return createBaseEpByPortIid(new UniqueId(uuid.getValue()));\r
+    }\r
+\r
+    private InstanceIdentifier<BaseEndpointByPort> createBaseEpByPortIid(UniqueId uuid) {\r
+        return InstanceIdentifier.builder(Mappings.class)\r
+            .child(GbpByNeutronMappings.class)\r
+            .child(BaseEndpointsByPorts.class)\r
+            .child(BaseEndpointByPort.class, new BaseEndpointByPortKey(uuid))\r
+            .build();\r
+    }\r
+\r
+    InstanceIdentifier<Port> createWildcartedPortIid() {\r
+        return portsIid().child(Port.class).build();\r
+    }\r
+\r
+    private InstanceIdentifier<Port> createPortIid(UniqueId uuid) {\r
+        return portsIid().child(Port.class, new PortKey(new Uuid(uuid.getValue()))).build();\r
+    }\r
+\r
+    private InstanceIdentifierBuilder<Ports> portsIid() {\r
+        return InstanceIdentifier.builder(Neutron.class).child(Ports.class);\r
+    }\r
+\r
+    @Override\r
+    public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,\r
+            Throwable cause) {\r
+        LOG.error("Transaction chain failed. {}", cause.getMessage());\r
+        transactionChain.close();\r
+        transactionChain = dataBroker.createTransactionChain(this);\r
+    }\r
+\r
+    @Override\r
+    public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {\r
+        LOG.trace("Transaction chain was successfull. {}", chain);\r
+    }\r
+}\r
diff --git a/neutron-vpp-mapper/src/main/yang/neutron-vpp-mapper-impl.yang b/neutron-vpp-mapper/src/main/yang/neutron-vpp-mapper-impl.yang
new file mode 100644 (file)
index 0000000..cac643d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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
+ */
+
+module neutron-vpp-mapper-impl {
+
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:neutron-vpp-mapper:impl";
+    prefix "neutron-vpp-mapper-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+
+    description
+        "This module contains the base YANG definitions for
+        neutron-vpp-mapper implementation.";
+
+    revision "2016-04-25" {
+        description
+            "Initial revision.";
+    }
+
+    // This is the definition of the service implementation as a module identity.
+    identity neutron-vpp-mapper-impl {
+        base config:module-type;
+
+        // Specifies the prefix for generated java classes.
+        config:java-name-prefix NeutronVppMapper;
+    }
+
+    // Augments the 'configuration' choice node under modules/module.
+    augment "/config:modules/config:module/config:configuration" {
+        case neutron-vpp-mapper-impl {
+            when "/config:modules/config:module/config:type = 'neutron-vpp-mapper-impl'";
+
+            container data-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-async-data-broker;
+                    }
+                }
+            }
+
+            container rpc-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-rpc-registry;
+                    }
+                }
+            }
+
+            leaf vhostSocketPath {
+                description "Base system directory path for the vhost user host socket filehandle";
+                type string;
+                default "/tmp/";
+            }
+
+            leaf vhostSocketPrefix {
+                description "Prefix for the vhost user host socket filehandle";
+                type string;
+                default "socket_";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NeutronListenerTest.java b/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NeutronListenerTest.java
new file mode 100644 (file)
index 0000000..ee359c1
--- /dev/null
@@ -0,0 +1,109 @@
+/*\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.mockito.Matchers.any;\r
+import static org.mockito.Matchers.eq;\r
+import static org.mockito.Mockito.verify;\r
+\r
+import java.util.concurrent.ExecutionException;\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.DataTreeIdentifier;\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.neutron.vpp.mapper.SocketInfo;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.Mappings;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.GbpByNeutronMappings;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.BaseEndpointsByPorts;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+\r
+public class NeutronListenerTest extends AbstractDataBrokerTest {\r
+\r
+    private DataBroker dataBroker;\r
+\r
+    private SocketInfo socketInfo;\r
+    private Port port;\r
+    private BaseEndpointByPort bebp;\r
+    private NeutronListener neutronListener;\r
+    private BaseEndpointByPortListener baseEpByPortListener;\r
+\r
+    @Before\r
+    public void init() {\r
+        port = TestUtils.createValidVppPort();\r
+        bebp = TestUtils.createBaseEndpointByPortForPort();\r
+        socketInfo = new SocketInfo("/tmp/", "_socket");\r
+        dataBroker = getDataBroker();\r
+        neutronListener = new NeutronListener(dataBroker, socketInfo);\r
+        neutronListener.clearDataChangeProviders();\r
+        baseEpByPortListener = Mockito.spy(new BaseEndpointByPortListener(new PortHandler(\r
+                dataBroker, socketInfo), dataBroker));\r
+        neutronListener.addDataChangeProvider(baseEpByPortListener);\r
+    }\r
+\r
+    @Test\r
+    public void constructorTest() {\r
+        dataBroker = Mockito.spy(dataBroker);\r
+        NeutronListener neutronListener = new NeutronListener(dataBroker, socketInfo);\r
+        verify(dataBroker).registerDataTreeChangeListener(\r
+                eq(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,\r
+                        InstanceIdentifier.builder(Neutron.class)\r
+                            .build())), any(NeutronListener.class));\r
+        verify(dataBroker).registerDataTreeChangeListener(\r
+                eq(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,\r
+                        InstanceIdentifier.builder(Mappings.class)\r
+                        .child(GbpByNeutronMappings.class)\r
+                        .child(BaseEndpointsByPorts.class)\r
+                        .child(BaseEndpointByPort.class)\r
+                        .build())), any(BaseEndpointByPortListener.class));\r
+        neutronListener.close();\r
+    }\r
+\r
+    @Test\r
+    public void testProcessCreatedNeutronDto() throws Exception {\r
+        putPortAndBaseEndpointByPort();\r
+        neutronListener.close();\r
+        verify(baseEpByPortListener).processCreatedNeutronDto(port);\r
+    }\r
+\r
+    @Test\r
+    public void testProcessUpdatedNeutronDto() throws Exception {\r
+        putPortAndBaseEndpointByPort();\r
+        Port updatedPort = new PortBuilder(port).setName("renamed").build();\r
+        WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();\r
+        wTx.put(LogicalDatastoreType.CONFIGURATION, TestUtils.createPortIid(updatedPort.getKey()), updatedPort);\r
+        wTx.submit().get();\r
+        neutronListener.close();\r
+        verify(baseEpByPortListener).processUpdatedNeutronDto(port, updatedPort);\r
+    }\r
+\r
+    @Test\r
+    public void testProcessDeletedNeutronDto() throws Exception {\r
+        putPortAndBaseEndpointByPort();\r
+        WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();\r
+        wTx.delete(LogicalDatastoreType.CONFIGURATION, TestUtils.createPortIid(port.getKey()));\r
+        wTx.submit().get();\r
+        verify(baseEpByPortListener).processDeletedNeutronDto(port);\r
+    }\r
+\r
+    private void putPortAndBaseEndpointByPort() throws InterruptedException, ExecutionException {\r
+        WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();\r
+        wTx.put(LogicalDatastoreType.CONFIGURATION, TestUtils.createPortIid(port.getKey()), port);\r
+        wTx.put(LogicalDatastoreType.OPERATIONAL, TestUtils.createBaseEpByPortIid(port.getUuid()), bebp);\r
+        wTx.submit().get();\r
+    }\r
+}\r
diff --git a/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandlerTest.java b/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandlerTest.java
new file mode 100644 (file)
index 0000000..7180b26
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * 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.neutron.vpp.mapper.processors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+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.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.SocketInfo;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;
+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.vpp.endpoint._interface.type.choice.VhostUserCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+
+public class PortHandlerTest extends AbstractDataBrokerTest {
+
+    private DataBroker dataBroker;
+    private PortHandler portHandler;
+    private BindingTransactionChain transactionChain;
+
+    private Port port;
+    private SocketInfo socketInfo;
+    private BaseEndpointByPort bebp;
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void init() {
+        port = TestUtils.createValidVppPort();
+        bebp = TestUtils.createBaseEndpointByPortForPort();
+        socketInfo = new SocketInfo("/tmp/", "_socket");
+        dataBroker = Mockito.spy(getDataBroker());
+        transactionChain = mock(BindingTransactionChain.class);
+        when(dataBroker.createTransactionChain(any(PortHandler.class))).thenReturn(transactionChain);
+        portHandler = new PortHandler(dataBroker, socketInfo);
+        when(transactionChain.newReadOnlyTransaction()).thenAnswer(new Answer<ReadTransaction>() {
+
+            @Override
+            public ReadTransaction answer(InvocationOnMock invocation) throws Throwable {
+                return dataBroker.newReadOnlyTransaction();
+            }
+        });
+        when(transactionChain.newWriteOnlyTransaction()).thenAnswer(new Answer<WriteTransaction>() {
+
+            @Override
+            public WriteTransaction answer(InvocationOnMock invocation) throws Throwable {
+                return dataBroker.newWriteOnlyTransaction();
+            }
+        });
+    }
+
+    @Test
+    public void testBuildVhostUserEndpoint() {
+        VppEndpoint vppEp = portHandler.buildVhostUserEndpoint(port, bebp);
+        assertEquals(vppEp.getAddress(), bebp.getAddress());
+        assertEquals(vppEp.getAddressType(), bebp.getAddressType());
+        assertEquals(vppEp.getContextId(), bebp.getContextId());
+        assertEquals(vppEp.getContextType(), bebp.getContextType());
+        assertTrue(vppEp.getInterfaceTypeChoice() instanceof VhostUserCase);
+        VhostUserCase vhostUserCase = (VhostUserCase) vppEp.getInterfaceTypeChoice();
+        assertNotNull(vhostUserCase);
+        assertEquals(vhostUserCase.getSocket(), socketInfo.getSocketPath() + socketInfo.getSocketPrefix()
+                + bebp.getPortId().getValue());
+    }
+
+    @Test
+    public void testBuildVhostUserEndpoint_notValidVppEp() {
+        port = TestUtils.createNonVppPort();
+        thrown.expect(NullPointerException.class);
+        portHandler.buildVhostUserEndpoint(port, bebp);
+    }
+
+    @Test
+    public void testCreateWildcartedPortIid() throws TransactionCommitFailedException {
+        InstanceIdentifier<Port> iid = portHandler.createWildcartedPortIid();
+        Class<?>[] expectedTypes = {Neutron.class, Ports.class, Port.class};
+        TestUtils.assertPathArgumentTypes(iid.getPathArguments(), expectedTypes);
+        assertEquals(iid.getTargetType(), Port.class);
+    }
+
+    @Test
+    public void testProcessCreatedData() throws Exception {
+        portHandler.processCreatedData(port, bebp);
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        Optional<VppEndpoint> optVppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                TestUtils.createVppEpIid(TestUtils.createVppEndpointKey(bebp)), rTx);
+        assertTrue(optVppEp.isPresent());
+    }
+
+    @Test
+    public void testProcessCreatedData_notValidVppEp() throws Exception {
+        port = TestUtils.createNonVppPort();
+        portHandler.processCreatedData(port, bebp);
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        Optional<VppEndpoint> optVppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                TestUtils.createVppEpIid(TestUtils.createVppEndpointKey(bebp)), rTx);
+        assertFalse(optVppEp.isPresent());
+    }
+
+    @Test
+    public void testProcessUpdated() throws Exception {
+        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+        putVppEp(port, bebp, tx);
+        putBaseEpByPort(port, bebp, tx);
+        DataStoreHelper.submitToDs(tx);
+        portHandler.processUpdated(port, port);
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        Optional<VppEndpoint> optVppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                TestUtils.createVppEpIid(TestUtils.createVppEndpointKey(bebp)), rTx);
+        verify(transactionChain).newReadOnlyTransaction();
+        verify(transactionChain, times(2)).newWriteOnlyTransaction();
+        assertTrue(optVppEp.isPresent());
+    }
+
+    @Test
+    public void testProcessUpdated_notValidVppEpAnymore() throws Exception {
+        Port delta = TestUtils.createNonVppPort();
+        ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
+        putVppEp(port, bebp, tx);
+        putBaseEpByPort(port, bebp, tx);
+        DataStoreHelper.submitToDs(tx);
+        portHandler.processUpdated(port, delta);
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        Optional<VppEndpoint> optVppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                TestUtils.createVppEpIid(TestUtils.createVppEndpointKey(bebp)), rTx);
+        // looks for existing Vpp endpoint
+        verify(transactionChain).newReadOnlyTransaction();
+        // only removes former valid vpp endpoint
+        verify(transactionChain).newWriteOnlyTransaction();
+        assertFalse(optVppEp.isPresent());
+    }
+
+    @Test
+    public void testProcessDeleted() throws Exception {
+        ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
+        putVppEp(port, bebp, tx);
+        DataStoreHelper.submitToDs(tx);
+        portHandler.processDeleted(bebp);
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        Optional<VppEndpoint> optVppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                TestUtils.createVppEpIid(TestUtils.createVppEndpointKey(bebp)), rTx);
+        assertFalse(optVppEp.isPresent());
+        verify(transactionChain).newReadOnlyTransaction();
+        verify(transactionChain).newWriteOnlyTransaction();
+    }
+
+    private void putVppEp(Port port, BaseEndpointByPort bebp, WriteTransaction rwTx) {
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, TestUtils.createVppEpIid(TestUtils.createVppEndpointKey(bebp)),
+                portHandler.buildVhostUserEndpoint(port, bebp));
+    }
+
+    private void putBaseEpByPort(Port port, BaseEndpointByPort bebp, WriteTransaction rwTx) {
+        rwTx.put(LogicalDatastoreType.OPERATIONAL, TestUtils.createBaseEpByPortIid(port.getUuid()), bebp, true);
+    }
+}
diff --git a/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/TestUtils.java b/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/TestUtils.java
new file mode 100644 (file)
index 0000000..2c1f2a3
--- /dev/null
@@ -0,0 +1,107 @@
+/*\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.assertNotNull;\r
+import static org.junit.Assert.assertTrue;\r
+\r
+import java.util.Iterator;\r
+\r
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;\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.common.rev140421.ContextId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.Mappings;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.GbpByNeutronMappings;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.BaseEndpointsByPorts;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPortBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPortKey;\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.config.VppEndpoint;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtensionBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;\r
+\r
+public class TestUtils {\r
+\r
+    public static Port createValidVppPort() {\r
+        PortBindingExtension portBindingExt = new PortBindingExtensionBuilder().setHostId("devstack-control")\r
+            .setVifType("vhostuser")\r
+            .build();\r
+        return new PortBuilder().setUuid(new Uuid("00000000-1111-2222-3333-444444444444"))\r
+            .setDeviceOwner("compute")\r
+            .addAugmentation(PortBindingExtension.class, portBindingExt)\r
+            .build();\r
+    }\r
+\r
+    public static Port createNonVppPort() {\r
+        return new PortBuilder().setUuid(new Uuid("00000000-1111-2222-3333-444444444444"))\r
+            .setDeviceOwner("owner1")\r
+            .build();\r
+    }\r
+\r
+    public static BaseEndpointByPort createBaseEndpointByPortForPort() {\r
+        return new BaseEndpointByPortBuilder().setContextId(new ContextId("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"))\r
+            .setAddress("00:11:11:11:11:11")\r
+            .setPortId(new UniqueId("00000000-1111-2222-3333-444444444444"))\r
+            .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)\r
+            .setAddressType(MacAddressType.class)\r
+            .build();\r
+    }\r
+\r
+    public static VppEndpointKey createVppEndpointKey(BaseEndpointByPort bebp) {\r
+        return new VppEndpointKey(bebp.getAddress(), bebp.getAddressType(), bebp.getContextId(), bebp.getContextType());\r
+    }\r
+\r
+    public static InstanceIdentifier<VppEndpoint> createVppEpIid(VppEndpointKey key) {\r
+        return InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, key).build();\r
+    }\r
+\r
+    public static InstanceIdentifier<VppEndpoint> createVppEpIid(String addr, Class<? extends AddressType> addrType,\r
+            ContextId ctxId, Class<? extends ContextType> ctxType) {\r
+        return createVppEpIid(new VppEndpointKey(addr, addrType, ctxId, ctxType));\r
+    }\r
+\r
+    public static InstanceIdentifier<Port> createPortIid(PortKey portKey) {\r
+        return InstanceIdentifier.builder(Neutron.class).child(Ports.class).child(Port.class, portKey).build();\r
+    }\r
+\r
+    public static InstanceIdentifier<BaseEndpointByPort> createBaseEpByPortIid(Uuid uuid) {\r
+        return createBaseEpByPortIid(new UniqueId(uuid.getValue()));\r
+    }\r
+\r
+    public static InstanceIdentifier<BaseEndpointByPort> createBaseEpByPortIid(UniqueId uuid) {\r
+        return InstanceIdentifier.builder(Mappings.class)\r
+            .child(GbpByNeutronMappings.class)\r
+            .child(BaseEndpointsByPorts.class)\r
+            .child(BaseEndpointByPort.class, new BaseEndpointByPortKey(uuid))\r
+            .build();\r
+    }\r
+\r
+    public static void assertPathArgumentTypes(Iterable<PathArgument> pathArguments, Class<?>[] expectedTypes) {\r
+        assertNotNull(pathArguments);\r
+        Iterator<PathArgument> it = pathArguments.iterator();\r
+        for (int i = 0; i < expectedTypes.length; ++i) {\r
+            assertTrue("Next path argument expected.", it.hasNext());\r
+            assertEquals("Unexpected path argument type.", expectedTypes[i], it.next().getType());\r
+        }\r
+    }\r
+}\r
diff --git a/pom.xml b/pom.xml
index 257a4c8d5b6ca5864c80229d6e83a2a9033ffbc2..6b9946ef86ee4c7afe86b4f96fade8fb13d7fb56 100644 (file)
--- a/pom.xml
+++ b/pom.xml
   <modules>
     <module>artifacts</module>
     <module>groupbasedpolicy</module>
+    <module>domain-extensions</module>
     <module>renderers</module>
     <module>location-providers</module>
     <module>neutron-mapper</module>
+    <module>neutron-vpp-mapper</module>
     <module>neutron-ovsdb</module>
     <module>ui-backend</module>
     <module>groupbasedpolicy-ui</module>
index da2527141e4eb35922dbe89704101ba6ca5e46fb..d44e7c0e6d4975348a7c00ed3f4f71bccc8d284b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015 Huawei Technologies 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
@@ -15,6 +15,7 @@ import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledExecutorService;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
@@ -96,7 +97,8 @@ public class FaasContractManagerListener implements DataChangeListener {
         });
     }
 
-    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+    @VisibleForTesting
+    void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
         // Create
         for (DataObject dao : change.getCreatedData().values()) {
             if (dao instanceof Contract) {
@@ -109,7 +111,7 @@ public class FaasContractManagerListener implements DataChangeListener {
         Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData();
         for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) {
             if (entry.getValue() instanceof Contract) {
-                Contract contract = (Contract) dao;
+                Contract contract = (Contract) entry.getValue();
                 LOG.debug("Contract {} is Updated.", contract.getId().getValue());
                 UlnDatastoreApi.submitSecurityGroupsToDs(initSecurityGroupBuilder(contract).build());
             }
index f47e375300ff66cd27079a6ed2c92bd271f64da3..cf4f5762b34cea3fb6f71803a24bda863d413add 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015 Huawei Technologies 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
@@ -16,6 +16,7 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ScheduledExecutorService;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
@@ -85,7 +86,8 @@ public class FaasEndpointManagerListener implements DataChangeListener, AutoClos
         });
     }
 
-    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+    @VisibleForTesting
+    void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
 
         // Create
         for (DataObject dao : change.getCreatedData().values()) {
@@ -97,25 +99,25 @@ public class FaasEndpointManagerListener implements DataChangeListener, AutoClos
                     processEndpoint(endpoint);
                 }
             } else if (dao instanceof EndpointL3) {
-                LOG.debug("Created EndpointL3 {}", (EndpointL3) dao);
+                LOG.debug("Created EndpointL3 {}", dao);
             } else if (dao instanceof EndpointL3Prefix) {
-                LOG.warn("Not Handled Event Yet by Faas Renderer. Created EndpointL3Prefix {}", (EndpointL3Prefix) dao);
+                LOG.warn("Not Handled Event Yet by Faas Renderer. Created EndpointL3Prefix {}", dao);
             }
         }
         // Update
         Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData();
         for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) {
             if (entry.getValue() instanceof Endpoint) {
-                Endpoint endpoint = (Endpoint) dao;
+                Endpoint endpoint = (Endpoint) entry.getValue();
                 LOG.debug("Updated Endpoint {}", endpoint);
                 if (validate(endpoint)) {
                     policyManager.registerTenant(endpoint.getTenant(), endpoint.getEndpointGroup());
                     processEndpoint(endpoint);
                 }
             } else if (entry.getValue() instanceof EndpointL3) {
-                LOG.debug("Updated EndpointL3 {}", (EndpointL3) dao);
+                LOG.debug("Updated EndpointL3 {}", entry.getValue());
             } else if (entry.getValue() instanceof EndpointL3Prefix) {
-                LOG.warn("Not Handled Event Yet by Faas Renderer. Updated EndpointL3Prefix {}", (EndpointL3Prefix) dao);
+                LOG.warn("Not Handled Event Yet by Faas Renderer. Updated EndpointL3Prefix {}", entry.getValue());
             }
         }
         // Remove
@@ -125,17 +127,17 @@ public class FaasEndpointManagerListener implements DataChangeListener, AutoClos
                 continue;
             }
             if (old instanceof Endpoint) {
-                Endpoint endpoint = (Endpoint) dao;
+                Endpoint endpoint = (Endpoint) old;
                 LOG.debug("Removed Endpoint {}", endpoint);
                 removeFaasEndpointLocationIfExist(endpoint.getTenant(), endpoint.getL2Context(),
                         endpoint.getMacAddress());
             } else if (old instanceof EndpointL3) {
-                EndpointL3 endpoint = (EndpointL3) dao;
+                EndpointL3 endpoint = (EndpointL3) old;
                 LOG.debug("Removed EndpointL3 {}", endpoint);
                 removeFaasEndpointLocationIfExist(endpoint.getTenant(), endpoint.getL2Context(),
                         endpoint.getMacAddress());
             } else if (old instanceof EndpointL3Prefix) {
-                LOG.warn("Not Handled Event Yet by Faas Renderer. Removed EndpointL3Prefix {}", (EndpointL3Prefix) old);
+                LOG.warn("Not Handled Event Yet by Faas Renderer. Removed EndpointL3Prefix {}", old);
             }
         }
     }
@@ -158,7 +160,7 @@ public class FaasEndpointManagerListener implements DataChangeListener, AutoClos
         }
         epLocBuilder.setUuid(epId);
         Uuid faasSubnetId = getFaasSubnetId(endpoint);
-        List<PrivateIps> privateIpAddresses = new ArrayList<PrivateIps>();
+        List<PrivateIps> privateIpAddresses = new ArrayList<>();
         for (L3Address ip : endpoint.getL3Address()) {
             PrivateIpsBuilder ipBuilder = new PrivateIpsBuilder();
             ipBuilder.setIpAddress(ip.getIpAddress());
index 3c2e86189307658fa4001373e3db237ab869a5da..8d1f364d77c1a06d7ec5cb835b8b9a90ed17a4cc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015 Huawei Technologies 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
@@ -19,6 +19,8 @@ import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledExecutorService;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
@@ -82,8 +84,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-
 public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(FaasPolicyManager.class);
@@ -93,7 +93,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
     private final DataBroker dataProvider;
     protected final Map<Pair<EndpointGroupId, TenantId>, List<SubnetId>> epgSubnetsMap = new HashMap<>();
     private final ConcurrentHashMap<TenantId, Uuid> mappedTenants = new ConcurrentHashMap<>();
-    protected final ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<DataChangeListener>>> registeredTenants = new ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<DataChangeListener>>>();
+    protected final ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<DataChangeListener>>> registeredTenants =
+            new ConcurrentHashMap<>();
 
     public FaasPolicyManager(DataBroker dataBroker, ScheduledExecutorService executor) {
         this.dataProvider = dataBroker;
@@ -250,7 +251,7 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
             /*
              * tenant registrations
              */
-            ArrayList<ListenerRegistration<DataChangeListener>> list = new ArrayList<ListenerRegistration<DataChangeListener>>();
+            ArrayList<ListenerRegistration<DataChangeListener>> list = new ArrayList<>();
             ListenerRegistration<DataChangeListener> reg;
             // contracts
             reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
@@ -316,7 +317,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         }
     }
 
-    private void registerFollowedEndpointgroup(TenantId gbpTenantId, EndpointGroupId epgId) {
+    @VisibleForTesting
+    void registerFollowedEndpointgroup(TenantId gbpTenantId, EndpointGroupId epgId) {
         if (epgId == null) {
             return;
         }
@@ -339,7 +341,7 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         if (val != null) {
             return val;
         }
-        Uuid faasTenantId = null;
+        Uuid faasTenantId;
         if (isUUid(tenantId.getValue())) {
             faasTenantId = new Uuid(tenantId.getValue());
         } else {
@@ -370,7 +372,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         ArrayList<ListenerRegistration<DataChangeListener>> list = registeredTenants.remove(tenantId);
         if (list != null) {
             for (ListenerRegistration<DataChangeListener> reg : list) {
-                reg.close();
+                if (reg != null)
+                    reg.close();
             }
             LOG.debug("Unregistered tenant {}", tenantId);
         }
@@ -385,7 +388,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return registeredTenants.containsKey(tenantId);
     }
 
-    private boolean handledPolicy(ResolvedPolicy policy) {
+    @VisibleForTesting
+    boolean handledPolicy(ResolvedPolicy policy) {
         if (!policy.getConsumerTenantId().equals(policy.getProviderTenantId())) {
             // FAAS always assumes consumer and provider EPGs belong to the same tenant
             LOG.warn(
@@ -393,10 +397,7 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
                     policy.getConsumerTenantId().getValue(), policy.getProviderTenantId().getValue());
             return false;
         }
-        if (!isTenantRegistered(policy.getConsumerTenantId())) {
-            return false;
-        }
-        return true;
+        return isTenantRegistered(policy.getConsumerTenantId());
     }
 
     private boolean isEqualService(ResolvedPolicy newPolicy, ResolvedPolicy oldPolicy) {
@@ -413,10 +414,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
     private void registerSubnetWithEpg(EndpointGroupId epgId, TenantId tenantId, SubnetId subnetId, boolean updateLn) {
         synchronized (this) {
             List<SubnetId> subnets = cloneAndGetEpgSubnets(epgId, tenantId);
-            for (SubnetId id : subnets) {
-                if (id.equals(subnetId)) {
-                    return;
-                }
+            if(subnets.contains(subnetId)){
+                return;
             }
             subnets.add(subnetId);
             epgSubnetsMap.put(new Pair<>(epgId, tenantId), subnets);
@@ -427,7 +426,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         }
     }
 
-    private void removeLogicalNetwork(ResolvedPolicy oldPolicy) {
+    @VisibleForTesting
+    void removeLogicalNetwork(ResolvedPolicy oldPolicy) {
         if (oldPolicy == null) {
             return;
         }
@@ -812,7 +812,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return builder;
     }
 
-    protected boolean needToCreateLogicalNetwork(ServiceCommunicationLayer comLayer, List<SubnetId> consSubnetIds,
+    @VisibleForTesting
+    boolean needToCreateLogicalNetwork(ServiceCommunicationLayer comLayer, List<SubnetId> consSubnetIds,
             List<SubnetId> provSubnetIds, TenantId tenantId, ContractId contractId, EndpointGroup providerEpg,
             EndpointGroup consumerEpg, ExternalImplicitGroup externalImplicitGroup) {
         Optional<LogicalNetwork> lnOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
@@ -841,10 +842,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
             return true;
         }
         Set<SubnetId> lnProvSubnets = new HashSet<>(logicalNet.getProviderNetwork().getGbpSubnetId());
-        if (lnProvSubnets.size() != provSubnetIds.size() || !lnProvSubnets.containsAll(provSubnetIds)) {
-            return true;
-        }
-        return false;
+        return lnProvSubnets.size() != provSubnetIds.size() || !lnProvSubnets.containsAll(
+                provSubnetIds);
     }
 
     private ServiceCommunicationLayer findLayerNetwork(TenantId tenantId, List<SubnetId> consSubnetIds,
@@ -950,7 +949,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return null;
     }
 
-    protected L3Context readL3ContextInstance(TenantId tenantId, L3ContextId l3cId) {
+    @VisibleForTesting
+    L3Context readL3ContextInstance(TenantId tenantId, L3ContextId l3cId) {
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         InstanceIdentifier<L3Context> iid = IidFactory.l3ContextIid(tenantId, l3cId);
         Optional<L3Context> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
@@ -962,7 +962,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return l2Op.get();
     }
 
-    protected L2BridgeDomain readL2BridgeDomainInstance(TenantId tenantId, L2BridgeDomainId l2bId) {
+    @VisibleForTesting
+    L2BridgeDomain readL2BridgeDomainInstance(TenantId tenantId, L2BridgeDomainId l2bId) {
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         InstanceIdentifier<L2BridgeDomain> iid = IidFactory.l2BridgeDomainIid(tenantId, l2bId);
         Optional<L2BridgeDomain> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
@@ -974,7 +975,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return l2Op.get();
     }
 
-    protected L2FloodDomain readL2FloodDomain(L2FloodDomainId l2fId, TenantId tenantId) {
+    @VisibleForTesting
+    L2FloodDomain readL2FloodDomain(L2FloodDomainId l2fId, TenantId tenantId) {
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         InstanceIdentifier<L2FloodDomain> iid = IidFactory.l2FloodDomainIid(tenantId, l2fId);
         Optional<L2FloodDomain> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
@@ -1023,7 +1025,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         removeTenantLogicalNetwork(gbpTenantId, faasTenantId, true);
     }
 
-    private void removeTenantLogicalNetwork(TenantId gbpTenantId, Uuid faasTenantId, boolean unregister) {
+    @VisibleForTesting
+    void removeTenantLogicalNetwork(TenantId gbpTenantId, Uuid faasTenantId, boolean unregister) {
         UlnDatastoreApi.removeTenantFromDsIfExists(faasTenantId);
         synchronized (this) {
             mappedTenants.remove(gbpTenantId);
index 4a3f6aab33f53e5983cdd37813edde7326b9802c..9f00538ed230109dc192b14f075664415eb75fcd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015 Huawei Technologies 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
@@ -14,6 +14,7 @@ import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledExecutorService;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
@@ -69,7 +70,8 @@ public class FaasSubnetManagerListener implements DataChangeListener {
         });
     }
 
-    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+    @VisibleForTesting
+    void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
         // Create
         for (DataObject dao : change.getCreatedData().values()) {
             if (dao instanceof Subnet) {
@@ -82,7 +84,7 @@ public class FaasSubnetManagerListener implements DataChangeListener {
         Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData();
         for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) {
             if (entry.getValue() instanceof Subnet) {
-                Subnet subnet = (Subnet) dao;
+                Subnet subnet = (Subnet) entry.getValue();
                 LOG.debug("Subnet {} is Updated.", subnet.getId().getValue());
                 UlnDatastoreApi.submitSubnetToDs(initSubnetBuilder(subnet).build());
             }
index c7a9179c422ab2a1eb5a942df8ef573415a232be..bb6f7408c9cbe10fa44efa25a8276da430bf9794 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015 Huawei Technologies 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
@@ -9,6 +9,7 @@ package org.opendaylight.groupbasedpolicy.renderer.faas;
 
 import java.util.concurrent.ScheduledExecutorService;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
@@ -45,7 +46,8 @@ public class FaasTenantManagerListener implements DataChangeListener {
         });
     }
 
-    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+    @VisibleForTesting
+    void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
         // Remove
         for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
             DataObject old = change.getOriginalData().get(iid);
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasContractManagerListenerCovrgTest.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasContractManagerListenerCovrgTest.java
new file mode 100644 (file)
index 0000000..4e9a599
--- /dev/null
@@ -0,0 +1,91 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
+import org.opendaylight.groupbasedpolicy.renderer.faas.test.DataChangeListenerTester;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.SecurityRuleGroups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ContractBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+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;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(UlnDatastoreApi.class)
+public class FaasContractManagerListenerCovrgTest {
+
+    private InstanceIdentifier<Contract> contractIid;
+    private ContractId contractId = new ContractId("contractId");
+    private FaasContractManagerListener listener;
+    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+    private TenantId gbpTenantId = new TenantId("b4511aac-ae43-11e5-bf7f-feff819cdc9f");
+    private Uuid faasTenantId = new Uuid("b4511aac-ae43-11e5-bf7f-feff819cdc9f");
+    private DataChangeListenerTester tester;
+    private DataBroker dataProvider;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void init() {
+        contractIid = mock(InstanceIdentifier.class);
+        dataProvider = mock(DataBroker.class);
+
+        listener = new FaasContractManagerListener(dataProvider, gbpTenantId, faasTenantId, executor);
+        tester = new DataChangeListenerTester(listener);
+        tester.setRemovedPath(contractIid);
+    }
+
+    @Test
+    public void testT() throws ReadFailedException {
+        PowerMockito.mockStatic(UlnDatastoreApi.class);
+        PowerMockito.doNothing().when(UlnDatastoreApi.class);
+        UlnDatastoreApi.submitSecurityGroupsToDs(any(SecurityRuleGroups.class));
+
+        ReadWriteTransaction rwTx = mock(ReadWriteTransaction.class);
+        WriteTransaction woTx = mock(WriteTransaction.class);
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid = mock(CheckedFuture.class);
+        when(rwTx.submit()).thenReturn(futureVoid);
+        when(woTx.submit()).thenReturn(futureVoid);
+        when(dataProvider.newReadWriteTransaction()).thenReturn(rwTx);
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(woTx);
+
+        CheckedFuture<Optional<MappedContract>, ReadFailedException> futureMappedContract = mock(CheckedFuture.class);
+        when(rwTx.read(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedContractIid(gbpTenantId, contractId)))
+            .thenReturn(futureMappedContract);
+        Optional<MappedContract> optMappedContract = mock(Optional.class);
+        when(optMappedContract.isPresent()).thenReturn(true);
+        when(futureMappedContract.checkedGet()).thenReturn(optMappedContract);
+
+        Contract contract = new ContractBuilder().setId(contractId).build();
+        tester.setDataObject(contractIid, contract);
+        listener.executeEvent(tester.getChangeMock());
+    }
+
+    private DataObject makeTestContract() {
+        ContractBuilder builder = new ContractBuilder();
+        builder.setId(new ContractId("b4511aac-ae43-11e5-bf7f-feff819cdc9f"));
+        return builder.build();
+    }
+}
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointAugCovrgTest.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointAugCovrgTest.java
new file mode 100644 (file)
index 0000000..1c1b6f7
--- /dev/null
@@ -0,0 +1,54 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentationRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.faas.endpoint.rev151009.FaasEndpointContextInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
+
+public class FaasEndpointAugCovrgTest {
+
+    EpRendererAugmentationRegistry epRendererAugmentationRegistry;
+
+    @Before
+    public void init() {
+        epRendererAugmentationRegistry = mock(EpRendererAugmentationRegistry.class);
+    }
+
+    @Test
+    public void testBuildEndpointAugmentation() throws Exception {
+        FaasEndpointAug aug = new FaasEndpointAug(epRendererAugmentationRegistry);
+        RegisterEndpointInput registerEndpointInput = mock(RegisterEndpointInput.class);
+        FaasEndpointContextInput pix = mock(FaasEndpointContextInput.class);
+
+        when(registerEndpointInput.getAugmentation(FaasEndpointContextInput.class)).thenReturn(pix);
+        aug.buildEndpointAugmentation(registerEndpointInput);
+
+        when(registerEndpointInput.getAugmentation(FaasEndpointContextInput.class)).thenReturn(null);
+        aug.buildEndpointAugmentation(registerEndpointInput);
+        aug.close();
+    }
+
+    @Test
+    public void testBuildEndpointL3Augmentation() throws Exception {
+        FaasEndpointAug aug = new FaasEndpointAug(epRendererAugmentationRegistry);
+        RegisterEndpointInput registerEndpointInput = mock(RegisterEndpointInput.class);
+
+        aug.buildEndpointL3Augmentation(registerEndpointInput);
+        aug.close();
+    }
+
+    @Test
+    public void testBuildL3PrefixEndpointAugmentation() throws Exception {
+        FaasEndpointAug aug = new FaasEndpointAug(epRendererAugmentationRegistry);
+        RegisterL3PrefixEndpointInput registerL3PrefixEndpointInput = mock(RegisterL3PrefixEndpointInput.class);
+
+        aug.buildL3PrefixEndpointAugmentation(registerL3PrefixEndpointInput);
+        aug.close();
+    }
+
+}
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointManagerListenerCovrgTest.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointManagerListenerCovrgTest.java
new file mode 100644 (file)
index 0000000..a59a191
--- /dev/null
@@ -0,0 +1,119 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+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.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.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.groupbasedpolicy.renderer.faas.test.DataChangeListenerTester;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FaasEndpointManagerListenerCovrgTest {
+
+    private static final L2BridgeDomainId L_2_BRIDGE_DOMAIN_ID = new L2BridgeDomainId("L2BridgeDomainId");
+    private static final MacAddress MAC_ADDRESS = new MacAddress("00:00:00:00:35:02");
+
+    private InstanceIdentifier<Endpoint> epIid;
+    private FaasEndpointManagerListener listener;
+    private TenantId gbpTenantId = new TenantId("gbpTenantId");
+    private SubnetId subnetId = new SubnetId("subnetId");
+    private Uuid faasTenantId = new Uuid("b4511aac-ae43-11e5-bf7f-feff819cdc9f");
+    private Uuid faasSubnetId = new Uuid("c4511aac-ae43-11e5-bf7f-feff819cdc9f");
+    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+    private DataChangeListenerTester tester;
+    private DataBroker dataProvider;
+    private FaasPolicyManager faasPolicyManager;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void init() throws ReadFailedException {
+        MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(L_2_BRIDGE_DOMAIN_ID, MAC_ADDRESS);
+
+        dataProvider = mock(DataBroker.class);
+
+        WriteTransaction woTx = mock(WriteTransaction.class);
+        ReadWriteTransaction rwTx = mock(ReadWriteTransaction.class);
+
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid = mock(CheckedFuture.class);
+        when(woTx.submit()).thenReturn(futureVoid);
+        when(rwTx.submit()).thenReturn(futureVoid);
+        doNothing().when(woTx).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
+                any(DataObject.class));
+
+        CheckedFuture<Optional<MappedEndpoint>, ReadFailedException> futureMappedEndpoint = mock(CheckedFuture.class);
+        Optional<MappedEndpoint> optMappedEndpoint = mock(Optional.class);
+        when(optMappedEndpoint.isPresent()).thenReturn(false);
+        when(futureMappedEndpoint.checkedGet()).thenReturn(optMappedEndpoint);
+        when(rwTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedEndpointIid(gbpTenantId, mappedEndpointKey))).thenReturn(futureMappedEndpoint);
+
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(woTx);
+        when(dataProvider.newReadWriteTransaction()).thenReturn(rwTx);
+
+        epIid = mock(InstanceIdentifier.class);
+        faasPolicyManager = spy(new FaasPolicyManager(dataProvider, executor));
+        doNothing().when(faasPolicyManager).removeTenantLogicalNetwork(gbpTenantId, faasTenantId);
+        listener = new FaasEndpointManagerListener(faasPolicyManager, dataProvider, executor);
+        tester = new DataChangeListenerTester(listener);
+        tester.setRemovedPath(epIid);
+    }
+
+    @Test
+    public void testOnDataChanged_Endpoint() {
+        Endpoint ep = new EndpointBuilder().setTenant(gbpTenantId)
+            .setL2Context(L_2_BRIDGE_DOMAIN_ID)
+            .setMacAddress(MAC_ADDRESS)
+            .build();
+        tester.setDataObject(epIid, ep);
+        tester.callOnDataChanged();
+        listener.executeEvent(tester.getChangeMock());
+    }
+
+    @Test
+    public void testOnDataChanged_EndpointL3() {
+        EndpointL3 ep = new EndpointL3Builder().setTenant(gbpTenantId)
+            .setL2Context(L_2_BRIDGE_DOMAIN_ID)
+            .setMacAddress(MAC_ADDRESS)
+            .build();
+        tester.setDataObject(epIid, ep);
+        tester.callOnDataChanged();
+        listener.executeEvent(tester.getChangeMock());
+    }
+
+    @Test
+    public void testOnDataChanged_EndpointL3Prefix() {
+        EndpointL3Prefix ep = new EndpointL3PrefixBuilder().setTenant(gbpTenantId).build();
+        tester.setDataObject(epIid, ep);
+        tester.callOnDataChanged();
+        listener.executeEvent(tester.getChangeMock());
+    }
+
+}
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasIidFactoryTest.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasIidFactoryTest.java
new file mode 100644 (file)
index 0000000..6e650dc
--- /dev/null
@@ -0,0 +1,77 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas;\r
+\r
+import static org.junit.Assert.assertNotNull;\r
+\r
+import org.junit.Test;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointKey;\r
+\r
+public class FaasIidFactoryTest {\r
+\r
+    @Test\r
+    public void testLogicalNetworksIid() {\r
+        assertNotNull(FaasIidFactory.logicalNetworksIid());\r
+    }\r
+\r
+    @Test\r
+    public void testLogicalNetworkIid() {\r
+        EndpointGroupId consumerEpgId = new EndpointGroupId("consumerEpgId");\r
+        TenantId consumerTenantId = new TenantId("consumerTenantId");\r
+        ContractId contractId = new ContractId("contractId");\r
+        EndpointGroupId providerEpgId = new EndpointGroupId("providerEpgId");\r
+        TenantId providerTenantId = new TenantId("providerTenantId");\r
+\r
+        assertNotNull(FaasIidFactory.logicalNetworkIid(consumerEpgId, consumerTenantId, contractId, providerEpgId,\r
+                providerTenantId));\r
+    }\r
+\r
+    @Test\r
+    public void testMappedTenantsEntitiesIid() {\r
+        assertNotNull(FaasIidFactory.mappedTenantsEntitiesIid());\r
+    }\r
+\r
+    @Test\r
+    public void testMappedSubnetIid() {\r
+        TenantId gbpTenantId = new TenantId("gbpTenantId");\r
+        SubnetId subnetId = new SubnetId("subnetId");\r
+\r
+        assertNotNull(FaasIidFactory.mappedSubnetIid(gbpTenantId, subnetId));\r
+    }\r
+\r
+    @Test\r
+    public void testMappedTenantIid() {\r
+        TenantId gbpTenantId = new TenantId("gbpTenantId");\r
+\r
+        assertNotNull(FaasIidFactory.mappedTenantIid(gbpTenantId));\r
+    }\r
+\r
+    @Test\r
+    public void testMappedEntityIid() {\r
+        TenantId gbpTenantId = new TenantId("gbpTenantId");\r
+\r
+        assertNotNull(FaasIidFactory.mappedEntityIid(gbpTenantId));\r
+    }\r
+\r
+    @Test\r
+    public void testMappedContractIid() {\r
+        TenantId gbpTenantId = new TenantId("gbpTenantId");\r
+        ContractId contractId = new ContractId("contractId");\r
+\r
+        assertNotNull(FaasIidFactory.mappedContractIid(gbpTenantId, contractId));\r
+    }\r
+\r
+    @Test\r
+    public void testMappedEndpointIid() {\r
+        TenantId gbpTenantId = new TenantId("gbpTenantId");\r
+        MappedEndpointKey mappedEndpointKey =\r
+                new MappedEndpointKey(new L2BridgeDomainId("L2BridgeDomainId"), new MacAddress("00:00:00:00:35:02"));\r
+\r
+        assertNotNull(FaasIidFactory.mappedEndpointIid(gbpTenantId, mappedEndpointKey));\r
+    }\r
+\r
+}\r
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasPolicyManagerCovrgTest.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasPolicyManagerCovrgTest.java
new file mode 100644 (file)
index 0000000..f4eaebe
--- /dev/null
@@ -0,0 +1,666 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+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.ReadOnlyTransaction;
+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.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.util.TenantUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.LogicalNetworks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.LogicalNetworksBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.ScopeType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.ServiceCommunicationLayer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.LogicalNetwork;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.LogicalNetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.logical.network.ConsumerNetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.logical.network.ProviderNetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedEntity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedTenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy.ExternalImplicitGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroupBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+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;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({UlnDatastoreApi.class})
+public class FaasPolicyManagerCovrgTest {
+
+    private InstanceIdentifier<DataObject> policyId;
+    private AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change;
+    DataBroker dataProvider;
+    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(Runtime.getRuntime()
+        .availableProcessors());
+    EndpointGroupId consumerEpgId = new EndpointGroupId("consumerEpgId");
+    SubnetId consumerSubnet = new SubnetId("consumerSubnet");
+    SubnetId providerSubnet = new SubnetId("providerSubnet");
+    EndpointGroupId providerEpgId = new EndpointGroupId("providerEpgId");
+    ContractId contractId = new ContractId("contractId");
+    TenantId tenantId = new TenantId("tenantId");
+    Uuid faasTenantId = new Uuid("0eb98cf5-086c-4a81-8a4e-0c3b4566108b");
+    Uuid faasSecRulesId = new Uuid("1eb98cf5-086c-4a81-8a4e-0c3b4566108b");
+    L3ContextId l3Context = new L3ContextId("l3ContextId");
+    EndpointGroupId epgId = new EndpointGroupId("epgId");
+    SubnetId subnetId = new SubnetId("subnetId");
+    Uuid dummyUuid1 = new Uuid("2eb98cf5-086c-4a81-8a4e-0c3b4566108b");
+    Uuid dummyUuid2 = new Uuid("3eb98cf5-086c-4a81-8a4e-0c3b4566108b");
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void init() throws Exception {
+        policyId = mock(InstanceIdentifier.class);
+        change = mock(AsyncDataChangeEvent.class);
+        policyId = mock(InstanceIdentifier.class);
+        dataProvider = mock(DataBroker.class);
+
+        WriteTransaction writeTransaction = mock(WriteTransaction.class);
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid =
+                mock(CheckedFuture.class);
+        when(writeTransaction.submit()).thenReturn(futureVoid);
+
+        Set<InstanceIdentifier<?>> removedPaths = new HashSet<>();
+        removedPaths.add(policyId);
+        when(change.getRemovedPaths()).thenReturn(removedPaths);
+    }
+
+    @Test
+    public void testConstructor() throws Exception {
+        FaasPolicyManager other = new MockFaasPolicyManager(dataProvider, executor);
+
+        verify(dataProvider).registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(ResolvedPolicies.class)
+                        .child(ResolvedPolicy.class)
+                        .build(), other, AsyncDataBroker.DataChangeScope.SUBTREE);
+        other.close();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testRegisterTenant() throws Exception {
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        ReadWriteTransaction rwTx = mock(ReadWriteTransaction.class);
+        when(dataProvider.newReadWriteTransaction()).thenReturn(rwTx);
+
+        CheckedFuture<Optional<MappedTenant>, ReadFailedException> futureMappedTenant =
+                mock(CheckedFuture.class);
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedTenantIid(tenantId))).thenReturn(futureMappedTenant);
+        Optional<MappedTenant> optMappedTenant = mock(Optional.class);
+        when(optMappedTenant.isPresent()).thenReturn(false);
+        when(futureMappedTenant.checkedGet()).thenReturn(optMappedTenant);
+
+        CheckedFuture<Optional<Tenant>, ReadFailedException> futureTenant =
+                mock(CheckedFuture.class);
+        when(roTx.read(LogicalDatastoreType.CONFIGURATION,
+                TenantUtils.tenantIid(tenantId))).thenReturn(futureTenant);
+        Optional<Tenant> optTenant = mock(Optional.class);
+        when(futureTenant.checkedGet()).thenReturn(optTenant);
+
+        CheckedFuture<Optional<MappedEntity>, ReadFailedException> futureMappedEntity =
+                mock(CheckedFuture.class);
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedEntityIid(tenantId))).thenReturn(futureMappedEntity);
+        Optional<MappedEntity> optMappedEntity = mock(Optional.class);
+        when(futureMappedEntity.checkedGet()).thenReturn(optMappedEntity);
+
+        CheckedFuture<Optional<ResolvedPolicies>, ReadFailedException> futureResolvedPolicies =
+                mock(CheckedFuture.class);
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(ResolvedPolicies.class).build())).thenReturn(futureResolvedPolicies);
+        Optional<ResolvedPolicies> optResolvedPolicies = mock(Optional.class);
+        when(optResolvedPolicies.isPresent()).thenReturn(false);
+        when(futureResolvedPolicies.checkedGet()).thenReturn(optResolvedPolicies);
+
+        CheckedFuture<Optional<LogicalNetworks>, ReadFailedException> futureLogicalNetworks =
+                mock(CheckedFuture.class);
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.logicalNetworksIid())).thenReturn(futureLogicalNetworks);
+        LogicalNetworks logicalNetworks = new LogicalNetworksBuilder()
+                .setLogicalNetwork( new ArrayList<LogicalNetwork>())
+                .build();
+        Optional<LogicalNetworks> optLogicalNetworks = mock(Optional.class);
+        when(optLogicalNetworks.isPresent()).thenReturn(true);
+        when(optLogicalNetworks.get()).thenReturn(logicalNetworks);
+        when(futureLogicalNetworks.checkedGet()).thenReturn(optLogicalNetworks);
+
+        EndpointGroupId epgId = new EndpointGroupId("epgId");
+        FaasPolicyManager policyManager = spy(new FaasPolicyManager(dataProvider, executor));
+        doNothing().when(policyManager).removeTenantLogicalNetwork(tenantId, faasTenantId, false);
+
+        policyManager.registerTenant(tenantId, epgId);
+    }
+
+    @Test
+    public void testRegisterTenant_null(){
+        FaasPolicyManager policyManager = spy(new FaasPolicyManager(dataProvider, executor));
+        doNothing().when(policyManager).registerTenant(tenantId, null);
+
+        policyManager.registerTenant(tenantId);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testRemoveTenantLogicalNetwork() throws ReadFailedException {
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        ReadWriteTransaction rwTx = mock(ReadWriteTransaction.class);
+        when(dataProvider.newReadWriteTransaction()).thenReturn(rwTx);
+
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid = mock(CheckedFuture.class);
+        when(rwTx.submit()).thenReturn(futureVoid);
+
+        CheckedFuture<Optional<LogicalNetworks>, ReadFailedException> futureLogicalNetworks =
+                mock(CheckedFuture.class);
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.logicalNetworksIid())).thenReturn(futureLogicalNetworks);
+        List<LogicalNetwork> lns = new ArrayList<>();
+        LogicalNetwork ln = new LogicalNetworkBuilder()
+                .setConsumerEpgId(consumerEpgId)
+                .setConsumerTenantId(tenantId)
+                .setContractId(contractId)
+                .setProviderEpgId(providerEpgId)
+                .setProviderTenantId(tenantId)
+                .build();
+        lns.add(ln);
+        LogicalNetworks logicalNetworks = new LogicalNetworksBuilder()
+                .setLogicalNetwork(lns)
+                .build();
+        Optional<LogicalNetworks> optLogicalNetworks = mock(Optional.class);
+        when(optLogicalNetworks.isPresent()).thenReturn(true);
+        when(optLogicalNetworks.get()).thenReturn(logicalNetworks);
+        when(futureLogicalNetworks.checkedGet()).thenReturn(optLogicalNetworks);
+
+        CheckedFuture<Optional<LogicalNetwork>, ReadFailedException> futureLogicalNetwork =
+                mock(CheckedFuture.class);
+        when(rwTx.read(eq(LogicalDatastoreType.OPERATIONAL),
+                eq(FaasIidFactory.logicalNetworkIid(consumerEpgId, tenantId, contractId,
+                        providerEpgId, tenantId)))).thenReturn(futureLogicalNetwork);
+        Optional<LogicalNetwork> optionalLogicalNetwork = mock(Optional.class);
+        when(futureLogicalNetwork.checkedGet()).thenReturn(optionalLogicalNetwork);
+
+        CheckedFuture<Optional<MappedEntity>, ReadFailedException> futureMappedEntity =
+                mock(CheckedFuture.class);
+        when(rwTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedEntityIid(tenantId))).thenReturn(futureMappedEntity);
+        Optional<MappedEntity> optMappedEntity = mock(Optional.class);
+        when(optMappedEntity.isPresent()).thenReturn(true);
+        when(futureMappedEntity.checkedGet()).thenReturn(optMappedEntity);
+
+        CheckedFuture<Optional<MappedTenant>, ReadFailedException> futureMappedTenant =
+                mock(CheckedFuture.class);
+        when(rwTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedTenantIid(tenantId))).thenReturn(futureMappedTenant);
+        Optional<MappedTenant> optMappedTenant = mock(Optional.class);
+        when(optMappedTenant.isPresent()).thenReturn(true);
+        when(futureMappedTenant.checkedGet()).thenReturn(optMappedTenant);
+
+        PowerMockito.mockStatic(UlnDatastoreApi.class);
+        PowerMockito.doNothing().when(UlnDatastoreApi.class);
+        UlnDatastoreApi.removeTenantFromDsIfExists(any(Uuid.class));
+
+        FaasPolicyManager policyManager = spy(new FaasPolicyManager(dataProvider, executor));
+
+        policyManager.removeTenantLogicalNetwork(tenantId, faasTenantId);
+    }
+
+    @Test
+    public void testUnregisterTenant() throws Exception {
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+
+        policyManager.unregisterTenant(tenantId);
+    }
+
+    @Test
+    public void testIsUuid(){
+        assertFalse(FaasPolicyManager.isUUid(null));
+        assertFalse(FaasPolicyManager.isUUid("non-matching string"));
+        assertTrue(FaasPolicyManager.isUUid("12345678-1234-5123-b123-0123456789ab"));
+    }
+
+    @Test
+    public void testHandledPolicy_notEquals(){
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+        ResolvedPolicy policy = new ResolvedPolicyBuilder()
+                .setConsumerTenantId(new TenantId("t1"))
+                .setProviderTenantId(new TenantId("t2"))
+                .build();
+
+        assertFalse(policyManager.handledPolicy(policy));
+    }
+
+    @Test
+    public void testRegisterFollowedEndpointgroup(){
+        EndpointGroupId epgId = new EndpointGroupId("epgId");
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+
+        policyManager.registerFollowedEndpointgroup(tenantId, null);
+        policyManager.registerFollowedEndpointgroup(tenantId, epgId);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testRegisterSubnetWithEpg() throws ReadFailedException {
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        CheckedFuture<Optional<ResolvedPolicies>, ReadFailedException> futureResolvedPolicies =
+                mock(CheckedFuture.class);
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(ResolvedPolicies.class).build())).thenReturn(futureResolvedPolicies);
+        Optional<ResolvedPolicies> optResolvedPolicies = mock(Optional.class);
+        when(optResolvedPolicies.isPresent()).thenReturn(false);
+        when(futureResolvedPolicies.checkedGet()).thenReturn(optResolvedPolicies);
+
+
+        policyManager.registerSubnetWithEpg(epgId, tenantId, subnetId);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadEndpointGroup() throws ReadFailedException {
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        CheckedFuture<Optional<EndpointGroup>, ReadFailedException> futureEndpointGroup =
+                mock(CheckedFuture.class);
+        Optional<EndpointGroup> optEndpointGroup = mock(Optional.class);
+        when(optEndpointGroup.isPresent()).thenReturn(true);
+        when(futureEndpointGroup.checkedGet()).thenReturn(optEndpointGroup);
+        when(roTx.read(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.endpointGroupIid(tenantId, epgId))).thenReturn(futureEndpointGroup);
+        doNothing().when(roTx).close();
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        policyManager.readEndpointGroup(epgId, tenantId);
+
+        when(optEndpointGroup.isPresent()).thenReturn(false);
+        policyManager.readEndpointGroup(epgId, tenantId);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadSubnet() throws ReadFailedException {
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        CheckedFuture<Optional<Subnet>, ReadFailedException> futureSubnet =
+                mock(CheckedFuture.class);
+        Optional<Subnet> optSubnet = mock(Optional.class);
+        when(optSubnet.isPresent()).thenReturn(true);
+        when(futureSubnet.checkedGet()).thenReturn(optSubnet);
+        when(roTx.read(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetId))).thenReturn(futureSubnet);
+        doNothing().when(roTx).close();
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        policyManager.readSubnet(subnetId, tenantId);
+
+        when(optSubnet.isPresent()).thenReturn(false);
+        policyManager.readSubnet(subnetId, tenantId);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadL3ContextInstance() throws ReadFailedException {
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        CheckedFuture<Optional<L3Context>, ReadFailedException> futureL3Context =
+                mock(CheckedFuture.class);
+        Optional<L3Context> optL3Context = mock(Optional.class);
+        when(optL3Context.isPresent()).thenReturn(true);
+        when(futureL3Context.checkedGet()).thenReturn(optL3Context);
+
+        L3ContextId l3cId = new L3ContextId("l3cId");
+        when(roTx.read(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3cId))).thenReturn(futureL3Context);
+        doNothing().when(roTx).close();
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        policyManager.readL3ContextInstance(tenantId, l3cId);
+
+        when(optL3Context.isPresent()).thenReturn(false);
+        policyManager.readL3ContextInstance(tenantId, l3cId);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadL2BridgeDomainInstance() throws ReadFailedException {
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        CheckedFuture<Optional<L2BridgeDomain>, ReadFailedException> futureL2BridgeDomain =
+                mock(CheckedFuture.class);
+        Optional<L2BridgeDomain> optL2BridgeDomain = mock(Optional.class);
+        when(optL2BridgeDomain.isPresent()).thenReturn(true);
+        when(futureL2BridgeDomain.checkedGet()).thenReturn(optL2BridgeDomain);
+
+        L2BridgeDomainId l2bId = new L2BridgeDomainId("l2bId");
+        when(roTx.read(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId,
+                l2bId))).thenReturn(futureL2BridgeDomain);
+        doNothing().when(roTx).close();
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        policyManager.readL2BridgeDomainInstance(tenantId, l2bId);
+
+        when(optL2BridgeDomain.isPresent()).thenReturn(false);
+        policyManager.readL2BridgeDomainInstance(tenantId, l2bId);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadL2FloodDomain() throws ReadFailedException {
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        CheckedFuture<Optional<L2FloodDomain>, ReadFailedException> futureL2FloodDomain =
+                mock(CheckedFuture.class);
+        Optional<L2FloodDomain> optL2FloodDomain = mock(Optional.class);
+        when(optL2FloodDomain.isPresent()).thenReturn(true);
+        when(futureL2FloodDomain.checkedGet()).thenReturn(optL2FloodDomain);
+
+        L2FloodDomainId l2fId = new L2FloodDomainId("l2fId");
+        when(roTx.read(LogicalDatastoreType.CONFIGURATION, IidFactory.l2FloodDomainIid(tenantId,
+                l2fId))).thenReturn(futureL2FloodDomain);
+        doNothing().when(roTx).close();
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        policyManager.readL2FloodDomain(l2fId, tenantId);
+
+        when(optL2FloodDomain.isPresent()).thenReturn(false);
+        policyManager.readL2FloodDomain(l2fId, tenantId);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testNeedToCreateLogicalNetwork() throws ReadFailedException {
+
+        ServiceCommunicationLayer comLayer = ServiceCommunicationLayer.Layer2;
+        List<SubnetId> consSubnetIds = new ArrayList<>();
+        SubnetId consSubnetId = new SubnetId("consSubnetId");
+        consSubnetIds.add(consSubnetId);
+        List<SubnetId> provSubnetIds = new ArrayList<>();
+        SubnetId provSubnetId = new SubnetId("provSubnetId");
+        provSubnetIds.add(provSubnetId);
+        ContractId contractId = new ContractId("contractId");
+        EndpointGroup providerEpg = new EndpointGroupBuilder()
+                .setId(providerEpgId)
+                .build();
+        EndpointGroup consumerEpg = new EndpointGroupBuilder()
+                .setId(consumerEpgId)
+                .build();
+        ExternalImplicitGroup externalImplicitGroup = ExternalImplicitGroup.ProviderEpg;
+
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+        CheckedFuture<Optional<LogicalNetwork>, ReadFailedException> futureLogicalNetwork =
+                mock(CheckedFuture.class);
+        Optional<LogicalNetwork> optLogicalNetwork = mock(Optional.class);
+        when(optLogicalNetwork.isPresent()).thenReturn(true);
+        LogicalNetwork logicalNet =
+                new LogicalNetworkBuilder()
+                        .setCommunicationLayer(ServiceCommunicationLayer.Layer2)
+                        .setConsumerNetwork(
+                                new ConsumerNetworkBuilder().setNetworkScopeType(ScopeType.Private)
+                                        .setGbpSubnetId(consSubnetIds)
+                                        .build())
+                        .setProviderNetwork(
+                                new ProviderNetworkBuilder().setNetworkScopeType(ScopeType.Public)
+                                        .setGbpSubnetId(provSubnetIds)
+                                        .build())
+                        .build();
+        when(optLogicalNetwork.get()).thenReturn(logicalNet);
+        when(futureLogicalNetwork.checkedGet()).thenReturn(optLogicalNetwork);
+
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.logicalNetworkIid(consumerEpg.getId(), tenantId, contractId,
+                        providerEpg.getId(), tenantId))).thenReturn(futureLogicalNetwork);
+        doNothing().when(roTx).close();
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        policyManager.needToCreateLogicalNetwork(comLayer, consSubnetIds, provSubnetIds, tenantId,
+                contractId, providerEpg, consumerEpg, externalImplicitGroup);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testRemoveLogicalNetwork()
+            throws ReadFailedException, TransactionCommitFailedException {
+        ServiceCommunicationLayer comLayer = ServiceCommunicationLayer.Layer2;
+        List<SubnetId> consSubnetIds = new ArrayList<>();
+        SubnetId consSubnetId = new SubnetId("consSubnetId");
+        consSubnetIds.add(consSubnetId);
+        List<SubnetId> provSubnetIds = new ArrayList<>();
+        SubnetId provSubnetId = new SubnetId("provSubnetId");
+        provSubnetIds.add(provSubnetId);
+        ContractId contractId = new ContractId("contractId");
+        EndpointGroup providerEpg = new EndpointGroupBuilder()
+                .setId(providerEpgId)
+                .build();
+        EndpointGroup consumerEpg = new EndpointGroupBuilder()
+                .setId(consumerEpgId)
+                .build();
+        ExternalImplicitGroup externalImplicitGroup = ExternalImplicitGroup.ProviderEpg;
+
+        PowerMockito.mockStatic(UlnDatastoreApi.class);
+        PowerMockito.doNothing().when(UlnDatastoreApi.class);
+        UlnDatastoreApi.removeLogicalSwitchFromDsIfExists(any(Uuid.class), any(Uuid.class));
+        PowerMockito.doNothing().when(UlnDatastoreApi.class);
+        UlnDatastoreApi.removeLogicalRouterFromDsIfExists(any(Uuid.class), any(Uuid.class));
+
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+        ReadWriteTransaction rwTx = mock(ReadWriteTransaction.class);
+        CheckedFuture<Optional<LogicalNetwork>, ReadFailedException> futureLogicalNetwork =
+                mock(CheckedFuture.class);
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid =
+                mock(CheckedFuture.class);
+        Optional<LogicalNetwork> optLogicalNetwork = mock(Optional.class);
+        Optional<Void> optVoid = mock(Optional.class);
+        when(optLogicalNetwork.isPresent()).thenReturn(true);
+        LogicalNetwork logicalNet =
+                new LogicalNetworkBuilder().setCommunicationLayer(ServiceCommunicationLayer.Layer2)
+                        .setConsumerNetwork(
+                                new ConsumerNetworkBuilder().setNetworkScopeType(ScopeType.Private)
+                                        .setGbpSubnetId(consSubnetIds)
+                                        .setLogicalRouterId(dummyUuid1)
+                                        .build())
+                        .setProviderNetwork(
+                                new ProviderNetworkBuilder().setNetworkScopeType(ScopeType.Public)
+                                        .setGbpSubnetId(provSubnetIds)
+                                        .setLogicalRouterId(dummyUuid2).build())
+                        .setConsumerTenantId(tenantId)
+                        .setProviderTenantId(tenantId)
+                        .build();
+        when(optLogicalNetwork.get()).thenReturn(logicalNet);
+        when(futureLogicalNetwork.checkedGet()).thenReturn(optLogicalNetwork);
+        when(futureVoid.checkedGet()).thenReturn(null);
+
+        when(rwTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.logicalNetworkIid(consumerEpg.getId(), tenantId, contractId,
+                        providerEpg.getId(), tenantId))).thenReturn(futureLogicalNetwork);
+        when(rwTx.submit()).thenReturn(futureVoid);
+        when(dataProvider.newReadWriteTransaction()).thenReturn(rwTx);
+
+        List<PolicyRuleGroup> prg = new ArrayList<>();
+        PolicyRuleGroup prgElement = new PolicyRuleGroupBuilder()
+                .setContractId(new ContractId("contractId"))
+                .build();
+        prg.add(prgElement);
+        List<PolicyRuleGroupWithEndpointConstraints> prgwec = new ArrayList<>();
+        PolicyRuleGroupWithEndpointConstraints prgwecElement = new PolicyRuleGroupWithEndpointConstraintsBuilder()
+                .setPolicyRuleGroup(prg)
+                .build();
+        prgwec.add(prgwecElement);
+        ResolvedPolicy oldPolicy = new ResolvedPolicyBuilder()
+                .setConsumerEpgId(consumerEpgId)
+                .setConsumerTenantId(tenantId)
+                .setProviderEpgId(providerEpgId)
+                .setProviderTenantId(tenantId)
+                .setPolicyRuleGroupWithEndpointConstraints(prgwec)
+                .build();
+
+        policyManager.removeLogicalNetwork(oldPolicy);
+
+    }
+
+    @Test
+    public void testRemoveLogicalNetwork_null(){
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+
+        policyManager.removeLogicalNetwork(null);
+    }
+
+    /*@SuppressWarnings("unchecked")
+    @Test
+    public void testCreateLayer3LogicalNetwork() throws ReadFailedException {
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);
+
+        CheckedFuture<Optional<ResolvedPolicies>, ReadFailedException> futureResolvedPolicies =
+                mock(CheckedFuture.class);
+        Optional<ResolvedPolicies> optResolvedPolicies = mock(Optional.class);
+        when(futureResolvedPolicies.checkedGet()).thenReturn(optResolvedPolicies);
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(ResolvedPolicies.class).build())).thenReturn(
+                futureResolvedPolicies);
+
+        MappedSubnet mappedSubnet = new MappedSubnetBuilder()
+                .setFaasSubnetId(dummyUuid1)
+                .build();
+        CheckedFuture<Optional<MappedSubnet>, ReadFailedException> futureMappedSubnet =
+                mock(CheckedFuture.class);
+        Optional<MappedSubnet> optMappedSubnet = mock(Optional.class);
+        when(optMappedSubnet.isPresent()).thenReturn(true);
+        when(optMappedSubnet.get()).thenReturn(mappedSubnet);
+        when(futureMappedSubnet.checkedGet()).thenReturn(optMappedSubnet);
+        when(roTx.read(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedSubnetIid(tenantId, subnetId))).thenReturn(
+                futureMappedSubnet);
+
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);
+
+        EndpointGroup consumerEpg = new EndpointGroupBuilder().setId(consumerEpgId).build();
+        EndpointGroup providerEpg = new EndpointGroupBuilder().setId(providerEpgId).build();
+        FaasPolicyManager policyManager = new FaasPolicyManager(dataProvider, executor);
+
+        policyManager.registerSubnetWithEpg(consumerEpgId, tenantId, consumerSubnet);
+        policyManager.registerSubnetWithEpg(providerEpgId, tenantId, providerSubnet);
+        policyManager.createLayer3LogicalNetwork(consumerEpg, contractId, providerEpg, tenantId,
+                ServiceCommunicationLayer.Layer3, ExternalImplicitGroup.ProviderEpg);
+    }*/
+
+
+
+
+
+    private L3Context makeTestL3Context() {
+        L3ContextBuilder builder = new L3ContextBuilder();
+        builder.setId(l3Context);
+        return builder.build();
+    }
+
+    private L2FloodDomain makeTestL2FloodDomain(String id, L2BridgeDomainId brdgId) {
+        L2FloodDomainBuilder builder = new L2FloodDomainBuilder();
+        builder.setId(new L2FloodDomainId(id));
+        builder.setParent(brdgId);
+        return builder.build();
+    }
+
+    private L2BridgeDomain makeTestBridgeDomain(String id) {
+        L2BridgeDomainBuilder builder = new L2BridgeDomainBuilder();
+        builder.setId(new L2BridgeDomainId(id));
+        builder.setParent(l3Context);
+        return builder.build();
+    }
+
+    private EndpointGroup makeTestEndpointGroup(EndpointGroupId epgId) {
+        EndpointGroupBuilder builder = new EndpointGroupBuilder();
+        builder.setId(epgId);
+        return builder.build();
+    }
+
+    private Subnet makeTestSubnet(SubnetId subnetId, L2FloodDomainId l2FloodDomainId) {
+        SubnetBuilder builder = new SubnetBuilder();
+        builder.setId(subnetId);
+        builder.setParent(l2FloodDomainId);
+        return builder.build();
+
+    }
+
+    private DataObject makeTestResolvedPolicy() {
+        ResolvedPolicyBuilder builder = new ResolvedPolicyBuilder();
+        builder.setConsumerEpgId(consumerEpgId);
+        builder.setConsumerTenantId(tenantId);
+        builder.setProviderEpgId(providerEpgId);
+        builder.setProviderTenantId(tenantId);
+        List<PolicyRuleGroupWithEndpointConstraints> pRulesGrpsWEp = new ArrayList<>();
+        PolicyRuleGroupWithEndpointConstraintsBuilder pRulesGrpWEp = new PolicyRuleGroupWithEndpointConstraintsBuilder();
+        List<PolicyRuleGroup> pRulesGrps = new ArrayList<>();
+        PolicyRuleGroupBuilder pRulesGrp = new PolicyRuleGroupBuilder();
+        pRulesGrp.setContractId(contractId);
+        pRulesGrps.add(pRulesGrp.build());
+        pRulesGrpWEp.setPolicyRuleGroup(pRulesGrps);
+        pRulesGrpsWEp.add(pRulesGrpWEp.build());
+        builder.setPolicyRuleGroupWithEndpointConstraints(pRulesGrpsWEp);
+        return builder.build();
+    }
+
+    private DataObject makeTestResolvedPolicyWithImpExternalEpg() {
+        ResolvedPolicyBuilder builder = new ResolvedPolicyBuilder((ResolvedPolicy) makeTestResolvedPolicy());
+        builder.setExternalImplicitGroup(ExternalImplicitGroup.ConsumerEpg);
+        return builder.build();
+    }
+}
index 1fa1ca12578ee38b55d51b5d11d4371ccfaa4828..77f0869240605e66c50fb88aecaa192f2f835dae 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016 Huawei Technologies 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
@@ -64,8 +64,6 @@ import org.powermock.modules.junit4.PowerMockRunner;
 
 import com.google.common.util.concurrent.CheckedFuture;
 
-@PrepareForTest(UlnDatastoreApi.class)
-@RunWith(PowerMockRunner.class)
 public class FaasPolicyManagerTest {
 
     private InstanceIdentifier<DataObject> policyId;
@@ -90,7 +88,6 @@ public class FaasPolicyManagerTest {
         change = mock(AsyncDataChangeEvent.class);
         policyId = mock(InstanceIdentifier.class);
         dataProvider = mock(DataBroker.class);
-        PowerMockito.mockStatic(UlnDatastoreApi.class);
         WriteTransaction writeTransaction = mock(WriteTransaction.class);
         when(dataProvider.newWriteOnlyTransaction()).thenReturn(writeTransaction);
         CheckedFuture<Void, TransactionCommitFailedException> checkedFuture = mock(CheckedFuture.class);
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasRendererCovrgTest.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasRendererCovrgTest.java
new file mode 100644 (file)
index 0000000..deed396
--- /dev/null
@@ -0,0 +1,36 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Test;
+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.groupbasedpolicy.api.EpRendererAugmentationRegistry;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FaasRendererCovrgTest {
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testConstructor() throws Exception {
+        DataBroker dataProvider = mock(DataBroker.class);
+        EpRendererAugmentationRegistry epRendererAugmentationRegistry = mock(EpRendererAugmentationRegistry.class);
+
+        WriteTransaction wTx = mock(WriteTransaction.class);
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid = mock(CheckedFuture.class);
+        when(wTx.submit()).thenReturn(futureVoid);
+        doNothing().when(wTx).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
+                any(DataObject.class));
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(wTx);
+
+        FaasRenderer renderer = new FaasRenderer(dataProvider, epRendererAugmentationRegistry);
+        renderer.close();
+    }
+}
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasSubnetManagerListenerCovrgTest.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasSubnetManagerListenerCovrgTest.java
new file mode 100644 (file)
index 0000000..76c2de9
--- /dev/null
@@ -0,0 +1,148 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
+import org.opendaylight.groupbasedpolicy.renderer.faas.test.DataChangeListenerTester;
+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.IpPrefix;
+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.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.subnet.Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.subnet.GatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.subnet.gateways.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.subnet.gateways.PrefixesBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+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;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(UlnDatastoreApi.class)
+public class FaasSubnetManagerListenerCovrgTest {
+
+    private InstanceIdentifier<Subnet> subnetIid;
+    private FaasSubnetManagerListener listener;
+    private TenantId gbpTenantId = new TenantId("gbpTenantId");
+    private SubnetId subnetId = new SubnetId("subnetId");
+    private Uuid faasTenantId = new Uuid("b4511aac-ae43-11e5-bf7f-feff819cdc9f");
+    private Uuid faasSubnetId = new Uuid("c4511aac-ae43-11e5-bf7f-feff819cdc9f");
+    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+    private DataChangeListenerTester tester;
+    private DataBroker dataProvider;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void init() {
+        dataProvider = mock(DataBroker.class);
+        subnetIid = mock(InstanceIdentifier.class);
+        listener = new FaasSubnetManagerListener(dataProvider, gbpTenantId, faasTenantId, executor);
+        tester = new DataChangeListenerTester(listener);
+        tester.setRemovedPath(subnetIid);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testOnDataChanged() throws ReadFailedException {
+        PowerMockito.mockStatic(UlnDatastoreApi.class);
+        PowerMockito.doNothing().when(UlnDatastoreApi.class);
+        UlnDatastoreApi.submitSubnetToDs(any(
+                org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.subnets.rev151013.subnets.container.subnets.Subnet.class));
+        PowerMockito.doNothing().when(UlnDatastoreApi.class);
+        UlnDatastoreApi.removeSubnetFromDsIfExists(any(Uuid.class), any(Uuid.class));
+
+        ReadWriteTransaction rwTx = mock(ReadWriteTransaction.class);
+        WriteTransaction woTx = mock(WriteTransaction.class);
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid = mock(CheckedFuture.class);
+        when(rwTx.submit()).thenReturn(futureVoid);
+        when(woTx.submit()).thenReturn(futureVoid);
+
+        CheckedFuture<Optional<MappedSubnet>, ReadFailedException> futureMappedSubnet = mock(CheckedFuture.class);
+        Optional<MappedSubnet> optMappedSubnet = mock(Optional.class);
+        when(optMappedSubnet.isPresent()).thenReturn(true);
+        when(futureMappedSubnet.checkedGet()).thenReturn(optMappedSubnet);
+        when(rwTx.read(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedSubnetIid(gbpTenantId, subnetId)))
+            .thenReturn(futureMappedSubnet);
+        doNothing().when(woTx).put(eq(LogicalDatastoreType.OPERATIONAL),
+                eq(FaasIidFactory.mappedSubnetIid(gbpTenantId, subnetId)), any(MappedSubnet.class));
+
+        when(dataProvider.newReadWriteTransaction()).thenReturn(rwTx);
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(woTx);
+
+        Subnet subnet = new SubnetBuilder().setId(subnetId).build();
+        tester.setDataObject(subnetIid, subnet);
+        tester.callOnDataChanged();
+        listener.executeEvent(tester.getChangeMock());
+    }
+
+    @Test
+    public void testLoadAll() {
+        PowerMockito.mockStatic(UlnDatastoreApi.class);
+        PowerMockito.doNothing().when(UlnDatastoreApi.class);
+        UlnDatastoreApi.submitSubnetToDs(any(
+                org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.subnets.rev151013.subnets.container.subnets.Subnet.class));
+
+        List<Subnet> subnets = new ArrayList<>();
+        List<MappedSubnet> mpSubnets = new ArrayList<>();
+
+        Subnet subnet = new SubnetBuilder().setId(subnetId).build();
+        subnets.add(subnet);
+        MappedSubnet mappedSubnet =
+                new MappedSubnetBuilder().setGbpSubnetId(subnetId).setFaasSubnetId(faasSubnetId).build();
+        mpSubnets.add(mappedSubnet);
+
+        listener.loadAll(subnets, mpSubnets);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testInitSubnetBuilder() {
+        WriteTransaction wTx = mock(WriteTransaction.class);
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid = mock(CheckedFuture.class);
+        when(wTx.submit()).thenReturn(futureVoid);
+        doNothing().when(wTx).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
+                any(DataObject.class));
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(wTx);
+
+        List<Gateways> gatewaysList = new ArrayList<>();
+        List<Prefixes> prefixesList = new ArrayList<>();
+        Prefixes prefixes = new PrefixesBuilder().setPrefix(new IpPrefix(new Ipv4Prefix("10.0.0.0/8"))).build();
+        prefixesList.add(prefixes);
+        Gateways gateways = new GatewaysBuilder().setGateway(new IpAddress(new Ipv4Address("10.0.0.55")))
+            .setPrefixes(prefixesList)
+            .build();
+        gatewaysList.add(gateways);
+
+        Subnet subnet = new SubnetBuilder().setId(subnetId).setGateways(gatewaysList).build();
+        listener.initSubnetBuilder(subnet);
+    }
+
+}
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasTenantManagerListenerCovrgTest.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasTenantManagerListenerCovrgTest.java
new file mode 100644 (file)
index 0000000..03f2655
--- /dev/null
@@ -0,0 +1,66 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+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.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.faas.test.DataChangeListenerTester;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FaasTenantManagerListenerCovrgTest {
+
+    private InstanceIdentifier<Tenant> tenantIid;
+    private FaasPolicyManager faasPolicyManager;
+    private FaasTenantManagerListener listener;
+    private TenantId gbpTenantId = new TenantId("gbpTenantId");
+    private Uuid faasTenantId = new Uuid("b4511aac-ae43-11e5-bf7f-feff819cdc9f");
+    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+    private DataChangeListenerTester tester;
+    private DataBroker dataProvider;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void init() {
+        dataProvider = mock(DataBroker.class);
+        WriteTransaction wTx = mock(WriteTransaction.class);
+        CheckedFuture<Void, TransactionCommitFailedException> futureVoid = mock(CheckedFuture.class);
+        when(wTx.submit()).thenReturn(futureVoid);
+        doNothing().when(wTx).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
+                any(DataObject.class));
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(wTx);
+
+        tenantIid = mock(InstanceIdentifier.class);
+        faasPolicyManager = spy(new FaasPolicyManager(dataProvider, executor));
+        doNothing().when(faasPolicyManager).removeTenantLogicalNetwork(gbpTenantId, faasTenantId);
+        listener = new FaasTenantManagerListener(faasPolicyManager, gbpTenantId, faasTenantId, executor);
+        tester = new DataChangeListenerTester(listener);
+        tester.setRemovedPath(tenantIid);
+
+    }
+
+    @Test
+    public void testOnDataChanged() {
+        Tenant tenant = new TenantBuilder().setId(gbpTenantId).build();
+        tester.setDataObject(tenantIid, tenant);
+        tester.callOnDataChanged();
+        listener.executeEvent(tester.getChangeMock());
+    }
+
+}
diff --git a/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/test/DataChangeListenerTester.java b/renderers/faas/src/test/java/org/opendaylight/groupbasedpolicy/renderer/faas/test/DataChangeListenerTester.java
new file mode 100644 (file)
index 0000000..a732b1e
--- /dev/null
@@ -0,0 +1,66 @@
+package org.opendaylight.groupbasedpolicy.renderer.faas.test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class DataChangeListenerTester {
+
+    private AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeMock;
+    private DataChangeListener listener;
+
+    private Map<InstanceIdentifier<?>, DataObject> testData;
+    private Set<InstanceIdentifier<?>> removedPaths;
+
+    @SuppressWarnings("unchecked")
+    public DataChangeListenerTester(DataChangeListener listener) {
+        changeMock = mock(AsyncDataChangeEvent.class);
+        testData = new HashMap<>();
+        removedPaths = new HashSet<>();
+
+        this.listener = listener;
+
+        when(changeMock.getCreatedData()).thenReturn(testData);
+        when(changeMock.getOriginalData()).thenReturn(testData);
+        when(changeMock.getUpdatedData()).thenReturn(testData);
+        when(changeMock.getRemovedPaths()).thenReturn(removedPaths);
+    }
+
+    public AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> getChangeMock() {
+        return changeMock;
+    }
+
+    public DataChangeListenerTester setDataObject(InstanceIdentifier<? extends DataObject> iid, DataObject dataObject){
+        testData.clear();
+        return addDataObject(iid, dataObject);
+    }
+
+    public DataChangeListenerTester addDataObject(InstanceIdentifier<? extends DataObject> iid, DataObject dataObject){
+        testData.put(iid, dataObject);
+        return this;
+    }
+
+    public DataChangeListenerTester setRemovedPath(InstanceIdentifier<? extends DataObject> iid){
+        removedPaths.clear();
+        return addRemovedPath(iid);
+    }
+
+    public DataChangeListenerTester addRemovedPath(InstanceIdentifier<? extends DataObject> iid){
+        removedPaths.add(iid);
+        return this;
+    }
+
+    public void callOnDataChanged(){
+        listener.onDataChanged(changeMock);
+    }
+
+}
index f888de8f1a783d426ae1c14584836031291e27cd..d6e5ad4f8e53cba70d590cc0fb889560f7619530 100644 (file)
@@ -8,8 +8,12 @@
 
 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;
+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.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.IosXeRendererProvider;
@@ -21,10 +25,30 @@ import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.NodeManager;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerZipImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.sf.ChainAction;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.sf.Classifier;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.sf.EtherTypeClassifier;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.sf.IpProtoClassifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+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.RendererBuilder;
+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.CapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedActionDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinitionBuilder;
+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
  */
@@ -87,5 +111,54 @@ public class IosXeRendererProviderImpl implements IosXeRendererProvider, Binding
         rendererConfigurationListener = new RendererConfigurationListenerImpl(dataBroker, rendererName, policyManagerZip);
         // supported node list maintenance
         // TODO: upkeep of available renderer-nodes
+
+        // provide renderer capabilities
+        writeRendererCapabilities();
+    }
+
+    private void writeRendererCapabilities() {
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+        ChainAction action = new ChainAction();
+        List<SupportedActionDefinition> actionDefinitions =
+                ImmutableList.of(new SupportedActionDefinitionBuilder().setActionDefinitionId(action.getId())
+                    .setSupportedParameterValues(action.getSupportedParameterValues())
+                    .build());
+
+        Classifier etherClassifier = new EtherTypeClassifier(null);
+        Classifier ipProtoClassifier = new IpProtoClassifier(etherClassifier.getId());
+        List<SupportedClassifierDefinition> classifierDefinitions = ImmutableList
+            .of(new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(etherClassifier.getId())
+                .setParentClassifierDefinitionId(etherClassifier.getParent())
+                .setSupportedParameterValues(etherClassifier.getSupportedParameterValues())
+                .build(),
+                new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(ipProtoClassifier.getId())
+                .setParentClassifierDefinitionId(ipProtoClassifier.getParent())
+                .setSupportedParameterValues(ipProtoClassifier.getSupportedParameterValues())
+                .build());
+
+        Renderer renderer = new RendererBuilder().setName(NodeManager.iosXeRenderer)
+            .setCapabilities(new CapabilitiesBuilder().setSupportedActionDefinition(actionDefinitions)
+                .setSupportedClassifierDefinition(classifierDefinitions)
+                .build())
+            .build();
+
+        InstanceIdentifier<Renderer> iid = InstanceIdentifier.builder(Renderers.class)
+        .child(Renderer.class, new RendererKey(new RendererName(NodeManager.iosXeRenderer)))
+        .build();
+        writeTransaction.merge(LogicalDatastoreType.OPERATIONAL, iid, renderer, true);
+        CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
+        Futures.addCallback(future, new FutureCallback<Void>() {
+
+            @Override
+            public void onFailure(Throwable throwable) {
+                LOG.error("Could not register renderer {}: {}", renderer, throwable);
+            }
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("Renderer {} successfully registered.", renderer);
+            }
+        });
     }
 }
index 9cb7194d1fd70d9988d7509350243631d4ee27f7..69d4691b614bc9c760e49d9bf493765752aac9b0 100644 (file)
@@ -17,6 +17,8 @@ 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.impl.manager.NodeManager;
 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.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.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -27,7 +29,7 @@ import java.util.Collection;
 
 import static org.opendaylight.sfc.provider.SfcProviderDebug.printTraceStart;
 
-public class IosXeCapableNodeListenerImpl implements DataTreeChangeListener<NetworkTopology>, AutoCloseable {
+public class IosXeCapableNodeListenerImpl implements DataTreeChangeListener<Node>, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(IosXeCapableNodeListenerImpl.class);
     private final NodeManager nodeManager;
@@ -37,29 +39,21 @@ public class IosXeCapableNodeListenerImpl implements DataTreeChangeListener<Netw
 
     public IosXeCapableNodeListenerImpl(final DataBroker dataBroker, final NodeManager nodeManager) {
         this.nodeManager = Preconditions.checkNotNull(nodeManager);
-        final DataTreeIdentifier<NetworkTopology> networkTopologyPath = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
-                InstanceIdentifier.builder(NetworkTopology.class).build());
+        final DataTreeIdentifier<Node> networkTopologyPath = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).child(Node.class).build());
         listenerRegistration = Preconditions.checkNotNull(dataBroker
                 .registerDataTreeChangeListener(networkTopologyPath, this));
         LOG.info("network-topology listener registered");
     }
 
     @Override
-    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<NetworkTopology>> changes) {
+    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> changes) {
         printTraceStart(LOG);
-        for (DataTreeModification<NetworkTopology> modification : changes) {
-            DataObjectModification<NetworkTopology> rootNode = modification.getRootNode();
-            NetworkTopology dataAfter = rootNode.getDataAfter();
-            NetworkTopology dataBefore = rootNode.getDataBefore();
-            if (dataAfter != null && dataBefore == null) {
-                nodeManager.syncNodes(dataAfter.getTopology(), null);
-            }
-            else if (dataAfter == null && dataBefore != null) {
-                nodeManager.syncNodes(null, dataBefore.getTopology());
-            }
-            else if (dataAfter != null) {
-                nodeManager.syncNodes(dataAfter.getTopology(), dataBefore.getTopology());
-            }
+        for (DataTreeModification<Node> modification : changes) {
+            DataObjectModification<Node> rootNode = modification.getRootNode();
+            Node dataAfter = rootNode.getDataAfter();
+            Node dataBefore = rootNode.getDataBefore();
+            nodeManager.syncNodes(dataAfter, dataBefore);
         }
     }
 
index 9b47ca23071a64a4bb324abee41df6b13ca9d126..3214c5753a876722d082065e8ef0ea880d0af4dd 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.controller.md.sal.binding.api.MountPoint;
 import org.opendaylight.controller.md.sal.binding.api.MountPointService;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.NodeWriter;
+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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeKey;
@@ -30,57 +31,159 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 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;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.UnableToConnect;
+
 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 Map<InstanceIdentifier, DataBroker> netconfNodeCache = new HashMap<>();
+    private static final Map<InstanceIdentifier, DataBroker> netconfNodeCache = new HashMap<>();
     private final DataBroker dataBroker;
-    private MountPointService mountService;
+    private final MountPointService mountService;
+    private final List<String> requiredCapabilities;
 
     public NodeManager(final DataBroker dataBroker, BindingAwareBroker.ProviderContext session) {
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         mountService = Preconditions.checkNotNull(session.getSALService(MountPointService.class));
+        requiredCapabilities = new RequiredCapabilities().initializeRequiredCapabilities();
     }
 
-    public static DataBroker getDataBrokerFromCache(InstanceIdentifier iid) {
+    static DataBroker getDataBrokerFromCache(InstanceIdentifier iid) {
         return netconfNodeCache.get(iid); // TODO read from DS
     }
 
-    public void syncNodes(List<Topology> dataAfter, List<Topology> dataBefore) {
-        if (dataAfter != null && !dataAfter.isEmpty()) {
-            updateNodes(dataAfter);
+    public void syncNodes(Node dataAfter, Node dataBefore) {
+        // New node
+        if (dataBefore == null && dataAfter != null) {
+            createNode(dataAfter);
+        }
+        // Connected/disconnected node
+        if (dataBefore != null && dataAfter != null) {
+            updateNode(dataAfter);
+        }
+        // Removed node
+        if (dataBefore != null && dataAfter == null) {
+            removeNode(dataBefore);
         }
     }
 
-    private void updateNodes(List<Topology> data) {
-        // WRITE
-        NodeWriter nodeWriter = new NodeWriter();
-        for (Topology topology : data) {
-            if (topology.getNode() == null || topology.getNode().isEmpty()) {
-                continue;
+    private void createNode(Node node) {
+        LOG.info("Registering new node {}", node.getNodeId().getValue());
+        NetconfNode netconfNode = getNodeAugmentation(node);
+        if (netconfNode == null) {
+            return;
+        }
+        NetconfNodeConnectionStatus.ConnectionStatus connectionStatus = netconfNode.getConnectionStatus();
+        switch (connectionStatus) {
+            case Connecting: {
+                LOG.info("Connecting device {} ...", node.getNodeId().getValue());
+                break;
             }
-            topology.getNode().stream().filter(this::isNetconfDevice).forEach(node -> {
-                DataBroker mountpoint = getNodeMountPoint(topology.getTopologyId(), node);
-                if (mountpoint != null) {
-                    netconfNodeCache.put(getMountpointIid(topology.getTopologyId(), node), mountpoint);
-                    RendererNode rendererNode = remap(topology.getTopologyId(), node);
-                    nodeWriter.write(rendererNode);
-                }
-            });
+            case Connected: {
+                resolveConnectedNode(node, netconfNode);
+                LOG.info("Node {} is ready, added to available nodes for IOS-XE Renderer", node.getNodeId().getValue());
+            }
+            case UnableToConnect: {
+                LOG.info("Unable to connect device {}", node.getNodeId().getValue());
+                break;
+            }
+        }
+    }
+
+    private void updateNode(Node node) {
+        NetconfNode netconfNode = getNodeAugmentation(node);
+        if (netconfNode == null || netconfNode.getConnectionStatus() == null) {
+            return;
+        }
+        NetconfNodeConnectionStatus.ConnectionStatus afterNodeStatus = netconfNode.getConnectionStatus();
+        if (afterNodeStatus.equals(Connected)) {
+            resolveConnectedNode(node, netconfNode);
+            LOG.info("Node {} is ready, added to available nodes for IOS-XE Renderer", node.getNodeId().getValue());
+        }
+        if (afterNodeStatus.equals(Connecting)) {
+            resolveDisconnectedNode(node);
+            LOG.info("Node {} has been disconnected, removing from available nodes", node.getNodeId().getValue());
+        }
+        if (afterNodeStatus.equals(UnableToConnect)) {
+            resolveDisconnectedNode(node);
+            LOG.info("Unable to connect node {}, removing from available nodes", node.getNodeId().getValue());
+        }
+    }
+
+    private void removeNode(Node node) {
+        resolveDisconnectedNode(node);
+        LOG.info("Node {} has been removed", node.getNodeId().getValue());
+    }
+
+    private void resolveConnectedNode(Node node, NetconfNode netconfNode) {
+        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)) {
+            return;
         }
         nodeWriter.commitToDatastore(dataBroker);
+        netconfNodeCache.put(mountPointIid, mountpoint);
     }
 
-    private DataBroker getNodeMountPoint(TopologyId topologyId, Node node) {
-        NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
-        if (netconfNode == null) {
-            return null;
+    private void resolveDisconnectedNode(Node node) {
+        InstanceIdentifier mountPointIid = getMountpointIid(node);
+        RendererNode rendererNode = remapNode(mountPointIid);
+        NodeWriter nodeWriter = new NodeWriter();
+        nodeWriter.cache(rendererNode);
+        nodeWriter.removeFromDatastore(dataBroker);
+        netconfNodeCache.remove(mountPointIid);
+    }
+
+    private RendererNode remapNode(InstanceIdentifier path) {
+        RendererNodeBuilder rendererNodeBuilder = new RendererNodeBuilder();
+        rendererNodeBuilder.setKey(new RendererNodeKey(path))
+                .setNodePath(path);
+        return rendererNodeBuilder.build();
+    }
+
+    private InstanceIdentifier getMountpointIid(Node node) {
+        return InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(TOPOLOGY_ID))
+                .child(Node.class, new NodeKey(node.getNodeId())).build();
+    }
+
+    private boolean isCapableNetconfDevice(Node node, NetconfNode netconfAugmentation) {
+        if (netconfAugmentation.getAvailableCapabilities() == null ||
+                netconfAugmentation.getAvailableCapabilities().getAvailableCapability() == null ||
+                netconfAugmentation.getAvailableCapabilities().getAvailableCapability().isEmpty()) {
+            LOG.warn("Node {} does not contain any capabilities", node.getNodeId().getValue());
+            return true;
+        }
+        if (!capabilityCheck(netconfAugmentation.getAvailableCapabilities().getAvailableCapability())) {
+            LOG.warn("Node {} does not contain all capabilities required by io-xe-renderer",
+                    node.getNodeId().getValue());
+            return true;
         }
-        InstanceIdentifier mountPointIid = getMountpointIid(topologyId, node);
+        return false;
+    }
+
+    private boolean capabilityCheck(final List<String> capabilities) {
+        for (String requiredCapability : requiredCapabilities) {
+            if (!capabilities.contains(requiredCapability)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private DataBroker getNodeMountPoint(InstanceIdentifier mountPointIid) {
         Optional<MountPoint> optionalObject = mountService.getMountPoint(mountPointIid);
         MountPoint mountPoint;
         if (optionalObject.isPresent()) {
@@ -99,33 +202,36 @@ public class NodeManager {
         return null;
     }
 
-    private InstanceIdentifier getMountpointIid(TopologyId topologyId, Node node) {
-        return InstanceIdentifier.builder(NetworkTopology.class)
-                .child(Topology.class, new TopologyKey(topologyId))
-                .child(Node.class, new NodeKey(node.getNodeId())).build();
+    private NetconfNode getNodeAugmentation(Node node) {
+        NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
+        if (netconfNode == null) {
+            LOG.warn("Node {} is not a netconf device", node.getNodeId().getValue());
+            return null;
+        }
+        return netconfNode;
     }
 
-    private RendererNode remap(TopologyId topologyId, Node node) {
-        InstanceIdentifier<Node> nodeIid = InstanceIdentifier.builder(NetworkTopology.class)
-                .child(Topology.class, new TopologyKey(topologyId))
-                .child(Node.class, new NodeKey(node.getNodeId())).build();
-        RendererNodeBuilder rendererNodeBuilder = new RendererNodeBuilder();
-        rendererNodeBuilder.setKey(new RendererNodeKey(nodeIid))
-                .setNodePath(nodeIid);
-        return rendererNodeBuilder.build();
-    }
+    private class RequiredCapabilities {
 
-    private boolean isNetconfDevice(Node node) {
-        NetconfNode netconfAugmentation = node.getAugmentation(NetconfNode.class);
-        if (netconfAugmentation == null) {
-            LOG.debug("Node {} is not a netconf device", node.getNodeId().getValue());
-            return false;
-        }
-        if (netconfAugmentation.getConnectionStatus().equals(NetconfNodeConnectionStatus.ConnectionStatus.Connected)) {
-            LOG.info("Node {} ready", node.getNodeId().getValue());
-            return true;
+        private static final String ned = "(urn:ios?revision=2016-03-08)ned";
+        private static final String tailfCommon = "(http://tail-f.com/yang/common?revision=2015-05-22)tailf-common";
+        private static final String tailfCliExtension = "(http://tail-f.com/yang/common?revision=2015-03-19)tailf-cli-extensions";
+        private static final String tailfMetaExtension = "(http://tail-f.com/yang/common?revision=2013-11-07)tailf-meta-extensions";
+        private static final String ietfYangTypes = "(urn:ietf:params:xml:ns:yang:ietf-yang-types?revision=2013-07-15)ietf-yang-types";
+        private static final String ietfInetTypes = "(urn:ietf:params:xml:ns:yang:ietf-inet-types?revision=2013-07-15)ietf-inet-types";
+
+        /**
+         * Initialize all common capabilities required by IOS-XE renderer. Any connected node is examined whether it's
+         * an appropriate device to handle configuration created by this renderer. A device must support all capabilities
+         * in list below.
+         *
+         * @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};
+            return Arrays.asList(capabilityEntries);
         }
-        LOG.info("Node {} not connected yet", node.getNodeId().getValue());
-        return false;
     }
 }
index 5c12c1806be6eb83b29c0c83410ffcfaa0839f10..c74d18b356fccaad7a4f70e2d01c5ca46b306534 100644 (file)
@@ -13,6 +13,7 @@ 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.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.NodeManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
 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;
@@ -20,6 +21,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.RendererNodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodesBuilder;
 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.RendererNodeKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,19 +38,21 @@ public class NodeWriter {
         rendererNodesCache = new ArrayList<>();
     }
 
-    public void write(RendererNode node) {
+    public void cache(RendererNode node) {
         rendererNodesCache.add(node);
     }
 
+    /**
+     * Put all cached items to data store
+     *
+     * @param dataBroker appropriate data provider
+     */
     public void commitToDatastore(DataBroker dataBroker) {
         RendererNodes rendererNodes = buildRendererNodes();
         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
-        InstanceIdentifier<RendererNodes> Iid = InstanceIdentifier.builder(Renderers.class)
-                .child(Renderer.class, new RendererKey(new RendererName("ios-xe-renderer"))) // TODO unify renderer name
-                .child(RendererNodes.class)
-                .build();
+        InstanceIdentifier<RendererNodes> iid = buildRendererNodesIid();
         try {
-            wtx.merge(LogicalDatastoreType.OPERATIONAL, Iid, rendererNodes, true);
+            wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, rendererNodes, true);
             CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
             submitFuture.checkedGet();
             // Clear cache
@@ -60,10 +64,47 @@ public class NodeWriter {
         }
     }
 
+    /**
+     * Removes all cached items from data store
+     *
+     * @param dataBroker appropriate data provider
+     */
+    public void removeFromDatastore(DataBroker dataBroker) {
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        for (RendererNode nodeToRemove : rendererNodesCache) {
+            InstanceIdentifier<RendererNode> iid = buildRendererNodeIid(nodeToRemove);
+            try {
+                wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+                CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+                submitFuture.checkedGet();
+                // Clear cache
+            } catch (TransactionCommitFailedException e) {
+                LOG.error("Write transaction failed to {}", e.getMessage());
+            } catch (Exception e) {
+                LOG.error("Failed to .. {}", e.getMessage());
+            }
+        }
+        rendererNodesCache.clear();
+    }
+
+    private InstanceIdentifier<RendererNodes> buildRendererNodesIid() {
+        return InstanceIdentifier.builder(Renderers.class)
+                .child(Renderer.class, new RendererKey(new RendererName(NodeManager.iosXeRenderer))) // TODO unify renderer name
+                .child(RendererNodes.class)
+                .build();
+    }
+
+    private InstanceIdentifier<RendererNode> buildRendererNodeIid(RendererNode rendererNode) {
+        return InstanceIdentifier.builder(Renderers.class)
+                .child(Renderer.class, new RendererKey(new RendererName(NodeManager.iosXeRenderer))) // TODO unify renderer name
+                .child(RendererNodes.class)
+                .child(RendererNode.class, new RendererNodeKey(rendererNode.getNodePath()))
+                .build();
+    }
+
     private RendererNodes buildRendererNodes() {
         RendererNodesBuilder rendererNodesBuilder = new RendererNodesBuilder();
         rendererNodesBuilder.setRendererNode(new ArrayList<>(rendererNodesCache));
         return rendererNodesBuilder.build();
     }
-
 }
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/Action.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/Action.java
new file mode 100644 (file)
index 0000000..fb4e5ca
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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.sf;
+
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.Validator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.action.definition.SupportedParameterValues;
+
+public abstract class Action implements Validator<ActionInstance> {
+
+    /**
+     * Get the action definition for this action.
+     *
+     * @return the {@link ActionDefinition} for this action
+     */
+    public abstract ActionDefinitionId getId();
+
+    /**
+     * The result represents supported parameters for the action by renderer.
+     *
+     * @return list of supported parameters by the action
+     */
+    public abstract List<SupportedParameterValues> getSupportedParameterValues();
+
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/ChainAction.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/ChainAction.java
new file mode 100644 (file)
index 0000000..01fb987
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.sf;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.ValidationResult;
+import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
+import org.opendaylight.groupbasedpolicy.dto.ValidationResultBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.action.definition.SupportedParameterValues;
+
+public class ChainAction extends Action {
+
+    @Override
+    public ActionDefinitionId getId() {
+        return ChainActionDefinition.ID;
+    }
+
+    @Override
+    public ValidationResult validate(ActionInstance actionInstance) {
+        return new ValidationResultBuilder().success().build();
+    }
+
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+        // allow action definition has no parameter
+        return Collections.emptyList();
+    }
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/Classifier.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/Classifier.java
new file mode 100644 (file)
index 0000000..ffb78e8
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.sf;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+
+/**
+ * Represent a classifier definition.
+ */
+public abstract class Classifier {
+
+    protected final ClassifierDefinitionId parent;
+
+    protected Classifier(ClassifierDefinitionId parent) {
+        this.parent = parent;
+    }
+
+    /**
+     * Get the classifier definition id for this classifier.
+     *
+     * @return the {@link ClassifierDefinitionId} for this classifier
+     */
+    public abstract ClassifierDefinitionId getId();
+
+    /**
+     * Get parent for this classifier.
+     *
+     * @return parent classifier, see {@link Classifier}
+     */
+    public final ClassifierDefinitionId getParent() {
+        return parent;
+    }
+
+    /**
+     * The result represents supported parameters for the classifier by renderer.
+     *
+     * @return list of supported parameters by the classifier
+     */
+    public abstract List<SupportedParameterValues> getSupportedParameterValues();
+
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/EtherTypeClassifier.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/EtherTypeClassifier.java
new file mode 100644 (file)
index 0000000..7c1aa53
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.sf;
+
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.sf.EtherTypeClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Match on the ether type of the traffic.
+ */
+public class EtherTypeClassifier extends Classifier {
+
+    public EtherTypeClassifier(ClassifierDefinitionId parent) {
+        super(parent);
+    }
+
+    @Override
+    public ClassifierDefinitionId getId() {
+        return EtherTypeClassifierDefinition.ID;
+    }
+
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+
+        List<SupportedIntValue> values = ImmutableList.of(
+                new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.IPv4_VALUE).build(),
+                new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.IPv6_VALUE).build());
+        SupportedParameterValuesBuilder builder = new SupportedParameterValuesBuilder();
+        builder.setParameterName(new ParameterName(EtherTypeClassifierDefinition.ETHERTYPE_PARAM));
+        builder.setParameterType(new IntBuilder().setSupportedIntValue(values).build());
+
+        return ImmutableList.of(builder.build());
+    }
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/IpProtoClassifier.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/sf/IpProtoClassifier.java
new file mode 100644 (file)
index 0000000..e185737
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.sf;
+
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.sf.IpProtoClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Match on the IP protocol of IP traffic.
+ */
+public class IpProtoClassifier extends Classifier {
+
+    public IpProtoClassifier(ClassifierDefinitionId parent) {
+        super(parent);
+    }
+
+    @Override
+    public ClassifierDefinitionId getId() {
+        return IpProtoClassifierDefinition.ID;
+    }
+
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+
+        List<SupportedIntValue> values = ImmutableList.of(
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.ICMP_VALUE).build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.SCTP_VALUE).build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.TCP_VALUE).build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.UDP_VALUE).build());
+        SupportedParameterValuesBuilder builder = new SupportedParameterValuesBuilder();
+        builder.setParameterName(new ParameterName(IpProtoClassifierDefinition.PROTO_PARAM));
+        builder.setParameterType(new IntBuilder().setSupportedIntValue(values).build());
+
+        return ImmutableList.of(builder.build());
+    }
+}
index f5e21304251dc94ba939a5cd9f5c3b7019a610af..183d236ebfdfbd940e0d38971418d8a306588ad7 100644 (file)
@@ -24,9 +24,9 @@ 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.impl.manager.NodeManager;
 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.NetworkTopologyBuilder;
-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.TopologyBuilder;
+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;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 
 /**
@@ -40,19 +40,19 @@ public class IosXeCapableNodeListenerImplTest {
     @Mock
     private NodeManager nodeManager;
     @Mock
-    private ListenerRegistration<DataTreeChangeListener<NetworkTopology>> listenerRegistration;
+    private ListenerRegistration<DataTreeChangeListener<Node>> listenerRegistration;
     @Mock
-    private DataTreeModification<NetworkTopology> dataTreeModification;
+    private DataTreeModification<Node> dataTreeModification;
     @Mock
-    private DataObjectModification<NetworkTopology> rootNode;
+    private DataObjectModification<Node> rootNode;
 
     private IosXeCapableNodeListenerImpl listener;
 
     @Before
     public void setUp() throws Exception {
         Mockito.when(dataBroker.registerDataTreeChangeListener(
-                Matchers.<DataTreeIdentifier<NetworkTopology>>any(),
-                Matchers.<DataTreeChangeListener<NetworkTopology>>any()))
+                Matchers.<DataTreeIdentifier<Node>>any(),
+                Matchers.<DataTreeChangeListener<Node>>any()))
                 .thenReturn(listenerRegistration);
         listener = new IosXeCapableNodeListenerImpl(dataBroker, nodeManager);
         Mockito.verify(dataBroker).registerDataTreeChangeListener(
@@ -67,44 +67,42 @@ public class IosXeCapableNodeListenerImplTest {
 
     @Test
     public void testOnDataTreeChanged_add() throws Exception {
-        final NetworkTopology networkTopology = createNetworkTopology("topology-id-1");
+        final Node topologyNode = createNetworkTopologyNode("topology-node-id-1");
         Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
-        Mockito.when(rootNode.getDataBefore()).thenReturn(networkTopology);
+        Mockito.when(rootNode.getDataBefore()).thenReturn(topologyNode);
         Mockito.when(rootNode.getDataAfter()).thenReturn(null);
 
         listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(nodeManager).syncNodes(null, networkTopology.getTopology());
+        Mockito.verify(nodeManager).syncNodes(null, topologyNode);
     }
 
 
     @Test
     public void testOnDataTreeChanged_update() throws Exception {
-        final NetworkTopology networkTopologyBefore = createNetworkTopology("topology-id-1");
-        final NetworkTopology networkTopologyAfter = createNetworkTopology("topology-id-2");
+        final Node topologyNodeBefore = createNetworkTopologyNode("topology-node-id-1");
+        final Node topologyNodeAfter = createNetworkTopologyNode("topology-node-id-2");
         Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
-        Mockito.when(rootNode.getDataBefore()).thenReturn(networkTopologyBefore);
-        Mockito.when(rootNode.getDataAfter()).thenReturn(networkTopologyAfter);
+        Mockito.when(rootNode.getDataBefore()).thenReturn(topologyNodeBefore);
+        Mockito.when(rootNode.getDataAfter()).thenReturn(topologyNodeAfter);
 
         listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(nodeManager).syncNodes(networkTopologyAfter.getTopology(), networkTopologyBefore.getTopology());
+        Mockito.verify(nodeManager).syncNodes(topologyNodeAfter, topologyNodeBefore);
     }
 
     @Test
     public void testOnDataTreeChanged_remove() throws Exception {
-        final NetworkTopology networkTopology = createNetworkTopology("topology-id-2");
+        final Node topologyNode = createNetworkTopologyNode("topology-node-id-2");
         Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
         Mockito.when(rootNode.getDataBefore()).thenReturn(null);
-        Mockito.when(rootNode.getDataAfter()).thenReturn(networkTopology);
+        Mockito.when(rootNode.getDataAfter()).thenReturn(topologyNode);
 
         listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
-        Mockito.verify(nodeManager).syncNodes(networkTopology.getTopology(), null);
+        Mockito.verify(nodeManager).syncNodes(topologyNode, null);
     }
 
-    private NetworkTopology createNetworkTopology(final String topologyId) {
-        return new NetworkTopologyBuilder()
-                .setTopology(Collections.singletonList(new TopologyBuilder()
-                        .setTopologyId(new TopologyId(topologyId))
-                        .build()))
+    private Node createNetworkTopologyNode(final String nodeId) {
+        return new NodeBuilder()
+                .setNodeId(new NodeId(nodeId))
                 .build();
     }
 
index 1493283477bdf57009cb5f7c650a2147fe1456ff..810a3f12d82a3a2d51fd10a5e0fdcaa1de1e84e6 100644 (file)
@@ -66,7 +66,7 @@ public class NodeWriterTest {
     @Test
     public void testCommitToDatastore_with_node() throws Exception {
         final RendererNode node = new RendererNodeBuilder().build();
-        nodeWriter.write(node);
+        nodeWriter.cache(node);
         nodeWriter.commitToDatastore(dataBroker);
 
         commonChecks();
index d092fbdeb0648dc11948785a6a5cde7c9f55b362..801a90c1649bda481f910d9db6d86866be1476ac 100755 (executable)
       <artifactId>powermock-api-mockito</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.sun.jersey.jersey-test-framework</groupId>
+      <artifactId>jersey-test-framework-grizzly2</artifactId>
+      <scope>test</scope>
+    </dependency>
 
   </dependencies>
 
index a17c3159f9aa5daab7dbafdbfd3eda77f4c58e68..e28d119b8e8db5e36af84853a9758dc8bda61e13 100755 (executable)
@@ -49,6 +49,8 @@ public class OFStatisticsManager implements AutoCloseable {
     // key is String (not a full IpAddress) because
     // we will get String from REST query to sFlow
     private static ConcurrentMap<String, EndpointL3> endpointL3ByIpMap = new ConcurrentHashMap<>();
+    private static final int CONNECT_TIMEOUT_MILLISEC = 20000;
+    private static final int READ_TIMEOUT_MILLISEC = 30000;
 
     private static final Logger LOG = LoggerFactory.getLogger(OFStatisticsManager.class);
 
@@ -94,7 +96,8 @@ public class OFStatisticsManager implements AutoCloseable {
         epgsByContractId.put(contractId, Pair.of(consEpgKey, provEpgKey));
         boolean isFlowCacheNew = flowCacheNames.add(flowCacheName);
         if (isFlowCacheNew) {
-            SFlowRTConnection sFlowRTConnection = new SFlowRTConnection(executor, sflowCollectorUri, flowCache);
+            SFlowRTConnection sFlowRTConnection = new SFlowRTConnection(executor, sflowCollectorUri, flowCache, new JsonRestClient(sflowCollectorUri, CONNECT_TIMEOUT_MILLISEC,
+                    READ_TIMEOUT_MILLISEC));
             ScheduledFuture<?> collectStatsTask = this.executor.scheduleWithFixedDelay(new ReadGbpFlowCacheTask(flowCacheName, sFlowRTConnection,
                     statisticsManager, MAX_FLOWS, MIN_VALUE_IN_FLOW, AGG_MODE), 0, delay, TimeUnit.SECONDS);
             collectStatsTasks.add(collectStatsTask);
index bd476cf561ce25301494ad3d8ba20701ea818b87..85db48d242bec9484b9f28fc7d6c846aa620d38b 100755 (executable)
@@ -18,6 +18,7 @@ import javax.ws.rs.core.MultivaluedMap;
 
 import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheData;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.SFlowQueryParams;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -31,9 +32,6 @@ public class ReadGbpFlowCacheTask implements Runnable {
 
     private static final Type LIST_OF_FLOW_CACHE_DATA = new TypeToken<List<FlowCacheData>>() {}.getType();
     private static final Gson GSON = new Gson();
-    private static final String MAX_FLOWS_PARAM = "maxFlows";
-    private static final String MIN_VALUE_PARAM = "minValue";
-    private static final String AGG_MODE_PARAM = "aggMode";
 
     private final SFlowRTConnection sFlowRTConnection;
     private final StatisticsManager statisticsManager;
@@ -55,9 +53,9 @@ public class ReadGbpFlowCacheTask implements Runnable {
     @Override
     public void run() {
         MultivaluedMap<String, String> params = new MultivaluedMapImpl();
-        params.add(MAX_FLOWS_PARAM, maxFlows);
-        params.add(MIN_VALUE_PARAM, minValue);
-        params.add(AGG_MODE_PARAM, aggMode);
+        params.add(SFlowQueryParams.MAX_FLOWS, maxFlows);
+        params.add(SFlowQueryParams.MIN_VALUE, minValue);
+        params.add(SFlowQueryParams.AGG_MODE, aggMode);
         JsonRestClientResponse result = sFlowRTConnection.get(path, params);
 
         if (result != null && result.getJsonResponse() != null) {
index 51ccc0f9122bf6b17f0edacd87bf9801c4baebe3..af9bec18044552c2edba32e7ab7e2dc0f9535d4f 100755 (executable)
@@ -51,9 +51,11 @@ public class ResolvedPolicyClassifierListener extends DataTreeChangeHandler<Reso
         ResolvedPolicy resolvedPolicy = rootNode.getDataAfter();
         Map<InstanceIdentifier<Classifier>, Classifier> classifierByIid =
                 resolveClassifiers(resolvedPolicy, rootIdentifier);
-        for (Entry<InstanceIdentifier<Classifier>, Classifier> classfierEntry : classifierByIid.entrySet()) {
-            LOG.trace("New classifier created: {}\n{}", classfierEntry.getKey(), classfierEntry.getValue());
-            ofStatsManager.pullStatsForClassifier(classfierEntry.getKey(), classfierEntry.getValue());
+        for (Entry<InstanceIdentifier<Classifier>, Classifier> classifierEntry : classifierByIid.entrySet()) {
+            LOG.trace("New classifier created: {}\n{}", classifierEntry.getKey(),
+                    classifierEntry.getValue());
+            ofStatsManager.pullStatsForClassifier(classifierEntry.getKey(),
+                    classifierEntry.getValue());
         }
     }
 
index 9a390fec785292fa77410b6f838107fefb51cd45..7189982c856d72c31d0057ef9a8707f5c5878583 100755 (executable)
@@ -21,25 +21,23 @@ public class SFlowRTConnection {
 
     private static final Logger LOG = LoggerFactory.getLogger(SFlowRTConnection.class);
 
-    private static final int CONNECT_TIMEOUT_MILLISEC = 20000;
-    private static final int READ_TIMEOUT_MILLISEC = 30000;
     private static final String GET = "GET";
     private static final String PUT = "PUT";
     private static final String DELETE = "DELETE";
 
+    static final String EX_MSG_NOT_INITIALIZED = "SFlowRTConnection is not initialized.";
+
     private final FlowCache flowCache;
     private JsonRestClient client;
     private boolean isInitialized = false;
     private final ScheduledExecutorService executor;
     private final String collectorUri;
 
-    public SFlowRTConnection(ScheduledExecutorService executor, String collectorUri, FlowCache flowCache) {
+    public SFlowRTConnection(ScheduledExecutorService executor, String collectorUri, FlowCache flowCache, JsonRestClient client) {
         this.executor = Preconditions.checkNotNull(executor);
         this.collectorUri = Preconditions.checkNotNull(collectorUri);
         this.flowCache = Preconditions.checkNotNull(flowCache);
-
-        this.client = new JsonRestClient(collectorUri, CONNECT_TIMEOUT_MILLISEC,
-                READ_TIMEOUT_MILLISEC);
+        this.client = client;
         initialize();
     }
 
@@ -60,7 +58,7 @@ public class SFlowRTConnection {
     public JsonRestClientResponse get(String path,
             MultivaluedMap<String, String> params) {
         if (!isInitialized()) {
-            throw new IllegalStateException("SFlowRTConnection is not initialized.");
+            throw new IllegalStateException(EX_MSG_NOT_INITIALIZED);
         }
         try {
             JsonRestClientResponse responce = client.get(path, params);
@@ -75,7 +73,7 @@ public class SFlowRTConnection {
     @Nullable
     public JsonRestClientResponse put(String path, String someJson) {
         if (!isInitialized()) {
-            throw new IllegalStateException("SFlowRTConnection is not initialized.");
+            throw new IllegalStateException(EX_MSG_NOT_INITIALIZED);
         }
         return putWithoutInitCheck(path, someJson);
     }
@@ -95,7 +93,7 @@ public class SFlowRTConnection {
 
     public JsonRestClientResponse delete(String path) {
         if (!isInitialized()) {
-            throw new IllegalStateException("SFlowRTConnection is not initialized.");
+            throw new IllegalStateException(EX_MSG_NOT_INITIALIZED);
         }
         try {
             JsonRestClientResponse responce = client.delete(path);
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/SFlowQueryParams.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/SFlowQueryParams.java
new file mode 100644 (file)
index 0000000..8e1b9cf
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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.ofoverlay.statistics.util;
+
+public class SFlowQueryParams {
+
+    public static final String MAX_FLOWS = "maxFlows";
+    public static final String MIN_VALUE = "minValue";
+    public static final String AGG_MODE = "aggMode";
+
+}
index 6d6b1eb7eeda39e25331493b8a937be3864c5fda..15453a0750bb5d2b02710fd95566eb4fafd9babc 100644 (file)
@@ -8,11 +8,21 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.arp;
 
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import java.net.InetAddress;
 import java.util.Collections;
 import java.util.concurrent.Future;
 
-import org.junit.Assert;
+import com.google.common.util.concurrent.UncheckedExecutionException;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -102,11 +112,11 @@ public class ArpTaskerTest extends OfOverlayDataBrokerTest {
     @Before
     public void init() {
 
-        PacketProcessingService packetService = Mockito.mock(PacketProcessingService.class);
-        flowService = Mockito.mock(SalFlowService.class);
-        rpcRegistry = Mockito.mock(RpcProviderRegistry.class);
-        Mockito.when(rpcRegistry.getRpcService(PacketProcessingService.class)).thenReturn(packetService);
-        Mockito.when(rpcRegistry.getRpcService(SalFlowService.class)).thenReturn(flowService);
+        PacketProcessingService packetService = mock(PacketProcessingService.class);
+        flowService = mock(SalFlowService.class);
+        rpcRegistry = mock(RpcProviderRegistry.class);
+        when(rpcRegistry.getRpcService(PacketProcessingService.class)).thenReturn(packetService);
+        when(rpcRegistry.getRpcService(SalFlowService.class)).thenReturn(flowService);
     }
 
     @SuppressWarnings("unchecked")
@@ -147,24 +157,25 @@ public class ArpTaskerTest extends OfOverlayDataBrokerTest {
                     .build()));
 
         // test without key
-        ReadOnlyTransaction rtx = Mockito.mock(ReadOnlyTransaction.class);
-        broker = Mockito.mock(DataBroker.class);
+        ReadOnlyTransaction rtx = mock(ReadOnlyTransaction.class);
+        broker = mock(DataBroker.class);
         arpTasker = new ArpTasker(rpcRegistry, broker);
 
-        epL3.setKey(new EndpointL3Key(Mockito.mock(IpAddress.class), null));
+        epL3.setKey(new EndpointL3Key(mock(IpAddress.class), null));
         arpTasker.addMacForL3EpAndCreateEp(epL3.build());
-        Mockito.verify(broker, Mockito.never()).newReadOnlyTransaction();
+        verify(broker, never()).newReadOnlyTransaction();
 
         // test without node with external interface
         epL3.setKey(key);
-        Mockito.when(broker.newReadOnlyTransaction()).thenReturn(rtx);
+        when(broker.newReadOnlyTransaction()).thenReturn(rtx);
         CheckedFuture<Optional<DataObject>, ReadFailedException> future =
                 Futures.immediateCheckedFuture(Optional.<DataObject>absent());
-        Mockito.when(rtx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), Matchers.any(InstanceIdentifier.class)))
+        when(rtx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
+                any(InstanceIdentifier.class)))
             .thenReturn(future);
         arpTasker.addMacForL3EpAndCreateEp(epL3.build());
-        Mockito.verify(broker).newReadOnlyTransaction();
-        Mockito.verify(rtx).close();
+        verify(broker).newReadOnlyTransaction();
+        verify(rtx).close();
 
         // test correct
         broker = getDataBroker();
@@ -177,27 +188,37 @@ public class ArpTaskerTest extends OfOverlayDataBrokerTest {
                 .child(NodeConnector.class, new NodeConnectorKey(connectorId))
                 .build(),
                 connector.build(), true);
-        wtx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(Tenants.class).build(), tenants.build(),
-                true);
+        // ignoring a Windows-specific bug
+        try {
+            wtx.put(LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.builder(Tenants.class).build(), tenants.build(), true);
+        } catch (UncheckedExecutionException e) {
+            assumeNoException(e);
+        }
         wtx.submit().get();
 
-        Future<RpcResult<AddFlowOutput>> flowFuture = Mockito.mock(Future.class);
-        Mockito.when(flowService.addFlow(Mockito.any(AddFlowInput.class))).thenReturn(flowFuture);
+        Future<RpcResult<AddFlowOutput>> flowFuture = mock(Future.class);
+        when(flowService.addFlow(any(AddFlowInput.class))).thenReturn(flowFuture);
 
         epL3.setNetworkContainment(domainId).setTenant(tenantId);
         arpTasker.addMacForL3EpAndCreateEp(epL3.build());
         ArgumentCaptor<AddFlowInput> argument = ArgumentCaptor.forClass(AddFlowInput.class);
-        Mockito.verify(flowService).addFlow(argument.capture());
+        verify(flowService).addFlow(argument.capture());
         AddFlowInput result = argument.getValue();
-        Assert.assertEquals(EtherTypes.ARP.intValue(),
-                result.getMatch().getEthernetMatch().getEthernetType().getType().getValue().intValue());
+        assertEquals(EtherTypes.ARP.intValue(), result.getMatch()
+                .getEthernetMatch()
+                .getEthernetType()
+                .getType()
+                .getValue()
+                .intValue());
         ArpMatch match = (ArpMatch)result.getMatch().getLayer3Match();
-        Assert.assertEquals(ArpOperation.REPLY.intValue(),match.getArpOp().intValue());
-        Assert.assertEquals("192.168.0.254/32",match.getArpTargetTransportAddress().getValue());
-        Assert.assertEquals("192.168.0.1/32", match.getArpSourceTransportAddress().getValue());
-        Assert.assertEquals(connectorId, result.getMatch().getInPort());
-        Assert.assertEquals(new NodeRef(InstanceIdentifier.builder(Nodes.class)
-                .child(Node.class, node.getKey()).build()), result.getNode());
+        assertEquals(ArpOperation.REPLY.intValue(), match.getArpOp().intValue());
+        assertEquals("192.168.0.254/32", match.getArpTargetTransportAddress().getValue());
+        assertEquals("192.168.0.1/32", match.getArpSourceTransportAddress().getValue());
+        assertEquals(connectorId, result.getMatch().getInPort());
+        assertEquals(new NodeRef(
+                InstanceIdentifier.builder(Nodes.class).child(Node.class, node.getKey()).build()),
+                result.getNode());
 
         // onPacketReceived
         Arp arp = new Arp();
@@ -255,13 +276,14 @@ public class ArpTaskerTest extends OfOverlayDataBrokerTest {
         arpTasker.onPacketReceived(packet);
         rtx = broker.newReadOnlyTransaction();
         Optional<EndpointL3> optional = rtx.read(LogicalDatastoreType.OPERATIONAL, epL3Iid).get();
-        Assert.assertTrue(optional.isPresent());
+        assertTrue(optional.isPresent());
         EndpointL3 epl3 = optional.get();
-        Assert.assertArrayEquals(sha, HexEncode.bytesFromHexString(epl3.getMacAddress().getValue()));
-        Assert.assertEquals(l2domain.getId(), epl3.getL2Context());
+        assertArrayEquals(sha, HexEncode.bytesFromHexString(epl3.getMacAddress().getValue()));
+        assertEquals(l2domain.getId(), epl3.getL2Context());
         Optional<Endpoint> optionalEp = rtx.read(LogicalDatastoreType.OPERATIONAL,
                 IidFactory.endpointIid(l2domainId, new MacAddress("00:00:00:00:00:01"))).get();
-        Assert.assertTrue(optionalEp.isPresent());
-        Assert.assertEquals(new OfOverlayContextBuilder(augment).build(), optionalEp.get().getAugmentation(OfOverlayContext.class));
+        assertTrue(optionalEp.isPresent());
+        assertEquals(new OfOverlayContextBuilder(augment).build(),
+                optionalEp.get().getAugmentation(OfOverlayContext.class));
     }
 }
index 7e46d96217ada5ac18525bfa54187f554e774948..3586f03bbfd68554930e44254ed2b9f786561c28 100644 (file)
@@ -8,6 +8,9 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.arp;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
 import java.net.InetAddress;
 
 import org.junit.Assert;
@@ -67,4 +70,11 @@ public class ArpUtilsTest {
         Assert.assertTrue(
                 result.contains("getTargetProtocolAddress()=" + InetAddress.getByAddress(tpa).getHostAddress()));
     }
+
+    @Test
+    public void testBytesToMac(){
+        byte[] macBytes = {0,1,0,1,0,1};
+        assertEquals(new MacAddress("00:01:00:01:00:01"), ArpUtils.bytesToMac(macBytes));
+        assertNull(ArpUtils.bytesToMac(null));
+    }
 }
index 0f92fac41fc2e1cbaed00225f9bb06f4c7b4b84c..c7dc70c39fff521ed0352f26ff47c53ba993f5b0 100755 (executable)
@@ -31,8 +31,7 @@ public class EndpointManagerListenerTest {
         endpointManager = mock(EndpointManager.class);
         DataBroker dataProvider = mock(DataBroker.class);
 
-        EndpointManagerListener endpointManagerListener =
-                new EndpointManagerListener(dataProvider, endpointManager);
+        EndpointManagerListener endpointManagerListener = new EndpointManagerListener(dataProvider, endpointManager);
         tester = new DataChangeListenerTester(endpointManagerListener);
         tester.setRemovedPath(endpointId);
     }
@@ -45,8 +44,7 @@ public class EndpointManagerListenerTest {
         tester.callOnDataChanged();
 
         verify(endpointManager, times(3)).processEndpoint(any(Endpoint.class), any(Endpoint.class));
-        verify(endpointManager, never()).processL3Endpoint(any(EndpointL3.class),
-                any(EndpointL3.class));
+        verify(endpointManager, never()).processL3Endpoint(any(EndpointL3.class), any(EndpointL3.class));
     }
 
     @Test
@@ -57,8 +55,7 @@ public class EndpointManagerListenerTest {
         tester.callOnDataChanged();
 
         verify(endpointManager, never()).processEndpoint(any(Endpoint.class), any(Endpoint.class));
-        verify(endpointManager, times(3)).processL3Endpoint(any(EndpointL3.class),
-                any(EndpointL3.class));
+        verify(endpointManager, times(3)).processL3Endpoint(any(EndpointL3.class), any(EndpointL3.class));
     }
 
     @Test
@@ -69,8 +66,7 @@ public class EndpointManagerListenerTest {
         tester.callOnDataChanged();
 
         verify(endpointManager, never()).processEndpoint(any(Endpoint.class), any(Endpoint.class));
-        verify(endpointManager, never()).processL3Endpoint(any(EndpointL3.class),
-                any(EndpointL3.class));
+        verify(endpointManager, never()).processL3Endpoint(any(EndpointL3.class), any(EndpointL3.class));
     }
 
 }
index 2b59de46991216dc2bef107c0c4a0252d0836fd0..aa54188d21262eb3b68be8562fd8abc78f73eb84 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+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.never;
@@ -16,17 +21,16 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 import java.util.concurrent.ScheduledExecutorService;
 
-import org.junit.Assert;
+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;
@@ -35,7 +39,6 @@ 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.NotificationService;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-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.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
@@ -67,18 +70,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
 public class EndpointManagerTest {
 
     private EndpointManager manager;
@@ -102,6 +99,8 @@ public class EndpointManagerTest {
     private EndpointL3 newL3Ep;
     private Optional<Endpoints> optionalRead;
 
+    // TODO get rid of unnecessary mocks (endpoint1, endpoint2, their parameters)
+
     @SuppressWarnings("unchecked")
     @Before
     public void initialisation() throws Exception {
@@ -114,7 +113,8 @@ public class EndpointManagerTest {
         when(dataProvider.newWriteOnlyTransaction()).thenReturn(writeTransaction);
         CheckedFuture<Void, TransactionCommitFailedException> checkedFutureWrite = mock(CheckedFuture.class);
         when(writeTransaction.submit()).thenReturn(checkedFutureWrite);
-        BindingAwareBroker.RpcRegistration<EndpointService> rpcRegistration = mock(BindingAwareBroker.RpcRegistration.class);
+        BindingAwareBroker.RpcRegistration<EndpointService> rpcRegistration =
+                mock(BindingAwareBroker.RpcRegistration.class);
         listenerReg = mock(ListenerRegistration.class);
         when(dataProvider.registerDataChangeListener(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
                 any(DataChangeListener.class), any(DataChangeScope.class))).thenReturn(listenerReg);
@@ -167,8 +167,8 @@ public class EndpointManagerTest {
         ReadOnlyTransaction readTransaction = mock(ReadOnlyTransaction.class);
         when(dataProvider.newReadOnlyTransaction()).thenReturn(readTransaction);
         CheckedFuture<Optional<Endpoints>, ReadFailedException> checkedFutureRead = mock(CheckedFuture.class);
-        when(readTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(
-                checkedFutureRead);
+        when(readTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
+            .thenReturn(checkedFutureRead);
         optionalRead = mock(Optional.class);
         when(checkedFutureRead.checkedGet()).thenReturn(optionalRead);
         when(optionalRead.isPresent()).thenReturn(false);
@@ -181,39 +181,39 @@ public class EndpointManagerTest {
 
     @Test
     public void getGroupsForNodeTest() {
-        Assert.assertTrue(manager.getGroupsForNode(nodeId1).isEmpty());
+        assertTrue(manager.getGroupsForNode(nodeId1).isEmpty());
         manager.processEndpoint(null, endpoint1);
-        Assert.assertFalse(manager.getGroupsForNode(nodeId1).isEmpty());
+        assertFalse(manager.getGroupsForNode(nodeId1).isEmpty());
     }
 
     @Test
     public void getNodesForGroupTest() {
         EgKey egKey = mock(EgKey.class);
         Set<NodeId> nodesForGroup = manager.getNodesForGroup(egKey);
-        Assert.assertNotNull(nodesForGroup);
-        Assert.assertTrue(nodesForGroup.isEmpty());
+        assertNotNull(nodesForGroup);
+        assertTrue(nodesForGroup.isEmpty());
     }
 
     @Test
     public void getEndpointsForNodeTestNodeIdEgKey() {
         EgKey egKey = new EgKey(tenantId, endpointGroupId);
-        Assert.assertTrue(manager.getEndpointsForNode(nodeId1, egKey).isEmpty());
+        assertTrue(manager.getEndpointsForNode(nodeId1, egKey).isEmpty());
         manager.processEndpoint(null, endpoint1);
-        Assert.assertFalse(manager.getEndpointsForNode(nodeId1, egKey).isEmpty());
+        assertFalse(manager.getEndpointsForNode(nodeId1, egKey).isEmpty());
     }
 
     @Test
     public void getEndpointsForNodeTestNodeId() {
-        Assert.assertTrue(manager.getEndpointsForNode(nodeId1).isEmpty());
+        assertTrue(manager.getEndpointsForNode(nodeId1).isEmpty());
         manager.processEndpoint(null, endpoint1);
-        Assert.assertFalse(manager.getEndpointsForNode(nodeId1).isEmpty());
+        assertFalse(manager.getEndpointsForNode(nodeId1).isEmpty());
     }
 
     @Test
     public void getEndpoint() {
         EpKey epKey = new EpKey(endpoint1.getL2Context(), endpoint1.getMacAddress());
         manager.processEndpoint(null, endpoint1);
-        Assert.assertEquals(endpoint1, manager.getEndpoint(epKey));
+        assertEquals(endpoint1, manager.getEndpoint(epKey));
     }
 
     @SuppressWarnings("unchecked")
@@ -222,8 +222,8 @@ public class EndpointManagerTest {
         ReadOnlyTransaction readTransaction = mock(ReadOnlyTransaction.class);
         when(dataProvider.newReadOnlyTransaction()).thenReturn(readTransaction);
         CheckedFuture<Optional<Endpoints>, ReadFailedException> resultFuture = mock(CheckedFuture.class);
-        when(readTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(
-                resultFuture);
+        when(readTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
+            .thenReturn(resultFuture);
         Optional<Endpoints> optional = mock(Optional.class);
         when(resultFuture.checkedGet()).thenReturn(optional);
         when(optional.isPresent()).thenReturn(true);
@@ -234,7 +234,7 @@ public class EndpointManagerTest {
         when(endpointL3Prefix.getTenant()).thenReturn(tenantId);
 
         Collection<EndpointL3Prefix> result = manager.getEndpointsL3PrefixForTenant(tenantId);
-        Assert.assertTrue(result.contains(endpointL3Prefix));
+        assertTrue(result.contains(endpointL3Prefix));
     }
 
     @SuppressWarnings("unchecked")
@@ -243,24 +243,25 @@ public class EndpointManagerTest {
         ReadOnlyTransaction transaction = mock(ReadOnlyTransaction.class);
         when(dataProvider.newReadOnlyTransaction()).thenReturn(transaction);
         CheckedFuture<Optional<Endpoints>, ReadFailedException> checkedFuture = mock(CheckedFuture.class);
-        when(transaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(checkedFuture);
+        when(transaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
+            .thenReturn(checkedFuture);
         Optional<Endpoints> optional = mock(Optional.class);
         when(checkedFuture.checkedGet()).thenReturn(optional);
         when(optional.isPresent()).thenReturn(false);
-        Assert.assertNull(manager.getEndpointsFromDataStore());
+        assertNull(manager.getEndpointsFromDataStore());
 
         when(optional.isPresent()).thenReturn(true);
         Endpoints endpoints = mock(Endpoints.class);
         when(optional.get()).thenReturn(endpoints);
-        Assert.assertEquals(endpoints, manager.getEndpointsFromDataStore());
+        assertEquals(endpoints, manager.getEndpointsFromDataStore());
 
         manager = new EndpointManager(null, rpcRegistry, notificationService, executor, switchManager);
-        Assert.assertNull(manager.getEndpointsFromDataStore());
+        assertNull(manager.getEndpointsFromDataStore());
     }
 
     @Test
     public void getL3EndpointsTestEndpointsNull() throws Exception {
-        Assert.assertNull(manager.getL3Endpoints());
+        assertNull(manager.getL3Endpoints());
     }
 
     @Test
@@ -270,7 +271,7 @@ public class EndpointManagerTest {
         when(optionalRead.get()).thenReturn(endpoints);
         when(endpoints.getEndpointL3()).thenReturn(null);
 
-        Assert.assertNull(manager.getL3Endpoints());
+        assertNull(manager.getL3Endpoints());
     }
 
     @Test
@@ -281,7 +282,7 @@ public class EndpointManagerTest {
         List<EndpointL3> endpointL3List = Collections.singletonList(mock(EndpointL3.class));
         when(endpoints.getEndpointL3()).thenReturn(endpointL3List);
 
-        Assert.assertEquals(endpointL3List, manager.getL3Endpoints());
+        assertEquals(endpointL3List, manager.getL3Endpoints());
     }
 
     @Test
@@ -301,13 +302,13 @@ public class EndpointManagerTest {
         when(endpointL3.getMacAddress()).thenReturn(mock(MacAddress.class));
 
         Map<EndpointKey, EndpointL3> result = manager.getL3EpWithNatByL2Key();
-        Assert.assertTrue(result.containsValue(endpointL3));
+        assertTrue(result.containsValue(endpointL3));
     }
 
     @Test
     public void getL3EpWithNatByL2KeyTestL3EpsNull() {
         Map<EndpointKey, EndpointL3> result = manager.getL3EpWithNatByL2Key();
-        Assert.assertTrue(result.isEmpty());
+        assertTrue(result.isEmpty());
     }
 
     @Test
@@ -326,7 +327,7 @@ public class EndpointManagerTest {
         when(endpointL3.getMacAddress()).thenReturn(null);
 
         Map<EndpointKey, EndpointL3> result = manager.getL3EpWithNatByL2Key();
-        Assert.assertTrue(result.isEmpty());
+        assertTrue(result.isEmpty());
     }
 
     @Test
@@ -345,26 +346,26 @@ public class EndpointManagerTest {
         when(endpointL3.getMacAddress()).thenReturn(mock(MacAddress.class));
 
         Map<EndpointKey, EndpointL3> result = manager.getL3EpWithNatByL2Key();
-        Assert.assertTrue(result.isEmpty());
+        assertTrue(result.isEmpty());
     }
 
     @Test
     public void getEndpointsForGroupTest() {
         EgKey newEgKey = new EgKey(tenantId, endpointGroupId);
-        Assert.assertTrue(manager.getEndpointsForGroup(newEgKey).isEmpty());
+        assertTrue(manager.getEndpointsForGroup(newEgKey).isEmpty());
         manager.processEndpoint(null, endpoint1);
-        Assert.assertFalse(manager.getEndpointsForGroup(newEgKey).isEmpty());
+        assertFalse(manager.getEndpointsForGroup(newEgKey).isEmpty());
     }
 
     @Test
     public void getConditionsForEndpoint() {
         Endpoint endpoint = mock(Endpoint.class);
         when(endpoint.getCondition()).thenReturn(null);
-        Assert.assertTrue(manager.getConditionsForEndpoint(endpoint).isEmpty());
+        assertTrue(manager.getConditionsForEndpoint(endpoint).isEmpty());
 
         List<ConditionName> conditionNameList = Collections.singletonList(mock(ConditionName.class));
         when(endpoint.getCondition()).thenReturn(conditionNameList);
-        Assert.assertEquals(conditionNameList, manager.getConditionsForEndpoint(endpoint));
+        assertEquals(conditionNameList, manager.getConditionsForEndpoint(endpoint));
     }
 
     @Test
@@ -386,7 +387,7 @@ public class EndpointManagerTest {
         when(endpointL3Key.getIpAddress()).thenReturn(ipAddress);
         when(newL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
         manager.processL3Endpoint(null, newL3Ep);
-        verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
+        verify(endpointListener, never()).endpointUpdated(any(EpKey.class));
     }
 
     @Test
@@ -407,7 +408,7 @@ public class EndpointManagerTest {
         when(endpointL3Key.getIpAddress()).thenReturn(ipAddress);
         when(newL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
         manager.processL3Endpoint(null, newL3Ep);
-        verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
+        verify(endpointListener, never()).endpointUpdated(any(EpKey.class));
     }
 
     @Test
@@ -437,7 +438,7 @@ public class EndpointManagerTest {
         when(newL3Ep.getIpAddress()).thenReturn(null);
         when(newL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
         manager.processL3Endpoint(null, newL3Ep);
-        verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
+        verify(endpointListener, never()).endpointUpdated(any(EpKey.class));
     }
 
     @Test
@@ -447,6 +448,30 @@ public class EndpointManagerTest {
         verify(endpointListener).endpointUpdated(any(EpKey.class));
     }
 
+    @Test
+    public void updateEndpointL3TestUpdate() throws Exception {
+        when(oldL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
+
+        when(newL3Ep.getTenant()).thenReturn(mock(TenantId.class));
+        when(newL3Ep.getEndpointGroup()).thenReturn(mock(EndpointGroupId.class));
+        when(newL3Ep.getL3Context()).thenReturn(mock(L3ContextId.class));
+        when(newL3Ep.getIpAddress()).thenReturn(mock(IpAddress.class));
+
+        OfOverlayL3Context ofOverlayL3Context = mock(OfOverlayL3Context.class);
+        when(newL3Ep.getAugmentation(OfOverlayL3Context.class)).thenReturn(ofOverlayL3Context);
+
+        when(newL3Ep.getNetworkContainment()).thenReturn(null);
+
+        when(newL3Ep.getL2Context()).thenReturn(mock(L2BridgeDomainId.class));
+        when(newL3Ep.getMacAddress()).thenReturn(mock(MacAddress.class));
+        when(newL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
+
+        manager.processL3Endpoint(null, oldL3Ep);
+        manager.processL3Endpoint(oldL3Ep, newL3Ep);
+
+        verify(endpointListener).endpointUpdated(any(EpKey.class));
+    }
+
     @Test
     public void updateEndpointTestNewEndpointRemove() {
         Collection<Endpoint> collection;
@@ -454,13 +479,13 @@ public class EndpointManagerTest {
         verify(endpointListener).endpointUpdated(any(EpKey.class));
         verify(endpointListener).nodeEndpointUpdated(any(NodeId.class), any(EpKey.class));
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, endpointGroupId));
-        Assert.assertFalse(collection.isEmpty());
+        assertFalse(collection.isEmpty());
 
         manager.processEndpoint(endpoint2, null);
         verify(endpointListener, times(2)).endpointUpdated(any(EpKey.class));
         verify(endpointListener, times(2)).nodeEndpointUpdated(any(NodeId.class), any(EpKey.class));
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, endpointGroupId));
-        Assert.assertTrue(collection.isEmpty());
+        assertTrue(collection.isEmpty());
     }
 
     @Test
@@ -516,7 +541,7 @@ public class EndpointManagerTest {
         // create: node1, update: node1 -> node2
         verify(endpointListener, times(3)).nodeEndpointUpdated(any(NodeId.class), any(EpKey.class));
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, endpointGroupId));
-        Assert.assertFalse(collection.isEmpty());
+        assertFalse(collection.isEmpty());
     }
 
     /**
@@ -534,9 +559,9 @@ public class EndpointManagerTest {
         verify(endpointListener, times(2)).endpointUpdated(any(EpKey.class));
         verify(endpointListener, times(1)).nodeEndpointUpdated(any(NodeId.class), any(EpKey.class));
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, endpointGroupId));
-        Assert.assertTrue(collection.isEmpty());
+        assertTrue(collection.isEmpty());
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, otherEndpointGroupId));
-        Assert.assertFalse(collection.isEmpty());
+        assertFalse(collection.isEmpty());
     }
 
     /**
@@ -554,9 +579,9 @@ public class EndpointManagerTest {
         // create: node1, update: node1 -> node2
         verify(endpointListener, times(3)).nodeEndpointUpdated(any(NodeId.class), any(EpKey.class));
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, endpointGroupId));
-        Assert.assertTrue(collection.isEmpty());
+        assertTrue(collection.isEmpty());
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, otherEndpointGroupId));
-        Assert.assertFalse(collection.isEmpty());
+        assertFalse(collection.isEmpty());
     }
 
     /**
@@ -573,7 +598,7 @@ public class EndpointManagerTest {
         verify(endpointListener, times(2)).endpointUpdated(any(EpKey.class));
         verify(endpointListener, times(2)).nodeEndpointUpdated(any(NodeId.class), any(EpKey.class));
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, endpointGroupId));
-        Assert.assertTrue(collection.isEmpty());
+        assertTrue(collection.isEmpty());
     }
 
     /**
@@ -590,7 +615,7 @@ public class EndpointManagerTest {
         verify(endpointListener).endpointUpdated(any(EpKey.class));
         verify(endpointListener).nodeEndpointUpdated(any(NodeId.class), any(EpKey.class));
         collection = manager.getEndpointsForGroup(new EgKey(tenantId, endpointGroupId));
-        Assert.assertFalse(collection.isEmpty());
+        assertFalse(collection.isEmpty());
     }
 
     @Test
@@ -599,36 +624,36 @@ public class EndpointManagerTest {
         verify(listenerReg, times(3)).close();
     }
 
-     //**************
-     //Helper Functions
-     //**************
+    // **************
+    // Helper Functions
+    // **************
 
     @Test
     public void getEgKeyTest() {
-        Assert.assertNotNull(manager.getEgKey(endpoint1));
-        Assert.assertNull(manager.getEgKey(null));
+        assertNotNull(manager.getEgKey(endpoint1));
+        assertNull(manager.getEgKey(null));
 
         when(endpoint1.getTenant()).thenReturn(null);
-        Assert.assertNull(manager.getEgKey(endpoint1));
+        assertNull(manager.getEgKey(endpoint1));
 
         when(endpoint1.getTenant()).thenReturn(tenantId);
         when(endpoint1.getEndpointGroup()).thenReturn(null);
-        Assert.assertNull(manager.getEgKey(endpoint1));
+        assertNull(manager.getEgKey(endpoint1));
 
         when(endpoint1.getEndpointGroup()).thenReturn(endpointGroupId);
         when(endpoint1.getEndpointGroups()).thenReturn(null);
-        Assert.assertNotNull(manager.getEgKey(endpoint1));
+        assertNotNull(manager.getEgKey(endpoint1));
 
         when(endpoint1.getEndpointGroup()).thenReturn(null);
-        Assert.assertNull(manager.getEgKey(endpoint1));
+        assertNull(manager.getEgKey(endpoint1));
 
         when(endpoint1.getEndpointGroup()).thenReturn(endpointGroupId);
         when(endpoint1.getL2Context()).thenReturn(null);
-        Assert.assertNull(manager.getEgKey(endpoint1));
+        assertNull(manager.getEgKey(endpoint1));
 
         when(endpoint1.getL2Context()).thenReturn(l2BridgeDomainId);
         when(endpoint1.getMacAddress()).thenReturn(null);
-        Assert.assertNull(manager.getEgKey(endpoint1));
+        assertNull(manager.getEgKey(endpoint1));
     }
 
     @Test
@@ -638,18 +663,18 @@ public class EndpointManagerTest {
 
         when(endpoint.getEndpointGroups()).thenReturn(null);
         egKeys = manager.getEgKeysForEndpoint(endpoint);
-        Assert.assertTrue(egKeys.isEmpty());
+        assertTrue(egKeys.isEmpty());
 
         EndpointGroupId endpointGroupId = mock(EndpointGroupId.class);
         when(endpoint.getEndpointGroup()).thenReturn(endpointGroupId);
         egKeys = manager.getEgKeysForEndpoint(endpoint);
-        Assert.assertEquals(1, egKeys.size());
+        assertEquals(1, egKeys.size());
 
         EndpointGroupId epgId = mock(EndpointGroupId.class);
         List<EndpointGroupId> endpointGroups = Collections.singletonList(epgId);
         when(endpoint.getEndpointGroups()).thenReturn(endpointGroups);
         egKeys = manager.getEgKeysForEndpoint(endpoint);
-        Assert.assertEquals(2, egKeys.size());
+        assertEquals(2, egKeys.size());
     }
 
     @Test
@@ -657,21 +682,42 @@ public class EndpointManagerTest {
         Endpoint endpoint = mock(Endpoint.class);
         when(endpoint.getAugmentation(OfOverlayContext.class)).thenReturn(null);
         // TODO
-//        Assert.assertFalse(manager.isExternal(endpoint));
-//        Assert.assertTrue(manager.isInternal(endpoint));
-//
-//        OfOverlayContext ofc = mock(OfOverlayContext.class);
-//        when(endpoint.getAugmentation(OfOverlayContext.class)).thenReturn(ofc);
-//        when(ofc.getLocationType()).thenReturn(null);
-//        Assert.assertFalse(manager.isExternal(endpoint));
-//        Assert.assertTrue(manager.isInternal(endpoint));
-//
-//        when(ofc.getLocationType()).thenReturn(LocationType.Internal);
-//        Assert.assertFalse(manager.isExternal(endpoint));
-//        Assert.assertTrue(manager.isInternal(endpoint));
-//
-//        when(ofc.getLocationType()).thenReturn(LocationType.External);
-//        Assert.assertTrue(manager.isExternal(endpoint));
-//        Assert.assertFalse(manager.isInternal(endpoint));
+        // assertFalse(manager.isExternal(endpoint));
+        // assertTrue(manager.isInternal(endpoint));
+        //
+        // OfOverlayContext ofc = mock(OfOverlayContext.class);
+        // when(endpoint.getAugmentation(OfOverlayContext.class)).thenReturn(ofc);
+        // when(ofc.getLocationType()).thenReturn(null);
+        // assertFalse(manager.isExternal(endpoint));
+        // assertTrue(manager.isInternal(endpoint));
+        //
+        // when(ofc.getLocationType()).thenReturn(LocationType.Internal);
+        // assertFalse(manager.isExternal(endpoint));
+        // assertTrue(manager.isInternal(endpoint));
+        //
+        // when(ofc.getLocationType()).thenReturn(LocationType.External);
+        // assertTrue(manager.isExternal(endpoint));
+        // assertFalse(manager.isInternal(endpoint));
+    }
+
+    @Test
+    public void testGetL2EndpointFromL3() {
+        when(newL3Ep.getL2Context()).thenReturn(mock(L2BridgeDomainId.class));
+        when(newL3Ep.getMacAddress()).thenReturn(mock(MacAddress.class));
+
+        Endpoint ep = manager.getL2EndpointFromL3(newL3Ep);
+
+        assertNull(ep);
+    }
+
+    @Test
+    public void testGetL2EndpointFromL3_noL2Context_noMacAddr() {
+        when(newL3Ep.getL2Context()).thenReturn(null);
+        when(newL3Ep.getMacAddress()).thenReturn(null);
+
+        Endpoint ep = manager.getL2EndpointFromL3(newL3Ep);
+
+        assertNull(ep);
     }
+
 }
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayAugTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayAugTest.java
new file mode 100644 (file)
index 0000000..ddd3700
--- /dev/null
@@ -0,0 +1,156 @@
+/*\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.renderer.ofoverlay.endpoint;\r
+\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertNull;\r
+import static org.mockito.Mockito.mock;\r
+import static org.mockito.Mockito.when;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.concurrent.ExecutionException;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\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.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentationRegistry;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.test.TransactionMockUtils;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInputBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;\r
+import org.opendaylight.yangtools.yang.binding.Augmentation;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+\r
+public class OfOverlayAugTest {\r
+\r
+    private static final String PORT_NAME = "portName";\r
+    private DataBroker dataProvider;\r
+    private EpRendererAugmentationRegistry epRendererAugmentationRegistry;\r
+    private OfOverlayAug ofOverlayAug;\r
+\r
+    @Before\r
+    public void init() {\r
+        dataProvider = mock(DataBroker.class);\r
+        epRendererAugmentationRegistry = mock(EpRendererAugmentationRegistry.class);\r
+        ofOverlayAug = new OfOverlayAug(dataProvider, epRendererAugmentationRegistry);\r
+    }\r
+\r
+    @Test\r
+    public void testConstructor() throws Exception {\r
+        OfOverlayAug other = new OfOverlayAug(dataProvider, epRendererAugmentationRegistry);\r
+        other.close();\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    @Test\r
+    public void testBuildEndpointAugmentation() throws ExecutionException, InterruptedException {\r
+        Nodes nodes = buildNodes();\r
+\r
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);\r
+        TransactionMockUtils.setupRoTx(roTx, LogicalDatastoreType.OPERATIONAL,\r
+                InstanceIdentifier.builder(Nodes.class).build(), true, nodes);\r
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);\r
+\r
+        OfOverlayContextInput contextInput =\r
+                new OfOverlayContextInputBuilder().setPortName(new Name(PORT_NAME)).build();\r
+\r
+        RegisterEndpointInput input =\r
+                new RegisterEndpointInputBuilder().addAugmentation(OfOverlayContextInput.class, contextInput).build();\r
+\r
+        Map.Entry<Class<? extends Augmentation<Endpoint>>, Augmentation<Endpoint>> entry =\r
+                ofOverlayAug.buildEndpointAugmentation(input);\r
+\r
+        assertNotNull(entry);\r
+        assertNotNull(entry.getValue());\r
+    }\r
+\r
+    @Test\r
+    public void testBuildEndpointAugmentation_null() {\r
+        RegisterEndpointInput input = new RegisterEndpointInputBuilder().build();\r
+\r
+        Map.Entry<Class<? extends Augmentation<Endpoint>>, Augmentation<Endpoint>> entry =\r
+                ofOverlayAug.buildEndpointAugmentation(input);\r
+\r
+        assertNull(entry);\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    @Test\r
+    public void testBuildEndpointL3Augmentation() throws ExecutionException, InterruptedException {\r
+        Nodes nodes = buildNodes();\r
+\r
+        ReadOnlyTransaction roTx = mock(ReadOnlyTransaction.class);\r
+        TransactionMockUtils.setupRoTx(roTx, LogicalDatastoreType.OPERATIONAL,\r
+                InstanceIdentifier.builder(Nodes.class).build(), true, nodes);\r
+        when(dataProvider.newReadOnlyTransaction()).thenReturn(roTx);\r
+\r
+        OfOverlayContextInput contextInput =\r
+                new OfOverlayContextInputBuilder().setPortName(new Name(PORT_NAME)).build();\r
+\r
+        RegisterEndpointInput input =\r
+                new RegisterEndpointInputBuilder().addAugmentation(OfOverlayContextInput.class, contextInput).build();\r
+\r
+        Map.Entry<Class<? extends Augmentation<EndpointL3>>, Augmentation<EndpointL3>> entry =\r
+                ofOverlayAug.buildEndpointL3Augmentation(input);\r
+\r
+        assertNotNull(entry);\r
+        assertNotNull(entry.getValue());\r
+    }\r
+\r
+    @Test\r
+    public void testBuildEndpointL3Augmentation_null() {\r
+        RegisterEndpointInput input = new RegisterEndpointInputBuilder().build();\r
+\r
+        Map.Entry<Class<? extends Augmentation<EndpointL3>>, Augmentation<EndpointL3>> entry =\r
+                ofOverlayAug.buildEndpointL3Augmentation(input);\r
+\r
+        assertNull(entry);\r
+    }\r
+\r
+    @Test\r
+    public void testBuildL3PrefixEndpointAugmentation() {\r
+        RegisterL3PrefixEndpointInput input = new RegisterL3PrefixEndpointInputBuilder().build();\r
+        Map.Entry<Class<? extends Augmentation<EndpointL3Prefix>>, Augmentation<EndpointL3Prefix>> entry =\r
+                ofOverlayAug.buildL3PrefixEndpointAugmentation(input);\r
+\r
+        // always returns null\r
+        assertNull(entry);\r
+    }\r
+\r
+    private Nodes buildNodes() {\r
+        FlowCapableNodeConnector fcnc = new FlowCapableNodeConnectorBuilder().setName(PORT_NAME).build();\r
+        NodeConnector nc = new NodeConnectorBuilder().addAugmentation(FlowCapableNodeConnector.class, fcnc).build();\r
+        List<NodeConnector> nodeConnectorList = new ArrayList<>();\r
+        nodeConnectorList.add(nc);\r
+        Node node = new NodeBuilder().setNodeConnector(nodeConnectorList).build();\r
+        List<Node> nodeList = new ArrayList<>();\r
+        nodeList.add(node);\r
+        return new NodesBuilder().setNode(nodeList).build();\r
+    }\r
+\r
+}\r
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayContextListenerTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayContextListenerTest.java
new file mode 100644 (file)
index 0000000..3e76591
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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.ofoverlay.endpoint;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+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.DataObjectModification;
+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.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class OfOverlayContextListenerTest {
+
+    private static final Name OLD_PORT_NAME = new Name("oldPort");
+    private static final Name NEW_PORT_NAME = new Name("newPort");
+    private OfOverlayContextListener listener;
+    private DataObjectModification<OfOverlayContext> rootNode;
+    private Set<DataTreeModification<OfOverlayContext>> changes;
+
+    private DataBroker dataProvider;
+    private SwitchManager switchManager;
+
+    private InstanceIdentifier<OfOverlayContext> rootIdentifier;
+    private OfOverlayContext oldContext;
+    private OfOverlayContext newContext;
+    private OfOverlayContext contextNoPortName;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void init() {
+
+        dataProvider = mock(DataBroker.class);
+        switchManager = mock(SwitchManager.class);
+
+        NodeKey nodeKey = new NodeKey(new NodeId("nodeId"));
+        NodeConnectorKey nodeConnectorKey = new NodeConnectorKey(new NodeConnectorId("ncId"));
+        InstanceIdentifier<NodeConnector> ncIid = InstanceIdentifier.builder(Nodes.class)
+            .child(Node.class, nodeKey)
+            .child(NodeConnector.class, nodeConnectorKey)
+            .build();
+        when(switchManager.getNodeConnectorIidForPortName(NEW_PORT_NAME)).thenReturn(ncIid);
+
+        listener = spy(new OfOverlayContextListener(dataProvider, switchManager));
+        EndpointKey epKey = mock(EndpointKey.class);
+
+        rootNode = mock(DataObjectModification.class);
+        rootIdentifier = InstanceIdentifier.builder(Endpoints.class)
+            .child(Endpoint.class, epKey)
+            .augmentation(OfOverlayContext.class)
+            .build();
+        DataTreeIdentifier<OfOverlayContext> rootPath =
+                new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, rootIdentifier);
+
+        DataTreeModification<OfOverlayContext> change = mock(DataTreeModification.class);
+
+        when(change.getRootNode()).thenReturn(rootNode);
+        when(change.getRootPath()).thenReturn(rootPath);
+
+        changes = ImmutableSet.of(change);
+
+        oldContext = new OfOverlayContextBuilder().setPortName(OLD_PORT_NAME).build();
+        newContext = new OfOverlayContextBuilder().setPortName(NEW_PORT_NAME).build();
+        contextNoPortName = new OfOverlayContextBuilder().build();
+    }
+
+    @Test
+    public void testOnDataTreeChanged_Write() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
+        when(rootNode.getDataAfter()).thenReturn(newContext);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(oldContext);
+        when(rootNode.getDataAfter()).thenReturn(newContext);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified_bothNoPortName() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(contextNoPortName);
+        when(rootNode.getDataAfter()).thenReturn(contextNoPortName);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt, never()).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified_oneNoPortName() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(oldContext);
+        when(rootNode.getDataAfter()).thenReturn(contextNoPortName);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt, never()).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified_oneNoPortName1() {
+        when(switchManager.getNodeConnectorIidForPortName(NEW_PORT_NAME)).thenReturn(null);
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(oldContext);
+        when(rootNode.getDataAfter()).thenReturn(newContext);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt, never()).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified_samePortName() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(newContext);
+        when(rootNode.getDataAfter()).thenReturn(newContext);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt, never()).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_Delete() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        // no op
+    }
+
+    private WriteTransaction resetTransaction() {
+        WriteTransaction wt = mock(WriteTransaction.class);
+        CheckedFuture checkedFuture = mock(CheckedFuture.class);
+        when(wt.submit()).thenReturn(checkedFuture);
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(wt);
+        return wt;
+    }
+
+}
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayL3ContextListenerTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayL3ContextListenerTest.java
new file mode 100644 (file)
index 0000000..78e646a
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * 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.ofoverlay.endpoint;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+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.DataObjectModification;
+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.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3ContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class OfOverlayL3ContextListenerTest {
+
+    private static final Name OLD_PORT_NAME = new Name("oldPort");
+    private static final Name NEW_PORT_NAME = new Name("newPort");
+    private OfOverlayL3ContextListener listener;
+    private DataObjectModification<OfOverlayL3Context> rootNode;
+    private Set<DataTreeModification<OfOverlayL3Context>> changes;
+
+    private DataBroker dataProvider;
+    private SwitchManager switchManager;
+
+    private InstanceIdentifier<OfOverlayL3Context> rootIdentifier;
+    private OfOverlayL3Context oldContext;
+    private OfOverlayL3Context newContext;
+    private OfOverlayL3Context contextNoPortName;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void init() {
+
+        dataProvider = mock(DataBroker.class);
+        switchManager = mock(SwitchManager.class);
+
+        NodeKey nodeKey = new NodeKey(new NodeId("nodeId"));
+        NodeConnectorKey nodeConnectorKey = new NodeConnectorKey(new NodeConnectorId("ncId"));
+        InstanceIdentifier<NodeConnector> ncIid = InstanceIdentifier.builder(Nodes.class)
+            .child(Node.class, nodeKey)
+            .child(NodeConnector.class, nodeConnectorKey)
+            .build();
+        when(switchManager.getNodeConnectorIidForPortName(NEW_PORT_NAME)).thenReturn(ncIid);
+
+        listener = spy(new OfOverlayL3ContextListener(dataProvider, switchManager));
+        EndpointL3Key epL3Key = mock(EndpointL3Key.class);
+
+        rootNode = mock(DataObjectModification.class);
+        rootIdentifier = InstanceIdentifier.builder(Endpoints.class)
+            .child(EndpointL3.class, epL3Key)
+            .augmentation(OfOverlayL3Context.class)
+            .build();
+        DataTreeIdentifier<OfOverlayL3Context> rootPath =
+                new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, rootIdentifier);
+
+        DataTreeModification<OfOverlayL3Context> change = mock(DataTreeModification.class);
+
+        when(change.getRootNode()).thenReturn(rootNode);
+        when(change.getRootPath()).thenReturn(rootPath);
+
+        changes = ImmutableSet.of(change);
+
+        oldContext = new OfOverlayL3ContextBuilder().setPortName(OLD_PORT_NAME).build();
+        newContext = new OfOverlayL3ContextBuilder().setPortName(NEW_PORT_NAME).build();
+        contextNoPortName = new OfOverlayL3ContextBuilder().build();
+    }
+
+    @Test
+    public void testOnDataTreeChanged_Write() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
+        when(rootNode.getDataAfter()).thenReturn(newContext);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(oldContext);
+        when(rootNode.getDataAfter()).thenReturn(newContext);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified_bothNoPortName() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(contextNoPortName);
+        when(rootNode.getDataAfter()).thenReturn(contextNoPortName);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt, never()).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified_oneNoPortName() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(oldContext);
+        when(rootNode.getDataAfter()).thenReturn(contextNoPortName);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt, never()).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified_oneNoPortName1() {
+        when(switchManager.getNodeConnectorIidForPortName(NEW_PORT_NAME)).thenReturn(null);
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(oldContext);
+        when(rootNode.getDataAfter()).thenReturn(newContext);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt, never()).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_SubtreeModified_samePortName() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+        when(rootNode.getDataBefore()).thenReturn(newContext);
+        when(rootNode.getDataAfter()).thenReturn(newContext);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        verify(wt, never()).merge(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
+                any(OfOverlayContext.class));
+    }
+
+    @Test
+    public void testOnDataTreeChanged_Delete() {
+        when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
+
+        WriteTransaction wt = resetTransaction();
+
+        listener.onDataTreeChanged(changes);
+
+        // no op
+    }
+
+    private WriteTransaction resetTransaction() {
+        WriteTransaction wt = mock(WriteTransaction.class);
+        CheckedFuture checkedFuture = mock(CheckedFuture.class);
+        when(wt.submit()).thenReturn(checkedFuture);
+        when(dataProvider.newWriteOnlyTransaction()).thenReturn(wt);
+        return wt;
+    }
+
+}
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayL3NatAugTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/OfOverlayL3NatAugTest.java
new file mode 100644 (file)
index 0000000..2d03a12
--- /dev/null
@@ -0,0 +1,80 @@
+/*\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.renderer.ofoverlay.endpoint;\r
+\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertNull;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentationRegistry;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInputBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddressInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddressInputBuilder;\r
+\r
+public class OfOverlayL3NatAugTest {\r
+\r
+    private OfOverlayL3NatAug ofOverlayL3NatAug;\r
+    private EpRendererAugmentationRegistry epRendererAugmentationRegistry;\r
+\r
+    @Before\r
+    public void init() {\r
+        epRendererAugmentationRegistry = mock(EpRendererAugmentationRegistry.class);\r
+        ofOverlayL3NatAug = new OfOverlayL3NatAug(epRendererAugmentationRegistry);\r
+    }\r
+\r
+    @Test\r
+    public void testConstructor() throws Exception {\r
+        OfOverlayL3NatAug other = new OfOverlayL3NatAug(epRendererAugmentationRegistry);\r
+        other.close();\r
+    }\r
+\r
+    @Test\r
+    public void testBuildEndpointAugmentation() {\r
+        RegisterEndpointInput input = new RegisterEndpointInputBuilder().build();\r
+        // no op\r
+        assertNull(ofOverlayL3NatAug.buildEndpointAugmentation(input));\r
+    }\r
+\r
+    @Test\r
+    public void testBuildEndpointL3Augmentation() {\r
+        NatAddressInput natAddressInput = new NatAddressInputBuilder().setNatAddress(\r
+                new IpAddress(new Ipv4Address("10.0.0.2"))).build();\r
+        RegisterEndpointInput input =\r
+                new RegisterEndpointInputBuilder().addAugmentation(NatAddressInput.class,\r
+                        natAddressInput).build();\r
+        assertNotNull(ofOverlayL3NatAug.buildEndpointL3Augmentation(input));\r
+    }\r
+\r
+    @Test\r
+    public void testBuildEndpointL3Augmentation_noAug() {\r
+        RegisterEndpointInput input = new RegisterEndpointInputBuilder().build();\r
+        assertNull(ofOverlayL3NatAug.buildEndpointL3Augmentation(input));\r
+    }\r
+\r
+    @Test\r
+    public void testBuildL3PrefixEndpointAugmentation() {\r
+        RegisterL3PrefixEndpointInput input = new RegisterL3PrefixEndpointInputBuilder().build();\r
+        // no op\r
+\r
+        assertNull(ofOverlayL3NatAug.buildL3PrefixEndpointAugmentation(input));\r
+    }\r
+\r
+    @Test\r
+    public void testClose() {\r
+        //        fail("Not yet implemented");\r
+    }\r
+\r
+}\r
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/equivalence/BucketsEquivalenceTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/equivalence/BucketsEquivalenceTest.java
new file mode 100644 (file)
index 0000000..d8b8a18
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.ofoverlay.equivalence;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+
+public class BucketsEquivalenceTest {
+    BucketsEquivalence eq;
+
+    @Before
+    public void init() {
+        eq = new BucketsEquivalence();
+    }
+
+    @Test
+    public void testDoEquivalent() {
+        Buckets a = new BucketsBuilder().build();
+        Buckets b = new BucketsBuilder().build();
+        eq.doEquivalent(a, b);
+    }
+
+    @Test
+    public void testDoHash() {
+        Buckets a = new BucketsBuilder().build();
+        eq.doHash(a);
+    }
+
+}
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/equivalence/GroupEquivalenceTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/equivalence/GroupEquivalenceTest.java
new file mode 100644 (file)
index 0000000..62ea64b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.ofoverlay.equivalence;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+
+public class GroupEquivalenceTest {
+
+    GroupEquivalence eq;
+
+    @Before
+    public void init() {
+        eq = new GroupEquivalence();
+    }
+
+    @Test
+    public void testDoEquivalent() {
+        Group a = new GroupBuilder().build();
+        Group b = new GroupBuilder().build();
+        eq.doEquivalent(a, b);
+    }
+
+    @Test
+    public void testDoHash() {
+
+        Group a = new GroupBuilder().build();
+        eq.doHash(a);
+    }
+
+}
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientResponseTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientResponseTest.java
new file mode 100644 (file)
index 0000000..cbb15da
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.ofoverlay.statistics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JsonRestClientResponseTest {
+
+    private static final String STRING_ENTITY = "string entity";
+    private ClientResponse clientResponse;
+
+    @Before
+    public void init() {
+        clientResponse = mock(ClientResponse.class);
+
+    }
+
+    @Test
+    public void testResponse_Ok() {
+        when(clientResponse.getEntity(String.class)).thenReturn(STRING_ENTITY);
+        when(clientResponse.getStatus()).thenReturn(200);
+        JsonRestClientResponse response = new JsonRestClientResponse(clientResponse);
+
+        assertSame(clientResponse, response.getClientResponse());
+        assertEquals(STRING_ENTITY, response.getJsonResponse());
+        assertEquals(200, response.getStatusCode());
+        assertNull(response.getClientHandlerException());
+    }
+
+    @Test
+    public void testResponse_UniformInterfaceException() {
+        UniformInterfaceException ex = new UniformInterfaceException(clientResponse);
+        when(clientResponse.getEntity(String.class)).thenThrow(ex);
+        when(clientResponse.getStatus()).thenReturn(204);
+
+        JsonRestClientResponse response = new JsonRestClientResponse(clientResponse);
+
+        assertNull(response.getJsonResponse());
+        assertEquals(204, response.getStatusCode());
+        assertNull(response.getClientHandlerException());
+    }
+
+    @Test
+    public void testResponse_ClientHandlerException() {
+        ClientHandlerException ex = new ClientHandlerException();
+        when(clientResponse.getEntity(String.class)).thenThrow(ex);
+        when(clientResponse.getStatus()).thenReturn(404);
+
+        JsonRestClientResponse response = new JsonRestClientResponse(clientResponse);
+
+        assertNull(response.getJsonResponse());
+        assertEquals(404, response.getStatusCode());
+        assertSame(ex, response.getClientHandlerException());
+    }
+}
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientTest.java
new file mode 100644 (file)
index 0000000..2c83548
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015 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.ofoverlay.statistics;
+
+import static org.junit.Assert.assertEquals;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+
+import com.google.common.collect.ImmutableList;
+import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
+import com.sun.jersey.api.core.ClassNamesResourceConfig;
+import com.sun.jersey.api.core.ResourceConfig;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+import com.sun.jersey.test.framework.AppDescriptor;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.SFlowQueryParams;
+
+public class JsonRestClientTest extends JerseyTest {
+
+    private static final int CONNECT_TIMEOUT_MILLISEC = 20000;
+    private static final int READ_TIMEOUT_MILLISEC = 30000;
+    private static final String SFLOW_HOST = "localhost";
+    private static final int SFLOW_PORT = 1234;
+    private static HttpServer server;
+    private static final String SFLOW_URI = "http://" + SFLOW_HOST + ":" + SFLOW_PORT;
+
+    private JsonRestClient client;
+    private String uri;
+    private static String responseJson =
+            " { \"resolved-policy-uri\" : \"/restconf/operational/resolved-policy:resolved-policies/resolved-policy/tenant-red/client/tenant-red/webserver/\" } ";
+
+    private static HttpServer startServer() throws IOException {
+        final ResourceConfig resourceConfig = new ClassNamesResourceConfig(dumbServer.class);
+        HttpServer httpServer;
+        httpServer = GrizzlyServerFactory.createHttpServer(java.net.URI.create(SFLOW_URI), resourceConfig);
+        return httpServer;
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws IOException {
+        server = startServer();
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        if (server != null && server.isStarted())
+            server.stop();
+    }
+
+    @Before
+    public void init() {
+        client = new JsonRestClient(SFLOW_URI, CONNECT_TIMEOUT_MILLISEC, READ_TIMEOUT_MILLISEC);
+    }
+
+    @Test
+    public void testGetHost() {
+        String host = client.getHost();
+
+        assertEquals(SFLOW_HOST, host);
+    }
+
+    @Test
+    public void testGet_coverageOnly() {
+        client.get("/");
+    }
+
+    @Test
+    public void testGet_params_coverageOnly() {
+        MultivaluedMap<String, String> params = new MultivaluedMapImpl();
+        params.add(SFlowQueryParams.MAX_FLOWS, "20");
+        params.add(SFlowQueryParams.MIN_VALUE, "0.1");
+        params.add(SFlowQueryParams.AGG_MODE, "sum");
+
+        client.get("/", params);
+    }
+
+    @Test
+    public void testPost_coverageOnly() {
+        client.post("/", "json");
+    }
+
+    @Test
+    public void testPut_coverageOnly() {
+        client.put("/", "json");
+    }
+
+    @Test
+    public void testDelete_coverageOnly() {
+        client.delete("/");
+    }
+
+    @Override
+    protected AppDescriptor configure() {
+        return new WebAppDescriptor.Builder().build();
+    }
+
+    @Path("/")
+    public static class dumbServer {
+
+        @GET
+        @Produces(MediaType.APPLICATION_JSON)
+        public Response get200() {
+            return Response.status(Response.Status.OK).entity(responseJson).build();
+        }
+
+        @POST
+        @Consumes(MediaType.APPLICATION_JSON)
+        public Response post200(String json) {
+            return Response.status(Response.Status.OK).build();
+        }
+
+    }
+}
index de1f7c2b7a0b745a96bbf2bc4aef96fe0a7d16f0..f819633e312da8fca3c2432d9872542d81f404b2 100755 (executable)
@@ -1,27 +1,85 @@
+/*\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.renderer.ofoverlay.statistics;\r
 \r
 import static org.mockito.Mockito.mock;\r
 \r
+import java.util.Map;\r
 import java.util.concurrent.ScheduledExecutorService;\r
 \r
 import org.junit.Before;\r
 import org.junit.Test;\r
 import org.opendaylight.groupbasedpolicy.api.StatisticsManager;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.test.TestUtils;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.ClassifierBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
 \r
 public class OFStatisticsManagerTest {\r
 \r
-    ScheduledExecutorService executor;\r
-    StatisticsManager statisticsManager;\r
+    private final EndpointGroupId consumerEpgId = new EndpointGroupId("consumerEpg1");\r
+    private final EndpointGroupId providerEpgId = new EndpointGroupId("providerEpg1");\r
+    private final ContractId contractId = new ContractId("contract1");\r
+    private final TenantId tenantId = new TenantId("tenant1");\r
+    private final ClassifierName classifierName = ClassifierName.getDefaultInstance("classifier1");\r
+    private final SubjectName subjectName = SubjectName.getDefaultInstance("subject1");\r
+    private final RuleName ruleName = new RuleName("rule1");\r
+\r
+    private InstanceIdentifier<ResolvedPolicy> rpIid;\r
+    private ResolvedPolicy resolvedPolicy;\r
+\r
+    private ScheduledExecutorService executor;\r
+    private StatisticsManager statisticsManager;\r
+\r
+    private OFStatisticsManager ofStatisticsManager;\r
+    private Classifier classifier;\r
+    private Map<InstanceIdentifier<Classifier>, Classifier> classifierByIid;\r
 \r
     @Before\r
     public void init() {\r
         executor = mock(ScheduledExecutorService.class);\r
         statisticsManager = mock(StatisticsManager.class);\r
+\r
+        classifier = new ClassifierBuilder()\r
+                .setName(classifierName)\r
+                .build();\r
+        resolvedPolicy = TestUtils.newResolvedPolicy(tenantId, contractId, subjectName, ruleName,\r
+                consumerEpgId, providerEpgId, classifier);\r
+\r
+        rpIid = InstanceIdentifier.create(ResolvedPolicy.class);\r
+\r
+        ofStatisticsManager = new OFStatisticsManager(executor, statisticsManager);\r
+        ofStatisticsManager.setDelay(20L);\r
+        ofStatisticsManager.setSflowCollectorUri("http://localhost:1234");\r
+\r
+        classifierByIid =\r
+                ResolvedPolicyClassifierListener.resolveClassifiers(resolvedPolicy, rpIid);\r
     }\r
 \r
     @Test\r
     public void testConstructor() throws Exception {\r
-        new OFStatisticsManager(executor, statisticsManager);\r
+        OFStatisticsManager other = new OFStatisticsManager(executor, statisticsManager);\r
+        other.close();\r
     }\r
 \r
+    @Test\r
+    public void testTTT(){\r
+        for (Map.Entry<InstanceIdentifier<Classifier>, Classifier> classifierEntry : classifierByIid.entrySet()) {\r
+            ofStatisticsManager.pullStatsForClassifier(classifierEntry.getKey(),\r
+                    classifierEntry.getValue());\r
+        }\r
+    }\r
 }\r
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ProcessDataTaskTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ProcessDataTaskTest.java
new file mode 100644 (file)
index 0000000..4c82d62
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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.ofoverlay.statistics;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
+import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey;
+import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
+import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCache;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheData;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.FlowCacheCons;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.IidSflowNameUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+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.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.StatRecords;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({OFStatisticsManager.class, IidSflowNameUtil.class, OFStatisticsManager.class})
+public class ProcessDataTaskTest {
+
+    private final String IP_PROTO = "6";
+    private final String SRC_IP = "192.168.35.2";
+    private final String DST_IP = "192.168.36.2";
+    private final TenantId tenantId = new TenantId("tenantId");
+    private final EndpointGroupId srcEpgId = new EndpointGroupId("srcEpgId");
+    private final EndpointGroupId dstEpgId = new EndpointGroupId("dstEpgId");
+    private final ContractId contractId = new ContractId("contractId");
+    private final ClassifierName classifierName = new ClassifierName("classifierName");
+
+    private FlowCache flowCache;
+    private FlowCacheData data;
+    private ProcessDataTask task;
+
+    private EndpointL3 srcEpL3;
+    private EndpointL3 dstEpL3;
+    private EndpointGroup srcEpg;
+    private EndpointGroup dstEpg;
+
+    @Before
+    public void init() {
+        PowerMockito.mockStatic(OFStatisticsManager.class);
+        PowerMockito.mockStatic(IidSflowNameUtil.class);
+        PowerMockito.mockStatic(OFStatisticsManager.class);
+
+        String[] keyNames = {FlowCacheCons.Key.IP_PROTOCOL.get(), FlowCacheCons.Key.IP_SOURCE.get(),
+                FlowCacheCons.Key.IP_DESTINATION.get()};
+        flowCache = mock(FlowCache.class);
+        when(flowCache.getKeyNum()).thenReturn(3);
+        when(flowCache.getKeyNames()).thenReturn(keyNames);
+        when(flowCache.getName()).thenReturn("flowcache1");
+        when(flowCache.getDirection()).thenReturn(HasDirection.Direction.Out);
+        data = mock(FlowCacheData.class);
+        when(data.getKey()).thenReturn(IP_PROTO + "," + SRC_IP + "," + DST_IP);
+        List<FlowCacheData> dataList = new ArrayList<>();
+        dataList.add(data);
+        BigInteger timestamp = BigInteger.ZERO;
+        StatisticsManager statisticsManager = mock(StatisticsManager.class);
+        when(statisticsManager.writeStat(any(StatRecords.class))).thenReturn(true);
+
+        task = new ProcessDataTask(flowCache, dataList, timestamp, statisticsManager);
+
+        srcEpg = new EndpointGroupBuilder().setId(srcEpgId).build();
+        dstEpg = new EndpointGroupBuilder().setId(dstEpgId).build();
+        srcEpL3 = new EndpointL3Builder().setTenant(tenantId).setEndpointGroup(srcEpg.getId()).build();
+        dstEpL3 = new EndpointL3Builder().setTenant(tenantId).setEndpointGroup(dstEpg.getId()).build();
+        ConsEpgKey consEpgKey = new EpgKeyDto(srcEpg.getId(), tenantId);
+        ProvEpgKey provEpgKey = new EpgKeyDto(dstEpg.getId(), tenantId);
+        Pair<ConsEpgKey, ProvEpgKey> pair = Pair.of(consEpgKey, provEpgKey);
+        Set<Pair<ConsEpgKey, ProvEpgKey>> epgsForContract = new HashSet<>();
+        epgsForContract.add(pair);
+
+        when(OFStatisticsManager.getEpgsForContract(contractId)).thenReturn(epgsForContract);
+    }
+
+    @Test
+    public void testRun() {
+        when(OFStatisticsManager.getEndpointL3ForIp(SRC_IP)).thenReturn(srcEpL3);
+        when(OFStatisticsManager.getEndpointL3ForIp(DST_IP)).thenReturn(dstEpL3);
+        when(IidSflowNameUtil.resolveContractIdFromFlowCacheName(flowCache.getName())).thenReturn(contractId);
+        when(IidSflowNameUtil.resolveClassifierNameFromFlowCacheName(flowCache.getName())).thenReturn(classifierName);
+        when(IidSflowNameUtil.resolveFlowCacheValue(flowCache.getName())).thenReturn(FlowCacheCons.Value.BYTES.get());
+
+        task.run();
+    }
+
+    @Test
+    public void testRun_reversedConsProv() {
+        when(OFStatisticsManager.getEndpointL3ForIp(SRC_IP)).thenReturn(srcEpL3);
+        when(OFStatisticsManager.getEndpointL3ForIp(DST_IP)).thenReturn(dstEpL3);
+        when(IidSflowNameUtil.resolveContractIdFromFlowCacheName(flowCache.getName())).thenReturn(contractId);
+        when(IidSflowNameUtil.resolveClassifierNameFromFlowCacheName(flowCache.getName())).thenReturn(classifierName);
+        when(IidSflowNameUtil.resolveFlowCacheValue(flowCache.getName())).thenReturn(FlowCacheCons.Value.FRAMES.get());
+
+        ConsEpgKey consEpgKey = new EpgKeyDto(dstEpg.getId(), tenantId);
+        ProvEpgKey provEpgKey = new EpgKeyDto(srcEpg.getId(), tenantId);
+        Pair<ConsEpgKey, ProvEpgKey> pair = Pair.of(consEpgKey, provEpgKey);
+        Set<Pair<ConsEpgKey, ProvEpgKey>> epgsForContract = new HashSet<>();
+        epgsForContract.add(pair);
+        when(OFStatisticsManager.getEpgsForContract(contractId)).thenReturn(epgsForContract);
+
+        task.run();
+    }
+
+    @Test
+    public void testRun_noConsProv() {
+        when(OFStatisticsManager.getEndpointL3ForIp(SRC_IP)).thenReturn(srcEpL3);
+        when(OFStatisticsManager.getEndpointL3ForIp(DST_IP)).thenReturn(dstEpL3);
+        when(IidSflowNameUtil.resolveContractIdFromFlowCacheName(flowCache.getName())).thenReturn(contractId);
+        when(IidSflowNameUtil.resolveClassifierNameFromFlowCacheName(flowCache.getName())).thenReturn(classifierName);
+        when(IidSflowNameUtil.resolveFlowCacheValue(flowCache.getName())).thenReturn(FlowCacheCons.Value.FRAMES.get());
+
+        Set<Pair<ConsEpgKey, ProvEpgKey>> epgsForContract = new HashSet<>();
+        when(OFStatisticsManager.getEpgsForContract(contractId)).thenReturn(epgsForContract);
+
+        task.run();
+    }
+
+    @Test
+    public void testRun_wrongDataResponse() {
+        when(data.getKey()).thenReturn("1,2");
+        task.run();
+    }
+
+}
index 41bba898d86541aa788dce5b2516774ba7cb510b..873b73dc89840d2032b0a17da941dfdee5f2da51 100755 (executable)
@@ -1,8 +1,14 @@
+/*\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.renderer.ofoverlay.statistics;\r
 \r
 import static org.mockito.Matchers.any;\r
-import static org.mockito.Matchers.anyMap;\r
-import static org.mockito.Matchers.anySet;\r
 import static org.mockito.Matchers.anyString;\r
 import static org.mockito.Mockito.doNothing;\r
 import static org.mockito.Mockito.mock;\r
@@ -10,26 +16,30 @@ import static org.mockito.Mockito.when;
 \r
 import javax.ws.rs.core.MultivaluedMap;\r
 \r
-import java.util.concurrent.ExecutorService;\r
 import java.util.concurrent.ScheduledExecutorService;\r
 \r
+import com.sun.jersey.api.client.ClientResponse;\r
 import org.junit.Before;\r
 import org.junit.Test;\r
+import org.mockito.Mockito;\r
 import org.opendaylight.groupbasedpolicy.api.StatisticsManager;\r
 \r
 public class ReadGbpFlowCacheTaskTest {\r
 \r
     ReadGbpFlowCacheTask task;\r
+    private JsonRestClientResponse response;\r
 \r
     @Before\r
     public void init() {\r
         StatisticsManager statisticsManager = mock(StatisticsManager.class);\r
         ScheduledExecutorService executor = mock(ScheduledExecutorService.class);\r
-        JsonRestClientResponse response = mock(JsonRestClientResponse.class);\r
+        ClientResponse clientResponse = mock(ClientResponse.class);\r
+        response = mock(JsonRestClientResponse.class);\r
         when(response.getJsonResponse()).thenReturn("[{\"one\":1, \"two\":2, \"three\":3}]");\r
         when(response.getStatusCode()).thenReturn(200);\r
+        when(response.getClientResponse()).thenReturn(clientResponse);\r
         SFlowRTConnection connection = mock(SFlowRTConnection.class);\r
-        when(connection.get(anyString(), any(MultivaluedMap.class))).thenReturn(response);\r
+        when(connection.get(anyString(), Mockito.<MultivaluedMap<String, String>>any())).thenReturn(response);\r
         when(connection.getExecutor()).thenReturn(executor);\r
         doNothing().when(executor).execute(any(Runnable.class));\r
 \r
@@ -38,7 +48,18 @@ public class ReadGbpFlowCacheTaskTest {
 \r
     @Test\r
     public void testRun() {\r
+        task.run();\r
+    }\r
+\r
+    @Test\r
+    public void testRun_response300() {\r
+        when(response.getStatusCode()).thenReturn(300);\r
+        task.run();\r
+    }\r
 \r
+    @Test\r
+    public void testRun_response400() {\r
+        when(response.getStatusCode()).thenReturn(400);\r
         task.run();\r
     }\r
 \r
index 14baad9ea04099445cfc82ec441b35a9da6b3b4e..430eb59d2a72672e2e333774ebb2351b6eac3d2a 100755 (executable)
@@ -1,3 +1,11 @@
+/*\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.renderer.ofoverlay.statistics;\r
 \r
 import static org.mockito.Mockito.mock;\r
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SFlowRTConnectionTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SFlowRTConnectionTest.java
new file mode 100644 (file)
index 0000000..ad3ca90
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * 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.ofoverlay.statistics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.concurrent.ScheduledExecutorService;
+
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCache;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.SFlowQueryParams;
+
+public class SFlowRTConnectionTest {
+
+    private static final String PATH = "/";
+    private static final String JSON_STRING = "jsonString";
+    private static final String JSON_RESPONSE = "jsonResponse";
+
+    private ScheduledExecutorService executor;
+    private String collectorUri;
+    private FlowCache flowCache;
+    private JsonRestClient client;
+    private MultivaluedMap<String, String> params;
+    private SFlowRTConnection connection;
+    private JsonRestClientResponse response;
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void init() {
+        params = new MultivaluedMapImpl();
+        params.add(SFlowQueryParams.MAX_FLOWS, "20");
+        params.add(SFlowQueryParams.MIN_VALUE, "0.1");
+        params.add(SFlowQueryParams.AGG_MODE, "sum");
+
+        executor = mock(ScheduledExecutorService.class);
+        collectorUri = "";
+        flowCache = mock(FlowCache.class);
+        client = mock(JsonRestClient.class);
+        response = mock(JsonRestClientResponse.class);
+        when(response.getJsonResponse()).thenReturn(JSON_RESPONSE);
+        when(response.getStatusCode()).thenReturn(200);
+        when(client.get(any(String.class), Mockito.<MultivaluedMap<String, String>>any())).thenReturn(response);
+        when(client.put(any(String.class), any(String.class))).thenReturn(response);
+        when(client.delete(any(String.class))).thenReturn(response);
+
+        connection = spy(new SFlowRTConnection(executor, collectorUri, flowCache, client));
+    }
+
+    @Test
+    public void testConstructor() {
+        SFlowRTConnection other = new SFlowRTConnection(executor, collectorUri, flowCache, client);
+
+        assertNotNull(other.getExecutor());
+        assertNotNull(other.getFlowCache());
+    }
+
+    @Test
+    public void testGetJsonResponse() {
+        String res = connection.getJsonResponse(PATH, params);
+
+        assertEquals(JSON_RESPONSE, res);
+    }
+
+    @Test(expected = ClientHandlerException.class)
+    public void testGetJsonResponse_ClientHandlerException_noCause() {
+        ClientHandlerException ex = new ClientHandlerException();
+        when(client.get(any(String.class), Mockito.<MultivaluedMap<String, String>>any())).thenThrow(ex);
+
+        connection.getJsonResponse(PATH, params);
+    }
+
+    @Test(expected = ClientHandlerException.class)
+    public void testGetJsonResponse_ClientHandlerException_caused() {
+        ClientHandlerException ex = new ClientHandlerException();
+        ex.initCause(new java.net.ConnectException());
+        when(client.get(any(String.class), Mockito.<MultivaluedMap<String, String>>any())).thenThrow(ex);
+
+        connection.getJsonResponse(PATH, params);
+    }
+
+    @Test
+    public void testGet() {
+        JsonRestClientResponse res = connection.get(PATH, params);
+
+        assertEquals(response, res);
+    }
+
+    @Test
+    public void testGet_notInitialized() {
+        when(connection.isInitialized()).thenReturn(false);
+
+        thrown.expect(IllegalStateException.class);
+        thrown.expectMessage(SFlowRTConnection.EX_MSG_NOT_INITIALIZED);
+        connection.get(PATH, params);
+    }
+
+    @Test(expected = ClientHandlerException.class)
+    public void testGet_ClientHandlerException_noCause() {
+        ClientHandlerException ex = new ClientHandlerException();
+        when(client.get(any(String.class), Mockito.<MultivaluedMap<String, String>>any())).thenThrow(ex);
+
+        connection.get(PATH, params);
+    }
+
+    @Test(expected = ClientHandlerException.class)
+    public void testGet_ClientHandlerException_caused() {
+        ClientHandlerException ex = new ClientHandlerException();
+        ex.initCause(new java.net.ConnectException());
+        when(client.get(any(String.class), Mockito.<MultivaluedMap<String, String>>any())).thenThrow(ex);
+
+        connection.get(PATH, params);
+    }
+
+    @Test
+    public void testPut() {
+        JsonRestClientResponse res = connection.put(PATH, JSON_STRING);
+
+        assertEquals(response, res);
+    }
+
+    @Test
+    public void testPut_notInitialized() {
+        when(connection.isInitialized()).thenReturn(false);
+
+        thrown.expect(IllegalStateException.class);
+        thrown.expectMessage(SFlowRTConnection.EX_MSG_NOT_INITIALIZED);
+        connection.put(PATH, JSON_STRING);
+    }
+
+    @Test(expected = ClientHandlerException.class)
+    public void testPut_ClientHandlerException_noCause() {
+        ClientHandlerException ex = new ClientHandlerException();
+        when(client.put(any(String.class), any(String.class))).thenThrow(ex);
+
+        connection.put(PATH, JSON_STRING);
+    }
+
+    @Test(expected = ClientHandlerException.class)
+    public void testPut_ClientHandlerException_caused() {
+        ClientHandlerException ex = new ClientHandlerException();
+        ex.initCause(new java.net.ConnectException());
+        when(client.put(any(String.class), any(String.class))).thenThrow(ex);
+
+        connection.put(PATH, JSON_STRING);
+    }
+
+    @Test
+    public void testDelete() {
+        JsonRestClientResponse res = connection.delete(PATH);
+
+        assertEquals(response, res);
+    }
+
+    @Test
+    public void testDelete_notInitialized() {
+        when(connection.isInitialized()).thenReturn(false);
+
+        thrown.expect(IllegalStateException.class);
+        thrown.expectMessage(SFlowRTConnection.EX_MSG_NOT_INITIALIZED);
+        connection.delete(PATH);
+    }
+
+    @Test(expected = ClientHandlerException.class)
+    public void testDelete_ClientHandlerException_noCause() {
+        ClientHandlerException ex = new ClientHandlerException();
+        when(client.delete(any(String.class))).thenThrow(ex);
+
+        connection.delete(PATH);
+    }
+
+    @Test(expected = ClientHandlerException.class)
+    public void testDelete_ClientHandlerException_caused() {
+        ClientHandlerException ex = new ClientHandlerException();
+        ex.initCause(new java.net.ConnectException());
+        when(client.delete(any(String.class))).thenThrow(ex);
+
+        connection.delete(PATH);
+    }
+
+    @Test
+    public void testInitialize() {
+        when(response.getStatusCode()).thenReturn(300);
+        connection.initialize();
+        assertTrue(connection.isInitialized());
+
+        when(response.getStatusCode()).thenReturn(400);
+        connection.initialize();
+        assertTrue(connection.isInitialized());
+    }
+
+    @Test
+    public void testLogStatusCode_coverage() {
+        when(response.getStatusCode()).thenReturn(300);
+        connection.getJsonResponse(PATH, params);
+        connection.delete(PATH);
+
+        when(response.getStatusCode()).thenReturn(400);
+        connection.getJsonResponse(PATH, params);
+        connection.delete(PATH);
+    }
+
+}
index 349532978ae7586b5ec5b321a454a8a241350072..c5e1b2074ce3605f69adc707a5d513aea4881412 100755 (executable)
@@ -1,3 +1,11 @@
+/*\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.renderer.ofoverlay.statistics;\r
 \r
 import static org.mockito.Mockito.mock;\r
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/test/TransactionMockUtils.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/test/TransactionMockUtils.java
new file mode 100644 (file)
index 0000000..96c7744
--- /dev/null
@@ -0,0 +1,47 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.ExecutionException;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+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.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class TransactionMockUtils {
+
+    /**
+     * Stubs {@link ReadOnlyTransaction#read(LogicalDatastoreType, InstanceIdentifier)}
+     * to return a given {@link DataObject}
+     *
+     * @param roTx mocked transaction to stub
+     * @param store {@link LogicalDatastoreType}
+     * @param path {@link InstanceIdentifier}
+     * @param isPresent stub {@link Optional#isPresent()}; if {@code true}, stub
+     *        {@link Optional#get()} to return {@code returnObject}
+     * @param returnObject {@link DataObject} to return
+     * @param <T> type of {@code returnObject}
+     * @throws ExecutionException
+     * @throws InterruptedException
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends DataObject> void setupRoTx(ReadOnlyTransaction roTx, LogicalDatastoreType store,
+            InstanceIdentifier<T> path, boolean isPresent, T returnObject)
+            throws ExecutionException, InterruptedException {
+
+        CheckedFuture<Optional<T>, ReadFailedException> future = mock(CheckedFuture.class);
+        when(roTx.read(store, path)).thenReturn(future);
+        Optional<T> opt = mock(Optional.class);
+        when(future.get()).thenReturn(opt);
+        when(opt.isPresent()).thenReturn(isPresent);
+        if (isPresent) {
+            when(opt.get()).thenReturn(returnObject);
+        }
+    }
+
+}
index 0da97aaec80ba8f636820d2811c5c578f62d1be3..e8a91201d30d48ade7d8b5cfcf66fa5342246385 100644 (file)
   <artifactId>vpp-renderer</artifactId>
   <packaging>bundle</packaging>
 
-  <properties></properties>
+  <properties>
+    <netconf.version>1.1.0-SNAPSHOT</netconf.version>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.opendaylight.netconf</groupId>
+        <artifactId>netconf-artifacts</artifactId>
+        <version>${netconf.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-artifacts</artifactId>
+        <version>${mdsal.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
 
   <dependencies>
     <!-- project specific dependencies -->
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>l2-l3-domain-extension</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>yang-ext</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.netconf</groupId>
+      <artifactId>sal-netconf-connector</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.honeycomb.vbd</groupId>
+      <artifactId>vbd-api</artifactId>
+      <version>1.0.0-SNAPSHOT</version>
+    </dependency>
 
     <!-- testing dependencies -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>groupbasedpolicy</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <!-- project build -->
         <configuration>
           <instructions>
             <Export-Package>
-              org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp.input.rev160425.*
-            </Export-Package> -->
+              org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.*
+            </Export-Package>
           </instructions>
         </configuration>
       </plugin>
index baff11b49262e1b626b0629c34378aaabface589..8049bcfaa3e52b0bc6bf410dcb38d339672edb67 100644 (file)
                       <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
                       <name>binding-data-broker</name>
                     </data-broker>
+                    <broker>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+                        <name>binding-osgi-broker</name>
+                    </broker>
                 </module>
             </modules>
         </data>
@@ -11,15 +11,15 @@ package org.opendaylight.controller.config.yang.config.vpp_provider.impl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class VppProviderModule extends org.opendaylight.controller.config.yang.config.vpp_provider.impl.AbstractVppProviderModule {
+public class GbpVppProviderModule extends org.opendaylight.controller.config.yang.config.vpp_provider.impl.AbstractGbpVppProviderModule {
 
-    private static final Logger LOG = LoggerFactory.getLogger(VppProviderModule.class);
+    private static final Logger LOG = LoggerFactory.getLogger(GbpVppProviderModule.class);
 
-    public VppProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+    public GbpVppProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public VppProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+    public GbpVppProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.vpp_provider.impl.GbpVppProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
@@ -30,7 +30,7 @@ public class VppProviderModule extends org.opendaylight.controller.config.yang.c
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        final VppRenderer vppRenderer = new VppRenderer(getDataBrokerDependency());
+        final VppRenderer vppRenderer = new VppRenderer(getDataBrokerDependency(), getBrokerDependency());
 
         LOG.info("VPP Renderer instance has been created");
 
 *
 * Generated from: yang module name: vpp-provider-impl yang module local name: vpp-provider-impl
 * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Thu May 05 09:46:48 CEST 2016
+* Generated at: Wed May 25 17:25:43 CEST 2016
 *
 * Do not modify this file unless it is present under src/main directory
 */
 package org.opendaylight.controller.config.yang.config.vpp_provider.impl;
-public class VppProviderModuleFactory extends org.opendaylight.controller.config.yang.config.vpp_provider.impl.AbstractVppProviderModuleFactory {
+public class GbpVppProviderModuleFactory extends org.opendaylight.controller.config.yang.config.vpp_provider.impl.AbstractGbpVppProviderModuleFactory {
 
 }
index f3885f2d3dbc4e2e1e48b9b12dafa771eb02feab..cf90406a2971cf72bf9ff25035f4db9ea62944de 100644 (file)
-/*\r
- * Copyright (c) 2014 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.controller.config.yang.config.vpp_provider.impl;\r
-\r
-import com.google.common.base.Preconditions;\r
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class VppRenderer implements AutoCloseable {\r
-    private static final Logger LOG = LoggerFactory.getLogger(VppRenderer.class);\r
-\r
-    private DataBroker dataBroker;\r
-\r
-    public VppRenderer(DataBroker dataBroker) {\r
-        Preconditions.checkNotNull(dataBroker);\r
-\r
-        this.dataBroker = dataBroker;\r
-\r
-        LOG.info("VPP Renderer has Started");\r
-    }\r
-\r
-    @Override\r
-    public void close() throws Exception {\r
-        this.dataBroker = null;\r
-    }\r
-\r
-}\r
+/*
+ * 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.controller.config.yang.config.vpp_provider.impl;
+
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+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.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+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.ForwardingManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.VppRendererPolicyManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.AllowAction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.EtherTypeClassifier;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererBuilder;
+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.CapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedActionDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinitionBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.eventbus.EventBus;
+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.ThreadFactoryBuilder;
+
+public class VppRenderer implements AutoCloseable, BindingAwareProvider {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VppRenderer.class);
+
+    public static final RendererName NAME = new RendererName("vpp-renderer");
+    /**
+     * Should be used for processing netconf responses so we do not consume netty thread.
+     */
+    private static final ExecutorService NETCONF_WORKER = Executors.newSingleThreadExecutor(
+            new ThreadFactoryBuilder().setNameFormat("netconf-processing-worker-%d").setDaemon(true).build());
+
+    private final List<SupportedActionDefinition> actionDefinitions =
+            ImmutableList.of(new SupportedActionDefinitionBuilder().setActionDefinitionId(new AllowAction().getId())
+                .setSupportedParameterValues(new AllowAction().getSupportedParameterValues())
+                .build());
+    private final List<SupportedClassifierDefinition> classifierDefinitions = ImmutableList
+        .of(new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(new EtherTypeClassifier(null).getId())
+            .setSupportedParameterValues(new EtherTypeClassifier(null).getSupportedParameterValues())
+            .build());
+
+    private final DataBroker dataBroker;
+
+    private VppNodeManager vppNodeManager;
+    private InterfaceManager interfaceManager;
+    private VppRendererPolicyManager vppRendererPolicyManager;
+
+    private VppNodeListener vppNodeListener;
+    private VppEndpointListener vppEndpointListener;
+    private RendererPolicyListener rendererPolicyListener;
+
+    public VppRenderer(DataBroker dataBroker, BindingAwareBroker bindingAwareBroker) {
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
+        bindingAwareBroker.registerProvider(this);
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("Closing Vpp renderer");
+        if (vppNodeListener != null) {
+            vppNodeListener.close();
+        }
+        if (vppEndpointListener != null) {
+            vppEndpointListener.close();
+        }
+        if (rendererPolicyListener != null) {
+            rendererPolicyListener.close();
+        }
+        if (interfaceManager != null) {
+            interfaceManager.close();
+        }
+        unregisterFromRendererManager();
+    }
+
+    @Override
+    public void onSessionInitiated(BindingAwareBroker.ProviderContext providerContext) {
+        LOG.info("starting vpp renderer");
+
+        MountPointService mountService =
+                Preconditions.checkNotNull(providerContext.getSALService(MountPointService.class));
+        MountedDataBrokerProvider mountDataProvider = new MountedDataBrokerProvider(mountService);
+        vppNodeManager = new VppNodeManager(dataBroker, providerContext);
+
+        EventBus dtoEventBus = new EventBus("DTO events");
+        interfaceManager = new InterfaceManager(mountDataProvider, dataBroker, NETCONF_WORKER);
+        dtoEventBus.register(interfaceManager);
+        ForwardingManager fwManager = new ForwardingManager(interfaceManager, new BridgeDomainManagerImpl(dataBroker));
+        vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, dataBroker);
+        dtoEventBus.register(vppRendererPolicyManager);
+
+        vppNodeListener = new VppNodeListener(dataBroker, vppNodeManager, dtoEventBus);
+        vppEndpointListener = new VppEndpointListener(dataBroker, dtoEventBus);
+        rendererPolicyListener = new RendererPolicyListener(dataBroker, dtoEventBus);
+
+        registerToRendererManager();
+    }
+
+    private void registerToRendererManager() {
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+        Renderer renderer = new RendererBuilder().setName(VppRenderer.NAME)
+            .setRendererNodes(new RendererNodesBuilder().build())
+            .setCapabilities(new CapabilitiesBuilder().setSupportedActionDefinition(actionDefinitions)
+                .setSupportedClassifierDefinition(classifierDefinitions)
+                .build())
+            .build();
+
+        writeTransaction.put(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererIID(renderer.getKey()),
+                renderer, true);
+        CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
+        Futures.addCallback(future, new FutureCallback<Void>() {
+
+            @Override
+            public void onFailure(Throwable throwable) {
+                LOG.error("Could not register renderer {}: {}", renderer, throwable);
+            }
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("Renderer {} successfully registered.", renderer);
+            }
+        });
+    }
+
+    private void unregisterFromRendererManager() {
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+        writeTransaction.delete(LogicalDatastoreType.OPERATIONAL,
+                VppIidFactory.getRendererIID(new RendererKey(VppRenderer.NAME)));
+
+        CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
+        Futures.addCallback(future, new FutureCallback<Void>() {
+
+            @Override
+            public void onFailure(Throwable throwable) {
+                LOG.error("Could not unregister renderer {}: {}", VppRenderer.NAME, throwable);
+            }
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("Renderer {} successfully unregistered.", VppRenderer.NAME);
+            }
+        });
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/api/BridgeDomainManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/api/BridgeDomainManager.java
new file mode 100644 (file)
index 0000000..1b8f8b0
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.api;
+
+import javax.annotation.Nonnull;
+
+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 com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Bridge domain manager interface.
+ */
+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
+     * @return {@link ListenableFuture}
+     */
+    ListenableFuture<Void> createVxlanBridgeDomainOnVppNode(@Nonnull String bridgeDomainName, @Nonnull VxlanVni vni,
+            NodeId vppNode);
+
+    /**
+     * 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);
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/AbstractInterfaceCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/AbstractInterfaceCommand.java
new file mode 100644 (file)
index 0000000..0493631
--- /dev/null
@@ -0,0 +1,50 @@
+/*\r
+ * Copyright (c) 2016 Cisco Systems. 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.renderer.vpp.commands;\r
+\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;\r
+\r
+public abstract class AbstractInterfaceCommand<T extends AbstractInterfaceCommand<T>> implements ConfigCommand {\r
+\r
+    protected General.Operations operation;\r
+    protected String name;\r
+    protected String description;\r
+    protected Boolean enabled;\r
+\r
+    protected enum linkUpDownTrap {\r
+        ENABLED, DISABLED\r
+    }\r
+\r
+    public General.Operations getOperation() {\r
+        return operation;\r
+    }\r
+\r
+    public String getName() {\r
+        return name;\r
+    }\r
+\r
+    public String getDescription() {\r
+        return description;\r
+    }\r
+\r
+    public AbstractInterfaceCommand<T> setDescription(String description) {\r
+        this.description = description;\r
+        return this;\r
+    }\r
+\r
+    public Boolean getEnabled() {\r
+        return enabled;\r
+    }\r
+\r
+    public AbstractInterfaceCommand<T> setEnabled(Boolean enabled) {\r
+        this.enabled = enabled;\r
+        return this;\r
+    }\r
+\r
+}\r
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ConfigCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ConfigCommand.java
new file mode 100644 (file)
index 0000000..cd8b690
--- /dev/null
@@ -0,0 +1,22 @@
+/*\r
+ * Copyright (c) 2016 Cisco Systems. 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.renderer.vpp.commands;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
+\r
+public interface ConfigCommand {\r
+\r
+    /**\r
+     * Execute command using a given data modification transaction\r
+     *\r
+     * @param readWriteTransaction Transaction for command execution\r
+     */\r
+    void execute(ReadWriteTransaction readWriteTransaction);\r
+\r
+}\r
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java
new file mode 100644 (file)
index 0000000..b5c8277
--- /dev/null
@@ -0,0 +1,231 @@
+/*\r
+ * Copyright (c) 2016 Cisco Systems. 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.renderer.vpp.commands;\r
+\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.renderer.vpp.util.General;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUserRole;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentationBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUserBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBasedBuilder;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.google.common.base.Preconditions;\r
+import com.google.common.base.Strings;\r
+\r
+public class VhostUserCommand extends AbstractInterfaceCommand<VhostUserCommand> {\r
+\r
+    private static final Logger LOG = LoggerFactory.getLogger(VhostUserCommand.class);\r
+    private String socket;\r
+    private VhostUserRole role;\r
+    private String bridgeDomain;\r
+\r
+    private VhostUserCommand(VhostUserCommandBuilder builder) {\r
+        this.name = builder.getName();\r
+        this.operation = builder.getOperation();\r
+        this.socket = builder.getSocket();\r
+        this.role = builder.getRole();\r
+        this.enabled = builder.isEnabled();\r
+        this.description = builder.getDescription();\r
+        this.bridgeDomain = builder.getBridgeDomain();\r
+\r
+    }\r
+\r
+    public static VhostUserCommandBuilder builder() {\r
+        return new VhostUserCommandBuilder();\r
+    }\r
+\r
+    public String getSocket() {\r
+        return socket;\r
+    }\r
+\r
+    public VhostUserRole getRole() {\r
+        return role;\r
+    }\r
+\r
+    public String getBridgeDomain() {\r
+        return bridgeDomain;\r
+    }\r
+\r
+    @Override\r
+    public void execute(ReadWriteTransaction readWriteTransaction) {\r
+        switch (getOperation()) {\r
+\r
+            case PUT:\r
+                LOG.debug("Executing Add operation for command: {}", this);\r
+                put(readWriteTransaction);\r
+                break;\r
+            case DELETE:\r
+                LOG.debug("Executing Delete operation for command: {}", this);\r
+                delete(readWriteTransaction);\r
+                break;\r
+            case MERGE:\r
+                LOG.debug("Executing Update operation for command: {}", this);\r
+                merge(readWriteTransaction);\r
+                break;\r
+            default:\r
+                LOG.error("Execution failed for command: {}", this);\r
+                break;\r
+        }\r
+    }\r
+\r
+    private void put(ReadWriteTransaction readWriteTransaction) {\r
+        InterfaceBuilder interfaceBuilder = getVhostUserInterfaceBuilder();\r
+\r
+        readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION,\r
+                VppIidFactory.getInterfaceIID(interfaceBuilder.getKey()), interfaceBuilder.build(), true);\r
+    }\r
+\r
+    private void merge(ReadWriteTransaction readWriteTransaction) {\r
+        InterfaceBuilder interfaceBuilder = getVhostUserInterfaceBuilder();\r
+\r
+            readWriteTransaction.merge(LogicalDatastoreType.CONFIGURATION,\r
+                    VppIidFactory.getInterfaceIID(interfaceBuilder.getKey()), interfaceBuilder.build());\r
+    }\r
+\r
+    private InterfaceBuilder getVhostUserInterfaceBuilder() {\r
+        InterfaceBuilder interfaceBuilder =\r
+                new InterfaceBuilder().setKey(new InterfaceKey(name))\r
+                        .setEnabled(enabled)\r
+                        .setDescription(description)\r
+                        .setType(\r
+                                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser.class)\r
+                        .setName(name)\r
+                        .setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Enabled);\r
+\r
+        // Create the vhost augmentation\r
+        VppInterfaceAugmentationBuilder vppAugmentationBuilder = new VppInterfaceAugmentationBuilder()\r
+            .setVhostUser(new VhostUserBuilder().setRole(role).setSocket(socket).build());\r
+        if (!Strings.isNullOrEmpty(bridgeDomain)) {\r
+            vppAugmentationBuilder.setL2(new L2Builder()\r
+                .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomain).build()).build());\r
+        }\r
+\r
+        interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentationBuilder.build());\r
+        return interfaceBuilder;\r
+    }\r
+\r
+    private void delete(ReadWriteTransaction readWriteTransaction) {\r
+        try {\r
+            readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION,\r
+                    VppIidFactory.getInterfaceIID(new InterfaceKey(name)));\r
+        } catch (IllegalStateException ex) {\r
+            LOG.debug("Vhost Interface is not present in DS", ex);\r
+        }\r
+\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        return "VhostUserCommand [socket=" + socket + ", role=" + role + ", bridgeDomain=" + bridgeDomain\r
+                + ", operation=" + operation + ", name=" + name + ", description=" + description + ", enabled="\r
+                + enabled + "]";\r
+    }\r
+\r
+\r
+\r
+    public static class VhostUserCommandBuilder {\r
+\r
+        private String name;\r
+        private General.Operations operation;\r
+        private String socket;\r
+        private VhostUserRole role = VhostUserRole.Server;\r
+        private boolean enabled = true;\r
+        private String description;\r
+        private String bridgeDomain;\r
+\r
+        public String getName() {\r
+            return name;\r
+        }\r
+\r
+        public VhostUserCommandBuilder setName(String name) {\r
+            this.name = name;\r
+            return this;\r
+        }\r
+\r
+        public General.Operations getOperation() {\r
+            return operation;\r
+        }\r
+\r
+        public VhostUserCommandBuilder setOperation(General.Operations operation) {\r
+            this.operation = operation;\r
+            return this;\r
+        }\r
+\r
+        public String getSocket() {\r
+            return socket;\r
+        }\r
+\r
+        public VhostUserCommandBuilder setSocket(String socket) {\r
+            this.socket = socket;\r
+            return this;\r
+        }\r
+\r
+        public VhostUserRole getRole() {\r
+            return role;\r
+        }\r
+\r
+        public VhostUserCommandBuilder setRole(VhostUserRole role) {\r
+            this.role = role;\r
+            return this;\r
+        }\r
+\r
+        public boolean isEnabled() {\r
+            return enabled;\r
+        }\r
+\r
+        public VhostUserCommandBuilder setEnabled(boolean enabled) {\r
+            this.enabled = enabled;\r
+            return this;\r
+        }\r
+\r
+        public String getDescription() {\r
+            return description;\r
+        }\r
+\r
+        public VhostUserCommandBuilder setDescription(String description) {\r
+            this.description = description;\r
+            return this;\r
+        }\r
+\r
+        public String getBridgeDomain() {\r
+            return bridgeDomain;\r
+        }\r
+\r
+        public VhostUserCommandBuilder setBridgeDomain(String bridgeDomain) {\r
+            this.bridgeDomain = bridgeDomain;\r
+            return this;\r
+        }\r
+\r
+        /**\r
+         * VhostUserCommand build method.\r
+         *\r
+         * @return VhostUserCommand\r
+         * @throws IllegalArgumentException if name, operation or socket is null.\r
+         */\r
+        public VhostUserCommand build() {\r
+            Preconditions.checkArgument(this.name != null);\r
+            Preconditions.checkArgument(this.operation != null);\r
+            if (operation == Operations.PUT) {\r
+                Preconditions.checkArgument(this.socket != null);\r
+            }\r
+\r
+            return new VhostUserCommand(this);\r
+        }\r
+    }\r
+}\r
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/DtoChangeEvent.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/DtoChangeEvent.java
new file mode 100644 (file)
index 0000000..3ae518a
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * 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.event;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public abstract class DtoChangeEvent<T extends DataObject> {
+
+    protected final InstanceIdentifier<T> iid;
+    protected final Optional<T> before;
+    protected final Optional<T> after;
+
+    public static enum DtoModificationType {
+        CREATED, UPDATED, DELETED;
+    }
+
+    public DtoChangeEvent(@Nonnull InstanceIdentifier<T> iid, @Nullable T before, @Nullable T after) {
+        this.iid = Preconditions.checkNotNull(iid);
+        Preconditions.checkArgument(!(before == null && after == null),
+                "before and after cannot be null at the same time");
+        this.before = Optional.fromNullable(before);
+        this.after = Optional.fromNullable(after);
+    }
+
+    public @Nonnull InstanceIdentifier<T> getIid() {
+        return iid;
+    }
+
+    public Optional<T> getBefore() {
+        return before;
+    }
+
+    public Optional<T> getAfter() {
+        return after;
+    }
+
+    /**
+     * Returns:<br>
+     * {@link DtoModificationType#CREATED} - when {@link #isDtoCreated()} is {@code true}<br>
+     * {@link DtoModificationType#UPDATED} - when {@link #isDtoUpdated()} is {@code true}<br>
+     * {@link DtoModificationType#DELETED} - when {@link #isDtoDeleted()} is {@code true}
+     * 
+     * @return DtoModificationType
+     */
+    public @Nonnull DtoModificationType getDtoModificationType() {
+        if (isDtoCreated()) {
+            return DtoModificationType.CREATED;
+        }
+        if (isDtoUpdated()) {
+            return DtoModificationType.UPDATED;
+        }
+        if (isDtoDeleted()) {
+            return DtoModificationType.DELETED;
+        }
+        throw new IllegalStateException("Unknown DTO modification type.");
+    }
+
+    /**
+     * Checks if {@link #getBefore()} is NOT present and if {@link #getAfter()} is present
+     * 
+     * @return {@code true} if DTO is created; {@code false} otherwise
+     */
+    public boolean isDtoCreated() {
+        return !before.isPresent() && after.isPresent();
+    }
+
+    /**
+     * Checks if {@link #getBefore()} is present and if {@link #getAfter()} is present
+     * 
+     * @return {@code true} if DTO is updated; {@code false} otherwise
+     */
+    public boolean isDtoUpdated() {
+        return before.isPresent() && after.isPresent();
+    }
+
+    /**
+     * Checks if {@link #getBefore()} is present and if {@link #getAfter()} is NOT present
+     * 
+     * @return {@code true} if DTO is deleted; {@code false} otherwise
+     */
+    public boolean isDtoDeleted() {
+        return before.isPresent() && !after.isPresent();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((after == null) ? 0 : after.hashCode());
+        result = prime * result + ((before == null) ? 0 : before.hashCode());
+        result = prime * result + ((iid == null) ? 0 : iid.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (!(obj instanceof DtoChangeEvent))
+            return false;
+        DtoChangeEvent other = (DtoChangeEvent) obj;
+        if (after == null) {
+            if (other.after != null)
+                return false;
+        } else if (!after.equals(other.after))
+            return false;
+        if (before == null) {
+            if (other.before != null)
+                return false;
+        } else if (!before.equals(other.before))
+            return false;
+        if (iid == null) {
+            if (other.iid != null)
+                return false;
+        } else if (!iid.equals(other.iid))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " [iid=" + iid + ", before=" + before + ", after=" + after + "]";
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/NodeOperEvent.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/NodeOperEvent.java
new file mode 100644 (file)
index 0000000..2ad4154
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.event;
+
+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.ConnectionStatus;
+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;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public class NodeOperEvent extends DtoChangeEvent<Node> {
+
+    public NodeOperEvent(InstanceIdentifier<Node> iid, Node before, Node after) {
+        super(iid, before, after);
+        if (before != null) {
+            Preconditions.checkArgument(before.getAugmentation(NetconfNode.class) != null);
+        }
+        if (after != null) {
+            Preconditions.checkArgument(after.getAugmentation(NetconfNode.class) != null);
+        }
+    }
+
+    public boolean isAfterConnected() {
+        return isConnected(after);
+    }
+
+    public boolean isBeforeConnected() {
+        return isConnected(before);
+    }
+
+    private static boolean isConnected(Optional<Node> potentialNode) {
+        if (!potentialNode.isPresent()) {
+            return false;
+        }
+        NetconfNode netconfNode = potentialNode.get().getAugmentation(NetconfNode.class);
+        if (ConnectionStatus.Connected == netconfNode.getConnectionStatus()) {
+            return true;
+        }
+        return false;
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/RendererPolicyConfEvent.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/RendererPolicyConfEvent.java
new file mode 100644 (file)
index 0000000..9d7b8c5
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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.event;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class RendererPolicyConfEvent extends DtoChangeEvent<RendererPolicy> {
+
+    public RendererPolicyConfEvent(InstanceIdentifier<RendererPolicy> iid, RendererPolicy before,
+            RendererPolicy after) {
+        super(iid, before, after);
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/VppEndpointConfEvent.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/VppEndpointConfEvent.java
new file mode 100644 (file)
index 0000000..8034a6a
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.event;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VppEndpointConfEvent extends DtoChangeEvent<VppEndpoint> {
+
+    public VppEndpointConfEvent(InstanceIdentifier<VppEndpoint> iid, VppEndpoint before, VppEndpoint after) {
+        super(iid, before, after);
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java
new file mode 100644 (file)
index 0000000..5fac50b
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * 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.iface;
+
+import java.util.concurrent.ExecutorService;
+
+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.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.renderer.vpp.commands.ConfigCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand.VhostUserCommandBuilder;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.event.NodeOperEvent;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+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.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+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.vpp.endpoint.InterfaceTypeChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUserRole;
+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.interfaces._interface.L2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder;
+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.l2.base.attributes.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.eventbus.Subscribe;
+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;
+
+public class InterfaceManager implements AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class);
+    private final MountedDataBrokerProvider mountDataProvider;
+    private final VppEndpointLocationProvider vppEndpointLocationProvider;
+    private final ExecutorService netconfWorker;
+
+    public InterfaceManager(@Nonnull MountedDataBrokerProvider mountDataProvider, @Nonnull DataBroker dataProvider, @Nonnull ExecutorService netconfWorker) {
+        this.mountDataProvider = Preconditions.checkNotNull(mountDataProvider);
+        this.netconfWorker = Preconditions.checkNotNull(netconfWorker);
+        this.vppEndpointLocationProvider = new VppEndpointLocationProvider(dataProvider);
+    }
+
+    @Subscribe
+    public synchronized void vppEndpointChanged(VppEndpointConfEvent event) {
+        switch (event.getDtoModificationType()) {
+            case CREATED:
+                vppEndpointCreated(event.getAfter().get());
+                break;
+            case UPDATED:
+                vppEndpointDeleted(event.getBefore().get());
+                vppEndpointCreated(event.getAfter().get());
+                break;
+            case DELETED:
+                vppEndpointDeleted(event.getBefore().get());
+                break;
+        }
+    }
+
+    private void vppEndpointCreated(VppEndpoint vppEndpoint) {
+        Optional<ConfigCommand> potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT);
+        if (!potentialIfaceCommand.isPresent()) {
+            return;
+        }
+        ConfigCommand ifaceWithoutBdCommand = potentialIfaceCommand.get();
+        InstanceIdentifier<?> vppNodeIid = vppEndpoint.getVppNodePath();
+        Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
+        if (!potentialVppDataProvider.isPresent()) {
+            LOG.debug("Cannot get data broker for mount point {}", vppNodeIid);
+            return;
+        }
+        DataBroker vppDataBroker = potentialVppDataProvider.get();
+        createIfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid);
+    }
+
+    private void createIfaceOnVpp(ConfigCommand createIfaceWithoutBdCommand, DataBroker vppDataBroker,
+            VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
+        ReadWriteTransaction rwTx = vppDataBroker.newReadWriteTransaction();
+        createIfaceWithoutBdCommand.execute(rwTx);
+        Futures.addCallback(rwTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("Create interface on VPP command was successful:\nVPP: {}\nCommand: {}", vppNodeIid,
+                        createIfaceWithoutBdCommand);
+                vppEndpointLocationProvider.createLocationForVppEndpoint(vppEndpoint);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("Create interface on VPP command was NOT successful:\nVPP: {}\nCommand: {}", vppNodeIid,
+                        createIfaceWithoutBdCommand, t);
+            }
+        }, netconfWorker);
+    }
+
+    private void vppEndpointDeleted(VppEndpoint vppEndpoint) {
+        Optional<ConfigCommand> potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE);
+        if (!potentialIfaceCommand.isPresent()) {
+            return;
+        }
+        ConfigCommand ifaceWithoutBdCommand = potentialIfaceCommand.get();
+        InstanceIdentifier<?> vppNodeIid = vppEndpoint.getVppNodePath();
+        Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
+        if (!potentialVppDataProvider.isPresent()) {
+            LOG.debug("Cannot get data broker for mount point {}", vppNodeIid);
+            return;
+        }
+        DataBroker vppDataBroker = potentialVppDataProvider.get();
+        deleteIfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid);
+    }
+
+    private void deleteIfaceOnVpp(ConfigCommand deleteIfaceWithoutBdCommand, DataBroker vppDataBroker,
+            VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
+        ReadWriteTransaction rwTx = vppDataBroker.newReadWriteTransaction();
+        deleteIfaceWithoutBdCommand.execute(rwTx);
+        Futures.addCallback(rwTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("Delete interface on VPP command was successful:\nVPP: {}\nCommand: {}", vppNodeIid,
+                        deleteIfaceWithoutBdCommand);
+                vppEndpointLocationProvider.deleteLocationForVppEndpoint(vppEndpoint);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("Delete interface on VPP command was NOT successful:\nVPP: {}\nCommand: {}", vppNodeIid,
+                        deleteIfaceWithoutBdCommand, t);
+            }
+        }, netconfWorker);
+    }
+
+    @Subscribe
+    public synchronized void vppNodeChanged(NodeOperEvent event) {
+        switch (event.getDtoModificationType()) {
+            case CREATED:
+                if (event.isAfterConnected()) {
+                    // TODO read VppEndpoints or cache them during vppEndpointChanged()
+                }
+                break;
+            case UPDATED:
+                if (!event.isBeforeConnected() && event.isAfterConnected()) {
+                    // TODO reconciliation - diff between disconnected snapshot and current snapshot
+                }
+                break;
+            case DELETED:
+                if (event.isBeforeConnected()) {
+                    // TODO we could do snapshot of VppEndpoints 
+                    // which can be used for reconciliation
+                }
+                break;
+        }
+    }
+
+    private static Optional<ConfigCommand> createInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp,
+            @Nonnull Operations operations) {
+        if (!hasNodeAndInterface(vppEp)) {
+            LOG.debug("Interface command is not created for {}", vppEp);
+            return Optional.absent();
+        }
+        VhostUserCommandBuilder builder = VhostUserCommand.builder();
+        builder.setName(vppEp.getVppInterfaceName());
+        InterfaceTypeChoice interfaceTypeChoice = vppEp.getInterfaceTypeChoice();
+        if (interfaceTypeChoice instanceof VhostUserCase) {
+            VhostUserCase vhostUserIface = (VhostUserCase) interfaceTypeChoice;
+            String socket = vhostUserIface.getSocket();
+            if (Strings.isNullOrEmpty(socket)) {
+                LOG.debug("Vhost user interface command is not created because socket is missing. {}", vppEp);
+                return Optional.absent();
+            }
+            builder.setSocket(socket);
+            builder.setRole(VhostUserRole.Client);
+        }
+        VhostUserCommand vhostUserCommand =
+                builder.setOperation(operations).setDescription(vppEp.getDescription()).build();
+        return Optional.of(vhostUserCommand);
+    }
+
+    /**
+     * Adds bridge domain to an interface if the interface exist.<br>
+     * It rewrites bridge domain in case it already exist.<br>
+     * {@link VppEndpointLocationProvider#VPP_ENDPOINT_LOCATION_PROVIDER} will update location
+     * when the interface is created successfully.<br>
+     * If the interface does not exist or other problems occur {@link ListenableFuture} will fail
+     * as {@link Futures#immediateFailedFuture(Throwable)} with {@link Exception}
+     * containing message in {@link Exception#getMessage()}
+     * 
+     * @param bridgeDomainName bridge domain
+     * @param addrEpWithLoc {@link AddressEndpointWithLocation} containing
+     *        {@link ExternalLocationCase} where
+     *        {@link ExternalLocationCase#getExternalNodeMountPoint()} MUST NOT be {@code null}
+     *        and {@link ExternalLocationCase#getExternalNodeConnector()} MUST NOT be {@code null}
+     * @return {@link ListenableFuture}
+     */
+    public synchronized @Nonnull ListenableFuture<Void> addBridgeDomainToInterface(@Nonnull String bridgeDomainName,
+            @Nonnull AddressEndpointWithLocation addrEpWithLoc) {
+        ExternalLocationCase epLoc = resolveAndValidateLocation(addrEpWithLoc);
+        InstanceIdentifier<?> vppNodeIid = epLoc.getExternalNodeMountPoint();
+        String interfacePath = epLoc.getExternalNodeConnector();
+
+        Optional<InstanceIdentifier<Interface>> optInterfaceIid =
+                VppPathMapper.interfaceToInstanceIdentifier(interfacePath);
+        if (!optInterfaceIid.isPresent()) {
+            return Futures.immediateFailedFuture(
+                    new Exception("Cannot resolve interface instance-identifier for interface path" + interfacePath));
+        }
+        InstanceIdentifier<Interface> interfaceIid = optInterfaceIid.get();
+
+        Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
+        if (!potentialVppDataProvider.isPresent()) {
+            return Futures.immediateFailedFuture(new Exception("Cannot get data broker for mount point " + vppNodeIid));
+        }
+
+        ReadWriteTransaction rwTx = potentialVppDataProvider.get().newReadWriteTransaction();
+        CheckedFuture<Optional<Interface>, ReadFailedException> futureIface =
+                rwTx.read(LogicalDatastoreType.CONFIGURATION, interfaceIid);
+        return Futures.transform(futureIface, new AsyncFunction<Optional<Interface>, Void>() {
+
+            @Override
+            public ListenableFuture<Void> apply(Optional<Interface> optIface) throws Exception {
+                if (!optIface.isPresent()) {
+                    return Futures.immediateFailedFuture(new Exception("Iterface "
+                            + interfaceIid.firstKeyOf(Interface.class) + " does not exist on node " + vppNodeIid));
+                }
+
+                String existingBridgeDomain = resolveBridgeDomain(optIface.get());
+                if (bridgeDomainName.equals(existingBridgeDomain)) {
+                    String nodePath = VppPathMapper.bridgeDomainToRestPath(bridgeDomainName);
+                    if (!nodePath.equals(epLoc.getExternalNode())) {
+                        vppEndpointLocationProvider.updateExternalNodeLocationForEndpoint(nodePath,
+                                epLoc.getExternalNodeMountPoint(), addrEpWithLoc.getKey());
+                    }
+                    return Futures.immediateFuture(null);
+                }
+
+                InstanceIdentifier<L2> l2Iid =
+                        interfaceIid.builder().augmentation(VppInterfaceAugmentation.class).child(L2.class).build();
+                L2 l2 = new L2Builder()
+                    .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomainName).build()).build();
+                rwTx.merge(LogicalDatastoreType.CONFIGURATION, l2Iid, l2);
+                return Futures.transform(rwTx.submit(), new Function<Void, Void>() {
+
+                    @Override
+                    public Void apply(Void input) {
+                        String nodePath = VppPathMapper.bridgeDomainToRestPath(bridgeDomainName);
+                        vppEndpointLocationProvider.updateExternalNodeLocationForEndpoint(nodePath,
+                                epLoc.getExternalNodeMountPoint(), addrEpWithLoc.getKey());
+                        return null;
+                    }
+                }, netconfWorker);
+            }
+        }, netconfWorker);
+    }
+
+    /**
+     * <p>
+     * Removes bridge domain (if exist) from an interface (if exist).<br>
+     * {@link VppEndpointLocationProvider#VPP_ENDPOINT_LOCATION_PROVIDER} will update endpoint
+     * location.
+     * <p>
+     * If the interface does not exist or other problems occur {@link ListenableFuture} will fail
+     * as {@link Futures#immediateFailedFuture(Throwable)} with {@link Exception}
+     * containing message in {@link Exception#getMessage()}
+     * 
+     * @param addrEpWithLoc {@link AddressEndpointWithLocation} containing
+     *        {@link ExternalLocationCase} where
+     *        {@link ExternalLocationCase#getExternalNodeMountPoint()} MUST NOT be {@code null}
+     *        and {@link ExternalLocationCase#getExternalNodeConnector()} MUST NOT be {@code null}
+     * @return {@link ListenableFuture}
+     */
+    public synchronized @Nonnull ListenableFuture<Void> deleteBridgeDomainFromInterface(
+            @Nonnull AddressEndpointWithLocation addrEpWithLoc) {
+        ExternalLocationCase epLoc = resolveAndValidateLocation(addrEpWithLoc);
+        InstanceIdentifier<?> vppNodeIid = epLoc.getExternalNodeMountPoint();
+        String interfacePath = epLoc.getExternalNodeConnector();
+
+        Optional<InstanceIdentifier<Interface>> optInterfaceIid =
+                VppPathMapper.interfaceToInstanceIdentifier(interfacePath);
+        if (!optInterfaceIid.isPresent()) {
+            return Futures.immediateFailedFuture(
+                    new Exception("Cannot resolve interface instance-identifier for interface path" + interfacePath));
+        }
+        InstanceIdentifier<Interface> interfaceIid = optInterfaceIid.get();
+
+        Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
+        if (!potentialVppDataProvider.isPresent()) {
+            return Futures.immediateFailedFuture(new Exception("Cannot get data broker for mount point " + vppNodeIid));
+        }
+
+        ReadWriteTransaction rwTx = potentialVppDataProvider.get().newReadWriteTransaction();
+        CheckedFuture<Optional<Interface>, ReadFailedException> futureIface =
+                rwTx.read(LogicalDatastoreType.CONFIGURATION, interfaceIid);
+        return Futures.transform(futureIface, new AsyncFunction<Optional<Interface>, Void>() {
+
+            @Override
+            public ListenableFuture<Void> apply(Optional<Interface> optIface) throws Exception {
+                if (!optIface.isPresent()) {
+                    // interface does not exist so we consider job done
+                    return Futures.immediateFuture(null);
+                }
+
+                String existingBridgeDomain = resolveBridgeDomain(optIface.get());
+                if (Strings.isNullOrEmpty(existingBridgeDomain)) {
+                    // bridge domain does not exist on interface so we consider job done
+                    vppEndpointLocationProvider.updateExternalNodeLocationForEndpoint(null,
+                            epLoc.getExternalNodeMountPoint(), addrEpWithLoc.getKey());
+                    return Futures.immediateFuture(null);
+                }
+
+                InstanceIdentifier<L2> l2Iid =
+                        interfaceIid.builder().augmentation(VppInterfaceAugmentation.class).child(L2.class).build();
+                rwTx.delete(LogicalDatastoreType.CONFIGURATION, l2Iid);
+                return Futures.transform(rwTx.submit(), new Function<Void, Void>() {
+
+                    @Override
+                    public Void apply(Void input) {
+                        vppEndpointLocationProvider.updateExternalNodeLocationForEndpoint(null,
+                                epLoc.getExternalNodeMountPoint(), addrEpWithLoc.getKey());
+                        return null;
+                    }
+                }, netconfWorker);
+            }
+        }, netconfWorker);
+    }
+
+    private static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
+        LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
+        if (!(locationType instanceof ExternalLocationCase)) {
+            throw new IllegalArgumentException("Endpoint does not have external location " + addrEpWithLoc);
+        }
+        ExternalLocationCase result = (ExternalLocationCase) locationType;
+        if (result.getExternalNodeMountPoint() == null || result.getExternalNodeConnector() == null) {
+            throw new IllegalArgumentException(
+                    "Endpoint does not have external-node-mount-point or external-node-connector " + addrEpWithLoc);
+        }
+        return result;
+    }
+
+    private static @Nullable String resolveBridgeDomain(@Nonnull Interface iface) {
+        VppInterfaceAugmentation vppInterfaceAugmentation = iface.getAugmentation(VppInterfaceAugmentation.class);
+        L2 existingL2 = vppInterfaceAugmentation.getL2();
+        if (existingL2 != null) {
+            Interconnection interconnection = existingL2.getInterconnection();
+            if (interconnection instanceof BridgeBased) {
+                return ((BridgeBased) interconnection).getBridgeDomain();
+            }
+        }
+        return null;
+    }
+
+    private static boolean hasNodeAndInterface(VppEndpoint vppEp) {
+        if (vppEp.getVppNodePath() == null) {
+            LOG.trace("vpp-node is missing. {}", vppEp);
+            return false;
+        }
+        if (Strings.isNullOrEmpty(vppEp.getVppInterfaceName())) {
+            LOG.trace("vpp-interface-name is missing. {}", vppEp);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public void close() throws Exception {
+        vppEndpointLocationProvider.close();
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppEndpointLocationProvider.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppEndpointLocationProvider.java
new file mode 100644 (file)
index 0000000..52accca
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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.iface;
+
+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.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+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.endpoint_location_provider.rev160419.ProviderName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProviderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationKey;
+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.vpp_renderer.rev160425.config.VppEndpoint;
+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.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class VppEndpointLocationProvider implements AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VppEndpointLocationProvider.class);
+    public static final ProviderName VPP_ENDPOINT_LOCATION_PROVIDER =
+            new ProviderName("VPP endpoint location provider");
+    public static final long PROVIDER_PRIORITY = 10L;
+    private final DataBroker dataProvider;
+
+    public VppEndpointLocationProvider(DataBroker dataProvider) {
+        this.dataProvider = Preconditions.checkNotNull(dataProvider);
+        LocationProvider locationProvider = new LocationProviderBuilder().setProvider(VPP_ENDPOINT_LOCATION_PROVIDER)
+            .setPriority(PROVIDER_PRIORITY)
+            .build();
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.locationProviderIid(VPP_ENDPOINT_LOCATION_PROVIDER),
+                locationProvider, true);
+
+        Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("{} was created", VPP_ENDPOINT_LOCATION_PROVIDER.getValue());
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("{} was NOT created", VPP_ENDPOINT_LOCATION_PROVIDER.getValue());
+            }
+        });
+    }
+
+    public void createLocationForVppEndpoint(VppEndpoint vppEndpoint) {
+        ProviderAddressEndpointLocation providerAddressEndpointLocation =
+                createProviderAddressEndpointLocation(vppEndpoint);
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER,
+                        providerAddressEndpointLocation.getKey()),
+                providerAddressEndpointLocation);
+
+        Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("{} provides location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
+                        providerAddressEndpointLocation);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("{} failed to provide location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
+                        providerAddressEndpointLocation, t);
+            }
+        });
+    }
+
+    public static ProviderAddressEndpointLocation createProviderAddressEndpointLocation(VppEndpoint vppEndpoint) {
+        String restIfacePath = VppPathMapper.interfaceToRestPath(vppEndpoint.getVppInterfaceName());
+        AbsoluteLocation absoluteLocation = new AbsoluteLocationBuilder()
+            .setLocationType(new ExternalLocationCaseBuilder().setExternalNodeMountPoint(vppEndpoint.getVppNodePath())
+                .setExternalNodeConnector(restIfacePath)
+                .build())
+            .build();
+        return new ProviderAddressEndpointLocationBuilder()
+            .setKey(createProviderAddressEndpointLocationKey(vppEndpoint))
+            .setAbsoluteLocation(absoluteLocation)
+            .build();
+    }
+
+    public void deleteLocationForVppEndpoint(VppEndpoint vppEndpoint) {
+        ProviderAddressEndpointLocationKey provAddrEpLocKey = createProviderAddressEndpointLocationKey(vppEndpoint);
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.delete(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER, provAddrEpLocKey));
+        Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("{} removes location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(), provAddrEpLocKey);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("{} failed to remove location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
+                        provAddrEpLocKey, t);
+            }
+        });
+    }
+
+    private static ProviderAddressEndpointLocationKey createProviderAddressEndpointLocationKey(
+            VppEndpoint vppEndpoint) {
+        return new ProviderAddressEndpointLocationKey(vppEndpoint.getAddress(), vppEndpoint.getAddressType(),
+                vppEndpoint.getContextId(), vppEndpoint.getContextType());
+    }
+
+    public void updateExternalNodeLocationForEndpoint(@Nullable String nodePath,
+            InstanceIdentifier<?> externalNodeMountPoint, @Nonnull AddressEndpointWithLocationKey addrEpWithLocKey) {
+        ProviderAddressEndpointLocationKey provAddrEpLocKey =
+                KeyFactory.providerAddressEndpointLocationKey(addrEpWithLocKey);
+        AbsoluteLocation absoluteLocation =
+                new AbsoluteLocationBuilder().setLocationType(new ExternalLocationCaseBuilder()
+                    .setExternalNodeMountPoint(externalNodeMountPoint).setExternalNode(nodePath).build()).build();
+        ProviderAddressEndpointLocation providerAddressEndpointLocation = new ProviderAddressEndpointLocationBuilder()
+            .setKey(provAddrEpLocKey).setAbsoluteLocation(absoluteLocation).build();
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.merge(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER,
+                        providerAddressEndpointLocation.getKey()),
+                providerAddressEndpointLocation);
+
+        Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("{} merges location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
+                        providerAddressEndpointLocation);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("{} failed to merge location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
+                        providerAddressEndpointLocation, t);
+            }
+        });
+    }
+
+    @Override
+    public void close() throws Exception {
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.delete(LogicalDatastoreType.CONFIGURATION, IidFactory.locationProviderIid(VPP_ENDPOINT_LOCATION_PROVIDER));
+        wTx.submit();
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapper.java
new file mode 100644 (file)
index 0000000..6cebc3f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.iface;
+
+import javax.annotation.Nullable;
+
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+
+public class VppPathMapper {
+
+    private static final String INTERFACE_PATH_BEFORE_KEY =
+            "/ietf-interfaces:interfaces/ietf-interfaces:interface[ietf-interfaces:name='";
+    private static final String INTERFACE_PATH_AFTER_KEY = "']";
+    private static final int INTERFACE_PATH_MIN_LENGTH =
+            INTERFACE_PATH_BEFORE_KEY.length() + INTERFACE_PATH_AFTER_KEY.length() + 1;
+    private static final String BD_PATH_BEFORE_KEY = "/v3po:vpp/v3po:bridge-domains/v3po:bridge-domain[v3po:name='";
+    private static final String BD_PATH_AFTER_KEY = "']";
+    private static final int BD_PATH_MIN_LENGTH = BD_PATH_BEFORE_KEY.length() + BD_PATH_AFTER_KEY.length() + 1;
+
+    private VppPathMapper() {}
+
+    public static String interfaceToRestPath(String interfaceName) {
+        return INTERFACE_PATH_BEFORE_KEY + interfaceName + INTERFACE_PATH_AFTER_KEY;
+    }
+
+    public static Optional<InstanceIdentifier<Interface>> interfaceToInstanceIdentifier(@Nullable String restPath) {
+        if (Strings.isNullOrEmpty(restPath)) {
+            return Optional.absent();
+        }
+        if (restPath.length() < INTERFACE_PATH_MIN_LENGTH) {
+            return Optional.absent();
+        }
+        if (!restPath.startsWith(INTERFACE_PATH_BEFORE_KEY)) {
+            return Optional.absent();
+        }
+        if (!restPath.endsWith(INTERFACE_PATH_AFTER_KEY)) {
+            return Optional.absent();
+        }
+        int endIndexInterfaceName = restPath.length() - INTERFACE_PATH_AFTER_KEY.length();
+        String interfaceName = restPath.substring(INTERFACE_PATH_BEFORE_KEY.length(), endIndexInterfaceName);
+        return Optional.of(VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceName)));
+    }
+
+    public static String bridgeDomainToRestPath(String bridgeDomainName) {
+        return BD_PATH_BEFORE_KEY + bridgeDomainName + BD_PATH_AFTER_KEY;
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/RendererPolicyListener.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/RendererPolicyListener.java
new file mode 100644 (file)
index 0000000..e246949
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.listener;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppRenderer;
+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.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.event.RendererPolicyConfEvent;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
+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.eventbus.EventBus;
+
+public class RendererPolicyListener extends DataTreeChangeHandler<RendererPolicy> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RendererPolicyListener.class);
+    private EventBus eventBus;
+
+    public RendererPolicyListener(@Nonnull DataBroker dataProvider, @Nonnull EventBus eventBus) {
+        super(dataProvider);
+        this.eventBus = Preconditions.checkNotNull(eventBus);
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.rendererIid(VppRenderer.NAME).child(RendererPolicy.class)));
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<RendererPolicy> rootNode,
+            InstanceIdentifier<RendererPolicy> rootIdentifier) {
+        RendererPolicyConfEvent event =
+                new RendererPolicyConfEvent(rootIdentifier, rootNode.getDataBefore(), rootNode.getDataAfter());
+        LOG.trace("Dispatching event on write: {}", event);
+        eventBus.post(event);
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<RendererPolicy> rootNode,
+            InstanceIdentifier<RendererPolicy> rootIdentifier) {
+        RendererPolicyConfEvent event =
+                new RendererPolicyConfEvent(rootIdentifier, rootNode.getDataBefore(), rootNode.getDataAfter());
+        LOG.trace("Dispatching event on delete: {}", event);
+        eventBus.post(event);
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<RendererPolicy> rootNode,
+            InstanceIdentifier<RendererPolicy> rootIdentifier) {
+        RendererPolicyConfEvent event =
+                new RendererPolicyConfEvent(rootIdentifier, rootNode.getDataBefore(), rootNode.getDataAfter());
+        LOG.trace("Dispatching event on subtree modified: {}", event);
+        eventBus.post(event);
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppEndpointListener.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppEndpointListener.java
new file mode 100644 (file)
index 0000000..5c31684
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.listener;
+
+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.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+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.VppEndpoint;
+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.eventbus.EventBus;
+
+public class VppEndpointListener extends DataTreeChangeHandler<VppEndpoint> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VppEndpointListener.class);
+    private EventBus eventBus;
+
+    public VppEndpointListener(DataBroker dataProvider, EventBus eventBus) {
+        super(dataProvider);
+        this.eventBus = Preconditions.checkNotNull(eventBus);
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                InstanceIdentifier.builder(Config.class).child(VppEndpoint.class).build()));
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<VppEndpoint> rootNode,
+            InstanceIdentifier<VppEndpoint> rootIdentifier) {
+        VppEndpointConfEvent event =
+                new VppEndpointConfEvent(rootIdentifier, rootNode.getDataBefore(), rootNode.getDataAfter());
+        LOG.trace("Dispatching event on write: {}", event);
+        eventBus.post(event);
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<VppEndpoint> rootNode,
+            InstanceIdentifier<VppEndpoint> rootIdentifier) {
+        VppEndpointConfEvent event =
+                new VppEndpointConfEvent(rootIdentifier, rootNode.getDataBefore(), rootNode.getDataAfter());
+        LOG.trace("Dispatching event on delete: {}", event);
+        eventBus.post(event);
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<VppEndpoint> rootNode,
+            InstanceIdentifier<VppEndpoint> rootIdentifier) {
+        VppEndpointConfEvent event =
+                new VppEndpointConfEvent(rootIdentifier, rootNode.getDataBefore(), rootNode.getDataAfter());
+        LOG.trace("Dispatching event on subtree modified: {}", event);
+        eventBus.post(event);
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppNodeListener.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppNodeListener.java
new file mode 100644 (file)
index 0000000..086b519
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.listener;
+
+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.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.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.concepts.ListenerRegistration;
+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.eventbus.EventBus;
+
+public class VppNodeListener implements DataTreeChangeListener<Node>, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VppNodeListener.class);
+
+    private final ListenerRegistration<VppNodeListener> listenerRegistration;
+    private final VppNodeManager nodeManager;
+    private final EventBus eventBus;
+
+    public VppNodeListener(DataBroker dataBroker, VppNodeManager nodeManager, EventBus eventBus) {
+        this.nodeManager = Preconditions.checkNotNull(nodeManager);
+        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());
+        listenerRegistration =
+                Preconditions.checkNotNull(dataBroker.registerDataTreeChangeListener(networkTopologyPath, this));
+        LOG.info("Network-Topology VppNodelistener registered");
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> changes) {
+        LOG.debug("Topology Node changed. Changes {}", changes);
+
+        for (DataTreeModification<Node> modification : changes) {
+            DataObjectModification<Node> rootNode = modification.getRootNode();
+            Node dataAfter = rootNode.getDataAfter();
+            Node dataBefore = rootNode.getDataBefore();
+            NodeOperEvent event =
+                    new NodeOperEvent(modification.getRootPath().getRootIdentifier(), dataBefore, dataAfter);
+            eventBus.post(event);
+            nodeManager.syncNodes(dataAfter, dataBefore);
+        }
+    }
+
+    public ListenerRegistration<VppNodeListener> getRegistrationObject() {
+        return listenerRegistration;
+    }
+
+    @Override
+    public void close() throws Exception {
+        listenerRegistration.close();
+    }
+}
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
new file mode 100644 (file)
index 0000000..c695be8
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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/manager/VppNodeManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/VppNodeManager.java
new file mode 100644 (file)
index 0000000..d2db589
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * 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 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 java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppNodeWriter;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeKey;
+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.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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public class VppNodeManager {
+
+    private static final TopologyId TOPOLOGY_ID = new TopologyId("topology-netconf");
+    private static final Logger LOG = LoggerFactory.getLogger(VppNodeManager.class);
+    private static final Map<InstanceIdentifier<Node>, DataBroker> netconfNodeCache = new HashMap<>();
+    private static final String V3PO_CAPABILITY = "(urn:opendaylight:params:xml:ns:yang:v3po?revision=2015-01-05)v3po";
+    private static final String INTERFACES_CAPABILITY =
+            "(urn:ietf:params:xml:ns:yang:ietf-interfaces?revision=2014-05-08)ietf-interfaces";
+    private final DataBroker dataBroker;
+    private final MountPointService mountService;
+    private final List<String> requiredCapabilities;
+
+    public VppNodeManager(DataBroker dataBroker, BindingAwareBroker.ProviderContext session) {
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
+        mountService = Preconditions.checkNotNull(session.getSALService(MountPointService.class));
+        requiredCapabilities = initializeRequiredCapabilities();
+    }
+
+    static DataBroker getDataBrokerFromCache(InstanceIdentifier<Node> iid) {
+        return netconfNodeCache.get(iid); // TODO read from DS
+    }
+
+    /**
+     * Synchronizes nodes to DataStore based on their modification state which results in
+     * create/update/remove of Node.
+     */
+    public void syncNodes(Node dataAfter, Node dataBefore) {
+        // New node
+        if (dataBefore == null && dataAfter != null) {
+            createNode(dataAfter);
+        }
+        // Connected/disconnected node
+        if (dataBefore != null && dataAfter != null) {
+            updateNode(dataAfter);
+        }
+        // Removed node
+        if (dataBefore != null && dataAfter == null) {
+            removeNode(dataBefore);
+        }
+    }
+
+    private void createNode(Node node) {
+        LOG.info("Registering new node {}", node.getNodeId().getValue());
+        NetconfNode netconfNode = getNodeAugmentation(node);
+        if (netconfNode == null) {
+            return;
+        }
+        NetconfNodeConnectionStatus.ConnectionStatus connectionStatus = netconfNode.getConnectionStatus();
+        switch (connectionStatus) {
+            case Connecting:
+                LOG.info("Connecting device {} ...", node.getNodeId().getValue());
+                break;
+            case Connected:
+                resolveConnectedNode(node, netconfNode);
+                LOG.info("Node {} is capable and ready", node.getNodeId().getValue());
+                break;
+            default:
+                break;
+        }
+    }
+
+    private void updateNode(Node node) {
+        NetconfNode netconfNode = getNodeAugmentation(node);
+        if (netconfNode == null || netconfNode.getConnectionStatus() == null) {
+            return;
+        }
+        NetconfNodeConnectionStatus.ConnectionStatus afterNodeStatus = netconfNode.getConnectionStatus();
+        if (afterNodeStatus.equals(Connected)) {
+            resolveConnectedNode(node, netconfNode);
+            LOG.info("Node {} is capable and ready", node.getNodeId().getValue());
+        }
+        if (afterNodeStatus.equals(Connecting)) {
+            resolveDisconnectedNode(node);
+            LOG.info("Node {} has been disconnected, removing from available nodes", node.getNodeId().getValue());
+        }
+    }
+
+    private void removeNode(Node node) {
+        resolveDisconnectedNode(node);
+        LOG.info("Node {} has been removed", node.getNodeId().getValue());
+    }
+
+    private void resolveConnectedNode(Node node, NetconfNode netconfNode) {
+        InstanceIdentifier<Node> mountPointIid = getMountpointIid(node);
+        // Mountpoint iid == path in renderer-node
+        RendererNode rendererNode = remapNode(mountPointIid);
+        VppNodeWriter vppNodeWriter = new VppNodeWriter();
+        vppNodeWriter.cache(rendererNode);
+        if (!isCapableNetconfDevice(node, netconfNode)) {
+            return;
+        }
+        vppNodeWriter.commitToDatastore(dataBroker);
+        DataBroker mountpoint = getNodeMountPoint(mountPointIid);
+        netconfNodeCache.put(mountPointIid, mountpoint);
+    }
+
+    private void resolveDisconnectedNode(Node node) {
+        InstanceIdentifier<Node> mountPointIid = getMountpointIid(node);
+        RendererNode rendererNode = remapNode(mountPointIid);
+        VppNodeWriter vppNodeWriter = new VppNodeWriter();
+        vppNodeWriter.cache(rendererNode);
+        vppNodeWriter.removeFromDatastore(dataBroker);
+        netconfNodeCache.remove(mountPointIid);
+    }
+
+    private RendererNode remapNode(InstanceIdentifier<Node> path) {
+        RendererNodeBuilder rendererNodeBuilder = new RendererNodeBuilder();
+        rendererNodeBuilder.setKey(new RendererNodeKey(path)).setNodePath(path);
+        return rendererNodeBuilder.build();
+    }
+
+    private InstanceIdentifier<Node> getMountpointIid(Node node) {
+        return InstanceIdentifier.builder(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(TOPOLOGY_ID))
+            .child(Node.class, new NodeKey(node.getNodeId()))
+            .build();
+    }
+
+    private boolean isCapableNetconfDevice(Node node, NetconfNode netconfAugmentation) {
+        if (netconfAugmentation.getAvailableCapabilities() == null
+                || netconfAugmentation.getAvailableCapabilities().getAvailableCapability() == null
+                || netconfAugmentation.getAvailableCapabilities().getAvailableCapability().isEmpty()) {
+            LOG.warn("Node {} does not contain any capabilities", node.getNodeId().getValue());
+            return false;
+        }
+        if (!capabilityCheck(netconfAugmentation.getAvailableCapabilities().getAvailableCapability())) {
+            LOG.warn("Node {} does not contain all capabilities required by vpp-renderer", node.getNodeId().getValue());
+            return false;
+        }
+        return true;
+    }
+
+    private boolean capabilityCheck(final List<String> capabilities) {
+        for (String requiredCapability : requiredCapabilities) {
+            if (!capabilities.contains(requiredCapability)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private DataBroker getNodeMountPoint(InstanceIdentifier<Node> mountPointIid) {
+        Optional<MountPoint> optionalObject = mountService.getMountPoint(mountPointIid);
+        MountPoint mountPoint;
+        if (optionalObject.isPresent()) {
+            mountPoint = optionalObject.get();
+            if (mountPoint != null) {
+                Optional<DataBroker> optionalDataBroker = mountPoint.getService(DataBroker.class);
+                if (optionalDataBroker.isPresent()) {
+                    return optionalDataBroker.get();
+                } else {
+                    LOG.debug("Cannot obtain data broker from mountpoint {}", mountPoint);
+                }
+            } else {
+                LOG.debug("Cannot obtain mountpoint with IID {}", mountPointIid);
+            }
+        }
+        return null;
+    }
+
+    private NetconfNode getNodeAugmentation(Node node) {
+        NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
+        if (netconfNode == null) {
+            LOG.warn("Node {} is not a netconf device", node.getNodeId().getValue());
+            return null;
+        }
+        return netconfNode;
+    }
+
+    /**
+     * Initialize all common capabilities required by VPP renderer. Any connected node is examined
+     * whether it's
+     * an appropriate device to handle configuration created by this renderer. A device must support
+     * all capabilities
+     * in list below.
+     *
+     * @return list of string representations of required capabilities
+     */
+    private List<String> initializeRequiredCapabilities() {
+        // Required device capabilities
+
+        String[] capabilityEntries = {V3PO_CAPABILITY, INTERFACES_CAPABILITY};
+        return Arrays.asList(capabilityEntries);
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java
new file mode 100644 (file)
index 0000000..6c5ba8f
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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.Set;
+import java.util.concurrent.ExecutionException;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
+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.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.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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 {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ForwardingManager.class);
+
+    private final InterfaceManager ifaceManager;
+    private final BridgeDomainManager bdManager;
+
+    public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull BridgeDomainManager bdManager) {
+        this.ifaceManager = Preconditions.checkNotNull(ifaceManager);
+        this.bdManager = Preconditions.checkNotNull(bdManager);
+    }
+
+    public void createVxlanBridgeDomainsOnNodes(SetMultimap<String, NodeId> vppNodesByBridgeDomain) {
+        for (String bd : vppNodesByBridgeDomain.keySet()) {
+            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);
+                }
+            }
+        }
+    }
+
+    public void removeVxlanBridgeDomainsOnNodes(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();
+                } catch (InterruptedException | ExecutionException e) {
+                    LOG.warn("Bridge domain {} was not removed from node {}", bd, vppNode.getValue(), e);
+                }
+            }
+        }
+    }
+
+    public void createForwardingForEndpoint(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
+        AddressEndpointWithLocation rEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
+        ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp);
+        if (Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
+            // TODO add it to the status for renderer manager
+            LOG.info("Rednerer endpoint does not have external-node-connector therefore it is ignored {}", rEp);
+            return;
+        }
+
+        if (Strings.isNullOrEmpty(rEpLoc.getExternalNode())) {
+            Optional<String> optL2FloodDomain = resolveL2FloodDomain(rEp.getNetworkContainment());
+            if (!optL2FloodDomain.isPresent()) {
+                // TODO add it to the status for renderer manager
+                LOG.info("Rednerer endpoint does not have l2FloodDomain as network containment {}", rEp);
+                return;
+            }
+            String l2FloodDomain = optL2FloodDomain.get();
+            try {
+                ifaceManager.addBridgeDomainToInterface(l2FloodDomain, rEp).get();
+                LOG.debug("Interface added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp);
+            } catch (InterruptedException | ExecutionException e) {
+                // TODO add it to the status for renderer manager
+                LOG.warn("Interface was not added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp, e);
+            }
+        }
+    }
+
+    public void removeForwardingForEndpoint(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
+        AddressEndpointWithLocation rEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
+        ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp);
+        if (Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
+            // nothing was created for endpoint therefore nothing is removed
+            return;
+        }
+
+        if (!Strings.isNullOrEmpty(rEpLoc.getExternalNode())) {
+            try {
+                ifaceManager.deleteBridgeDomainFromInterface(rEp).get();
+                LOG.debug("bridge-domain was deleted from interface for endpoint {}", rEp);
+            } catch (InterruptedException | ExecutionException e) {
+                // TODO add it to the status for renderer manager
+                LOG.warn("bridge-domain was not deleted from interface for endpoint {}", rEp, e);
+            }
+        }
+    }
+
+    public static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
+        LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
+        if (!(locationType instanceof ExternalLocationCase)) {
+            throw new IllegalStateException("Endpoint does not have external location " + addrEpWithLoc);
+        }
+        ExternalLocationCase result = (ExternalLocationCase) locationType;
+        if (result.getExternalNodeMountPoint() == null) {
+            throw new IllegalStateException("Endpoint does not have external-node-mount-point " + addrEpWithLoc);
+        }
+        return result;
+    }
+
+    public static Optional<String> resolveL2FloodDomain(@Nullable NetworkContainment netCont) {
+        if (netCont == null) {
+            return Optional.absent();
+        }
+        Containment containment = netCont.getContainment();
+        if (containment instanceof ForwardingContextContainment) {
+            ForwardingContextContainment fwCtxCont = (ForwardingContextContainment) containment;
+            if (fwCtxCont.getContextType().isAssignableFrom(L2FloodDomain.class)) {
+                return fwCtxCont.getContextId() == null ? null : Optional.of(fwCtxCont.getContextId().getValue());
+            }
+        }
+        if (containment instanceof NetworkDomainContainment) {
+            // TODO address missing impl
+            LOG.info("Network domain containment in endpoint is not supported yet. {}", netCont);
+            return Optional.absent();
+        }
+        return Optional.absent();
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/PolicyContext.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/PolicyContext.java
new file mode 100644 (file)
index 0000000..4a69b08
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.TreeSet;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
+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.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.RendererEndpointKey;
+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.RuleGroupKey;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.ImmutableTable.Builder;
+import com.google.common.collect.Maps;
+
+public class PolicyContext {
+
+    private final RendererPolicy policy;
+    private final ImmutableTable<RendererEndpointKey, PeerEndpointKey, ImmutableSortedSet<RendererResolvedPolicy>> policyTable;
+    private final ImmutableMap<RuleGroupKey, ResolvedRuleGroup> ruleGroupByKey;
+    private final ImmutableMap<AddressEndpointKey, AddressEndpointWithLocation> addrEpByKey;
+
+    public PolicyContext(@Nonnull RendererPolicy policy) {
+        this.policy = Preconditions.checkNotNull(policy);
+        Optional<Configuration> optConfig = resolveValidConfig(policy);
+        if (optConfig.isPresent()) {
+            Configuration config = optConfig.get();
+            this.ruleGroupByKey = resolveRuleGroups(config);
+            List<RendererEndpoint> rendererEps = resolveRendererEndpoints(config);
+            this.policyTable = resolvePolicy(rendererEps, ruleGroupByKey);
+            addrEpByKey = resolveAddrEpWithLoc(config);
+        } else {
+            this.ruleGroupByKey = ImmutableMap.of();
+            this.policyTable = ImmutableTable.of();
+            this.addrEpByKey = ImmutableMap.of();
+        }
+    }
+
+    private static List<RendererEndpoint> resolveRendererEndpoints(Configuration config) {
+        if (config.getRendererEndpoints() == null) {
+            return Collections.emptyList();
+        }
+        List<RendererEndpoint> rendererEndpoints = config.getRendererEndpoints().getRendererEndpoint();
+        if (rendererEndpoints == null) {
+            return Collections.emptyList();
+        }
+        return rendererEndpoints;
+    }
+
+    private static ImmutableTable<RendererEndpointKey, PeerEndpointKey, ImmutableSortedSet<RendererResolvedPolicy>> resolvePolicy(
+            List<RendererEndpoint> rendererEps, Map<RuleGroupKey, ResolvedRuleGroup> ruleGroupInfoByRuleGroupKey) {
+        Builder<RendererEndpointKey, PeerEndpointKey, ImmutableSortedSet<RendererResolvedPolicy>> resultBuilder =
+                new Builder<>();
+        Supplier<TreeSet<RendererResolvedPolicy>> rendererPolicySupplier = () -> new TreeSet<>();
+        rendererEps.stream().forEach(rEp -> {
+            rEp.getPeerEndpointWithPolicy().stream().filter(Objects::nonNull).forEach(peer -> {
+                ImmutableSortedSet<RendererResolvedPolicy> rPolicy =
+                        peer.getRuleGroupWithRendererEndpointParticipation()
+                            .stream()
+                            .map(ruleGroup -> new RendererResolvedPolicy(ruleGroup.getRendererEndpointParticipation(),
+                                    ruleGroupInfoByRuleGroupKey.get(KeyFactory.ruleGroupKey(ruleGroup.getKey()))))
+                            .collect(Collectors.collectingAndThen(Collectors.toCollection(rendererPolicySupplier),
+                                    ImmutableSortedSet::copyOfSorted));
+                resultBuilder.put(rEp.getKey(), KeyFactory.peerEndpointKey(peer.getKey()),
+                        ImmutableSortedSet.copyOfSorted(rPolicy));
+            });
+        });
+        return resultBuilder.build();
+    }
+
+    private static ImmutableMap<RuleGroupKey, ResolvedRuleGroup> resolveRuleGroups(Configuration config) {
+        return config.getRuleGroups().getRuleGroup().stream().collect(Collectors
+            .collectingAndThen(Collectors.toMap(RuleGroup::getKey, ResolvedRuleGroup::new), ImmutableMap::copyOf));
+    }
+
+    private static ImmutableMap<AddressEndpointKey, AddressEndpointWithLocation> resolveAddrEpWithLoc(
+            Configuration config) {
+        return Maps.uniqueIndex(config.getEndpoints().getAddressEndpointWithLocation(),
+                new com.google.common.base.Function<AddressEndpointWithLocation, AddressEndpointKey>() {
+
+                    @Override
+                    public AddressEndpointKey apply(AddressEndpointWithLocation input) {
+                        return new AddressEndpointKey(input.getAddress(), input.getAddressType(), input.getContextId(),
+                                input.getContextType());
+                    }
+                });
+    }
+
+    private static Optional<Configuration> resolveValidConfig(RendererPolicy policy) {
+        Configuration config = policy.getConfiguration();
+        if (config == null) {
+            return Optional.empty();
+        }
+        if (config.getRendererEndpoints() == null) {
+            return Optional.empty();
+        }
+        return Optional.of(config);
+    }
+
+    public @Nonnull RendererPolicy getPolicy() {
+        return policy;
+    }
+
+    public @Nonnull ImmutableTable<RendererEndpointKey, PeerEndpointKey, ImmutableSortedSet<RendererResolvedPolicy>> getPolicyTable() {
+        return policyTable;
+    }
+
+    public @Nonnull ImmutableMap<RuleGroupKey, ResolvedRuleGroup> getRuleGroupByKey() {
+        return ruleGroupByKey;
+    }
+
+    public @Nonnull ImmutableMap<AddressEndpointKey, AddressEndpointWithLocation> getAddrEpByKey() {
+        return addrEpByKey;
+    }
+
+    @Override
+    public String toString() {
+        return "PolicyContext [policy=" + policy + ", policyTable=" + policyTable + ", ruleGroupByKey=" + ruleGroupByKey
+                + ", addrEpByKey=" + addrEpByKey + "]";
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/RendererResolvedPolicy.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/RendererResolvedPolicy.java
new file mode 100644 (file)
index 0000000..b5f18d6
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 javax.annotation.Nonnull;
+import javax.annotation.concurrent.Immutable;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
+
+import com.google.common.base.Preconditions;
+
+@Immutable
+public class RendererResolvedPolicy implements Comparable<RendererResolvedPolicy> {
+
+    private final EndpointPolicyParticipation rendererEndpointParticipation;
+    private final ResolvedRuleGroup ruleGroup;
+
+    public RendererResolvedPolicy(@Nonnull EndpointPolicyParticipation rendererEndpointParticipation,
+            @Nonnull ResolvedRuleGroup ruleGroupInfo) {
+        this.rendererEndpointParticipation = Preconditions.checkNotNull(rendererEndpointParticipation);
+        this.ruleGroup = Preconditions.checkNotNull(ruleGroupInfo);
+    }
+
+    public EndpointPolicyParticipation getRendererEndpointParticipation() {
+        return rendererEndpointParticipation;
+    }
+
+    public ResolvedRuleGroup getRuleGroup() {
+        return ruleGroup;
+    }
+
+    @Override
+    public int compareTo(RendererResolvedPolicy arg0) {
+        return ruleGroup.compareTo(arg0.getRuleGroup());
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result
+                + ((rendererEndpointParticipation == null) ? 0 : rendererEndpointParticipation.hashCode());
+        result = prime * result + ((ruleGroup == null) ? 0 : ruleGroup.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        RendererResolvedPolicy other = (RendererResolvedPolicy) obj;
+        if (rendererEndpointParticipation != other.rendererEndpointParticipation)
+            return false;
+        if (ruleGroup == null) {
+            if (other.ruleGroup != null)
+                return false;
+        } else if (!ruleGroup.equals(other.ruleGroup))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "RendererResolvedPolicy [rendererEndpointParticipation=" + rendererEndpointParticipation + ", ruleGroup="
+                + ruleGroup + "]";
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ResolvedRuleGroup.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ResolvedRuleGroup.java
new file mode 100644 (file)
index 0000000..8219d9c
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * 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.Comparator;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.Immutable;
+
+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.tenants.tenant.policy.contract.subject.Rule;
+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.resolved.rules.ResolvedRule;
+
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Ordering;
+
+/**
+ * Represent a group of rules applied to a given pair of endpoints.
+ * Includes references back to the normalized policy that resulted in the rule
+ * group.
+ */
+@Immutable
+public class ResolvedRuleGroup implements Comparable<ResolvedRuleGroup> {
+
+    private static final ResolvedRuleComparator RULE_COMPARATOR = new ResolvedRuleComparator();
+    private ImmutableSortedSet<ResolvedRule> rules;
+    private final Integer order;
+    private final TenantId contractTenantId;
+    private final ContractId contractId;
+    private final SubjectName relatedSubject;
+
+    public static class ResolvedRuleComparator implements Comparator<ResolvedRule> {
+
+        @Override
+        public int compare(ResolvedRule o1, ResolvedRule o2) {
+            return ComparisonChain.start()
+                .compare(o1.getOrder(), o2.getOrder(), Ordering.natural().nullsLast())
+                .compare(o1.getName().getValue(), o2.getName().getValue(), Ordering.natural().nullsLast())
+                .result();
+        }
+
+    }
+
+    public ResolvedRuleGroup(@Nonnull RuleGroup ruleGroup) {
+        this.rules = ImmutableSortedSet.copyOf(RULE_COMPARATOR, ruleGroup.getResolvedRule());
+        this.order = ruleGroup.getOrder();
+        this.contractTenantId = ruleGroup.getTenantId();
+        this.contractId = ruleGroup.getContractId();
+        this.relatedSubject = ruleGroup.getSubjectName();
+    }
+
+    public ResolvedRuleGroup(List<ResolvedRule> rules, Integer order, TenantId contractTenantId, ContractId contractId,
+            SubjectName subject) {
+        this.rules = ImmutableSortedSet.copyOf(RULE_COMPARATOR, rules);
+        this.order = order;
+        this.contractTenantId = contractTenantId;
+        this.contractId = contractId;
+        this.relatedSubject = subject;
+    }
+
+    /**
+     * @return sorted {@link Rule} list
+     */
+    public ImmutableSortedSet<ResolvedRule> getRules() {
+        return rules;
+    }
+
+    public Integer getOrder() {
+        return order;
+    }
+
+    public TenantId getContractTenantId() {
+        return contractTenantId;
+    }
+
+    public ContractId getContractId() {
+        return contractId;
+    }
+
+    public SubjectName getRelatedSubject() {
+        return relatedSubject;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((order == null) ? 0 : order.hashCode());
+        result = prime * result + ((rules == null) ? 0 : rules.hashCode());
+        result = prime * result + ((relatedSubject == null) ? 0 : relatedSubject.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ResolvedRuleGroup other = (ResolvedRuleGroup) obj;
+        if (order == null) {
+            if (other.order != null)
+                return false;
+        } else if (!order.equals(other.order))
+            return false;
+        if (rules == null) {
+            if (other.rules != null)
+                return false;
+        } else if (!rules.equals(other.rules))
+            return false;
+        if (relatedSubject == null) {
+            if (other.relatedSubject != null)
+                return false;
+        } else if (!relatedSubject.equals(other.relatedSubject))
+            return false;
+        return true;
+    }
+
+    @Override
+    public int compareTo(ResolvedRuleGroup o) {
+        return ComparisonChain.start()
+            .compare(order, o.order, Ordering.natural().nullsLast())
+            .compare(relatedSubject.getValue(), o.relatedSubject.getValue(), Ordering.natural().nullsLast())
+            .result();
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java
new file mode 100644 (file)
index 0000000..3d21b62
--- /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.vpp.policy;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppRenderer;
+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.vpp.event.NodeOperEvent;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.event.RendererPolicyConfEvent;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
+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.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;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.MapDifference;
+import com.google.common.collect.MapDifference.ValueDifference;
+import com.google.common.collect.Maps;
+import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Sets.SetView;
+import com.google.common.eventbus.Subscribe;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class VppRendererPolicyManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VppRendererPolicyManager.class);
+    private final DataBroker dataProvider;
+    private ForwardingManager fwManager;
+
+    public VppRendererPolicyManager(@Nonnull ForwardingManager fwManager, @Nonnull DataBroker dataProvider) {
+        this.fwManager = Preconditions.checkNotNull(fwManager);
+        this.dataProvider = Preconditions.checkNotNull(dataProvider);
+    }
+
+    @Subscribe
+    public void rendererPolicyChanged(RendererPolicyConfEvent event) {
+        RendererPolicyBuilder responseBuilder = new RendererPolicyBuilder();
+        switch (event.getDtoModificationType()) {
+            case CREATED:
+                LOG.trace("CREATED : {}", event);
+                responseBuilder.setVersion(event.getAfter().get().getVersion());
+                rendererPolicyCreated(event.getAfter().get());
+                break;
+            case UPDATED:
+                LOG.trace("UPDATED: {}", event);
+                RendererPolicy rPolicyBefore = event.getBefore().get();
+                RendererPolicy rPolicyAfter = event.getAfter().get();
+                responseBuilder.setVersion(rPolicyAfter.getVersion());
+                if (!isConfigurationChanged(rPolicyBefore, rPolicyAfter)) {
+                    LOG.debug("Configuration is not changed only updating config version from {} to {}",
+                            rPolicyBefore.getVersion(), rPolicyAfter.getVersion());
+                } else {
+                    // TODO collect unconfigured rules and put them to responseBuilder
+                    rendererPolicyUpdated(rPolicyBefore, rPolicyAfter);
+                }
+                break;
+            case DELETED:
+                LOG.trace("DELETED: {}", event);
+                responseBuilder.setVersion(event.getBefore().get().getVersion());
+                rendererPolicyDeleted(event.getBefore().get());
+                break;
+        }
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        RendererPolicy response = responseBuilder.build();
+        wTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.rendererIid(VppRenderer.NAME).child(RendererPolicy.class),
+                response, true);
+        Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("Renderer updated renderer policy {}", response);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.warn("Renderer DIDN'T update renderer-policy {}", response);
+            }
+        });
+    }
+
+    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);
+
+        MapDifference<String, Collection<NodeId>> vppNodesByL2FlDiff =
+                createDiffForVppNodesByL2Fd(policyCtxBefore, policyCtxAfter);
+        SetMultimap<String, NodeId> removedVppNodesByL2Fd = HashMultimap.create();
+        SetMultimap<String, NodeId> createdVppNodesByL2Fd = HashMultimap.create();
+        for (Entry<String, ValueDifference<Collection<NodeId>>> entry : vppNodesByL2FlDiff.entriesDiffering()
+            .entrySet()) {
+            String bridgeDomain = entry.getKey();
+            Collection<NodeId> beforeNodes = entry.getValue().leftValue();
+            Collection<NodeId> afterNodes = entry.getValue().rightValue();
+            if (beforeNodes != null && afterNodes != null) {
+                SetView<NodeId> removedNodes = Sets.difference(new HashSet<>(beforeNodes), new HashSet<>(afterNodes));
+                removedVppNodesByL2Fd.putAll(bridgeDomain, removedNodes);
+                SetView<NodeId> createdNodes = Sets.difference(new HashSet<>(afterNodes), new HashSet<>(beforeNodes));
+                createdVppNodesByL2Fd.putAll(bridgeDomain, createdNodes);
+            } else if (beforeNodes != null) {
+                removedVppNodesByL2Fd.putAll(bridgeDomain, beforeNodes);
+            } else if (afterNodes != null) {
+                createdVppNodesByL2Fd.putAll(bridgeDomain, afterNodes);
+            }
+        }
+        Map<String, Collection<NodeId>> removedL2Fds = vppNodesByL2FlDiff.entriesOnlyOnLeft();
+        for (Entry<String, Collection<NodeId>> entry : removedL2Fds.entrySet()) {
+            String bridgeDomain = entry.getKey();
+            Collection<NodeId> removedNodes = entry.getValue();
+            if (removedNodes != null) {
+                removedVppNodesByL2Fd.putAll(bridgeDomain, removedNodes);
+            }
+        }
+        Map<String, Collection<NodeId>> createdL2Fds = vppNodesByL2FlDiff.entriesOnlyOnRight();
+        for (Entry<String, Collection<NodeId>> entry : createdL2Fds.entrySet()) {
+            String bridgeDomain = entry.getKey();
+            Collection<NodeId> createdNodes = entry.getValue();
+            if (createdNodes != null) {
+                createdVppNodesByL2Fd.putAll(bridgeDomain, createdNodes);
+            }
+        }
+
+        ImmutableSet<RendererEndpointKey> rendEpsBefore = policyCtxBefore.getPolicyTable().rowKeySet();
+        ImmutableSet<RendererEndpointKey> rendEpsAfter = policyCtxAfter.getPolicyTable().rowKeySet();
+
+        SetView<RendererEndpointKey> removedRendEps = Sets.difference(rendEpsBefore, rendEpsAfter);
+        removedRendEps.forEach(rEpKey -> fwManager.removeForwardingForEndpoint(rEpKey, policyCtxBefore));
+
+        fwManager.removeVxlanBridgeDomainsOnNodes(removedVppNodesByL2Fd);
+        fwManager.createVxlanBridgeDomainsOnNodes(createdVppNodesByL2Fd);
+
+        SetView<RendererEndpointKey> createdRendEps = Sets.difference(rendEpsAfter, rendEpsBefore);
+        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));
+    }
+
+    private static MapDifference<String, Collection<NodeId>> createDiffForVppNodesByL2Fd(PolicyContext policyCtxBefore,
+            PolicyContext policyCtxAfter) {
+        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);
+        return Maps.difference(vppNodesByL2FdBefore.asMap(), vppNodesByL2FdAfter.asMap());
+    }
+
+    private void rendererPolicyCreated(RendererPolicy rPolicy) {
+        PolicyContext policyCtx = new PolicyContext(rPolicy);
+        ImmutableSet<RendererEndpointKey> rEpKeys = policyCtx.getPolicyTable().rowKeySet();
+
+        SetMultimap<String, NodeId> vppNodesByL2Fd = resolveVppNodesByL2Fd(rEpKeys, policyCtx);
+        fwManager.createVxlanBridgeDomainsOnNodes(vppNodesByL2Fd);
+
+        rEpKeys.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtx));
+    }
+
+    private void rendererPolicyDeleted(RendererPolicy rendererPolicy) {
+        PolicyContext policyCtx = new PolicyContext(rendererPolicy);
+        ImmutableSet<RendererEndpointKey> rEpKeys = policyCtx.getPolicyTable().rowKeySet();
+
+        rEpKeys.forEach(rEpKey -> fwManager.removeForwardingForEndpoint(rEpKey, policyCtx));
+
+        SetMultimap<String, NodeId> vppNodesByL2Fd = resolveVppNodesByL2Fd(rEpKeys, policyCtx);
+        fwManager.removeVxlanBridgeDomainsOnNodes(vppNodesByL2Fd);
+    }
+
+    private static SetMultimap<String, NodeId> resolveVppNodesByL2Fd(Set<RendererEndpointKey> rEpKeys,
+            PolicyContext policyCtx) {
+        SetMultimap<String, NodeId> vppNodesByL2Fd = HashMultimap.create();
+        rEpKeys.stream()
+            .map(rEpKey -> KeyFactory.addressEndpointKey(rEpKey))
+            .map(addrEpKey -> policyCtx.getAddrEpByKey().get(addrEpKey))
+            .collect(Collectors.toSet())
+            .forEach(addrEpWithLoc -> {
+                Optional<String> optL2Fd =
+                        ForwardingManager.resolveL2FloodDomain(addrEpWithLoc.getNetworkContainment());
+                if (optL2Fd.isPresent()) {
+                    ExternalLocationCase rEpLoc = ForwardingManager.resolveAndValidateLocation(addrEpWithLoc);
+                    InstanceIdentifier<?> externalNodeMountPoint = rEpLoc.getExternalNodeMountPoint();
+                    NodeId vppNode = externalNodeMountPoint.firstKeyOf(Node.class).getNodeId();
+                    vppNodesByL2Fd.put(optL2Fd.get(), vppNode);
+                }
+            });
+        return vppNodesByL2Fd;
+    }
+
+    @Subscribe
+    public void vppNodeChanged(NodeOperEvent event) {
+        switch (event.getDtoModificationType()) {
+            case CREATED:
+                if (event.isAfterConnected()) {
+                    // TODO
+                }
+                break;
+            case UPDATED:
+                if (!event.isBeforeConnected() && event.isAfterConnected()) {
+                    // TODO
+                }
+                break;
+            case DELETED:
+                if (event.isBeforeConnected()) {
+                    // TODO
+                }
+                break;
+        }
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/Action.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/Action.java
new file mode 100755 (executable)
index 0000000..e5b4cd3
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 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.sf;
+
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.Validator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.action.definition.SupportedParameterValues;
+
+/**
+ * Represent an action definition, and provide tools for generating
+ * flow instructions based on the action.
+ */
+public abstract class Action implements Validator<ActionInstance> {
+
+    /**
+     * Get the action definition for this action.
+     *
+     * @return the {@link ActionDefinition} for this action
+     */
+    public abstract ActionDefinitionId getId();
+
+    /**
+     * Get the action definition for this action.
+     *
+     * @return the {@link ActionDefinition} for this action
+     */
+    public abstract ActionDefinition getActionDef();
+
+    /**
+     * The result represents supported parameters for the action by renderer.
+     *
+     * @return list of supported parameters by the action
+     */
+    public abstract List<SupportedParameterValues> getSupportedParameterValues();
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/AllowAction.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/AllowAction.java
new file mode 100755 (executable)
index 0000000..1ad169a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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.sf;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.ValidationResult;
+import org.opendaylight.groupbasedpolicy.api.sf.AllowActionDefinition;
+import org.opendaylight.groupbasedpolicy.dto.ValidationResultBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.action.definition.SupportedParameterValues;
+
+/**
+ * Allow action.
+ */
+public class AllowAction extends Action {
+
+    @Override
+    public ActionDefinitionId getId() {
+        return AllowActionDefinition.ID;
+    }
+
+    @Override
+    public ActionDefinition getActionDef() {
+        return AllowActionDefinition.DEFINITION;
+    }
+
+    @Override
+    public ValidationResult validate(ActionInstance actionInstance) {
+        return new ValidationResultBuilder().success().build();
+    }
+
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+        // allow action definition has no parameter
+        return Collections.emptyList();
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/Classifier.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/Classifier.java
new file mode 100755 (executable)
index 0000000..f6beb86
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014 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.sf;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+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.capabilities.supported.classifier.definition.SupportedParameterValues;
+
+/**
+ * Represent a classifier definition.
+ */
+public abstract class Classifier {
+
+    protected final Classifier parent;
+
+    public static final EtherTypeClassifier ETHER_TYPE_CL = new EtherTypeClassifier(null);
+    public static final IpProtoClassifier IP_PROTO_CL = new IpProtoClassifier(ETHER_TYPE_CL);
+
+    protected Classifier(Classifier parent) {
+        this.parent = parent;
+    }
+
+    /**
+     * Get the classifier definition id for this classifier.
+     *
+     * @return the {@link ClassifierDefinitionId} for this classifier
+     */
+    public abstract ClassifierDefinitionId getId();
+
+    /**
+     * Get the classifier definition for this classifier.
+     *
+     * @return the {@link ClassifierDefinition} for this classifier
+     */
+    public abstract ClassifierDefinition getClassifierDefinition();
+
+    /**
+     * Get parent for this classifier.
+     *
+     * @return parent classifier, see {@link Classifier}
+     */
+    public final Classifier getParent() {
+        return parent;
+    }
+
+    /**
+     * The result represents supported parameters for the classifier by renderer.
+     *
+     * @return list of supported parameters by the classifier
+     */
+    public abstract List<SupportedParameterValues> getSupportedParameterValues();
+
+    /**
+     * Checks presence of required {@code params} in order to decide if classifier can update
+     * {@code matches} properly.
+     *
+     * @param params inserted parameters, not null
+     * @throws IllegalArgumentException when any of required {@code params} is not present
+     */
+    protected abstract void checkPresenceOfRequiredParams(Map<String, ParameterValue> params);
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/EtherTypeClassifier.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/EtherTypeClassifier.java
new file mode 100755 (executable)
index 0000000..447fb1b
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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.sf;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.groupbasedpolicy.api.sf.EtherTypeClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+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.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Match on the ether type of the traffic.
+ */
+public class EtherTypeClassifier extends Classifier {
+
+    public EtherTypeClassifier(Classifier parent) {
+        super(parent);
+    }
+
+    @Override
+    public ClassifierDefinitionId getId() {
+        return EtherTypeClassifierDefinition.ID;
+    }
+
+    @Override
+    public ClassifierDefinition getClassifierDefinition() {
+        return EtherTypeClassifierDefinition.DEFINITION;
+    }
+
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+
+        List<SupportedIntValue> values = ImmutableList.of(
+                new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.IPv4_VALUE).build(),
+                new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.IPv6_VALUE).build());
+        SupportedParameterValuesBuilder builder = new SupportedParameterValuesBuilder();
+        builder.setParameterName(new ParameterName(EtherTypeClassifierDefinition.ETHERTYPE_PARAM));
+        builder.setParameterType(new IntBuilder().setSupportedIntValue(values).build());
+
+        return ImmutableList.of(builder.build());
+    }
+
+    @Override
+    protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
+        if (params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM) == null) {
+            throw new IllegalArgumentException(
+                    "Parameter " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM + " not specified.");
+        }
+        if (params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM).getIntValue() == null) {
+            throw new IllegalArgumentException(
+                    "Value of " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM + " parameter is not present.");
+        }
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/IpProtoClassifier.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/IpProtoClassifier.java
new file mode 100755 (executable)
index 0000000..019bde0
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014 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.sf;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.groupbasedpolicy.api.sf.IpProtoClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+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.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Match on the IP protocol of IP traffic.
+ */
+public class IpProtoClassifier extends Classifier {
+
+    protected IpProtoClassifier(Classifier parent) {
+        super(parent);
+    }
+
+    @Override
+    public ClassifierDefinitionId getId() {
+        return IpProtoClassifierDefinition.ID;
+    }
+
+    @Override
+    public ClassifierDefinition getClassifierDefinition() {
+        return IpProtoClassifierDefinition.DEFINITION;
+    }
+
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+
+        List<SupportedIntValue> values = ImmutableList.of(
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.ICMP_VALUE).build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.SCTP_VALUE).build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.TCP_VALUE).build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.UDP_VALUE).build());
+        SupportedParameterValuesBuilder builder = new SupportedParameterValuesBuilder();
+        builder.setParameterName(new ParameterName(IpProtoClassifierDefinition.PROTO_PARAM));
+        builder.setParameterType(new IntBuilder().setSupportedIntValue(values).build());
+
+        return ImmutableList.of(builder.build());
+    }
+
+    @Override
+    protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
+        if (params.get(IpProtoClassifierDefinition.PROTO_PARAM) == null) {
+            throw new IllegalArgumentException(
+                    "Parameter " + IpProtoClassifierDefinition.PROTO_PARAM + " not specified.");
+        }
+        if (params.get(IpProtoClassifierDefinition.PROTO_PARAM).getIntValue() == null) {
+            throw new IllegalArgumentException(
+                    "Value of " + IpProtoClassifierDefinition.PROTO_PARAM + " parameter is not present.");
+        }
+    }
+
+    /**
+     * Return the IpProtocol value. May return null.
+     *
+     * @param params the parameters of classifier-instance inserted by user
+     * @return the IpProtocol value
+     */
+    public static Long getIpProtoValue(Map<String, ParameterValue> params) {
+        if (params == null) {
+            return null;
+        }
+        if (params.get(IpProtoClassifierDefinition.PROTO_PARAM) == null) {
+            return null;
+        }
+        Long proto = params.get(IpProtoClassifierDefinition.PROTO_PARAM).getIntValue();
+        if (proto != null) {
+            return proto;
+        }
+        return null;
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/General.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/General.java
new file mode 100644 (file)
index 0000000..41ce174
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems. 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.util;
+
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class General {
+
+    /**
+     * Operations that can be executed over ConfigCommand. Operation names reflect operations used
+     * in WriteTransaction.
+     * For more information on these operations, please see the documentation in:
+     * <br>
+     * {@link WriteTransaction#put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}
+     * <br>
+     * {@link WriteTransaction#merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}
+     * <br>
+     * {@link WriteTransaction#delete(LogicalDatastoreType, InstanceIdentifier)}<br>
+     */
+    public enum Operations {
+        PUT, DELETE, MERGE
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/KeyFactory.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/KeyFactory.java
new file mode 100644 (file)
index 0000000..6484686
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
+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.endpoints.AddressEndpointWithLocationKey;
+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.PeerEndpointWithPolicyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupKey;
+
+public class KeyFactory {
+
+    private KeyFactory() {}
+
+    public static AddressEndpointWithLocationKey addressEndpointWithLocationKey(RendererEndpointKey fromKey) {
+        return new AddressEndpointWithLocationKey(fromKey.getAddress(), fromKey.getAddressType(),
+                fromKey.getContextId(), fromKey.getContextType());
+    }
+
+    public static PeerEndpointKey peerEndpointKey(PeerEndpointWithPolicyKey fromKey) {
+        return new PeerEndpointKey(fromKey.getAddress(), fromKey.getAddressType(), fromKey.getContextId(),
+                fromKey.getContextType());
+    }
+
+    public static RuleGroupKey ruleGroupKey(RuleGroupWithRendererEndpointParticipationKey fromKey) {
+        return new RuleGroupKey(fromKey.getContractId(), fromKey.getSubjectName(), fromKey.getTenantId());
+    }
+
+    public static AddressEndpointKey addressEndpointKey(RendererEndpointKey fromKey) {
+        return new AddressEndpointKey(fromKey.getAddress(), fromKey.getAddressType(), fromKey.getContextId(),
+                fromKey.getContextType());
+    }
+
+    public static ProviderAddressEndpointLocationKey providerAddressEndpointLocationKey(
+            AddressEndpointWithLocationKey fromKey) {
+        return new ProviderAddressEndpointLocationKey(fromKey.getAddress(), fromKey.getAddressType(),
+                fromKey.getContextId(), fromKey.getContextType());
+    }
+
+    public static RendererEndpointKey rendererEndpointKey(AddressEndpointWithLocationKey fromKey) {
+        return new RendererEndpointKey(fromKey.getAddress(), fromKey.getAddressType(), fromKey.getContextId(),
+                fromKey.getContextType());
+    }
+
+    public static PeerEndpointWithPolicyKey peerEndpointWithPolicyKey(AddressEndpointWithLocationKey fromKey) {
+        return new PeerEndpointWithPolicyKey(fromKey.getAddress(), fromKey.getAddressType(), fromKey.getContextId(),
+                fromKey.getContextType());
+    }
+
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/MountedDataBrokerProvider.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/MountedDataBrokerProvider.java
new file mode 100644 (file)
index 0000000..071e14d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.util;
+
+import javax.annotation.Nonnull;
+
+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.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public class MountedDataBrokerProvider {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MountedDataBrokerProvider.class);
+    private final MountPointService mountService;
+
+    public MountedDataBrokerProvider(@Nonnull MountPointService mountService) {
+        this.mountService = Preconditions.checkNotNull(mountService);
+    }
+
+    public Optional<DataBroker> getDataBrokerForMountPoint(@Nonnull InstanceIdentifier<?> iidToMountPoint) {
+        Optional<MountPoint> potentialMountPoint = mountService.getMountPoint(iidToMountPoint);
+        if (!potentialMountPoint.isPresent()) {
+            LOG.debug("Mount point does not exist for {}", iidToMountPoint);
+            return Optional.absent();
+        }
+        return potentialMountPoint.get().getService(DataBroker.class);
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java
new file mode 100644 (file)
index 0000000..50426de
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 Cisco Systems. 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.util;
+
+import org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppRenderer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+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.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.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeKey;
+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.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;
+
+public class VppIidFactory {
+
+    public static InstanceIdentifier<Interface> getInterfaceIID(InterfaceKey interfaceKey) {
+        return InstanceIdentifier.create(Interfaces.class).child(Interface.class, interfaceKey);
+    }
+
+    public static InstanceIdentifier<Renderer> getRendererIID(RendererKey rendererKey) {
+        return InstanceIdentifier.create(Renderers.class).child(Renderer.class, rendererKey);
+    }
+
+    public static InstanceIdentifier<RendererNodes> getRendererNodesIid() {
+        return InstanceIdentifier.builder(Renderers.class)
+            .child(Renderer.class, new RendererKey(VppRenderer.NAME))
+            .child(RendererNodes.class)
+            .build();
+    }
+
+    public static InstanceIdentifier<RendererNode> getRendererNodeIid(RendererNode rendererNode) {
+        return InstanceIdentifier.builder(Renderers.class)
+            .child(Renderer.class, new RendererKey(VppRenderer.NAME))
+            .child(RendererNodes.class)
+            .child(RendererNode.class, new RendererNodeKey(rendererNode.getNodePath()))
+            .build();
+    }
+
+    public static InstanceIdentifier<Node> getNodeIid(TopologyKey topologyKey, NodeKey nodeKey) {
+        return InstanceIdentifier.builder(NetworkTopology.class)
+            .child(Topology.class, topologyKey)
+            .child(Node.class, nodeKey)
+            .build();
+    }
+
+    public static InstanceIdentifier<Topology> getTopologyIid(TopologyKey bridgeDomainKey) {
+        return InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, bridgeDomainKey).build();
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppNodeWriter.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppNodeWriter.java
new file mode 100644 (file)
index 0000000..1e65549
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.CheckedFuture;
+
+public class VppNodeWriter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VppNodeWriter.class);
+    private List<RendererNode> rendererNodesCache;
+
+    public VppNodeWriter() {
+        rendererNodesCache = new ArrayList<>();
+    }
+
+    public void cache(RendererNode node) {
+        rendererNodesCache.add(node);
+    }
+
+    /**
+     * Put all cached items to data store.
+     *
+     * @param dataBroker appropriate data provider
+     */
+    public void commitToDatastore(DataBroker dataBroker) {
+        RendererNodes rendererNodes = buildRendererNodes();
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        InstanceIdentifier<RendererNodes> iid = VppIidFactory.getRendererNodesIid();
+        try {
+            wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, rendererNodes, true);
+            CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+            submitFuture.checkedGet();
+            // Clear cache
+            rendererNodesCache.clear();
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("Write transaction failed to {}", e.getMessage());
+        } catch (Exception e) {
+            LOG.error("Failed to .. {}", e.getMessage());
+        }
+    }
+
+    /**
+     * Removes all cached items from data store.
+     *
+     * @param dataBroker appropriate data provider
+     */
+    public void removeFromDatastore(DataBroker dataBroker) {
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        for (RendererNode nodeToRemove : rendererNodesCache) {
+            InstanceIdentifier<RendererNode> iid = VppIidFactory.getRendererNodeIid(nodeToRemove);
+            try {
+                wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+                CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+                submitFuture.checkedGet();
+                // Clear cache
+            } catch (TransactionCommitFailedException e) {
+                LOG.error("Write transaction failed to {}", e.getMessage());
+            } catch (Exception e) {
+                LOG.error("Failed to .. {}", e.getMessage());
+            }
+        }
+        rendererNodesCache.clear();
+    }
+
+    private RendererNodes buildRendererNodes() {
+        RendererNodesBuilder rendererNodesBuilder = new RendererNodesBuilder();
+        rendererNodesBuilder.setRendererNode(new ArrayList<>(rendererNodesCache));
+        return rendererNodesBuilder.build();
+    }
+}
index b70d8c97ce343075b9125f4b7023853fcd765a99..6401c4b987ad74c55f72589dc591123798e1738d 100644 (file)
@@ -29,7 +29,7 @@ module vpp-provider-impl {
     identity vpp-provider-impl {
         base "config:module-type";
 
-        config:java-name-prefix VppProvider;
+        config:java-name-prefix GbpVppProvider;
     }
 
     // Augments the 'configuration' choice node under modules/module.
@@ -46,6 +46,15 @@ module vpp-provider-impl {
                     }
                 }
             }
+            // binding aware broker
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-broker-osgi-registry;
+                    }
+                }
+            }
         }
     }
 }
diff --git a/renderers/vpp/src/main/yang/vpp-renderer.yang b/renderers/vpp/src/main/yang/vpp-renderer.yang
new file mode 100644 (file)
index 0000000..e15b1d7
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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
+ */
+
+module vpp-renderer {
+    yang-version 1;
+
+    namespace "urn:opendaylight:groupbasedpolicy:vpp_renderer";
+    prefix "vpp-renderer";
+
+    import base-endpoint { prefix base-ep; revision-date 2016-04-27; }
+
+    description
+        "This module is a baseline for the group-based policy vpp renderer model.";
+
+    revision "2016-04-25" {
+        description
+            "Initial revision.";
+    }
+
+    container config {
+        list vpp-endpoint {
+            description "Renderer creates/removes interface on VPP node based on given parameters.";
+
+            key "context-type context-id address-type address";
+            uses base-ep:address-endpoint-key;
+
+            leaf vpp-node-path {
+                description "Path to a node representing mount-point to VPP instance.";
+                type instance-identifier;
+            }
+            leaf vpp-interface-name {
+                description "Name of interface for the endpoint on VPP";
+                type string;
+            }
+            leaf description {
+                description "Additional description of the vpp-endpoint";
+                type string;
+            }
+            choice interface-type-choice {
+                case vhost-user-case {
+                    leaf socket {
+                        description "A unique ID for the neutron port";
+                        type string {
+                            length 1..255;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/CustomDataBrokerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/CustomDataBrokerTest.java
new file mode 100644 (file)
index 0000000..1528320
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+
+/**
+ * Loads only modules of GBP and it's dependencies for data broker.
+ * <br>
+ * Therefore this implementation is faster than {@link AbstractDataBrokerTest}
+ */
+public abstract class CustomDataBrokerTest extends AbstractDataBrokerTest {
+
+    public static void loadModuleInfos(Class<?> clazzFromModule, Builder<YangModuleInfo> moduleInfoSet)
+            throws Exception {
+        YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(clazzFromModule);
+        checkState(moduleInfo != null, "Module Info for %s is not available.", clazzFromModule);
+        collectYangModuleInfo(moduleInfo, moduleInfoSet);
+    }
+
+    private static void collectYangModuleInfo(final YangModuleInfo moduleInfo,
+            final Builder<YangModuleInfo> moduleInfoSet) throws IOException {
+        moduleInfoSet.add(moduleInfo);
+        for (YangModuleInfo dependency : moduleInfo.getImportedModules()) {
+            collectYangModuleInfo(dependency, moduleInfoSet);
+        }
+    }
+
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        Builder<YangModuleInfo> moduleInfoSet = ImmutableSet.<YangModuleInfo>builder();
+        for (Class<?> clazz : getClassesFromModules()) {
+            loadModuleInfos(clazz, moduleInfoSet);
+        }
+        return moduleInfoSet.build();
+    }
+
+    /**
+     * @return a class from every yang module which needs to be loaded. Cannot return {@code null}
+     *         or empty collection.
+     */
+    public abstract @Nonnull Collection<Class<?>> getClassesFromModules();
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/VppRendererDataBrokerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/VppRendererDataBrokerTest.java
new file mode 100644 (file)
index 0000000..551f19b
--- /dev/null
@@ -0,0 +1,32 @@
+/*\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.renderer.vpp;\r
+\r
+import com.google.common.collect.ImmutableList;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUser;\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.network.topology.Topology;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;\r
+\r
+import javax.annotation.Nonnull;\r
+import java.util.Collection;\r
+\r
+public class VppRendererDataBrokerTest extends CustomDataBrokerTest {\r
+\r
+    @Nonnull\r
+    @Override\r
+    public Collection<Class<?>> getClassesFromModules() {\r
+        return ImmutableList.of(Interfaces.class, Interface.class, VhostUser.class, NetworkTopology.class,\r
+                Topology.class, Node.class, NetconfNode.class, Renderer.class);\r
+    }\r
+}\r
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommandTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommandTest.java
new file mode 100644 (file)
index 0000000..5bbfa41
--- /dev/null
@@ -0,0 +1,184 @@
+/*\r
+ * Copyright (c) 2016 Cisco Systems. 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.renderer.vpp.commands;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Before;\r
+import org.junit.Test;\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.renderer.vpp.VppRendererDataBrokerTest;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUserRole;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentationBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUser;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUserBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBased;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBasedBuilder;\r
+\r
+import com.google.common.base.Optional;\r
+\r
+public class VhostUserCommandTest extends VppRendererDataBrokerTest {\r
+\r
+    private final static String BRIDGE_DOMAIN = "testBD";\r
+    private final static String DESCRIPTION = "used for testing";\r
+    private final static String INTERFACE_NAME = "testInterface";\r
+    private final static String SOCKET_NAME = "soc1";\r
+\r
+    private final static String UPD_BRIDGE_DOMAIN = "testBD2";\r
+    private final static String UPD_DESCRIPTION = "updated description";\r
+    private final static String UPD_SOCKET_NAME = "soc2";\r
+    private final static short SPLIT_HORIZON_GROUP_DEFAULT = 0;\r
+    private final static boolean IS_BRIDGED_DEFAULT = false;\r
+\r
+    private static Interface BASIC_INTERFACE;\r
+\r
+    private DataBroker dataBroker;\r
+\r
+    @Before\r
+    public void init() {\r
+        dataBroker = getDataBroker();\r
+\r
+        VhostUser vhostUser = new VhostUserBuilder().setRole(VhostUserRole.Server).setSocket(SOCKET_NAME).build();\r
+\r
+        VppInterfaceAugmentation vppAugmentation = new VppInterfaceAugmentationBuilder().setVhostUser(vhostUser)\r
+            .setL2(new L2Builder().setInterconnection(new BridgeBasedBuilder().setBridgeDomain(BRIDGE_DOMAIN)\r
+                .setSplitHorizonGroup(SPLIT_HORIZON_GROUP_DEFAULT)\r
+                .setBridgedVirtualInterface(IS_BRIDGED_DEFAULT)\r
+                .build()).build())\r
+            .build();\r
+\r
+        BASIC_INTERFACE =\r
+                new InterfaceBuilder().setDescription(DESCRIPTION)\r
+                    .setEnabled(true)\r
+                    .setKey(new InterfaceKey(INTERFACE_NAME))\r
+                    .setName(INTERFACE_NAME)\r
+                    .setType(\r
+                            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser.class)\r
+                    .setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Enabled)\r
+                    .addAugmentation(VppInterfaceAugmentation.class, vppAugmentation)\r
+                    .build();\r
+    }\r
+\r
+    @Test\r
+    public void AddVhostTest() {\r
+        ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();\r
+        VhostUserCommand addCommand = VhostUserCommand.builder()\r
+            .setOperation(General.Operations.PUT)\r
+            .setName(INTERFACE_NAME)\r
+            .setDescription(DESCRIPTION)\r
+            .setRole(VhostUserRole.Server)\r
+            .setSocket(SOCKET_NAME)\r
+            .setBridgeDomain(BRIDGE_DOMAIN)\r
+            .setEnabled(true)\r
+            .build();\r
+\r
+        addCommand.execute(transaction);\r
+\r
+        transaction.submit();\r
+\r
+        ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();\r
+\r
+        Optional<Interface> optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                VppIidFactory.getInterfaceIID(new InterfaceKey(INTERFACE_NAME)), readOnlyTransaction);\r
+\r
+        Assert.assertTrue("Interface was not written to DS", optional.isPresent());\r
+\r
+        Interface anInterface = optional.get();\r
+\r
+        Assert.assertEquals(BASIC_INTERFACE, anInterface);\r
+\r
+    }\r
+\r
+    @Test\r
+    public void DeleteVhostTest() {\r
+        ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();\r
+\r
+        transaction.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getInterfaceIID(BASIC_INTERFACE.getKey()),\r
+                BASIC_INTERFACE, true);\r
+        transaction.submit();\r
+\r
+        Optional<Interface> optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                VppIidFactory.getInterfaceIID(BASIC_INTERFACE.getKey()), dataBroker.newReadOnlyTransaction());\r
+\r
+        Assert.assertTrue("Interface was not written to DS", optional.isPresent());\r
+\r
+        VhostUserCommand deleteCommand = VhostUserCommand.builder()\r
+                .setOperation(General.Operations.DELETE)\r
+                .setName(INTERFACE_NAME)\r
+                .setSocket(SOCKET_NAME)\r
+                .build();\r
+\r
+        ReadWriteTransaction deleteTransaction = dataBroker.newReadWriteTransaction();\r
+        deleteCommand.execute(deleteTransaction);\r
+        deleteTransaction.submit();\r
+\r
+        Optional<Interface> optionalDeleted = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                VppIidFactory.getInterfaceIID(new InterfaceKey(deleteCommand.getName())),\r
+                dataBroker.newReadOnlyTransaction());\r
+\r
+        Assert.assertFalse("Interface was not deleted from DS", optionalDeleted.isPresent());\r
+    }\r
+\r
+    @Test\r
+    public void UpdateVhostTest() {\r
+        ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();\r
+\r
+        transaction.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getInterfaceIID(BASIC_INTERFACE.getKey()),\r
+                BASIC_INTERFACE, true);\r
+        transaction.submit();\r
+\r
+        Optional<Interface> optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                VppIidFactory.getInterfaceIID(BASIC_INTERFACE.getKey()), dataBroker.newReadOnlyTransaction());\r
+\r
+        Assert.assertTrue("Interface was not written to DS", optional.isPresent());\r
+\r
+        VhostUserCommand updateCommand = VhostUserCommand.builder()\r
+            .setOperation(General.Operations.MERGE)\r
+            .setName(INTERFACE_NAME)\r
+            .setDescription(UPD_DESCRIPTION)\r
+            .setEnabled(false)\r
+            .setRole(VhostUserRole.Client)\r
+            .setSocket(UPD_SOCKET_NAME)\r
+            .setBridgeDomain(UPD_BRIDGE_DOMAIN)\r
+            .build();\r
+\r
+        ReadWriteTransaction deleteTransaction = dataBroker.newReadWriteTransaction();\r
+        updateCommand.execute(deleteTransaction);\r
+        deleteTransaction.submit();\r
+\r
+        Optional<Interface> optionalUpdated = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+                VppIidFactory.getInterfaceIID(new InterfaceKey(updateCommand.getName())),\r
+                dataBroker.newReadOnlyTransaction());\r
+\r
+        Assert.assertTrue("Interface was not found in DS", optionalUpdated.isPresent());\r
+        Interface updatedInterface = optionalUpdated.get();\r
+\r
+        Assert.assertEquals(UPD_DESCRIPTION, updatedInterface.getDescription());\r
+        Assert.assertFalse(updatedInterface.isEnabled());\r
+        VppInterfaceAugmentation vppInterfaceAugmentation =\r
+                updatedInterface.getAugmentation(VppInterfaceAugmentation.class);\r
+        Assert.assertEquals(VhostUserRole.Client, vppInterfaceAugmentation.getVhostUser().getRole());\r
+        Assert.assertEquals(UPD_SOCKET_NAME, vppInterfaceAugmentation.getVhostUser().getSocket());\r
+\r
+        Assert.assertTrue(vppInterfaceAugmentation.getL2().getInterconnection() instanceof BridgeBased);\r
+\r
+        Assert.assertEquals(UPD_BRIDGE_DOMAIN,\r
+                ((BridgeBased) vppInterfaceAugmentation.getL2().getInterconnection()).getBridgeDomain());\r
+    }\r
+}\r
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/DtoChangeEventTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/DtoChangeEventTest.java
new file mode 100644 (file)
index 0000000..b01938e
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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.event;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+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;
+
+public class DtoChangeEventTest {
+
+    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> NODE_IID = InstanceIdentifier.builder(NetworkTopology.class)
+        .child(Topology.class, TOPO_KEY)
+        .child(Node.class, NODE_KEY)
+        .build();
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    private static class DummyDtoEvent extends DtoChangeEvent<Node> {
+
+        public DummyDtoEvent(InstanceIdentifier<Node> iid, Node before, Node after) {
+            super(iid, before, after);
+        }
+    }
+
+    @Test
+    public void testConstructor_nodeCreated() {
+        Node node = new NodeBuilder().setKey(NODE_KEY).build();
+        DummyDtoEvent event = new DummyDtoEvent(NODE_IID, null, node);
+        Assert.assertNotNull(event.getIid());
+        Assert.assertTrue(event.getAfter().isPresent());
+        Assert.assertFalse(event.getBefore().isPresent());
+        Assert.assertEquals(DtoChangeEvent.DtoModificationType.CREATED, event.getDtoModificationType());
+        Assert.assertTrue(event.isDtoCreated());
+        Assert.assertFalse(event.isDtoDeleted());
+        Assert.assertFalse(event.isDtoUpdated());
+    }
+
+    @Test
+    public void testConstructor_nodeDeleted() {
+        Node node = new NodeBuilder().setKey(NODE_KEY).build();
+        DummyDtoEvent event = new DummyDtoEvent(NODE_IID, node, null);
+        Assert.assertNotNull(event.getIid());
+        Assert.assertFalse(event.getAfter().isPresent());
+        Assert.assertTrue(event.getBefore().isPresent());
+        Assert.assertEquals(DtoChangeEvent.DtoModificationType.DELETED, event.getDtoModificationType());
+        Assert.assertFalse(event.isDtoCreated());
+        Assert.assertTrue(event.isDtoDeleted());
+        Assert.assertFalse(event.isDtoUpdated());
+    }
+
+    @Test
+    public void testConstructor_nodeUpdated() {
+        Node node = new NodeBuilder().setKey(NODE_KEY).build();
+        DummyDtoEvent event = new DummyDtoEvent(NODE_IID, node, node);
+        Assert.assertNotNull(event.getIid());
+        Assert.assertTrue(event.getAfter().isPresent());
+        Assert.assertTrue(event.getBefore().isPresent());
+        Assert.assertEquals(DtoChangeEvent.DtoModificationType.UPDATED, event.getDtoModificationType());
+        Assert.assertFalse(event.isDtoCreated());
+        Assert.assertFalse(event.isDtoDeleted());
+        Assert.assertTrue(event.isDtoUpdated());
+    }
+
+    @Test
+    public void testConstructor_nullNodes_Exception() {
+        thrown.expect(IllegalArgumentException.class);
+        new DummyDtoEvent(NODE_IID, null, null);
+    }
+
+    @Test
+    public void testConstructor_nullIid_Exception() {
+        Node node = new NodeBuilder().setKey(NODE_KEY).build();
+        thrown.expect(NullPointerException.class);
+        new DummyDtoEvent(null, node, node);
+    }
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/NodeOperEventTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/NodeOperEventTest.java
new file mode 100644 (file)
index 0000000..67f12cd
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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.event;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+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.ConnectionStatus;
+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;
+
+public class NodeOperEventTest {
+
+    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> NODE_IID = InstanceIdentifier.builder(NetworkTopology.class)
+        .child(Topology.class, TOPO_KEY)
+        .child(Node.class, NODE_KEY)
+        .build();
+    private final static NetconfNode NETCONF_NODE_AUG_CONNECTED =
+            new NetconfNodeBuilder().setConnectionStatus(ConnectionStatus.Connected).build();
+    private final static NetconfNode NETCONF_NODE_AUG_CONNECTING =
+            new NetconfNodeBuilder().setConnectionStatus(ConnectionStatus.Connecting).build();
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Test
+    public void testConstructor_nodeCreated() {
+        Node node = new NodeBuilder().setKey(NODE_KEY)
+            .addAugmentation(NetconfNode.class, NETCONF_NODE_AUG_CONNECTED)
+            .build();
+        NodeOperEvent event = new NodeOperEvent(NODE_IID, null, node);
+        Assert.assertTrue(event.getAfter().isPresent());
+        Assert.assertFalse(event.getBefore().isPresent());
+    }
+
+    @Test
+    public void testConstructor_nodeDeleted() {
+        Node node = new NodeBuilder().setKey(NODE_KEY)
+            .addAugmentation(NetconfNode.class, NETCONF_NODE_AUG_CONNECTED)
+            .build();
+        NodeOperEvent event = new NodeOperEvent(NODE_IID, node, null);
+        Assert.assertFalse(event.getAfter().isPresent());
+        Assert.assertTrue(event.getBefore().isPresent());
+    }
+
+    @Test
+    public void testConstructor_nodeUpdated() {
+        Node node = new NodeBuilder().setKey(NODE_KEY)
+            .addAugmentation(NetconfNode.class, NETCONF_NODE_AUG_CONNECTED)
+            .build();
+        NodeOperEvent event = new NodeOperEvent(NODE_IID, node, node);
+        Assert.assertTrue(event.getAfter().isPresent());
+        Assert.assertTrue(event.getBefore().isPresent());
+    }
+
+    @Test
+    public void testConstructor_beforeNodeMissingNetconfNodeAug_Exception() {
+        Node node = new NodeBuilder().setKey(NODE_KEY).build();
+        thrown.expect(IllegalArgumentException.class);
+        new NodeOperEvent(NODE_IID, node, null);
+    }
+
+    @Test
+    public void testConstructor_afterNodeMissingNetconfNodeAug_Exception() {
+        Node node = new NodeBuilder().setKey(NODE_KEY).build();
+        thrown.expect(IllegalArgumentException.class);
+        new NodeOperEvent(NODE_IID, null, node);
+    }
+
+    @Test
+    public void testConstructor_nullNodes_Exception() {
+        thrown.expect(IllegalArgumentException.class);
+        new NodeOperEvent(NODE_IID, null, null);
+    }
+
+    @Test
+    public void testConstructor_nullIid_Exception() {
+        Node node = new NodeBuilder().setKey(NODE_KEY)
+            .addAugmentation(NetconfNode.class, NETCONF_NODE_AUG_CONNECTED)
+            .build();
+        thrown.expect(NullPointerException.class);
+        new NodeOperEvent(null, node, node);
+    }
+
+    @Test
+    public void testIsAfterConnected() {
+        Node node = new NodeBuilder().setKey(NODE_KEY)
+            .addAugmentation(NetconfNode.class, NETCONF_NODE_AUG_CONNECTED)
+            .build();
+        NodeOperEvent event = new NodeOperEvent(NODE_IID, null, node);
+        Assert.assertTrue(event.isAfterConnected());
+    }
+
+    @Test
+    public void testIsBeforeConnected() {
+        Node node = new NodeBuilder().setKey(NODE_KEY)
+            .addAugmentation(NetconfNode.class, NETCONF_NODE_AUG_CONNECTED)
+            .build();
+        NodeOperEvent event = new NodeOperEvent(NODE_IID, node, null);
+        Assert.assertTrue(event.isBeforeConnected());
+    }
+
+    @Test
+    public void testIsAfterConnected_false() {
+        Node node = new NodeBuilder().setKey(NODE_KEY)
+            .addAugmentation(NetconfNode.class, NETCONF_NODE_AUG_CONNECTING)
+            .build();
+        NodeOperEvent event = new NodeOperEvent(NODE_IID, null, node);
+        Assert.assertFalse(event.isAfterConnected());
+    }
+    
+    @Test
+    public void testIsBeforeConnected_false() {
+        Node node = new NodeBuilder().setKey(NODE_KEY)
+            .addAugmentation(NetconfNode.class, NETCONF_NODE_AUG_CONNECTING)
+            .build();
+        NodeOperEvent event = new NodeOperEvent(NODE_IID, null, node);
+        Assert.assertFalse(event.isBeforeConnected());
+    }
+
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/VppEndpointConfEventTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/event/VppEndpointConfEventTest.java
new file mode 100644 (file)
index 0000000..d37fbfd
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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.event;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
+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.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.yangtools.yang.binding.InstanceIdentifier;
+
+public class VppEndpointConfEventTest {
+
+    private final static String ADDRESS = "1.1.1.1/32";
+    private final static ContextId CONTEXT_ID = new ContextId("ctx1");
+    private final static VppEndpointKey BASIC_VPP_EP_KEY =
+            new VppEndpointKey(ADDRESS, AddressType.class, CONTEXT_ID, ContextType.class);
+    private final static InstanceIdentifier<VppEndpoint> BASIC_VPP_EP_IID =
+            InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, BASIC_VPP_EP_KEY).build();
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Test
+    public void testConstructor_vppEpCreated() {
+        VppEndpoint vppEndpoint = basicVppEpBuilder().build();
+        VppEndpointConfEvent event = new VppEndpointConfEvent(BASIC_VPP_EP_IID, null, vppEndpoint);
+        Assert.assertTrue(event.getAfter().isPresent());
+        Assert.assertFalse(event.getBefore().isPresent());
+    }
+
+    @Test
+    public void testConstructor_vppEpDeleted() {
+        VppEndpoint vppEndpoint = basicVppEpBuilder().build();
+        VppEndpointConfEvent event = new VppEndpointConfEvent(BASIC_VPP_EP_IID, vppEndpoint, null);
+        Assert.assertFalse(event.getAfter().isPresent());
+        Assert.assertTrue(event.getBefore().isPresent());
+    }
+
+    @Test
+    public void testConstructor_vppEpUpdated() {
+        VppEndpoint vppEndpoint = basicVppEpBuilder().build();
+        VppEndpointConfEvent event = new VppEndpointConfEvent(BASIC_VPP_EP_IID, vppEndpoint, vppEndpoint);
+        Assert.assertTrue(event.getAfter().isPresent());
+        Assert.assertTrue(event.getBefore().isPresent());
+    }
+
+    @Test
+    public void testConstructor_nullVppEp_Exception() {
+        thrown.expect(IllegalArgumentException.class);
+        new VppEndpointConfEvent(BASIC_VPP_EP_IID, null, null);
+    }
+
+    private VppEndpointBuilder basicVppEpBuilder() {
+        return new VppEndpointBuilder().setAddress(ADDRESS)
+            .setAddressType(AddressType.class)
+            .setContextId(CONTEXT_ID)
+            .setContextType(ContextType.class);
+    }
+
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManagerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManagerTest.java
new file mode 100644 (file)
index 0000000..2ebd647
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * 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.iface;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+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.event.VppEndpointConfEvent;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
+import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
+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.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.vpp.endpoint._interface.type.choice.VhostUserCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUserRole;
+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.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;
+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 com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class InterfaceManagerTest extends CustomDataBrokerTest {
+
+    private final static String ADDRESS = "1.1.1.1/32";
+    private final static ContextId CONTEXT_ID = new ContextId("ctx1");
+    private final static String IFACE_NAME = "ifaceName1";
+    private final static VppEndpointKey BASIC_VPP_EP_KEY =
+            new VppEndpointKey(ADDRESS, AddressType.class, CONTEXT_ID, ContextType.class);
+    private final static InstanceIdentifier<VppEndpoint> BASIC_VPP_EP_IID =
+            InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, BASIC_VPP_EP_KEY).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> NODE_IID = InstanceIdentifier.builder(NetworkTopology.class)
+        .child(Topology.class, TOPO_KEY)
+        .child(Node.class, NODE_KEY)
+        .build();
+    private final static String SOCKET = "socket1";
+
+    private InterfaceManager manager;
+    private MountedDataBrokerProvider mountedDataProviderMock;
+    private DataBroker mountPointDataBroker;
+    private DataBroker dataBroker;
+
+    @Override
+    public Collection<Class<?>> getClassesFromModules() {
+        return Arrays.asList(Node.class, VppEndpoint.class, Interfaces.class, BridgeDomains.class,
+                LocationProviders.class);
+    }
+
+    @Before
+    public void init() throws Exception {
+        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));
+        manager = new InterfaceManager(mountedDataProviderMock, dataBroker, MoreExecutors.newDirectExecutorService());
+    }
+
+    @Test
+    public void testVppEndpointChanged_created() throws Exception {
+        VppEndpoint vhostEp = vhostVppEpBuilder().build();
+        VppEndpointConfEvent event = new VppEndpointConfEvent(BASIC_VPP_EP_IID, null, vhostEp);
+
+        manager.vppEndpointChanged(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(vhostEp.getVppInterfaceName()))
+                    .build()).get();
+        Assert.assertTrue(potentialIface.isPresent());
+        Interface iface = potentialIface.get();
+        Assert.assertEquals(VhostUser.class, iface.getType());
+        Assert.assertTrue(iface.isEnabled());
+        VppInterfaceAugmentation vppIface = iface.getAugmentation(VppInterfaceAugmentation.class);
+        Assert.assertNotNull(vppIface);
+        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUser vhostUserIface =
+                vppIface.getVhostUser();
+        Assert.assertNotNull(vhostUserIface);
+        Assert.assertEquals(VhostUserRole.Client, vhostUserIface.getRole());
+        Assert.assertEquals(SOCKET, vhostUserIface.getSocket());
+        L2 l2Iface = vppIface.getL2();
+        if (l2Iface != null) {
+            Interconnection interconnection = l2Iface.getInterconnection();
+            if (interconnection != null) {
+                if (interconnection instanceof BridgeBased) {
+                    BridgeBased bridgeL2Iface = (BridgeBased) interconnection;
+                    Assert.assertTrue(Strings.isNullOrEmpty(bridgeL2Iface.getBridgeDomain()));
+                }
+            }
+        }
+        // assert state on ODL data store
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        Optional<LocationProvider> optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION, IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER)).get();
+        Assert.assertTrue(optLocationProvider.isPresent());
+        List<ProviderAddressEndpointLocation> epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
+        Assert.assertNotNull(epLocs);
+        Assert.assertEquals(1, epLocs.size());
+        ProviderAddressEndpointLocation epLoc = VppEndpointLocationProvider.createProviderAddressEndpointLocation(vhostEp);
+        Assert.assertEquals(epLoc, epLocs.get(0));
+    }
+
+    @Test
+    public void testVppEndpointChanged_deleted() throws Exception {
+        VppEndpoint vhostEp = vhostVppEpBuilder().build();
+        VppEndpointConfEvent createVppEpEvent = new VppEndpointConfEvent(BASIC_VPP_EP_IID, null, vhostEp);
+        VppEndpointConfEvent deleteVppEpEvent = new VppEndpointConfEvent(BASIC_VPP_EP_IID, vhostEp, null);
+
+        manager.vppEndpointChanged(createVppEpEvent);
+        manager.vppEndpointChanged(deleteVppEpEvent);
+        // 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(vhostEp.getVppInterfaceName()))
+                    .build()).get();
+        Assert.assertFalse(potentialIface.isPresent());
+        // assert state on ODL data store
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        ProviderAddressEndpointLocation providerAddressEndpointLocation =
+                VppEndpointLocationProvider.createProviderAddressEndpointLocation(vhostEp);
+        InstanceIdentifier<ProviderAddressEndpointLocation> providerAddressEndpointLocationIid = IidFactory
+            .providerAddressEndpointLocationIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER,
+                    providerAddressEndpointLocation.getKey());
+        Optional<ProviderAddressEndpointLocation> optProvEpLoc =
+                rTx.read(LogicalDatastoreType.CONFIGURATION, providerAddressEndpointLocationIid).get();
+        Assert.assertFalse(optProvEpLoc.isPresent());
+    }
+
+    private VppEndpointBuilder vhostVppEpBuilder() {
+        return basicVppEpBuilder().setVppInterfaceName(IFACE_NAME)
+            .setVppNodePath(NODE_IID)
+            .setInterfaceTypeChoice(new VhostUserCaseBuilder().setSocket(SOCKET).build());
+    }
+
+    private VppEndpointBuilder basicVppEpBuilder() {
+        return new VppEndpointBuilder().setAddress(ADDRESS)
+            .setAddressType(AddressType.class)
+            .setContextId(CONTEXT_ID)
+            .setContextType(ContextType.class);
+    }
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapperTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapperTest.java
new file mode 100644 (file)
index 0000000..558a515
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.iface;
+
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+
+public class VppPathMapperTest {
+
+    private static final String INTERFACE_PATH = "/ietf-interfaces:interfaces/ietf-interfaces:interface";
+    private static final String INTERFACE_KEY_START = "[ietf-interfaces:name='";
+    private static final String INTERFACE_KEY_END = "']";
+    private static final String INTERFACE_NAME = "12345";
+    private static final InterfaceKey INTERFACE_KEY = new InterfaceKey(INTERFACE_NAME);
+
+    @Test
+    public void testToInstanceIdentifier() {
+        String restPath = INTERFACE_PATH + INTERFACE_KEY_START + INTERFACE_NAME + INTERFACE_KEY_END;
+        Optional<InstanceIdentifier<Interface>> optIid = VppPathMapper.interfaceToInstanceIdentifier(restPath);
+        Assert.assertTrue(optIid.isPresent());
+        InstanceIdentifier<Interface> iid = optIid.get();
+        Assert.assertNotNull(iid);
+        Assert.assertEquals(INTERFACE_KEY, iid.firstKeyOf(Interface.class));
+    }
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppEndpointListenerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/listener/VppEndpointListenerTest.java
new file mode 100644 (file)
index 0000000..37c68c8
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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.listener;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+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.vpp.event.VppEndpointConfEvent;
+import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
+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.VppEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;
+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;
+
+import com.google.common.base.Optional;
+import com.google.common.eventbus.EventBus;
+
+public class VppEndpointListenerTest extends CustomDataBrokerTest {
+
+    private final static String ADDRESS = "1.1.1.1/32";
+    private final static ContextId CONTEXT_ID = new ContextId("ctx1");
+    private final static String IFACE_NAME = "ifaceName";
+
+    private DataBroker dataBroker;
+    private VppEndpointListener listener;
+    private EventBus eventBusMock;
+
+    @Override
+    public Collection<Class<?>> getClassesFromModules() {
+        return Arrays.asList(Node.class, VppEndpoint.class, Forwarding.class, LocationProviders.class);
+    }
+
+    @Before
+    public void init() {
+        dataBroker = getDataBroker();
+        eventBusMock = Mockito.mock(EventBus.class);
+        listener = new VppEndpointListener(dataBroker, eventBusMock);
+    }
+
+    @Test
+    public void testOnWrite() throws Exception {
+        ArgumentCaptor<VppEndpointConfEvent> argVppEpEvent = ArgumentCaptor.forClass(VppEndpointConfEvent.class);
+        VppEndpoint vppEndpoint = new VppEndpointBuilder().setAddress(ADDRESS)
+            .setAddressType(AddressType.class)
+            .setContextId(CONTEXT_ID)
+            .setContextType(ContextType.class)
+            .build();
+        InstanceIdentifier<VppEndpoint> vppEpIid =
+                InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, vppEndpoint.getKey()).build();
+        WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION, vppEpIid, vppEndpoint);
+        wTx.submit().get();
+
+        Mockito.verify(eventBusMock).post(argVppEpEvent.capture());
+        VppEndpointConfEvent capturedVppEpEvent = argVppEpEvent.getValue();
+        Assert.assertEquals(vppEpIid, capturedVppEpEvent.getIid());
+        assertEqualsOptional(null, capturedVppEpEvent.getBefore());
+        assertEqualsOptional(vppEndpoint, capturedVppEpEvent.getAfter());
+    }
+
+    @Test
+    public void testOnDelete() throws Exception {
+        ArgumentCaptor<VppEndpointConfEvent> argVppEpEvent = ArgumentCaptor.forClass(VppEndpointConfEvent.class);
+        VppEndpoint vppEndpoint = new VppEndpointBuilder().setAddress(ADDRESS)
+            .setAddressType(AddressType.class)
+            .setContextId(CONTEXT_ID)
+            .setContextType(ContextType.class)
+            .build();
+        InstanceIdentifier<VppEndpoint> vppEpIid =
+                InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, vppEndpoint.getKey()).build();
+        WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION, vppEpIid, vppEndpoint);
+        wTx.submit().get();
+        wTx = getDataBroker().newWriteOnlyTransaction();
+        wTx.delete(LogicalDatastoreType.CONFIGURATION, vppEpIid);
+        wTx.submit().get();
+
+        Mockito.verify(eventBusMock, Mockito.times(2)).post(argVppEpEvent.capture());
+        VppEndpointConfEvent capturedVppEpEvent = argVppEpEvent.getAllValues().get(1);
+        Assert.assertEquals(vppEpIid, capturedVppEpEvent.getIid());
+        assertEqualsOptional(vppEndpoint, capturedVppEpEvent.getBefore());
+        assertEqualsOptional(null, capturedVppEpEvent.getAfter());
+    }
+
+    @Test
+    public void testOnSubtreeModified() throws Exception {
+        ArgumentCaptor<VppEndpointConfEvent> argVppEpEvent = ArgumentCaptor.forClass(VppEndpointConfEvent.class);
+        VppEndpointBuilder vppEndpointBuilder = new VppEndpointBuilder().setAddress(ADDRESS)
+            .setAddressType(AddressType.class)
+            .setContextId(CONTEXT_ID)
+            .setContextType(ContextType.class);
+        VppEndpoint vppEndpoint = vppEndpointBuilder.build();
+        InstanceIdentifier<VppEndpoint> vppEpIid =
+                InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, vppEndpoint.getKey()).build();
+        WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION, vppEpIid, vppEndpoint);
+        wTx.submit().get();
+        VppEndpoint modifiedVppEndpoint = vppEndpointBuilder.setVppInterfaceName(IFACE_NAME).build();
+        wTx = getDataBroker().newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION, vppEpIid, modifiedVppEndpoint);
+        wTx.submit().get();
+
+        Mockito.verify(eventBusMock, Mockito.times(2)).post(argVppEpEvent.capture());
+        VppEndpointConfEvent capturedFirstVppEpEvent = argVppEpEvent.getAllValues().get(0);
+        Assert.assertEquals(vppEpIid, capturedFirstVppEpEvent.getIid());
+        assertEqualsOptional(null, capturedFirstVppEpEvent.getBefore());
+        assertEqualsOptional(vppEndpoint, capturedFirstVppEpEvent.getAfter());
+        VppEndpointConfEvent capturedSecondVppEpEvent = argVppEpEvent.getAllValues().get(1);
+        Assert.assertEquals(vppEpIid, capturedSecondVppEpEvent.getIid());
+        assertEqualsOptional(vppEndpoint, capturedSecondVppEpEvent.getBefore());
+        assertEqualsOptional(modifiedVppEndpoint, capturedSecondVppEpEvent.getAfter());
+    }
+
+    private <T> void assertEqualsOptional(T expected, Optional<T> actual) {
+        if (expected == null) {
+            Assert.assertFalse(actual.isPresent());
+        } else {
+            Assert.assertTrue(actual.isPresent());
+            Assert.assertEquals(expected, actual.get());
+        }
+    }
+
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/BridgeDomainManagerImplTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/BridgeDomainManagerImplTest.java
new file mode 100644 (file)
index 0000000..3889fb7
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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 java.util.Collection;
+
+import org.junit.Assert;
+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.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+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.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.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.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.util.concurrent.ListenableFuture;
+
+public class BridgeDomainManagerImplTest extends CustomDataBrokerTest {
+
+    private static final TopologyId SUPPORTING_TOPOLOGY_NETCONF = new TopologyId("topology-netconf");
+    private final static String BRIDGE_DOMAIN_ID = "bridge-domain-test";
+    private final static TopologyId BASE_TOPOLOGY_ID = new TopologyId(BRIDGE_DOMAIN_ID);
+    private final static VxlanVni BRIDGE_DOMAIN_VNI = new VxlanVni(10L);
+    private final static boolean BRIDGE_DOMAIN_FLOOD = true;
+    private final static boolean BRIDGE_DOMAIN_FORWARD = true;
+    private final static boolean BRIDGE_DOMAIN_LEARN = true;
+    private final static boolean BRIDGE_DOMAIN_UNICAST_FLOOD = true;
+    private final static boolean BRIDGE_DOMAIN_ARP = false;
+    private final static NodeId VPP_NODE_ID = new NodeId("vppNode");
+    private final static Topology BASE_TOPOLOGY = new TopologyBuilder().setTopologyId(BASE_TOPOLOGY_ID)
+        .setNode(Arrays.asList(new NodeBuilder().setNodeId(VPP_NODE_ID)
+            .setSupportingNode(Arrays.asList(new SupportingNodeBuilder().setTopologyRef(SUPPORTING_TOPOLOGY_NETCONF)
+                .setNodeRef(VPP_NODE_ID)
+                .build()))
+            .build()))
+        .setTopologyTypes(new TopologyTypesBuilder()
+            .addAugmentation(TopologyTypesVbridgeAugment.class, new TopologyTypesVbridgeAugmentBuilder()
+                .setVbridgeTopology(new VbridgeTopologyBuilder().build()).build())
+            .build())
+        .addAugmentation(TopologyVbridgeAugment.class,
+                new TopologyVbridgeAugmentBuilder().setTunnelType(TunnelTypeVxlan.class)
+                    .setTunnelParameters(new VxlanTunnelParametersBuilder().setVni(BRIDGE_DOMAIN_VNI).build())
+                    .setForward(BRIDGE_DOMAIN_FORWARD)
+                    .setUnknownUnicastFlood(BRIDGE_DOMAIN_UNICAST_FLOOD)
+                    .setLearn(BRIDGE_DOMAIN_LEARN)
+                    .setArpTermination(BRIDGE_DOMAIN_ARP)
+                    .setFlood(BRIDGE_DOMAIN_FLOOD)
+                    .build())
+        .build();
+
+    private DataBroker dataBroker;
+    private BridgeDomainManagerImpl bridgeDomainManager;
+
+    @Override
+    public Collection<Class<?>> getClassesFromModules() {
+        return Arrays.asList(NetworkTopology.class, Topology.class, TopologyVbridgeAugment.class,
+                TunnelTypeVxlan.class);
+    }
+
+    @Before
+    public void init() {
+        dataBroker = getDataBroker();
+        bridgeDomainManager = new BridgeDomainManagerImpl(dataBroker);
+    }
+
+    @Test
+    public void testCreateVxlanBridgeDomainOnVppNode() {
+        ListenableFuture<Void> registered =
+                bridgeDomainManager.createVxlanBridgeDomainOnVppNode(BRIDGE_DOMAIN_ID, BRIDGE_DOMAIN_VNI, VPP_NODE_ID);
+        Assert.assertTrue(registered.isDone());
+
+        Optional<Topology> topologyOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                VppIidFactory.getTopologyIid(BASE_TOPOLOGY.getKey()), dataBroker.newReadOnlyTransaction());
+        Assert.assertTrue(topologyOptional.isPresent());
+
+        Topology topology = topologyOptional.get();
+        Assert.assertEquals(BASE_TOPOLOGY, topology);
+    }
+
+    @Test
+    public void testRemoveBridgeDomainFromVppNode() {
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+        writeTransaction.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getTopologyIid(BASE_TOPOLOGY.getKey()),
+                BASE_TOPOLOGY, true);
+        boolean result = DataStoreHelper.submitToDs(writeTransaction);
+        Assert.assertTrue(result);
+
+        Optional<Node> topologyOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                VppIidFactory.getNodeIid(new TopologyKey(BASE_TOPOLOGY_ID), new NodeKey(VPP_NODE_ID)),
+                dataBroker.newReadOnlyTransaction());
+        Assert.assertTrue(topologyOptional.isPresent());
+
+        ListenableFuture<Void> deleted =
+                bridgeDomainManager.removeBridgeDomainFromVppNode(BRIDGE_DOMAIN_ID, VPP_NODE_ID);
+        Assert.assertTrue(deleted.isDone());
+
+        topologyOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                VppIidFactory.getNodeIid(new TopologyKey(BASE_TOPOLOGY_ID), new NodeKey(VPP_NODE_ID)),
+                dataBroker.newReadOnlyTransaction());
+        Assert.assertFalse(topologyOptional.isPresent());
+    }
+
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/VppManagerDataStoreTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/VppManagerDataStoreTest.java
new file mode 100644 (file)
index 0000000..4760a3e
--- /dev/null
@@ -0,0 +1,168 @@
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.manager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Assert;
+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.config.yang.config.vpp_provider.impl.VppRenderer;
+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.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.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.VppRendererDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppNodeListener;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+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.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.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
+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.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 com.google.common.base.Optional;
+import com.google.common.eventbus.EventBus;
+import com.google.common.util.concurrent.CheckedFuture;
+
+/**
+ * Test for {@link VppNodeManager} and {@link VppNodeListener}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class VppManagerDataStoreTest extends VppRendererDataBrokerTest {
+
+    private static final String V3PO_CAPABILITY = "(urn:opendaylight:params:xml:ns:yang:v3po?revision=2015-01-05)v3po";
+    private static final String INTERFACES_CAPABILITY =
+            "(urn:ietf:params:xml:ns:yang:ietf-interfaces?revision=2014-05-08)ietf-interfaces";
+    private static final String NODE_NAME = "testVpp";
+    private static final InstanceIdentifier<Node> NODE_IID = VppIidFactory
+        .getNodeIid(new TopologyKey(new TopologyId("topology-netconf")), new NodeKey(new NodeId(NODE_NAME)));
+
+    @Mock
+    BindingAwareBroker.ProviderContext providerContext;
+    @Mock
+    MountPointService mountPointService;
+    @Mock
+    MountPoint mountPoint;
+    @Mock
+    DataBroker dataBroker2;
+
+    private DataBroker dataBroker;
+    private VppNodeListener vppNodeListener;
+    private VppNodeManager vppNodeManager;
+
+    @Before
+    public void setUp() throws Exception {
+        Mockito.when(providerContext.getSALService(Matchers.<Class<MountPointService>>any()))
+            .thenReturn(mountPointService);
+        Mockito.when(mountPointService.getMountPoint(Matchers.<InstanceIdentifier<Node>>any()))
+            .thenReturn(Optional.of(mountPoint));
+        Mockito.when(mountPoint.getService(Matchers.<Class<DataBroker>>any())).thenReturn(Optional.of(dataBroker2));
+        dataBroker = getDataBroker();
+        vppNodeManager = new VppNodeManager(dataBroker, providerContext);
+        vppNodeListener = new VppNodeListener(dataBroker, vppNodeManager, new EventBus());
+    }
+
+    private Node createNode(final String name, NetconfNodeConnectionStatus.ConnectionStatus status) {
+        Host host = new Host(new IpAddress(new Ipv4Address("192.168.255.101")));
+        PortNumber portNumber = new PortNumber(2830);
+
+        List<String> avaibleCapabilitiesList = new ArrayList<>();
+        avaibleCapabilitiesList.add(V3PO_CAPABILITY);
+        avaibleCapabilitiesList.add(INTERFACES_CAPABILITY);
+
+        NetconfNode netconfNode = new NetconfNodeBuilder().setHost(host)
+            .setPort(portNumber)
+            .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().build())
+            .setAvailableCapabilities(
+                    new AvailableCapabilitiesBuilder().setAvailableCapability(avaibleCapabilitiesList).build())
+            .setConnectionStatus(status)
+            .build();
+
+        return new NodeBuilder().setNodeId(new NodeId(name)).addAugmentation(NetconfNode.class, netconfNode).build();
+    }
+
+    @Test
+    public void connectNode() throws ReadFailedException {
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+        Node testVppNode = createNode(NODE_NAME, NetconfNodeConnectionStatus.ConnectionStatus.Connected);
+
+        writeTransaction.put(LogicalDatastoreType.OPERATIONAL, NODE_IID, testVppNode, true);
+
+        writeTransaction.submit();
+
+        ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();
+        CheckedFuture<Optional<Renderer>, ReadFailedException> future =
+                readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL,
+                        VppIidFactory.getRendererIID(new RendererKey(VppRenderer.NAME)));
+        Optional<Renderer> rendererOptional = future.checkedGet();
+
+        Assert.assertTrue(rendererOptional.isPresent());
+        Assert.assertEquals(1, rendererOptional.get().getRendererNodes().getRendererNode().size());
+        Assert.assertEquals(NODE_IID, rendererOptional.get().getRendererNodes().getRendererNode().get(0).getNodePath());
+    }
+
+    @Test
+    public void disconnectNode() throws ReadFailedException, InterruptedException {
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+        Node testVppNode = createNode(NODE_NAME, NetconfNodeConnectionStatus.ConnectionStatus.Connected);
+
+        writeTransaction.put(LogicalDatastoreType.OPERATIONAL, NODE_IID, testVppNode, true);
+
+        writeTransaction.submit();
+
+        ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();
+        CheckedFuture<Optional<Renderer>, ReadFailedException> future =
+                readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL,
+                        VppIidFactory.getRendererIID(new RendererKey(VppRenderer.NAME)));
+        Optional<Renderer> rendererOptional = future.checkedGet();
+
+        Assert.assertTrue(rendererOptional.isPresent());
+        Assert.assertEquals(1, rendererOptional.get().getRendererNodes().getRendererNode().size());
+        Assert.assertEquals(NODE_IID, rendererOptional.get().getRendererNodes().getRendererNode().get(0).getNodePath());
+
+        WriteTransaction writeTransaction2 = dataBroker.newWriteOnlyTransaction();
+        Node testVppNode2 = createNode(NODE_NAME, NetconfNodeConnectionStatus.ConnectionStatus.Connecting);
+
+        writeTransaction2.put(LogicalDatastoreType.OPERATIONAL, NODE_IID, testVppNode2, true);
+
+        writeTransaction2.submit();
+
+        ReadOnlyTransaction readOnlyTransaction2 = dataBroker.newReadOnlyTransaction();
+        CheckedFuture<Optional<Renderer>, ReadFailedException> future2 =
+                readOnlyTransaction2.read(LogicalDatastoreType.OPERATIONAL,
+                        VppIidFactory.getRendererIID(new RendererKey(VppRenderer.NAME)));
+        Optional<Renderer> rendererOptional2 = future2.checkedGet();
+
+        Assert.assertTrue(rendererOptional2.isPresent());
+        Assert.assertEquals(0, rendererOptional2.get().getRendererNodes().getRendererNode().size());
+    }
+
+    @After
+    public void cleanUp() throws Exception {
+        vppNodeListener.close();
+    }
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java
new file mode 100644 (file)
index 0000000..9e79c52
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * 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.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppRenderer;
+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.event.RendererPolicyConfEvent;
+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;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+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.NetworkContainmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.ForwardingContextContainmentBuilder;
+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.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
+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.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.ConfigurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints;
+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.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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRuleBuilder;
+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.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.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.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;
+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.tunnel.vxlan.rev160429.TunnelTypeVxlan;
+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 com.google.common.base.Optional;
+import com.google.common.util.concurrent.MoreExecutors;
+
+@RunWith(MockitoJUnitRunner.class)
+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)
+        .child(Topology.class, TOPO_KEY)
+        .child(Node.class, NODE_KEY)
+        .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 =
+            new RuleGroupWithRendererEndpointParticipationBuilder().setContractId(CONTRACT_ID)
+                .setTenantId(TENANT_ID)
+                .setSubjectName(SUBJECT_NAME)
+                .setRendererEndpointParticipation(EndpointPolicyParticipation.CONSUMER)
+                .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;
+    private DataBroker mountPointDataBroker;
+    private DataBroker dataBroker;
+
+    private BridgeDomainManager bdManager;
+    private InterfaceManager ifaceManager;
+    private ForwardingManager fwManager;
+    private VppRendererPolicyManager vppRendererPolicyManager;
+
+    @Override
+    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);
+    }
+
+    @Before
+    public void init() throws Exception {
+        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());
+        bdManager = new BridgeDomainManagerImpl(mountPointDataBroker);
+        fwManager = new ForwardingManager(ifaceManager, bdManager);
+        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);
+
+        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();
+        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_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());
+        // assert state on ODL data store
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        Optional<LocationProvider> optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
+            .get();
+        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());
+    }
+
+    @Test
+    public void testRendererPolicyChanged_createdClientAndThenWeb() throws Exception {
+        testRendererPolicyChanged_createdClient();
+
+        storeInterfaceFor(WEB_EP_KEY, IFACE_NAME_WEB_EP, BASIC_VPP_WEB_EP_IID);
+
+        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();
+        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 ODL data store
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        Optional<LocationProvider> optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
+            .get();
+        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());
+        } 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());
+        }
+    }
+
+    private void storeInterfaceFor(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)
+            .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();
+    }
+
+}
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppNodeWriterTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppNodeWriterTest.java
new file mode 100644 (file)
index 0000000..911d2c5
--- /dev/null
@@ -0,0 +1,94 @@
+package org.opendaylight.groupbasedpolicy.renderer.vpp.util;
+
+import com.google.common.util.concurrent.Futures;
+import org.junit.After;
+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.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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link VppNodeWriter}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class VppNodeWriterTest {
+
+    private static final String RENDERER_NAME = "vpp-renderer";
+
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private WriteTransaction wTx;
+    @Captor
+    private ArgumentCaptor<InstanceIdentifier<RendererNodes>> rendererNodesPathCpt;
+    @Captor
+    private ArgumentCaptor<RendererNodes> rendererNodesCpt;
+
+    private InOrder inOrder;
+
+    private VppNodeWriter nodeWriter;
+
+    @Before
+    public void setUp() throws Exception {
+        nodeWriter = new VppNodeWriter();
+        Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wTx);
+        Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testCommitToDatastore_with_node() throws Exception {
+        final RendererNode node = new RendererNodeBuilder().build();
+        nodeWriter.cache(node);
+        nodeWriter.commitToDatastore(dataBroker);
+
+        commonChecks();
+
+        final RendererNodes rendererNodes = rendererNodesCpt.getValue();
+        Assert.assertEquals(1, rendererNodes.getRendererNode().size());
+    }
+
+    @Test
+    public void testCommitToDatastore_empty() throws Exception {
+        nodeWriter.commitToDatastore(dataBroker);
+
+        commonChecks();
+
+        final RendererNodes rendererNodes = rendererNodesCpt.getValue();
+        Assert.assertEquals(0, rendererNodes.getRendererNode().size());
+    }
+
+    private void commonChecks() {
+        inOrder = Mockito.inOrder(dataBroker, wTx);
+        inOrder.verify(dataBroker).newWriteOnlyTransaction();
+        inOrder.verify(wTx).merge(Matchers.eq(LogicalDatastoreType.OPERATIONAL), rendererNodesPathCpt.capture(),
+                rendererNodesCpt.capture(), Matchers.eq(true));
+        inOrder.verify(wTx).submit();
+
+        final InstanceIdentifier<RendererNodes> rendererNodesPath = rendererNodesPathCpt.getValue();
+        Assert.assertEquals(RENDERER_NAME, extractRendererName(rendererNodesPath));
+    }
+
+    private String extractRendererName(final InstanceIdentifier<RendererNodes> rendererNodesPath) {
+        return rendererNodesPath.firstKeyOf(Renderer.class).getName().getValue();
+    }
+}
diff --git a/renderers/vpp/src/test/resources/log4j.xml b/renderers/vpp/src/test/resources/log4j.xml
new file mode 100644 (file)
index 0000000..e4ba3c5
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\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
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">\r
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">\r
+\r
+    <appender name="console" class="org.apache.log4j.ConsoleAppender">\r
+        <layout class="org.apache.log4j.PatternLayout">\r
+            <param name="ConversionPattern" value="%-6p %d{HH:mm:ss.SSS} [%10.10t] %30.30c %x - %m%n"/>\r
+        </layout>\r
+        <!--         <param name="Threshold" value="DEBUG" /> -->\r
+    </appender>\r
+\r
+    <logger name="org.opendaylight.groupbasedpolicy.renderer.vpp" additivity="false">\r
+        <level value="DEBUG"/>\r
+        <appender-ref ref="console"/>\r
+    </logger>\r
+\r
+    <root>\r
+        <priority value="INFO"/>\r
+        <appender-ref ref="console"/>\r
+    </root>\r
+</log4j:configuration>\r
index 0eac9d76448de4d9f21786a050c62a045493b817..cc720f7ba690371e38a9f2d8d33ab2d1f4b061e0 100755 (executable)
@@ -57,7 +57,7 @@
         </dependency>
         <dependency>
             <groupId>org.opendaylight.groupbasedpolicy</groupId>
-            <artifactId>groupbasedpolicy</artifactId>
+            <artifactId>l2-l3-domain-extension</artifactId>
         </dependency>
 
         <!-- sxp deps -->