From: Michal Rehak Date: Thu, 21 Jul 2016 16:38:01 +0000 (+0200) Subject: BUG-6650: ep-sgt/ip, propose initial sxp-ep-provider X-Git-Tag: release/carbon~105 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=eace708ec9dd394c5eb7b74c46d1176d82e775e7;p=groupbasedpolicy.git BUG-6650: ep-sgt/ip, propose initial sxp-ep-provider Change-Id: I639435ab23048cf318f4b760a5c1b92ae2249a97 Signed-off-by: Michal Rehak (cherry picked from commit e97dcf9add5c5738035b28d970a7bb937be5f8c1) --- diff --git a/artifacts/pom.xml b/artifacts/pom.xml index 9cabf7095..3e66bcd5b 100755 --- a/artifacts/pom.xml +++ b/artifacts/pom.xml @@ -101,6 +101,11 @@ groupbasedpolicy-ise-adapter ${project.version} + + org.opendaylight.groupbasedpolicy + sxp-ep-provider + ${project.version} + diff --git a/pom.xml b/pom.xml index 83080309e..4966133f2 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,7 @@ features sxp-mapper groupbasedpolicy-ise-adapter + sxp-integration diff --git a/sxp-integration/pom.xml b/sxp-integration/pom.xml new file mode 100644 index 000000000..a3180a698 --- /dev/null +++ b/sxp-integration/pom.xml @@ -0,0 +1,61 @@ + + + + 4.0.0 + + + org.opendaylight.controller + config-parent + 0.6.0-SNAPSHOT + + + + org.opendaylight.groupbasedpolicy + sxp-integration + 0.5.0-SNAPSHOT + pom + + + 1.4.0-SNAPSHOT + + + + sxp-ep-provider + + + + + + + org.opendaylight.groupbasedpolicy + groupbasedpolicy-artifacts + ${project.version} + import + pom + + + + + org.opendaylight.sxp + sxp-api + ${sxp.version} + + + org.opendaylight.sxp + sxp-core + ${sxp.version} + + + + + + + org.opendaylight.groupbasedpolicy + groupbasedpolicy + + + diff --git a/sxp-integration/sxp-ep-provider/pom.xml b/sxp-integration/sxp-ep-provider/pom.xml new file mode 100755 index 000000000..9e04c8c97 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/pom.xml @@ -0,0 +1,84 @@ + + + + 4.0.0 + + org.opendaylight.groupbasedpolicy + sxp-integration + 0.5.0-SNAPSHOT + .. + + + sxp-ep-provider + bundle + sxp-integration_sxp-ep-provider + + + + + org.opendaylight.mdsal.model + ietf-inet-types-2013-07-15 + + + + org.opendaylight.mdsal.model + yang-ext + + + org.opendaylight.groupbasedpolicy + l2-l3-domain-extension + + + + + org.opendaylight.sxp + sxp-api + + + org.opendaylight.sxp + sxp-core + + + commons-net + commons-net + + + + + junit + junit + test + + + org.mockito + mockito-all + test + + + org.slf4j + slf4j-log4j12 + test + + + org.opendaylight.controller + sal-binding-broker-impl + test-jar + test + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + diff --git a/sxp-integration/sxp-ep-provider/src/main/config/default-config.xml b/sxp-integration/sxp-ep-provider/src/main/config/default-config.xml new file mode 100755 index 000000000..0f2d59bb8 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/config/default-config.xml @@ -0,0 +1,44 @@ + + + + + + + + + + sxp-mapper:sxp-mapper-impl + + sxp-mapper + + + binding:binding-async-data-broker + binding-data-broker + + + binding:binding-rpc-registry + binding-rpc-broker + + + + gbp:domain-specific-registry + + domain-specific-registry + + + + + + + + + urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:sxp-mapper?module=sxp-mapper-cfg&revision=2016-03-02 + + + diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModule.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModule.java new file mode 100644 index 000000000..56458dbd2 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModule.java @@ -0,0 +1,36 @@ +/* + * 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.groupbasedpolicy.sxp_integration.sxp_ep_provider; + +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpEpProviderProviderImpl; + +/** +* sxp-ep-provider impl module +*/ +public class SxpEpProviderProviderModule extends org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider.AbstractSxpEpProviderProviderModule { + public SxpEpProviderProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public SxpEpProviderProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider.SxpEpProviderProviderModule 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() { + return new SxpEpProviderProviderImpl(getDataBrokerDependency(), getRpcRegistryDependency(), + getDomainSpecificRegistryDependency()); + } + +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModuleFactory.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModuleFactory.java new file mode 100644 index 000000000..7e16cc469 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModuleFactory.java @@ -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 + */ + +/* +* Generated file +* +* Generated from: yang module name: sxp-ep-provider-cfg yang module local name: sxp-ep-provider-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Thu Jul 21 17:55:05 CEST 2016 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider; +public class SxpEpProviderProviderModuleFactory extends org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider.AbstractSxpEpProviderProviderModuleFactory { + +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/DSAsyncDao.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/DSAsyncDao.java new file mode 100644 index 000000000..c97a13477 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/DSAsyncDao.java @@ -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.groupbasedpolicy.sxp.ep.provider.impl; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.ListenableFuture; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; + +/** + * Purpose: encapsulate access to DS by exposing + *
+ *
read
+ *
search through values (either in local cache or directly in DataStore)
+ *
+ * + * @param data key type + * @param data type + */ +public interface DSAsyncDao { + + /** + * @param key for search + * @return value found by key + */ + ListenableFuture> read(@Nonnull K key); + +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/EPTemplateListener.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/EPTemplateListener.java new file mode 100644 index 000000000..c6183f056 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/EPTemplateListener.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapper; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Purpose: provide listener capability to EndPoint templates + */ +public interface EPTemplateListener extends ClusteredDataTreeChangeListener, AutoCloseable { + + InstanceIdentifier SXP_MAPPER_TEMPLATE_PARENT_PATH = InstanceIdentifier.create(SxpEpMapper.class); + + //NOBODY +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/IpPrefixEqualCommand.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/IpPrefixEqualCommand.java new file mode 100644 index 000000000..472a182d6 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/IpPrefixEqualCommand.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; + +/** + * Purpose: provide different strategies for {@link IpPrefix} comparison + */ +public interface IpPrefixEqualCommand { + + boolean isEqualTo(IpPrefix value); +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/MasterDatabaseBindingListener.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/MasterDatabaseBindingListener.java new file mode 100644 index 000000000..b278833ee --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/MasterDatabaseBindingListener.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener; +import org.opendaylight.sxp.core.Configuration; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +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.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +/** + * Purpose: provide listener capability to {@link MasterDatabaseBinding} (Sxp - MasterDB) + */ +public interface MasterDatabaseBindingListener extends ClusteredDataTreeChangeListener, AutoCloseable { + /** path to SXP topology */ + KeyedInstanceIdentifier SXP_TOPOLOGY_PATH = InstanceIdentifier.create(NetworkTopology.class) + .child(Topology.class, new TopologyKey(new TopologyId(Configuration.TOPOLOGY_NAME))); +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableAsyncByKey.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableAsyncByKey.java new file mode 100644 index 000000000..6ee943548 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableAsyncByKey.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import com.google.common.util.concurrent.ListenableFuture; +import java.util.Collection; +import javax.annotation.Nonnull; + +/** + * Purpose: simple asynchronous search interface allowing for custom key and returning list of values + * + * @param special key type + * @param value type + */ +public interface ReadableAsyncByKey { + + /** + * @param specialKey custom key to search by + * @return list of found values + */ + ListenableFuture> readBy(@Nonnull X specialKey); +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableByKey.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableByKey.java new file mode 100644 index 000000000..535754426 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableByKey.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import java.util.Collection; +import javax.annotation.Nonnull; + +/** + * Purpose: simple search interface allowing for custom key and returning list of values + * + * @param special key type + * @param value type + */ +public interface ReadableByKey { + + /** + * @param specialKey custom key to search by + * @return list of found values + */ + Collection readBy(@Nonnull X specialKey); +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleCachedDao.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleCachedDao.java new file mode 100644 index 000000000..913274bd3 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleCachedDao.java @@ -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.sxp.ep.provider.impl; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Purpose: encapsulate access to DS by exposing + *
+ *
find
+ *
search through cached values
+ *
update
+ *
stores given pair (key, value) to local cache
+ *
+ * + * @param data key type + * @param data type + */ +public interface SimpleCachedDao extends SimpleDao { + + /** + * store given pair to local cache + * + * @param key associated to value + * @param value associated to key + */ + V update(@Nonnull K key, @Nullable V value); + + /** + * invalidate all cache entries + */ + void invalidateCache(); + + /** + * @return true if there is nothing cached + */ + boolean isEmpty(); + + /** + * @return unmodifiable iterator through all cached values + */ + Iterable values(); +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleDao.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleDao.java new file mode 100644 index 000000000..1196930b8 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleDao.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import com.google.common.base.Optional; +import javax.annotation.Nonnull; + +/** + * Purpose: encapsulate access to DS by exposing + *
+ *
find
+ *
search through available values (e.g.: in local cache)
+ *
+ * + * @param data key type + * @param data type + */ +public interface SimpleDao { + + /** + * @param key for search + * @return value found by key + */ + Optional find(@Nonnull K key); + +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImpl.java new file mode 100644 index 000000000..8fd1f4796 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImpl.java @@ -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.sxp.ep.provider.impl; + +import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.Map.Entry; +import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKey; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKeyFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.ContainmentEndpointWithLocation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yangtools.yang.binding.Augmentation; + +public class SxpEndpointAugmentorImpl implements EndpointAugmentor { + + private final ReadableByKey epPolicyTemplateDao; + private final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory; + + public SxpEndpointAugmentorImpl(final ReadableByKey epPolicyTemplateDao, + final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory) { + this.epPolicyTemplateKeyFactory = Preconditions.checkNotNull(epPolicyTemplateKeyFactory, "epPolicyTemplateKeyFactory can not be null"); + this.epPolicyTemplateDao = Preconditions.checkNotNull(epPolicyTemplateDao, "epPolicyTemplateDao can not be null"); + } + + @Override + public Entry>, Augmentation> buildAddressEndpointAugmentation( + AddressEndpointReg input) { + return null; + } + + @Override + public Entry>, Augmentation> buildContainmentEndpointAugmentation( + ContainmentEndpointReg input) { + return null; + } + + @Override + public Entry>, Augmentation> buildAddressEndpointWithLocationAugmentation( + AddressEndpoint input) { + final EpPolicyTemplateValueKey templateValueKey = epPolicyTemplateKeyFactory.createKey( + input.getTenant(), input.getEndpointGroup(), input.getCondition()); + + final Collection epPolicyTemplates = epPolicyTemplateDao.readBy(templateValueKey); + final Entry>, Augmentation> entry; + + if (epPolicyTemplates.isEmpty()) { + entry = null; + } else { + //TODO: cover case when multiple templates found +// final Augmentation addressEndpointWithLocationAug = +// new AddressEndpointWithLocationAugBuilder() +// .setSgt(Iterables.getFirst(epPolicyTemplates, null).getSgt()) +// .build(); +// entry = new AbstractMap.SimpleEntry<>(AddressEndpointWithLocationAug.class, addressEndpointWithLocationAug); + } + + return null; //entry; + } + + @Override + public Entry>, Augmentation> buildContainmentEndpointWithLocationAugmentation( + ContainmentEndpoint input) { + return null; + } + +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEpProviderProviderImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEpProviderProviderImpl.java new file mode 100644 index 000000000..8e3896fb1 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEpProviderProviderImpl.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.groupbasedpolicy.api.DomainSpecificRegistry; +import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EPForwardingTemplateDaoImpl; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EPPolicyTemplateDaoImpl; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKeyFactory; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.MasterDatabaseBindingDaoImpl; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.SimpleCachedDaoEPForwardingTemplateImpl; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.SimpleCachedDaoImpl; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen.EPForwardingTemplateListenerImpl; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen.EPPolicyTemplateListenerImpl; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen.MasterDatabaseBindingListenerImpl; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * SxpMapper provider implementation. + */ +public class SxpEpProviderProviderImpl implements AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(SxpEpProviderProviderImpl.class); + + private final MasterDatabaseBindingListenerImpl sxpDatabaseListener; + private final SxpMapperReactor sxpMapperReactor; + private final EPTemplateListener epPolicyTemplateListener; + private final EPTemplateListener epForwardingTemplateListener; + private final DomainSpecificRegistry domainSpecificRegistry; + private final EndpointAugmentor sxpEndpointAugmentor; + + public SxpEpProviderProviderImpl(final DataBroker dataBroker, final RpcProviderRegistry rpcRegistryDependency, + final DomainSpecificRegistry domainSpecificRegistry) { + LOG.info("starting SxmMapper .."); + this.domainSpecificRegistry = domainSpecificRegistry; + + final BaseEndpointService endpointService = rpcRegistryDependency.getRpcService(BaseEndpointService.class); + sxpMapperReactor = new SxpMapperReactorImpl(endpointService, dataBroker); + + final SimpleCachedDao epPolicyTemplateCachedDao = new SimpleCachedDaoImpl<>(); + final SimpleCachedDao epForwardingTemplateCachedDao = + new SimpleCachedDaoEPForwardingTemplateImpl(); + final SimpleCachedDao masterDBBindingCachedDao = new SimpleCachedDaoImpl<>(); + + final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory = new EpPolicyTemplateValueKeyFactory( + EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering()); + final EPPolicyTemplateDaoImpl epPolicyTemplateDao = new EPPolicyTemplateDaoImpl(dataBroker, epPolicyTemplateCachedDao, epPolicyTemplateKeyFactory); + final EPForwardingTemplateDaoImpl epForwardingTemplateDao = new EPForwardingTemplateDaoImpl(dataBroker, + epForwardingTemplateCachedDao); + final MasterDatabaseBindingDaoImpl masterDBBindingDao = new MasterDatabaseBindingDaoImpl(dataBroker, masterDBBindingCachedDao); + + sxpDatabaseListener = new MasterDatabaseBindingListenerImpl(dataBroker, sxpMapperReactor, masterDBBindingCachedDao, + epPolicyTemplateDao, epForwardingTemplateDao); + epPolicyTemplateListener = new EPPolicyTemplateListenerImpl(dataBroker, sxpMapperReactor, epPolicyTemplateCachedDao, + masterDBBindingDao, epForwardingTemplateDao); + epForwardingTemplateListener = new EPForwardingTemplateListenerImpl(dataBroker, sxpMapperReactor, epForwardingTemplateCachedDao, + masterDBBindingDao, epPolicyTemplateDao); + sxpEndpointAugmentor = new SxpEndpointAugmentorImpl(epPolicyTemplateDao, epPolicyTemplateKeyFactory); + domainSpecificRegistry.getEndpointAugmentorRegistry().register(sxpEndpointAugmentor); + LOG.info("started SxmMapper"); + } + + @Override + public void close() throws Exception { + sxpDatabaseListener.close(); + epPolicyTemplateListener.close(); + epForwardingTemplateListener.close(); + domainSpecificRegistry.getEndpointAugmentorRegistry().unregister(sxpEndpointAugmentor); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactor.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactor.java new file mode 100644 index 000000000..8e5c46e59 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactor.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import com.google.common.util.concurrent.ListenableFuture; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yangtools.yang.common.RpcResult; + +/** + * Purpose: process given ip-sgt binding and EP-template in order to create L3-EP + */ +public interface SxpMapperReactor { + + /** + * apply sgt/ip binding on policy template and delegate to appropriate GBP service + * @param epPolicyTemplate policy template + * @param epForwardingTemplate forwarding template + * @param masterDatabaseBinding sxpMasterDB item + */ + ListenableFuture> processTemplatesAndSxpMasterDB(EndpointPolicyTemplateBySgt epPolicyTemplate, + EndpointForwardingTemplateBySubnet epForwardingTemplate, + MasterDatabaseBinding masterDatabaseBinding); +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImpl.java new file mode 100644 index 000000000..be9491691 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImpl.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.JdkFutureAdapters; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.Collections; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService; +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.RegisterEndpointInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder; +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.NetworkDomainContainmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints; +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.register.endpoint.input.AddressEndpointReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; +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.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: exclusively processes sxp master database changes and EGP templates changes + */ +public class SxpMapperReactorImpl implements SxpMapperReactor { + + private static final Logger LOG = LoggerFactory.getLogger(SxpMapperReactorImpl.class); + + private final BaseEndpointService l3EndpointService; + private final DataBroker dataBroker; + + public SxpMapperReactorImpl(final BaseEndpointService l3EndpointService, final DataBroker dataBroker) { + this.l3EndpointService = Preconditions.checkNotNull(l3EndpointService, "l3Endpoint service missing"); + this.dataBroker = Preconditions.checkNotNull(dataBroker, "dataBroker missing"); + } + + @Override + public ListenableFuture> processTemplatesAndSxpMasterDB( + final EndpointPolicyTemplateBySgt epPolicyTemplate, + final EndpointForwardingTemplateBySubnet epForwardingTemplate, + final MasterDatabaseBinding masterDBBinding) { + LOG.debug("processing ep-templates + sxpMasterDB entry: {} - {}", + masterDBBinding.getSecurityGroupTag(), masterDBBinding.getIpPrefix()); + // apply sxpMasterDB to policy template + final Ipv4Prefix address = new Ipv4Prefix(epForwardingTemplate.getIpPrefix().getIpv4Prefix().getValue()); + final NetworkContainment networkContainment = new NetworkContainmentBuilder() + .setContainment(new NetworkDomainContainmentBuilder() + .setNetworkDomainType(epForwardingTemplate.getNetworkContainment().getNetworkDomainType()) + .setNetworkDomainId(epForwardingTemplate.getNetworkContainment().getNetworkDomainId()) + .build()) + .build(); + final RegisterEndpointInput epInput = new RegisterEndpointInputBuilder().setAddressEndpointReg( + Collections.singletonList(new AddressEndpointRegBuilder().setAddressType(IpPrefixType.class) + .setAddress(address.getValue()) + .setContextType(L3Context.class) + .setContextId(epForwardingTemplate.getL3Context()) + .setNetworkContainment(networkContainment) + .setCondition(epPolicyTemplate.getConditions()) + .setTenant(epPolicyTemplate.getTenant()) + .setEndpointGroup(epPolicyTemplate.getEndpointGroups()) + .build())) + .build(); + epForwardingTemplate.getL3Context(); + + return chainL3EPServiceIfEpAbsent(epInput); + } + + private CheckedFuture, ReadFailedException> findExistingEndPoint(final ContextId containment, + final String address) { + KeyedInstanceIdentifier addressEndpointPath = + InstanceIdentifier.create(Endpoints.class).child(AddressEndpoints.class).child(AddressEndpoint.class, + new AddressEndpointKey(address, IpPrefixType.class, containment, L3Context.class)); + final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction(); + final CheckedFuture, ReadFailedException> read = rTx.read( + LogicalDatastoreType.OPERATIONAL, addressEndpointPath); + Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx)); + return read; + } + + private ListenableFuture> chainL3EPServiceIfEpAbsent(final RegisterEndpointInput epInput) { + AddressEndpointReg addressEndpoint = epInput.getAddressEndpointReg().get(0); + CheckedFuture, ReadFailedException> existingEndpointFuture = + findExistingEndPoint(addressEndpoint.getContextId(), addressEndpoint.getAddress()); + + return Futures.transform(existingEndpointFuture, new AsyncFunction, RpcResult>() { + @Override + public ListenableFuture> apply(final Optional input) throws Exception { + final ListenableFuture> nextResult; + if (input == null || !input.isPresent() || !isSameEpg(epInput, input.get())) { + // invoke service + return JdkFutureAdapters.listenInPoolThread(l3EndpointService.registerEndpoint(epInput)); + } else { + final String existingL3EpMsg = String.format("address-endpoint for given key already exists: %s | %s", + addressEndpoint.getContextId(), addressEndpoint.getAddress() ); + nextResult = Futures.immediateFailedFuture(new IllegalStateException(existingL3EpMsg)); + } + return nextResult; + } + }); + } + + private boolean isSameEpg(RegisterEndpointInput epInput, AddressEndpoint input) { + if (epInput == null || epInput.getAddressEndpointReg() == null || epInput.getAddressEndpointReg().isEmpty()) { + return true; + } + final AddressEndpointReg epInputAddressEndpoint = epInput.getAddressEndpointReg().get(0); + if (epInputAddressEndpoint.getEndpointGroup() == null || epInputAddressEndpoint.getEndpointGroup().isEmpty()) { + return true; + } + if (input == null || input.getEndpointGroup() == null || input.getEndpointGroup().isEmpty()) { + return true; + } + final EndpointGroupId addressEndpointGroupId = epInputAddressEndpoint.getEndpointGroup().get(0); + final EndpointGroupId existingEndpointGroupId = input.getEndpointGroup().get(0); + return addressEndpointGroupId.equals(existingEndpointGroupId); + } + +} + diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImpl.java new file mode 100644 index 000000000..31458ed0a --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapper; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Purpose: general dao for EndPoint templates + */ +public class EPForwardingTemplateDaoImpl implements DSAsyncDao { + + private static final ListenableFuture> READ_FUTURE_ABSENT = Futures.immediateFuture(Optional.absent()); + private final DataBroker dataBroker; + private final SimpleCachedDao cachedDao; + + public EPForwardingTemplateDaoImpl(final DataBroker dataBroker, + final SimpleCachedDao cachedDao) { + this.dataBroker = dataBroker; + this.cachedDao = cachedDao; + } + + @Override + public ListenableFuture> read(@Nonnull final IpPrefix key) { + final Optional value = lookup(cachedDao, key); + final ListenableFuture> readResult; + if (value.isPresent()) { + readResult = Futures.immediateFuture(value); + } else if (!cachedDao.isEmpty()) { + return READ_FUTURE_ABSENT; + } else { + final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction(); + final CheckedFuture, ReadFailedException> read = + rTx.read(LogicalDatastoreType.CONFIGURATION, buildReadPath(key)); + + Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx)); + + readResult = Futures.transform(read, new Function, Optional>() { + @Nullable + @Override + public Optional apply(@Nullable final Optional input) { + if (input.isPresent()) { + // clean cache + cachedDao.invalidateCache(); + + // iterate through all template entries and update cachedDao + final List templateLot = input.get().getEndpointForwardingTemplateBySubnet(); + if (templateLot != null) { + for (EndpointForwardingTemplateBySubnet template : templateLot) { + cachedDao.update(template.getIpPrefix(), template); + } + } + return lookup(cachedDao, key); + } else { + return Optional.absent(); + } + } + }); + } + return readResult; + } + + protected InstanceIdentifier buildReadPath(final IpPrefix key) { + return EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH; + } + + private Optional lookup(final SimpleCachedDao cachedDao, final IpPrefix key) { + return cachedDao.find(key); + } + +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImpl.java new file mode 100644 index 000000000..d53f13886 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImpl.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.ArrayList; +import java.util.Collection; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.ReadableByKey; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + + +/** + * Purpose: general dao for EndPoint templates + */ +public class EPPolicyTemplateDaoImpl implements DSAsyncDao, + ReadableByKey { + + private static final ListenableFuture> READ_FUTURE_ABSENT = Futures.immediateFuture(Optional.absent()); + + private final DataBroker dataBroker; + private final SimpleCachedDao cachedDao; + private final EpPolicyTemplateValueKeyFactory keyFactory; + + public EPPolicyTemplateDaoImpl(final DataBroker dataBroker, + final SimpleCachedDao cachedDao, + final EpPolicyTemplateValueKeyFactory keyFactory) { + this.dataBroker = dataBroker; + this.cachedDao = cachedDao; + this.keyFactory = keyFactory; + } + + @Override + public ListenableFuture> read(@Nonnull final Sgt key) { + final Optional cachedEndpointPolicyTemplateBySgtalue = lookup(cachedDao, key); + if (cachedEndpointPolicyTemplateBySgtalue.isPresent()) { + return Futures.immediateFuture(cachedEndpointPolicyTemplateBySgtalue); + } else if (!cachedDao.isEmpty()) { + return READ_FUTURE_ABSENT; + } else { + final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction(); + final CheckedFuture, ReadFailedException> read = + rTx.read(LogicalDatastoreType.CONFIGURATION, buildReadPath(key)); + + Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx)); + + return Futures.transform(read, new Function, Optional>() { + @Nullable + @Override + public Optional apply(@Nullable final Optional input) { + if (input.isPresent()) { + cachedDao.update(key, keyFactory.sortValueKeyLists(input.get())); + } + return input; + } + }); + } + } + + protected InstanceIdentifier buildReadPath(final Sgt key) { + return EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH + .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(key)); + } + + private Optional lookup(final SimpleCachedDao cachedDao, final Sgt key) { + return cachedDao.find(key); + } + + @Override + public Collection readBy(@Nonnull final EpPolicyTemplateValueKey specialKey) { + final Predicate templateValuePredicate = Predicates.equalTo(specialKey); + final Collection foundTemplates = new ArrayList<>(); + + for (EndpointPolicyTemplateBySgt epPolicyTemplate : cachedDao.values()) { + final EpPolicyTemplateValueKey templateValueKey = keyFactory.createKeyWithDefaultOrdering(epPolicyTemplate); + if (templateValuePredicate.apply(templateValueKey)) { + foundTemplates.add(epPolicyTemplate); + } + } + + return foundTemplates; + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKey.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKey.java new file mode 100644 index 000000000..83ee7939c --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKey.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import java.util.List; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; + +/** + * Purpose: composite key holcer for {@link EndpointPolicyTemplateBySgt} + */ +public class EpPolicyTemplateValueKey { + + private final TenantId tenantId; + private final List epgId; + private final List conditionName; + + public EpPolicyTemplateValueKey(final TenantId tenantId, final List epgId, final List conditionName) { + this.tenantId = tenantId; + this.epgId = epgId; + this.conditionName = conditionName; + } + + public EpPolicyTemplateValueKey(AddressEndpointWithLocation endpoint) { + this(endpoint.getTenant(), endpoint.getEndpointGroup(), endpoint.getCondition()); + } + + public TenantId getTenantId() { + return tenantId; + } + + public List getEpgId() { + return epgId; + } + + public List getConditionName() { + return conditionName; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final EpPolicyTemplateValueKey that = (EpPolicyTemplateValueKey) o; + + if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false; + if (epgId != null ? !epgId.equals(that.epgId) : that.epgId != null) return false; + return conditionName != null ? conditionName.equals(that.conditionName) : that.conditionName == null; + + } + + @Override + public int hashCode() { + return tenantId != null ? tenantId.hashCode() : 0; + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKeyFactory.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKeyFactory.java new file mode 100644 index 000000000..58190d461 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKeyFactory.java @@ -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.sxp.ep.provider.impl.dao; + +import com.google.common.collect.Ordering; +import java.util.Collections; +import java.util.List; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; + +/** + * Purpose: create cache keys with ordered lists inside + */ +public class EpPolicyTemplateValueKeyFactory { + private final Ordering epgIdOrdering; + private final Ordering conditionOrdering; + + public EpPolicyTemplateValueKeyFactory(final Ordering epgIdOrdering, + final Ordering conditionOrdering) { + this.epgIdOrdering = epgIdOrdering; + this.conditionOrdering = conditionOrdering; + } + + public EndpointPolicyTemplateBySgt sortValueKeyLists(final EndpointPolicyTemplateBySgt template) { + if (template.getEndpointGroups() != null) { + Collections.sort(template.getEndpointGroups(), epgIdOrdering); + } + if (template.getConditions() != null) { + Collections.sort(template.getConditions(), conditionOrdering); + } + return template; + } + + public EpPolicyTemplateValueKey createKeyWithDefaultOrdering(final EndpointPolicyTemplateBySgt newSource) { + return new EpPolicyTemplateValueKey( + newSource.getTenant(), newSource.getEndpointGroups(), newSource.getConditions()); + } + + public EpPolicyTemplateValueKey sortValueKeyLists(final EpPolicyTemplateValueKey existingKey) { + Collections.sort(existingKey.getEpgId(), epgIdOrdering); + if (existingKey.getConditionName() != null) { + Collections.sort(existingKey.getConditionName(), conditionOrdering); + } + return existingKey; + } + + public EpPolicyTemplateValueKey createKey(final TenantId tenant, final List endpointGroup, + final List condition) { + return sortValueKeyLists(new EpPolicyTemplateValueKey(tenant, endpointGroup, condition)); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImpl.java new file mode 100644 index 000000000..ebf16d3e0 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImpl.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.MasterDatabaseBindingListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.ReadableAsyncByKey; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.MasterDatabaseFields; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpDatabasesFields; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: general dao for EndPoint templates + */ +public class MasterDatabaseBindingDaoImpl implements DSAsyncDao, + ReadableAsyncByKey { + + private static final Logger LOG = LoggerFactory.getLogger(MasterDatabaseBindingDaoImpl.class); + private static final ListenableFuture> READ_FUTURE_ABSENT = Futures.immediateFuture(Optional.absent()); + + private final DataBroker dataBroker; + private final SimpleCachedDao cachedDao; + + public MasterDatabaseBindingDaoImpl(final DataBroker dataBroker, + final SimpleCachedDao cachedDao) { + this.dataBroker = dataBroker; + this.cachedDao = cachedDao; + } + + @Override + public ListenableFuture> read(@Nonnull final IpPrefix key) { + final Optional cachedMasterDatabaseBinding = lookup(cachedDao, key); + if (cachedMasterDatabaseBinding.isPresent()) { + return Futures.immediateFuture(cachedMasterDatabaseBinding); + } else if (!cachedDao.isEmpty()) { + return READ_FUTURE_ABSENT; + } else { + final ListenableFuture cacheUpdatedFt = updateCache(); + + return Futures.transform(cacheUpdatedFt, new Function>() { + @Nullable + @Override + public Optional apply(@Nullable final Void input) { + return lookup(cachedDao, key); + } + }); + } + } + + private ListenableFuture updateCache() { + final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction(); + final CheckedFuture, ReadFailedException> read = + rTx.read(LogicalDatastoreType.CONFIGURATION, buildReadPath(null)); + + Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx)); + + return Futures.transform(read, new Function, Void>() { + @Nullable + @Override + public Void apply(@Nullable final Optional input) { + if (input.isPresent()) { + // clean cache + cachedDao.invalidateCache(); + + for (Node node : input.get().getNode()) { + java.util.Optional.ofNullable(node.getAugmentation(SxpNodeIdentity.class)) + .map(SxpNodeIdentity::getSxpDomains) + .map(SxpDomains::getSxpDomain) + .ifPresent((sxpDomain) -> { + final List masterDBBindings = sxpDomain.stream() + .map(SxpDatabasesFields::getMasterDatabase) + .filter(masterDb -> masterDb != null) + .map(MasterDatabaseFields::getMasterDatabaseBinding) + .filter(binding -> binding != null) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + + for (MasterDatabaseBinding masterDBItem : masterDBBindings) { + // update all + final MasterDatabaseBinding + previousValue = + cachedDao.update(masterDBItem.getIpPrefix(), masterDBItem); + if (previousValue != null) { + LOG.warn("updated key already obtained: [node:{}, sgt:{}]", + node.getNodeId().getValue(), masterDBItem.getSecurityGroupTag()); + } + } + }); + } + } else { + LOG.warn("failed to update cache of SxpMasterDB - no data"); + } + return null; + } + }); + } + + private InstanceIdentifier buildReadPath(final Sgt key) { + return MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH; + } + + private Optional lookup(final SimpleCachedDao cachedDao, final IpPrefix key) { + return cachedDao.find(key); + } + + @Override + public ListenableFuture> readBy(@Nonnull final Sgt specialKey) { + final ListenableFuture cacheUpdatedFt; + if (!cachedDao.isEmpty()) { + cacheUpdatedFt = Futures.immediateFuture(null); + } else { + cacheUpdatedFt = updateCache(); + } + + return Futures.transform(cacheUpdatedFt, new Function>() { + @Nullable + @Override + public Collection apply(@Nullable final Void input) { + final Collection foundGroups = new ArrayList<>(); + + for (MasterDatabaseBinding masterDBItem : cachedDao.values()) { + if (masterDBItem.getSecurityGroupTag().equals(specialKey)) { + foundGroups.add(masterDBItem); + } + } + return foundGroups; + } + }); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java new file mode 100644 index 000000000..e04aa1a8c --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Pattern; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.apache.commons.net.util.SubnetUtils; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SubnetInfoKeyDecorator; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; + +/** + * Purpose: generic implementation of {@link SimpleCachedDao} + */ +public class SimpleCachedDaoEPForwardingTemplateImpl implements SimpleCachedDao { + + private final ConcurrentMap plainCache; + private final ConcurrentMap subnetCache; + private final Pattern IP_MASK_EATER_RE = Pattern.compile("/[0-9]+"); + + public SimpleCachedDaoEPForwardingTemplateImpl() { + plainCache = new ConcurrentHashMap<>(); + subnetCache = new ConcurrentHashMap<>(); + } + + @Override + public EndpointForwardingTemplateBySubnet update(@Nonnull final IpPrefix key, @Nullable final EndpointForwardingTemplateBySubnet value) { + final EndpointForwardingTemplateBySubnet previousValue; + if (EPTemplateUtil.isPlain(key)) { + previousValue = updatePlainCache(key, value); + } else { + previousValue = updateSubnetCache(key, value); + } + + return previousValue; + } + + private EndpointForwardingTemplateBySubnet updateSubnetCache(final IpPrefix key, final EndpointForwardingTemplateBySubnet value) { + final EndpointForwardingTemplateBySubnet previousValue; + final SubnetInfoKeyDecorator subnetKey = EPTemplateUtil.buildSubnetInfoKey(key); + if (value != null) { + previousValue = subnetCache.put(subnetKey, value); + } else { + previousValue = subnetCache.remove(subnetKey); + } + return previousValue; + } + + private EndpointForwardingTemplateBySubnet updatePlainCache(final @Nonnull IpPrefix key, final @Nullable EndpointForwardingTemplateBySubnet value) { + final EndpointForwardingTemplateBySubnet previousValue; + if (value != null) { + previousValue = plainCache.put(key, value); + } else { + previousValue = plainCache.remove(key); + } + return previousValue; + } + + @Override + public Optional find(@Nonnull final IpPrefix key) { + final Optional template; + if (EPTemplateUtil.isPlain(key)) { + final Optional fastPlain = Optional.fromNullable(plainCache.get(key)); + if (fastPlain.isPresent()) { + template = fastPlain; + } else { + template = lookupSlowSubnet(key.getIpv4Prefix().getValue()); + } + } else { + final SubnetInfoKeyDecorator keyDecorator = EPTemplateUtil.buildSubnetInfoKey(key); + final Optional fastSubnet = + Optional.fromNullable(subnetCache.get(keyDecorator)); + if (fastSubnet.isPresent()) { + template = fastSubnet; + } else { + template = Optional.absent(); + } + } + return template; + } + + private Optional lookupSlowSubnet(final String value) { + final String plainIp = IP_MASK_EATER_RE.matcher(value).replaceFirst(""); + EndpointForwardingTemplateBySubnet valueCandidate = null; + int addressCount = 0; + for (Map.Entry entry : subnetCache.entrySet()) { + final SubnetUtils.SubnetInfo subnetInfo = entry.getKey().getDelegate(); + if (subnetInfo.isInRange(plainIp)) { + final int addressCountTmp = subnetInfo.getAddressCount(); + if (valueCandidate == null || addressCount > addressCountTmp) { + valueCandidate = entry.getValue(); + addressCount = addressCountTmp; + } + } + } + return Optional.fromNullable(valueCandidate); + } + + @Override + public void invalidateCache() { + plainCache.clear(); + subnetCache.clear(); + } + + @Override + public boolean isEmpty() { + return plainCache.isEmpty() && subnetCache.isEmpty(); + } + + @Override + public Iterable values() { + return Iterables.unmodifiableIterable(Iterables.concat(plainCache.values(), subnetCache.values())); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImpl.java new file mode 100644 index 000000000..a6c162971 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImpl.java @@ -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.sxp.ep.provider.impl.dao; + +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.yangtools.yang.binding.DataObject; + +/** + * Purpose: generic implementation of {@link SimpleCachedDao} + */ +public class SimpleCachedDaoImpl implements SimpleCachedDao { + + private final ConcurrentMap cache; + + public SimpleCachedDaoImpl() { + cache = new ConcurrentHashMap<>(); + } + + @Override + public V update(@Nonnull final K key, @Nullable final V value) { + final V previousValue; + if (value != null) { + previousValue = cache.put(key, value); + } else { + previousValue = cache.remove(key); + } + + return previousValue; + } + + @Override + public Optional find(@Nonnull final K key) { + return Optional.fromNullable(cache.get(key)); + } + + @Override + public void invalidateCache() { + cache.clear(); + } + + @Override + public boolean isEmpty() { + return cache.isEmpty(); + } + + @Override + public Iterable values() { + return Iterables.unmodifiableIterable(cache.values()); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImpl.java new file mode 100644 index 000000000..4b89303fa --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImpl.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen; + +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.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.Collection; +import javax.annotation.Nonnull; +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +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.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.L3EPServiceUtil; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: listens to EP forwarding template and propagates change events for further processing + */ +public class EPForwardingTemplateListenerImpl implements EPTemplateListener { + + private static final Logger LOG = LoggerFactory.getLogger(EPForwardingTemplateListenerImpl.class); + + public static final FutureCallback> ANY_RPC_FUTURE_CALLBACK = + L3EPServiceUtil.createFailureLoggingCallback("failed to read epForwardingTemplate"); + + private final SxpMapperReactor sxpMapperReactor; + private final SimpleCachedDao templateCachedDao; + private final DSAsyncDao masterDBBindingDao; + private final ListenerRegistration listenerRegistration; + private final InstanceIdentifier templatePath; + private final DSAsyncDao epPolicyTemplateDao; + + public EPForwardingTemplateListenerImpl(final DataBroker dataBroker, + final SxpMapperReactor sxpMapperReactor, + final SimpleCachedDao templateCachedDao, + final DSAsyncDao masterDBBindingDao, + final DSAsyncDao epPolicyTemplateDao) { + this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor); + this.templateCachedDao = Preconditions.checkNotNull(templateCachedDao); + this.masterDBBindingDao = Preconditions.checkNotNull(masterDBBindingDao); + this.epPolicyTemplateDao = Preconditions.checkNotNull(epPolicyTemplateDao); + templatePath = EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH.child(EndpointForwardingTemplateBySubnet.class); + + final DataTreeIdentifier dataTreeIdentifier = new DataTreeIdentifier<>( + LogicalDatastoreType.CONFIGURATION, templatePath); + listenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIdentifier, this); + LOG.debug("started listening to {}", templatePath); + } + + @Override + public void onDataTreeChanged(@Nonnull final Collection> collection) { + for (DataTreeModification change : collection) { + LOG.trace("received modification: {} -> {}", change.getRootPath(), change.getRootNode().getModificationType()); + // update cached dao + final InstanceIdentifier changePath = change.getRootPath().getRootIdentifier(); + final IpPrefix changeKey = changePath.firstKeyOf(EndpointForwardingTemplateBySubnet.class).getIpPrefix(); + SxpListenerUtil.updateCachedDao(templateCachedDao, changeKey, change); + + final EndpointForwardingTemplateBySubnet epForwardingTemplate = change.getRootNode().getDataAfter(); + processWithEPTemplates(epForwardingTemplate); + } + } + + private void processWithEPTemplates(final EndpointForwardingTemplateBySubnet epForwardingTemplate) { + final ListenableFuture> sxpMasterDbItemRead = + masterDBBindingDao.read(epForwardingTemplate.getIpPrefix()); + + // find all available epForwardingTemplates and pair those to sxpMasterDBBinding + final ListenableFuture>> searchResult = + Futures.transform(sxpMasterDbItemRead, createReadAndPairTemplateToBindingFunction(epForwardingTemplate)); + + // invoke sxpMapperReactor.process for every valid combination of sxpMasterDBBinding, epPolicyTemplate, epForwardingTemplate + final ListenableFuture> rpcResult = + Futures.transform(searchResult, createProcessAllFunction(epForwardingTemplate)); + + Futures.addCallback(rpcResult, ANY_RPC_FUTURE_CALLBACK); + } + + private AsyncFunction>, RpcResult> + createProcessAllFunction(final EndpointForwardingTemplateBySubnet epForwardingTemplate) { + return new AsyncFunction>, RpcResult>() { + @Override + public ListenableFuture> + apply(final Optional> input) throws Exception { + final ListenableFuture> result; + if (input == null || !input.isPresent()) { + LOG.debug("no epPolicyTemplate available for ip-prefix: {}", epForwardingTemplate.getIpPrefix()); + result = Futures.immediateFuture( + RpcResultBuilder.failed() + .withError(RpcError.ErrorType.APPLICATION, + "no epForwardingTemplate available for ip-prefix " + epForwardingTemplate.getIpPrefix()) + .build()); + } else { + LOG.trace("processing epForwardingTemplate event for ip-prefix: {}", epForwardingTemplate.getIpPrefix()); + final Pair pair = input.get(); + final MasterDatabaseBinding sxpMasterDBBinding = pair.getLeft(); + final EndpointPolicyTemplateBySgt epPolicyTemplate = pair.getRight(); + LOG.trace("processing epForwardingTemplate event with resolved sxpMasterDb entry and " + + "epPolicyTemplate for sgt/ip-prefix: {}/{}", + sxpMasterDBBinding.getSecurityGroupTag(), sxpMasterDBBinding.getImplementedInterface()); + result = sxpMapperReactor.processTemplatesAndSxpMasterDB(epPolicyTemplate, epForwardingTemplate, sxpMasterDBBinding); + } + + return result; + } + }; + } + + private AsyncFunction, Optional>> + createReadAndPairTemplateToBindingFunction(final EndpointForwardingTemplateBySubnet epFowardingTemplate) { + return new AsyncFunction, Optional>>() { + @Override + public ListenableFuture>> + apply(final Optional input) throws Exception { + final ListenableFuture> result; + if (input == null || !input.isPresent()) { + LOG.debug("no sxpMasterDB entry available for ip-prefix: {}", epFowardingTemplate.getIpPrefix()); + result = Futures.immediateFuture(null); + } else { + LOG.trace("processing sxpMasterDB entry for ip-prefix: {}", epFowardingTemplate.getIpPrefix()); + final MasterDatabaseBinding masterDBItem = input.get(); + final ListenableFuture> epPolicyTemplateRead = + epPolicyTemplateDao.read(masterDBItem.getSecurityGroupTag()); + result = EPTemplateUtil.wrapToPair(masterDBItem, epPolicyTemplateRead); + } + + return EPTemplateUtil.wrapToOptional(result); + } + }; + } + + + @Override + public void close() throws Exception { + LOG.debug("closing listener registration to {}", templatePath); + listenerRegistration.close(); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImpl.java new file mode 100644 index 000000000..a31d4acf0 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImpl.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen; + +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.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nonnull; +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +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.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.ReadableAsyncByKey; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.L3EPServiceUtil; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: listens to EP policy template and propagates change events for further processing + */ +public class EPPolicyTemplateListenerImpl implements EPTemplateListener { + + private static final Logger LOG = LoggerFactory.getLogger(EPPolicyTemplateListenerImpl.class); + + private static final FutureCallback>> RPC_RESULT_FUTURE_CALLBACK = + L3EPServiceUtil.createFailureLoggingCallback("failed to apply epPolicyTemplate"); + + private final ListenerRegistration listenerRegistration; + private final InstanceIdentifier templatePath; + private final SxpMapperReactor sxpMapperReactor; + private final SimpleCachedDao templateCachedDao; + private final ReadableAsyncByKey masterDBBindingDao; + private final DSAsyncDao epForwardingTemplateDao; + + public EPPolicyTemplateListenerImpl(final DataBroker dataBroker, + final SxpMapperReactor sxpMapperReactor, + final SimpleCachedDao templateCachedDao, + final ReadableAsyncByKey masterDBBindingDao, + final DSAsyncDao epForwardingTemplateDao) { + this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor); + this.templateCachedDao = Preconditions.checkNotNull(templateCachedDao); + this.masterDBBindingDao = Preconditions.checkNotNull(masterDBBindingDao); + this.epForwardingTemplateDao = Preconditions.checkNotNull(epForwardingTemplateDao); + templatePath = EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH.child(EndpointPolicyTemplateBySgt.class); + + final DataTreeIdentifier dataTreeIdentifier = new DataTreeIdentifier<>( + LogicalDatastoreType.CONFIGURATION, templatePath); + listenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIdentifier, this); + LOG.debug("started listening to {}", templatePath); + } + + @Override + public void onDataTreeChanged(@Nonnull final Collection> collection) { + for (DataTreeModification change : collection) { + LOG.trace("received modification: {} -> {}", change.getRootPath(), change.getRootNode().getModificationType()); + + // update cached dao + final InstanceIdentifier changePath = change.getRootPath().getRootIdentifier(); + final Sgt changeKey = changePath.firstKeyOf(EndpointPolicyTemplateBySgt.class).getSgt(); + SxpListenerUtil.updateCachedDao(templateCachedDao, changeKey, change); + + final EndpointPolicyTemplateBySgt epPolicyTemplate = change.getRootNode().getDataAfter(); + processWithEPTemplates(epPolicyTemplate); + } + } + + private void processWithEPTemplates(final EndpointPolicyTemplateBySgt epPolicyTemplate) { + final ListenableFuture> sxpMasterDbItemsRead = + masterDBBindingDao.readBy(epPolicyTemplate.getSgt()); + + // find all available epForwardingTemplates and pair those to sxpMasterDBBinding + final ListenableFuture>> epForwardingTemplatesRead = + Futures.transform(sxpMasterDbItemsRead, createReadAndPairTemplateToBindingFunction(epPolicyTemplate)); + + // invoke sxpMapperReactor.process for every valid combination of sxpMasterDBBinding, epPolicyTemplate, epForwardingTemplate + final ListenableFuture>> rpcResult = + Futures.transform(epForwardingTemplatesRead, createProcessAllFunction(epPolicyTemplate)); + + Futures.addCallback(rpcResult, RPC_RESULT_FUTURE_CALLBACK); + } + + private AsyncFunction>, List>> + createProcessAllFunction(final EndpointPolicyTemplateBySgt epPolicyTemplate) { + return new AsyncFunction>, List>>() { + @Override + public ListenableFuture>> + apply(final List> input) throws Exception { + final ListenableFuture>> result; + if (input == null || input.isEmpty()) { + LOG.debug("no epForwardingTemplate available for sgt: {}", epPolicyTemplate.getSgt()); + result = Futures.immediateFuture(Collections.singletonList( + RpcResultBuilder.failed() + .withError(RpcError.ErrorType.APPLICATION, + "no epForwardingTemplate available for sgt " + epPolicyTemplate.getSgt()) + .build())); + } else { + LOG.trace("processing epPolicyTemplate event for sgt: {}", epPolicyTemplate.getSgt()); + List>> allResults = new ArrayList<>(input.size()); + for (Pair pair : input) { + final MasterDatabaseBinding sxpMasterDBBinding = pair.getLeft(); + final EndpointForwardingTemplateBySubnet epForwardingTemplate = pair.getRight(); + if (epForwardingTemplate != null) { + LOG.trace("processing epPolicyTemplate event with resolved sxpMasterDb entry and " + + "epForwardingTemplate for sgt/ip-prefix: {}/{}", + sxpMasterDBBinding.getSecurityGroupTag(), sxpMasterDBBinding.getImplementedInterface()); + allResults.add(sxpMapperReactor.processTemplatesAndSxpMasterDB( + epPolicyTemplate, epForwardingTemplate, sxpMasterDBBinding)); + } + } + result = Futures.successfulAsList(allResults); + } + + return result; + } +}; + } + + private AsyncFunction, List>> + createReadAndPairTemplateToBindingFunction(final EndpointPolicyTemplateBySgt epPolicyTemplate) { + return new AsyncFunction, List>>() { + @Override + public ListenableFuture>> + apply(final Collection input) throws Exception { + final ListenableFuture>> result; + if (input == null || input.isEmpty()) { + LOG.debug("no sxpMasterDB entry available for sgt: {}", epPolicyTemplate.getSgt()); + result = Futures.immediateFuture(Collections.emptyList()); + } else { + LOG.trace("processing sxpMasterDB entries for sgt: {}", epPolicyTemplate.getSgt()); + List>> allResults = + new ArrayList<>(input.size()); + for (MasterDatabaseBinding masterDBItem : input) { + final ListenableFuture> epForwardingTemplateRead = + epForwardingTemplateDao.read(masterDBItem.getIpPrefix()); + allResults.add(EPTemplateUtil.wrapToPair(masterDBItem, epForwardingTemplateRead)); + } + result = Futures.successfulAsList(allResults); + } + + return result; + } + }; + } + + @Override + public void close() throws Exception { + LOG.debug("closing listener registration to {}", templatePath); + listenerRegistration.close(); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImpl.java new file mode 100644 index 000000000..9e65b3bb6 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImpl.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen; + +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.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +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.ClusteredDataTreeChangeListener; +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.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.MasterDatabaseBindingListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.L3EPServiceUtil; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * listens to sxp master database and propagates change events for further processing + */ +public class MasterDatabaseBindingListenerImpl implements MasterDatabaseBindingListener { + + private static final Logger LOG = LoggerFactory.getLogger(MasterDatabaseBindingListenerImpl.class); + + private static final FutureCallback> RPC_POLICY_RESULT_FUTURE_CALLBACK = + L3EPServiceUtil.createFailureLoggingCallback("failed to read epPolicyTemplate"); + + public static final FutureCallback> RPC_FW_RESULT_FUTURE_CALLBACK = + L3EPServiceUtil.createFailureLoggingCallback("failed to read epForwardingTemplate"); + + private final SxpMapperReactor sxpMapperReactor; + private final SimpleCachedDao masterDBBindingDaoCached; + private final DSAsyncDao epPolicyTemplateDao; + private final DSAsyncDao epForwardingTemplateDao; + + private final ListenerRegistration listenerRegistration; + private final InstanceIdentifier sxpDbPath; + + public MasterDatabaseBindingListenerImpl(final DataBroker dataBroker, + final SxpMapperReactor sxpMapperReactor, + final SimpleCachedDao masterDBBindingDaoCached, + final DSAsyncDao epPolicyTemplateDao, + final DSAsyncDao epForwardingTemplateDao) { + this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor); + this.masterDBBindingDaoCached = Preconditions.checkNotNull(masterDBBindingDaoCached); + this.epPolicyTemplateDao = Preconditions.checkNotNull(epPolicyTemplateDao); + this.epForwardingTemplateDao = Preconditions.checkNotNull(epForwardingTemplateDao); + + //TODO: get exact sxp-node path from config (pointing to ise listener).. start listening later - when config appears + sxpDbPath = MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH + .child(Node.class) + .augmentation(SxpNodeIdentity.class) + .child(SxpDomains.class) + .child(SxpDomain.class) + .child(MasterDatabase.class) + .child(MasterDatabaseBinding.class); + + final DataTreeIdentifier dataTreeIdentifier = new DataTreeIdentifier<>( + LogicalDatastoreType.OPERATIONAL, sxpDbPath); + listenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIdentifier, this); + LOG.debug("started listening to {}", sxpDbPath); + } + + @Override + public void onDataTreeChanged(@Nonnull final Collection> collection) { + for (DataTreeModification change : collection) { + LOG.trace("received modification: {} -> {}", change.getRootPath(), change.getRootNode().getModificationType()); + // update cached dao + final MasterDatabaseBinding sxpMasterDBItem = change.getRootNode().getDataAfter(); + if (sxpMasterDBItem == null) { + //TODO: cover sgt-ip mapping removal + LOG.debug("ip-sgt mapping was removed - NOOP: {}", + change.getRootPath().getRootIdentifier().firstKeyOf(MasterDatabaseBinding.class)); + } else { + final IpPrefix ipPrefixKey = sxpMasterDBItem.getIpPrefix(); + SxpListenerUtil.updateCachedDao(masterDBBindingDaoCached, ipPrefixKey, change); + processWithEPTemplates(sxpMasterDBItem); + } + } + } + + private void processWithEPTemplates(final MasterDatabaseBinding sxpMasterDBItem) { + final ListenableFuture> epPolicyTemplateFuture = + epPolicyTemplateDao.read(sxpMasterDBItem.getSecurityGroupTag()); + + final ListenableFuture> epForwardingTemplateFuture = + epForwardingTemplateDao.read(sxpMasterDBItem.getIpPrefix()); + + final ListenableFuture> compositeRead + = EPTemplateUtil.compositeRead(epPolicyTemplateFuture, epForwardingTemplateFuture); + + final ListenableFuture> rpcResult = Futures.transform(compositeRead, + new AsyncFunction, RpcResult>() { + @Override + public ListenableFuture> apply(final EPTemplateUtil.OptionalMutablePair input) throws Exception { + final ListenableFuture> result; + if (input == null) { + LOG.debug("no ep*Templates available for sgt/ip-prefix: {}/{}", + sxpMasterDBItem.getSecurityGroupTag(), + sxpMasterDBItem.getIpPrefix()); + result = RpcResultBuilder.failed() + .withError(RpcError.ErrorType.APPLICATION, + "no ep-templates available for" + sxpMasterDBItem) + .buildFuture(); + + } else if (!input.getLeft().isPresent()) { + LOG.debug("no epPolicyTemplate available for sgt: {}", sxpMasterDBItem.getSecurityGroupTag()); + result = RpcResultBuilder.failed() + .withError(RpcError.ErrorType.APPLICATION, + "no epPolicyTemplate available for " + sxpMasterDBItem) + .buildFuture(); + } else if (!input.getRight().isPresent()) { + LOG.debug("no epForwardingTemplate available for ip-prefix: {}", + sxpMasterDBItem.getIpPrefix()); + result = RpcResultBuilder.failed() + .withError(RpcError.ErrorType.APPLICATION, + "no epForwardingTemplate available for " + sxpMasterDBItem) + .buildFuture(); + } else { + LOG.trace("processing sxpMasterDB event and epPolicyTemplate for sgt/ip-prefix: {}/{}", + sxpMasterDBItem.getSecurityGroupTag(), + sxpMasterDBItem.getIpPrefix()); + result = sxpMapperReactor.processTemplatesAndSxpMasterDB(input.getLeft().get(), + input.getRight().get(), sxpMasterDBItem); + } + return result; + } + }); + + Futures.addCallback(rpcResult, RPC_POLICY_RESULT_FUTURE_CALLBACK); + } + + @Override + public void close() throws Exception { + LOG.debug("closing listener registration to {}", sxpDbPath); + listenerRegistration.close(); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtil.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtil.java new file mode 100644 index 000000000..f7ea75576 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtil.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util; + +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.base.Optional; +import com.google.common.collect.Ordering; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.net.util.SubnetUtils; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; + +/** + * Purpose: util methods for {@link EndpointForwardingTemplateBySubnet} and {@link EndpointPolicyTemplateBySgt} + */ +public final class EPTemplateUtil { + + public static final String FULL_IPV4_MASK_SUFFIX = "/32"; + private static final Comparable EMPTY_COMPARABLE = ""; + + private EPTemplateUtil() { + throw new IllegalAccessError("constructing util class"); + } + + public static boolean isPlain(final IpPrefix key) { + return key.getIpv4Prefix().getValue().endsWith(FULL_IPV4_MASK_SUFFIX); + } + + public static SubnetInfoKeyDecorator buildSubnetInfoKey(@Nonnull final IpPrefix value) { + return new SubnetInfoKeyDecorator(new SubnetUtils(value.getIpv4Prefix().getValue()).getInfo()); + } + + public static ListenableFuture> compositeRead( + final ListenableFuture> leftRead, final ListenableFuture> rightRead) { + + final OptionalMutablePair compositeResult = new OptionalMutablePair<>(); + final List> results = new ArrayList<>(2); + + results.add(Futures.transform(leftRead, new Function, OptionalMutablePair>() { + @Nullable + @Override + public OptionalMutablePair apply(@Nullable final Optional input) { + compositeResult.setLeft(input); + return compositeResult; + } + })); + + results.add(Futures.transform(rightRead, new Function, OptionalMutablePair>() { + @Nullable + @Override + public OptionalMutablePair apply(@Nullable final Optional input) { + compositeResult.setRight(input); + return compositeResult; + } + })); + + return Futures.transform(Futures.successfulAsList(results), + new Function, OptionalMutablePair>() { + @Nullable + @Override + public OptionalMutablePair apply(@Nullable final List input) { + return compositeResult; + } + }); + } + + public static ListenableFuture> wrapToPair( + final K keyItem, + final ListenableFuture> valueFromRead) { + return Futures.transform(valueFromRead, new Function, Pair>() { + @Nullable + @Override + public Pair apply(@Nullable final Optional input) { + return new MutablePair<>(keyItem, input.orNull()); + } + }); + } + + public static ListenableFuture> wrapToOptional(final ListenableFuture value) { + return Futures.transform(value, new Function>() { + @Nullable + @Override + public Optional apply(@Nullable final V input) { + return Optional.fromNullable(input); + } + }); + } + + public static Ordering createEndpointGroupIdOrdering() { + return Ordering.natural().onResultOf(new Function() { + @Nullable + @Override + public Comparable apply(@Nullable final EndpointGroupId input) { + if (input == null) { + return EMPTY_COMPARABLE; + } + return MoreObjects.firstNonNull(input.getValue(), EMPTY_COMPARABLE); + } + }); + } + + public static Ordering createConditionNameOrdering() { + return Ordering.natural().onResultOf(new Function() { + @Nullable + @Override + public Comparable apply(@Nullable final ConditionName input) { + if (input == null) { + return EMPTY_COMPARABLE; + } + return MoreObjects.firstNonNull(input.getValue(), EMPTY_COMPARABLE); + } + }); + } + + public static class OptionalMutablePair extends MutablePair, Optional> { + public OptionalMutablePair() { + super(Optional.absent(), Optional.absent()); + } + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandDirectImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandDirectImpl.java new file mode 100644 index 000000000..e5fe29ab9 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandDirectImpl.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util; + +import javax.annotation.Nonnull; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.IpPrefixEqualCommand; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; + +/** + * Purpose: provide simple equal using direct invocation of {@link Object#equals(Object)} method + */ +public class IpPrefixEqualCommandDirectImpl implements IpPrefixEqualCommand { + private final IpPrefix myValue; + + public IpPrefixEqualCommandDirectImpl(@Nonnull final IpPrefix myValue) { + this.myValue = myValue; + } + + @Override + public boolean isEqualTo(final IpPrefix value) { + return myValue.equals(value); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandSubnetImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandSubnetImpl.java new file mode 100644 index 000000000..673abe8a1 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandSubnetImpl.java @@ -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.groupbasedpolicy.sxp.ep.provider.impl.util; + +import javax.annotation.Nonnull; +import org.apache.commons.net.util.SubnetUtils; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.IpPrefixEqualCommand; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; + +/** + * Purpose: provide equal using {@link SubnetUtils.SubnetInfo#isInRange(String)} method + */ +public class IpPrefixEqualCommandSubnetImpl implements IpPrefixEqualCommand { + private final SubnetUtils.SubnetInfo myValue; + + public IpPrefixEqualCommandSubnetImpl(@Nonnull final IpPrefix myValue) { + this.myValue = new SubnetUtils(stripToCidr(myValue)).getInfo(); + } + + @Override + public boolean isEqualTo(final IpPrefix value) { + return myValue.isInRange(stripToCidr(value)); + } + + private String stripToCidr(final IpPrefix value) { + return value.getIpv4Prefix().getValue(); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/L3EPServiceUtil.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/L3EPServiceUtil.java new file mode 100644 index 000000000..3d26c6f26 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/L3EPServiceUtil.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util; + +import com.google.common.util.concurrent.FutureCallback; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: place for common functionality regarding endpoint tasks + */ +public final class L3EPServiceUtil { + + private static final Logger LOG = LoggerFactory.getLogger(L3EPServiceUtil.class); + + private L3EPServiceUtil() { + throw new IllegalAccessError("constructing util class"); + } + + public static FutureCallback createFailureLoggingCallback(final String failMessage) { + return new FutureCallback() { + @Override + public void onSuccess(@Nullable final O result) { + // NOOP + } + + @Override + public void onFailure(final Throwable t) { + LOG.warn(failMessage, t); + } + }; + } + +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SubnetInfoKeyDecorator.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SubnetInfoKeyDecorator.java new file mode 100644 index 000000000..b0c4c6be7 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SubnetInfoKeyDecorator.java @@ -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.groupbasedpolicy.sxp.ep.provider.impl.util; + +import org.apache.commons.net.util.SubnetUtils; + +/** + * Purpose: wraps {@link SubnetUtils.SubnetInfo} and overwrites hashcode and equals methods in order to + * be applicable as map key + * + */ +public class SubnetInfoKeyDecorator { + + private final SubnetUtils.SubnetInfo delegate; + + public SubnetInfoKeyDecorator(final SubnetUtils.SubnetInfo delegate) { + this.delegate = delegate; + } + + public SubnetUtils.SubnetInfo getDelegate() { + return delegate; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final SubnetInfoKeyDecorator that = (SubnetInfoKeyDecorator) o; + + return delegate.getCidrSignature().equals(that.delegate.getCidrSignature()); + + } + + @Override + public int hashCode() { + return delegate.getCidrSignature().hashCode(); + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SxpListenerUtil.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SxpListenerUtil.java new file mode 100644 index 000000000..15128c344 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SxpListenerUtil.java @@ -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 + */ +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.FutureCallback; +import javax.annotation.Nullable; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.yangtools.yang.binding.DataObject; + +/** + * Purpose: provide general logic used by listeners + */ +public final class SxpListenerUtil { + + private SxpListenerUtil() { + throw new IllegalAccessError("constructing util class"); + } + + + public static void updateCachedDao(final SimpleCachedDao valueCachedDao, + final K key, + final DataTreeModification change) { + final V value = change.getRootNode().getDataAfter(); + valueCachedDao.update(key, value); + } + + public static FutureCallback> createTxCloseCallback(final ReadOnlyTransaction rTx) { + return new FutureCallback>() { + @Override + public void onSuccess(@Nullable final Optional result) { + rTx.close(); + } + + @Override + public void onFailure(final Throwable t) { + rTx.close(); + } + }; + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-cfg.yang b/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-cfg.yang new file mode 100644 index 000000000..ea5ebbbd7 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-cfg.yang @@ -0,0 +1,69 @@ +/* + * 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 sxp-ep-provider-cfg { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:sxp-integration:sxp-ep-provider"; + prefix "sxp-ep-prvd-cfg"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; } + import groupbasedpolicy-cfg {prefix gbpcfg; revision-date 2015-11-06; } + + description + "This module contains the base YANG definitions for + sxf-integration : sxp-ep-provider impl configuration."; + + revision "2016-07-22" { + description + "Initial revision."; + } + + identity sxp-ep-provider-impl { + description + "sxp-ep-provider impl module"; + + base "config:module-type"; + config:java-name-prefix SxpEpProviderProvider; + } + + // Augments the 'configuration' choice node under modules/module. + augment "/config:modules/config:module/config:configuration" { + case sxp-ep-provider-impl { + when "/config:modules/config:module/config:type = 'sxp-ep-provider-impl'"; + + //wires in the data-broker service + container data-broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity mdsal:binding-async-data-broker; + } + } + } + //RPC Registry + container rpc-registry { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity mdsal:binding-rpc-registry; + } + } + } + //Domain specific registry + container domain-specific-registry { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity gbpcfg:domain-specific-registry; + } + } + } + } + } +} diff --git a/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-model.yang b/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-model.yang new file mode 100644 index 000000000..0391eb0fc --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-model.yang @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module sxp-ep-provider-model { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:sxp-ep-provider:model"; + prefix "sxp-ep-prvd-model"; + + import sxp-database { prefix sxp-database; revision-date 2016-03-08; } + import gbp-common { prefix gbp-common; revision-date 2014-04-21; } + import ietf-inet-types { prefix inet; revision-date 2013-07-15; } + import forwarding { prefix forwarding; revision-date 2016-04-27; } + import base-endpoint { prefix base-edpoint; revision-date 2016-04-27; } + import yang-ext { prefix ext; revision-date 2013-07-09; } + import renderer { prefix renderer; revision-date 2015-11-03; } + + description + "This module contains the YANG definitions for + sxp-ep-provider implementation."; + + revision "2016-03-02" { + description + "Initial revision."; + } + + container sxp-ep-mapper { + description "root point for endpoint templates"; + + list endpoint-policy-template-by-sgt { + key sgt; + leaf sgt { + type sxp-database:sgt; + description + "SGT for which this endpoint template is used"; + } + leaf tenant { + type gbp-common:tenant-id; + mandatory true; + description + "The tenant of this endpoint"; + } + leaf-list endpoint-groups { + type gbp-common:endpoint-group-id; + min-elements 1; + description + "The groups associated with this endpoint"; + } + leaf-list conditions { + type gbp-common:condition-name; + description + "The conditions associated with this endpoint"; + } + } + + list endpoint-forwarding-template-by-subnet { + description "If the IP from IP/SGT binding is inside of ip-prefix then + the endpoint will be in the l3-context."; + key ip-prefix; + leaf ip-prefix { + type inet:ip-prefix; + description + "The IP prefix where an endpoint can be connected."; + } + leaf l3-context { + type gbp-common:context-id; + mandatory true; + description + "The context for the endpoint's layer 3 address"; + } + container network-containment { + description + "The network domain associated with this endpoint's fowarding + context."; + uses forwarding:network-domain-key; + } + } + } +} diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImplTest.java new file mode 100644 index 000000000..cf6c8ec96 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImplTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKey; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKeyFactory; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yangtools.yang.binding.Augmentation; + +/** + * Test for {@link SxpEndpointAugmentorImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class SxpEndpointAugmentorImplTest { + + @Mock + private ReadableByKey epPolicyDao; + @Spy + private EpPolicyTemplateValueKeyFactory keyFactory = new EpPolicyTemplateValueKeyFactory( + EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering()); + @Captor + private ArgumentCaptor keyCapt; + + private SxpEndpointAugmentorImpl augmetor; + + @Before + public void setUp() throws Exception { + augmetor = new SxpEndpointAugmentorImpl(epPolicyDao, keyFactory); + } + + @Test + public void testBuildAddressEndpointWithLocationAugmentation() throws Exception { + final TenantId tenantId = new TenantId("tn1"); + final AddressEndpoint endpoint = new AddressEndpointBuilder() + .setTenant(tenantId) + .setCondition(buildConditions(new String[]{"cn2", "cn1"})) + .setEndpointGroup(buildEndpointGroupIds(new String[]{"epg2", "epg1"})) + .build(); + + Mockito.doCallRealMethod().when(keyFactory).sortValueKeyLists(Matchers.any()); + final List conditions = buildConditions(new String[]{"cn1", "cn2"}); + final List endpointGroupIds = buildEndpointGroupIds(new String[]{"epg1", "epg2"}); + final EndpointPolicyTemplateBySgt epPolicyTemplate = new EndpointPolicyTemplateBySgtBuilder() + .setTenant(tenantId) + .setEndpointGroups(endpointGroupIds) + .setConditions(conditions) + .setSgt(new Sgt(42)) + .build(); + + Mockito.when(epPolicyDao.readBy(keyCapt.capture())).thenReturn(Collections.singletonList(epPolicyTemplate)); + + final Map.Entry>, Augmentation> + augmentationEntry = augmetor.buildAddressEndpointWithLocationAugmentation(endpoint); + +// Assert.assertEquals(AddressEndpointWithLocationAug.class, augmentationEntry.getKey()); +// Assert.assertTrue(DataObject.class.isAssignableFrom(augmentationEntry.getValue().getClass())); +// Assert.assertEquals(AddressEndpointWithLocationAug.class, ((DataObject) augmentationEntry.getValue()).getImplementedInterface()); +// Assert.assertEquals(42, ((AddressEndpointWithLocationAug) augmentationEntry.getValue()).getSgt().getValue().intValue()); + + final EpPolicyTemplateValueKey keyValue = keyCapt.getValue(); + Assert.assertEquals(tenantId, keyValue.getTenantId()); + Assert.assertEquals(endpointGroupIds, keyValue.getEpgId()); + Assert.assertEquals(conditions, keyValue.getConditionName()); + } + + private static List buildEndpointGroupIds(final String[] names) { + final List endpointGroupIds = new ArrayList<>(); + for (String epgId : names) { + endpointGroupIds.add(new EndpointGroupId(epgId)); + } + return endpointGroupIds; + } + + private static List buildConditions(final String[] names) { + final List conditions = new ArrayList<>(); + for (String condition : names) { + conditions.add(new ConditionName(condition)); + } + return conditions; + } + + @Test + public void testBuildAddressEndpointAugmentation() throws Exception { + final AddressEndpointReg endpoint = new AddressEndpointRegBuilder().build(); + Assert.assertNull(augmetor.buildAddressEndpointAugmentation(endpoint)); + } + + @Test + public void testBuildContainmentEndpointAugmentation() throws Exception { + final ContainmentEndpointReg endpoint = new ContainmentEndpointRegBuilder().build(); + Assert.assertNull(augmetor.buildContainmentEndpointAugmentation(endpoint)); + } + + @Test + public void testBuildContainmentEndpointWithLocationAugmentation() throws Exception { + final ContainmentEndpoint endpoint = new ContainmentEndpointBuilder().build(); + Assert.assertNull(augmetor.buildContainmentEndpointWithLocationAugmentation(endpoint)); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImplTest.java new file mode 100644 index 000000000..777bfd667 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImplTest.java @@ -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.sxp.ep.provider.impl; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.Futures; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService; +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.endpoints.address.endpoints.AddressEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.endpoint.forwarding.template.by.subnet.NetworkContainment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +/** + * Test for {@link SxpMapperReactorImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class SxpMapperReactorImplTest { + + private static final IpPrefix IP_PREFIX = new IpPrefix(new Ipv4Prefix("10.11.12.1/32")); + + @Mock + private BaseEndpointService l3EndpointService; + @Mock + private EndpointPolicyTemplateBySgt epPolicyTemplate; + @Mock + private MasterDatabaseBinding masterDBBinding; + @Mock + private EndpointForwardingTemplateBySubnet epForwardingTemplate; + @Mock + private NetworkContainment networkContainment; + @Mock + private DataBroker dataBroker; + @Mock + private ReadOnlyTransaction rTx; + + private SxpMapperReactorImpl sxpMapperReactor; + + @Before + public void setUp() throws Exception { + sxpMapperReactor = new SxpMapperReactorImpl(l3EndpointService, dataBroker); + Mockito.when(l3EndpointService.registerEndpoint(Matchers.any())) + .thenReturn(RpcResultBuilder.success().buildFuture()); + Mockito.when(masterDBBinding.getIpPrefix()).thenReturn(IP_PREFIX); + Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx); + Mockito.when(rTx.read(Matchers.same(LogicalDatastoreType.OPERATIONAL), + Matchers.>any())).thenReturn(Futures.immediateCheckedFuture(Optional.absent())); + Mockito.when(epForwardingTemplate.getNetworkContainment()).thenReturn(networkContainment); + } + + @After + public void tearDown() throws Exception { + Mockito.verifyNoMoreInteractions(l3EndpointService); + } + + @Test + public void testProcessTemplatesAndSxpMasterDB() throws Exception { + Mockito.when(epForwardingTemplate.getIpPrefix()).thenReturn(IP_PREFIX); + sxpMapperReactor.processTemplatesAndSxpMasterDB(epPolicyTemplate, epForwardingTemplate, masterDBBinding); + Mockito.verify(l3EndpointService).registerEndpoint(Matchers.any()); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImplTest.java new file mode 100644 index 000000000..6b9e9b236 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImplTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.base.Optional; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +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.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapper; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapperBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Test for {@link EPForwardingTemplateDaoImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class EPForwardingTemplateDaoImplTest { + + public static final InstanceIdentifier SXP_MAPPER_PATH = InstanceIdentifier.create(SxpEpMapper.class); + private static final IpPrefix KEY_1 = new IpPrefix(new Ipv4Prefix("1.2.3.4/32")); + private final SxpEpMapper SXP_MAPPER_VALUE; + private final EndpointForwardingTemplateBySubnet EP_FW_TEMPLATE_VALUE; + + @Mock + private DataBroker dataBroker; + @Mock + private SimpleCachedDao cachedDao; + @Mock + private ReadOnlyTransaction rTx; + + private EPForwardingTemplateDaoImpl dao; + + public EPForwardingTemplateDaoImplTest() { + EP_FW_TEMPLATE_VALUE = new EndpointForwardingTemplateBySubnetBuilder() + .setIpPrefix(KEY_1) + .build(); + SXP_MAPPER_VALUE = new SxpEpMapperBuilder() + .setEndpointForwardingTemplateBySubnet(Lists.newArrayList(EP_FW_TEMPLATE_VALUE)) + .build(); + } + + @Before + public void setUp() throws Exception { + dao = new EPForwardingTemplateDaoImpl(dataBroker, cachedDao); + } + + @Test + public void testRead_absent() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn(Optional.absent()); + Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx); + Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), + Matchers.>any())).thenReturn( + Futures., ReadFailedException>immediateCheckedFuture(Optional.absent())); + + + final ListenableFuture> read = dao.read(KEY_1); + Assert.assertTrue(read.isDone()); + Assert.assertFalse(read.get().isPresent()); + } + + @Test + public void testRead_presentCached() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn(Optional.of(EP_FW_TEMPLATE_VALUE)); + + final ListenableFuture> read = dao.read(KEY_1); + Assert.assertTrue(read.isDone()); + Assert.assertTrue(read.get().isPresent()); + Assert.assertEquals(KEY_1, read.get().get().getIpPrefix()); + } + + @Test + public void testRead_presentDS() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn( + Optional.absent(), + Optional.of(EP_FW_TEMPLATE_VALUE)); + Mockito.when(cachedDao.isEmpty()).thenReturn(true, false); + Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx); + Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), + Matchers.>any())).thenReturn( + Futures., ReadFailedException>immediateCheckedFuture(Optional.of(SXP_MAPPER_VALUE))); + + final ListenableFuture> read = dao.read(KEY_1); + Assert.assertTrue(read.isDone()); + Assert.assertTrue(read.get().isPresent()); + Assert.assertEquals(KEY_1, read.get().get().getIpPrefix()); + + final InOrder inOrder = Mockito.inOrder(cachedDao); + inOrder.verify(cachedDao).invalidateCache(); + inOrder.verify(cachedDao).update(KEY_1, EP_FW_TEMPLATE_VALUE); + inOrder.verify(cachedDao).find(KEY_1); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testBuildReadPath() throws Exception { + final InstanceIdentifier readPath = dao.buildReadPath(KEY_1); + Assert.assertEquals(SXP_MAPPER_PATH, readPath); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImplTest.java new file mode 100644 index 000000000..5edeea110 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImplTest.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InOrder; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapper; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +/** + * Test for {@link EPPolicyTemplateDaoImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class EPPolicyTemplateDaoImplTest { + + private static final Sgt KEY_1 = new Sgt(1); + private final EndpointPolicyTemplateBySgt EP_POLICY_TEMPLATE_VALUE; + @Mock + private DataBroker dataBroker; + @Mock + private SimpleCachedDao cachedDao; + @Mock + private ReadOnlyTransaction rTx; + @Spy + private EpPolicyTemplateValueKeyFactory keyFactory = new EpPolicyTemplateValueKeyFactory( + EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering()); + @Captor + ArgumentCaptor sgtCapt; + @Captor + ArgumentCaptor epPolicyTemplateCapt; + + private EPPolicyTemplateDaoImpl dao; + + public EPPolicyTemplateDaoImplTest() { + EP_POLICY_TEMPLATE_VALUE = new EndpointPolicyTemplateBySgtBuilder() + .setSgt(KEY_1) + .build(); + } + + @Before + public void setUp() throws Exception { + dao = new EPPolicyTemplateDaoImpl(dataBroker, cachedDao, keyFactory); + } + + @Test + public void testRead_absent() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn(Optional.absent()); + Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx); + Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), + Matchers.>any())).thenReturn( + Futures., ReadFailedException>immediateCheckedFuture( + Optional.absent())); + + + final ListenableFuture> read = dao.read(KEY_1); + Assert.assertTrue(read.isDone()); + Assert.assertFalse(read.get().isPresent()); + } + + @Test + public void testRead_presentCached() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn(Optional.of(EP_POLICY_TEMPLATE_VALUE)); + + final ListenableFuture> read = dao.read(KEY_1); + Assert.assertTrue(read.isDone()); + Assert.assertTrue(read.get().isPresent()); + Assert.assertEquals(KEY_1, read.get().get().getSgt()); + } + + @Test + public void testRead_presentDS() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn( + Optional.absent()); + Mockito.when(cachedDao.isEmpty()).thenReturn(true); + Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx); + Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), + Matchers.>any())).thenReturn( + Futures., ReadFailedException>immediateCheckedFuture( + Optional.of(EP_POLICY_TEMPLATE_VALUE))); + Mockito.doCallRealMethod().when(keyFactory).sortValueKeyLists(Matchers.any()); + + final ListenableFuture> read = dao.read(KEY_1); + Assert.assertTrue(read.isDone()); + Assert.assertTrue(read.get().isPresent()); + Assert.assertEquals(KEY_1, read.get().get().getSgt()); + + final InOrder inOrder = Mockito.inOrder(cachedDao); + inOrder.verify(cachedDao).update(KEY_1, EP_POLICY_TEMPLATE_VALUE); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testBuildReadPath() throws Exception { + final KeyedInstanceIdentifier expectedPath = + InstanceIdentifier.create(SxpEpMapper.class) + .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(KEY_1)); + + final InstanceIdentifier readPath = dao.buildReadPath(KEY_1); + Assert.assertEquals(expectedPath, readPath); + } + + @Test + public void testReadBy_single() throws Exception { + final EpPolicyTemplateValueKey key = new EpPolicyTemplateValueKey(new TenantId("tn1"), + buildEndpointGroupIds(new String[]{"epg1", "epg2"}), + buildConditions(new String[]{"cn1", "cn2"})); + + Mockito.doCallRealMethod().when(keyFactory).createKeyWithDefaultOrdering(Matchers.any()); + + Mockito.when(cachedDao.values()).thenReturn(Lists.newArrayList( + createEpPolicytemplate(new Sgt(1), new String[]{"cn2", "cn1"}, new String[]{"epg1", "epg2"}, "tn1"), + createEpPolicytemplate(new Sgt(2), new String[]{"cn1", "cn2"}, new String[]{"epg2", "epg1"}, "tn1"), + createEpPolicytemplate(new Sgt(3), new String[]{"cn2", "cn1"}, new String[]{"epg2", "epg1"}, "tn1"), + createEpPolicytemplate(new Sgt(4), new String[]{"cn1", "cn2"}, new String[]{"epg1", "epg2"}, "tn1") + )); + + final Collection policyTemplates = dao.readBy(key); + Assert.assertEquals(1, policyTemplates.size()); + Assert.assertEquals(4, Iterables.getFirst(policyTemplates, null).getSgt().getValue().intValue()); + } + + @Test + public void testRead_unsortedLists() throws Exception { + final EndpointPolicyTemplateBySgt epPolicytemplateUnsorted = createEpPolicytemplate(new Sgt(1), + new String[]{"cn2", "cn1"}, new String[]{"epg2", "epg1"}, "tn1"); + + Mockito.doCallRealMethod().when(keyFactory).createKeyWithDefaultOrdering(Matchers.any()); + + Mockito.when(cachedDao.find(Matchers.any())).thenReturn( + Optional.absent()); + Mockito.when(cachedDao.isEmpty()).thenReturn(true); + Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx); + + Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), + Matchers.>any())).thenReturn( + Futures., ReadFailedException>immediateCheckedFuture( + Optional.of(epPolicytemplateUnsorted))); + + dao.read(new Sgt(1)); + + Mockito.verify(cachedDao).update(sgtCapt.capture(), epPolicyTemplateCapt.capture()); + Mockito.verify(cachedDao).find(sgtCapt.capture()); + + Assert.assertEquals(1, sgtCapt.getValue().getValue().intValue()); + final EndpointPolicyTemplateBySgt template = epPolicyTemplateCapt.getValue(); + Assert.assertEquals(1, template.getSgt().getValue().intValue()); + Assert.assertEquals("tn1", template.getTenant().getValue()); + Assert.assertEquals(buildEndpointGroupIds(new String[]{"epg1", "epg2"}), template.getEndpointGroups()); + Assert.assertEquals(buildConditions(new String[]{"cn1", "cn2"}), template.getConditions()); + } + + + private EndpointPolicyTemplateBySgt createEpPolicytemplate(final Sgt sgt, final String[] conditionNames, + final String[] epgIds, final String tenant) { + return new EndpointPolicyTemplateBySgtBuilder() + .setSgt(sgt) + .setEndpointGroups(buildEndpointGroupIds(epgIds)) + .setConditions(buildConditions(conditionNames)) + .setTenant(new TenantId(tenant)) + .build(); + } + + private static List buildEndpointGroupIds(final String[] names) { + final List endpointGroupIds = new ArrayList<>(); + for (String epgId : names) { + endpointGroupIds.add(new EndpointGroupId(epgId)); + } + return endpointGroupIds; + } + + private static List buildConditions(final String[] names) { + final List conditions = new ArrayList<>(); + for (String condition : names) { + conditions.add(new ConditionName(condition)); + } + return conditions; + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImplTest.java new file mode 100644 index 000000000..d54936769 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImplTest.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.base.Optional; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.Collection; +import java.util.Collections; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +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.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.sxp.core.Configuration; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentityBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomainsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabaseBuilder; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; +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.topology.NodeBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Test for {@link MasterDatabaseBindingDaoImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class MasterDatabaseBindingDaoImplTest { + + private static final Sgt KEY_1 = new Sgt(1); + private static final IpPrefix IP_PREFIX = new IpPrefix(new Ipv4Prefix("1.2.3.4/32")); + private final Topology TOPOLOGY_VALUE; + private final MasterDatabaseBinding MASTER_DB_BINDING_VALUE; + + @Mock + private DataBroker dataBroker; + @Mock + private SimpleCachedDao cachedDao; + @Mock + private ReadOnlyTransaction rTx; + + private MasterDatabaseBindingDaoImpl dao; + + public MasterDatabaseBindingDaoImplTest() { + MASTER_DB_BINDING_VALUE = new MasterDatabaseBindingBuilder() + .setSecurityGroupTag(KEY_1) + .setIpPrefix(IP_PREFIX) + .build(); + + TOPOLOGY_VALUE = new TopologyBuilder() + .setTopologyId(new TopologyId(Configuration.TOPOLOGY_NAME)) + .setNode(Lists.newArrayList(new NodeBuilder() + .setNodeId(new NodeId("utNodeId")) + .addAugmentation(SxpNodeIdentity.class, new SxpNodeIdentityBuilder() + .setSxpDomains(new SxpDomainsBuilder() + .setSxpDomain(Collections.singletonList(new SxpDomainBuilder() + .setDomainName("global") + .setMasterDatabase(new MasterDatabaseBuilder() + .setMasterDatabaseBinding(Lists.newArrayList(MASTER_DB_BINDING_VALUE)) + .build()) + .build())) + .build()) + .build()) + .build())) + .build(); + } + + + @Before + public void setUp() throws Exception { + dao = new MasterDatabaseBindingDaoImpl(dataBroker, cachedDao); + } + + @Test + public void testRead_absent() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn(Optional.absent()); + Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx); + Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), + Matchers.>any())).thenReturn( + Futures., ReadFailedException>immediateCheckedFuture( + Optional.absent())); + + + final ListenableFuture> read = dao.read(IP_PREFIX); + Assert.assertTrue(read.isDone()); + Assert.assertFalse(read.get().isPresent()); + } + + @Test + public void testRead_presentCached() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn(Optional.of(MASTER_DB_BINDING_VALUE)); + + final ListenableFuture> read = dao.read(IP_PREFIX); + Assert.assertTrue(read.isDone()); + Assert.assertTrue(read.get().isPresent()); + Assert.assertEquals(KEY_1, read.get().get().getSecurityGroupTag()); + } + + @Test + public void testRead_presentDS() throws Exception { + Mockito.when(cachedDao.find(Matchers.any())).thenReturn( + Optional.absent(), + Optional.of(MASTER_DB_BINDING_VALUE)); + Mockito.when(cachedDao.isEmpty()).thenReturn(true); + Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx); + Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), + Matchers.>any())).thenReturn( + Futures., ReadFailedException>immediateCheckedFuture( + Optional.of(TOPOLOGY_VALUE))); + + final ListenableFuture> read = dao.read(IP_PREFIX); + Assert.assertTrue(read.isDone()); + Assert.assertTrue(read.get().isPresent()); + Assert.assertEquals(KEY_1, read.get().get().getSecurityGroupTag()); + + final InOrder inOrder = Mockito.inOrder(cachedDao); + inOrder.verify(cachedDao).invalidateCache(); + inOrder.verify(cachedDao).update(IP_PREFIX, MASTER_DB_BINDING_VALUE); + inOrder.verify(cachedDao).find(IP_PREFIX); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testReadBy() throws Exception { + Mockito.when(cachedDao.isEmpty()).thenReturn(false); + Mockito.when(cachedDao.values()).thenReturn(Collections.singleton(MASTER_DB_BINDING_VALUE)); + + final ListenableFuture> readByFt = dao.readBy(KEY_1); + Assert.assertTrue(readByFt.isDone()); + Assert.assertEquals(1, readByFt.get().size()); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java new file mode 100644 index 000000000..7aa545820 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.collect.Iterables; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder; + +/** + * Test for {@link SimpleCachedDaoEPForwardingTemplateImpl}. + */ +public class SimpleCachedDaoEPForwardingTemplateImplTest { + + private static final IpPrefix IP_PREFIX_1 = buildIpPrefix("1.2.3.0/24"); + + + private static final IpPrefix IP_PREFIX_2 = buildIpPrefix("1.2.3.4/32"); + + private SimpleCachedDaoEPForwardingTemplateImpl dao; + + @Before + public void setUp() throws Exception { + dao = new SimpleCachedDaoEPForwardingTemplateImpl(); + Assert.assertTrue(dao.isEmpty()); + } + + @Test + public void testUpdate() throws Exception { + dao.update(IP_PREFIX_1, buildValue(IP_PREFIX_1)); + dao.update(IP_PREFIX_2, buildValue(IP_PREFIX_2)); + + Assert.assertEquals(2, Iterables.size(dao.values())); + } + + private EndpointForwardingTemplateBySubnet buildValue(final IpPrefix ipPrefix) { + return new EndpointForwardingTemplateBySubnetBuilder() + .setIpPrefix(ipPrefix) + .build(); + } + + @Test + public void testFind() throws Exception { + final EndpointForwardingTemplateBySubnet value1 = buildValue(IP_PREFIX_1); + final EndpointForwardingTemplateBySubnet value2 = buildValue(IP_PREFIX_2); + dao.update(IP_PREFIX_1, value1); + dao.update(IP_PREFIX_2, value2); + Assert.assertFalse(dao.isEmpty()); + + Assert.assertTrue(dao.find(IP_PREFIX_1).isPresent()); + Assert.assertEquals(value1, dao.find(IP_PREFIX_1).get()); + Assert.assertTrue(dao.find(IP_PREFIX_2).isPresent()); + Assert.assertEquals(value2, dao.find(IP_PREFIX_2).get()); + + final IpPrefix key = buildIpPrefix("1.2.3.1/32"); + Assert.assertTrue(dao.find(key).isPresent()); + Assert.assertEquals(value1, dao.find(key).get()); + } + + private static IpPrefix buildIpPrefix(final String ipv4PrefixValue) { + return new IpPrefix(new Ipv4Prefix(ipv4PrefixValue)); + } + + @Test + public void testInvalidateCache() throws Exception { + dao.update(IP_PREFIX_1, buildValue(IP_PREFIX_1)); + dao.update(IP_PREFIX_2, buildValue(IP_PREFIX_2)); + + Assert.assertEquals(2, Iterables.size(dao.values())); + dao.invalidateCache(); + Assert.assertTrue(dao.isEmpty()); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImplTest.java new file mode 100644 index 000000000..80ca2794d --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImplTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao; + +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.yangtools.yang.binding.DataContainer; +import org.opendaylight.yangtools.yang.binding.DataObject; + +/** + * Test for {@link SimpleCachedDaoImpl}. + */ +public class SimpleCachedDaoImplTest { + + private static final String KEY_1 = "dummyKey1"; + private static final String KEY_2 = "dummyKey2"; + private static final DummyDataObject DUMMY_DATA_1 = new DummyDataObject("dummyData1"); + private static final DummyDataObject DUMMY_DATA_2 = new DummyDataObject("dummyData2"); + + private SimpleCachedDaoImpl dao; + + @Before + public void setUp() throws Exception { + dao = new SimpleCachedDaoImpl<>(); + Assert.assertFalse(dao.find(KEY_1).isPresent()); + } + + @Test + public void testUpdate() throws Exception { + dao.update(KEY_1, DUMMY_DATA_1); + final Optional dataOpt = dao.find(KEY_1); + Assert.assertTrue(dataOpt.isPresent()); + Assert.assertEquals(DUMMY_DATA_1.getDummyData(), dataOpt.get().getDummyData()); + } + + @Test + public void testInvalidateCache() throws Exception { + dao.update(KEY_1, DUMMY_DATA_1); + Assert.assertTrue(dao.find(KEY_1).isPresent()); + dao.invalidateCache(); + Assert.assertFalse(dao.find(KEY_1).isPresent()); + } + + @Test + public void testIsEmpty() throws Exception { + Assert.assertTrue(dao.isEmpty()); + dao.update(KEY_1, DUMMY_DATA_1); + Assert.assertFalse(dao.isEmpty()); + } + + @Test + public void testValues() throws Exception { + Assert.assertEquals(0, Iterables.size(dao.values())); + dao.update(KEY_1, DUMMY_DATA_1); + dao.update(KEY_1, DUMMY_DATA_2); + Assert.assertEquals(1, Iterables.size(dao.values())); + + dao.update(KEY_2, DUMMY_DATA_2); + Assert.assertEquals(2, Iterables.size(dao.values())); + } + + private static final class DummyDataObject implements DataObject { + private final String dummyData; + + public DummyDataObject(final String dummyData) { + this.dummyData = dummyData; + } + + public String getDummyData() { + return dummyData; + } + + @Override + public Class getImplementedInterface() { + return getClass(); + } + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImplTest.java new file mode 100644 index 000000000..f30b1a214 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImplTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.Futures; +import java.util.Collections; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +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.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener; +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.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +/** + * Test for {@link EPForwardingTemplateListenerImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class EPForwardingTemplateListenerImplTest { + + private static final IpPrefix IP_PREFIX_TMPL = buildIpPrefix("1.2.3.0/24"); + private static final EndpointForwardingTemplateBySubnetKey EP_FW_TEMPLATE_KEY = + new EndpointForwardingTemplateBySubnetKey(IP_PREFIX_TMPL); + private static final KeyedInstanceIdentifier EP_FW_TEMPLATE_PATH = + EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH + .child(EndpointForwardingTemplateBySubnet.class, EP_FW_TEMPLATE_KEY); + private static final DataTreeIdentifier TEMPLATE_TREE_PATH = + new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, EP_FW_TEMPLATE_PATH); + private final EndpointForwardingTemplateBySubnet EP_FW_TEMPLATE_VALUE; + + + @Mock + private DataBroker dataBroker; + @Mock + private SxpMapperReactor sxpMapper; + @Mock + private SimpleCachedDao simpleCachedDao; + @Mock + private DSAsyncDao masterDBBindingDao; + @Mock + private DSAsyncDao epPolicyTemplateDao; + @Mock + private ListenerRegistration listenerRegistration; + @Mock + private DataTreeModification dataTreeModification; + @Mock + private DataObjectModification dataObjectModification; + + private EPForwardingTemplateListenerImpl listener; + public static final Sgt SGT = new Sgt(1); + public static final EndpointPolicyTemplateBySgt EP_POLICY_TEMPLATE = new EndpointPolicyTemplateBySgtBuilder() + .setSgt(SGT) + .build(); + + public EPForwardingTemplateListenerImplTest() { + EP_FW_TEMPLATE_VALUE = new EndpointForwardingTemplateBySubnetBuilder() + .setIpPrefix(IP_PREFIX_TMPL) + .build(); + } + + @Before + public void setUp() throws Exception { + Mockito.when(dataBroker.registerDataTreeChangeListener(Matchers.any(), + Matchers.any())).thenReturn(listenerRegistration); + listener = new EPForwardingTemplateListenerImpl(dataBroker, sxpMapper, simpleCachedDao, masterDBBindingDao, epPolicyTemplateDao); + } + + @Test + public void testOnDataTreeChanged() throws Exception { + Mockito.when(dataTreeModification.getRootNode()).thenReturn(dataObjectModification); + Mockito.when(dataTreeModification.getRootPath()).thenReturn(TEMPLATE_TREE_PATH); + Mockito.when(dataObjectModification.getDataAfter()).thenReturn(EP_FW_TEMPLATE_VALUE); + + final IpPrefix ipPrefix = buildIpPrefix("1.2.3.4/32"); + final MasterDatabaseBinding masterDBBinding = new MasterDatabaseBindingBuilder() + .setSecurityGroupTag(SGT) + .setIpPrefix(ipPrefix) + .build(); + Mockito.when(masterDBBindingDao.read(Matchers.any())).thenReturn( + Futures.immediateFuture(Optional.of(masterDBBinding))); + Mockito.when(epPolicyTemplateDao.read(Matchers.any())).thenReturn( + Futures.immediateFuture(Optional.of(EP_POLICY_TEMPLATE))); + Mockito.when(sxpMapper.processTemplatesAndSxpMasterDB(Matchers.any(), + Matchers.any(),Matchers.any())).thenReturn( + RpcResultBuilder.success((Void) null).buildFuture()); + + listener.onDataTreeChanged(Collections.singleton(dataTreeModification)); + + final InOrder inOrder = Mockito.inOrder(masterDBBindingDao, simpleCachedDao, epPolicyTemplateDao, sxpMapper); + inOrder.verify(simpleCachedDao).update(IP_PREFIX_TMPL, EP_FW_TEMPLATE_VALUE); + inOrder.verify(masterDBBindingDao).read(IP_PREFIX_TMPL); + inOrder.verify(epPolicyTemplateDao).read(SGT); + inOrder.verify(sxpMapper).processTemplatesAndSxpMasterDB(EP_POLICY_TEMPLATE, EP_FW_TEMPLATE_VALUE, masterDBBinding); + inOrder.verifyNoMoreInteractions(); + } + + private static IpPrefix buildIpPrefix(final String ipv4PrefixValue) { + return new IpPrefix(new Ipv4Prefix(ipv4PrefixValue)); + } + + @Test + public void testClose() throws Exception { + Mockito.verify(listenerRegistration, Mockito.never()).close(); + listener.close(); + Mockito.verify(listenerRegistration).close(); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImplTest.java new file mode 100644 index 000000000..2caf57095 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImplTest.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen; + +import com.google.common.base.Optional; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; +import java.util.Collections; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +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.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener; +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.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.ReadableAsyncByKey; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +/** + * Test for {@link EPPolicyTemplateListenerImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class EPPolicyTemplateListenerImplTest { + + private static final Sgt SGT_1 = new Sgt(1); + private static final KeyedInstanceIdentifier EP_PL_TEMPLATE_PATH = + EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH + .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(SGT_1)); + private static final DataTreeIdentifier TEMPLATE_TREE_PATH = + new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, EP_PL_TEMPLATE_PATH); + private static final IpPrefix IP_PREFIX_1 = new IpPrefix(new Ipv4Prefix("1.2.3.4/32")); + private static final IpPrefix IP_PREFIX_2 = new IpPrefix(new Ipv4Prefix("1.2.3.5/32")); + private final EndpointPolicyTemplateBySgt EP_PL_TEMPLATE_VALUE; + + @Mock + private DataBroker dataBroker; + @Mock + private SxpMapperReactor sxpMapper; + @Mock + private SimpleCachedDao simpleCachedDao; + @Mock + private DSAsyncDao epForwardingTemplateDao; + @Mock + private ReadableAsyncByKey masterDBDao; + @Mock + private ListenerRegistration listenerRegistration; + @Mock + private DataTreeModification dataTreeModification; + @Mock + private DataObjectModification dataObjectModification; + + private EPPolicyTemplateListenerImpl listener; + + public EPPolicyTemplateListenerImplTest() { + EP_PL_TEMPLATE_VALUE = new EndpointPolicyTemplateBySgtBuilder() + .setSgt(SGT_1) + .build(); + } + + @Before + public void setUp() throws Exception { + Mockito.when(dataBroker.registerDataTreeChangeListener(Matchers.any(), + Matchers.any())).thenReturn(listenerRegistration); + listener = new EPPolicyTemplateListenerImpl(dataBroker, sxpMapper, simpleCachedDao, masterDBDao, epForwardingTemplateDao); + } + + @Test + public void testOnDataTreeChanged() throws Exception { + Mockito.when(dataTreeModification.getRootNode()).thenReturn(dataObjectModification); + Mockito.when(dataTreeModification.getRootPath()).thenReturn(TEMPLATE_TREE_PATH); + Mockito.when(dataObjectModification.getDataAfter()).thenReturn(EP_PL_TEMPLATE_VALUE); + + final MasterDatabaseBinding masterDBBinding1 = new MasterDatabaseBindingBuilder() + .setSecurityGroupTag(SGT_1) + .setIpPrefix(IP_PREFIX_1) + .build(); + final MasterDatabaseBinding masterDBBinding2 = new MasterDatabaseBindingBuilder() + .setSecurityGroupTag(SGT_1) + .setIpPrefix(IP_PREFIX_2) + .build(); + + final EndpointForwardingTemplateBySubnet epForwardingTemplate1 = new EndpointForwardingTemplateBySubnetBuilder() + .setIpPrefix(IP_PREFIX_1) + .build(); + final EndpointForwardingTemplateBySubnet epForwardingTemplate2 = new EndpointForwardingTemplateBySubnetBuilder() + .setIpPrefix(IP_PREFIX_2) + .build(); + + Mockito.when(masterDBDao.readBy(Matchers.any())).thenReturn( + Futures.immediateFuture(Lists.newArrayList(masterDBBinding1, masterDBBinding2))); + Mockito.when(epForwardingTemplateDao.read(Matchers.any())).thenReturn( + Futures.immediateFuture(Optional.of(epForwardingTemplate1)), + Futures.immediateFuture(Optional.of(epForwardingTemplate2))); + Mockito.when(sxpMapper.processTemplatesAndSxpMasterDB(Matchers.any(), + Matchers.any(), Matchers.any())).thenReturn( + RpcResultBuilder.success((Void) null).buildFuture()); + + listener.onDataTreeChanged(Collections.singleton(dataTreeModification)); + + final InOrder inOrder = Mockito.inOrder(masterDBDao, simpleCachedDao, epForwardingTemplateDao, sxpMapper); + inOrder.verify(simpleCachedDao).update(SGT_1, EP_PL_TEMPLATE_VALUE); + inOrder.verify(masterDBDao).readBy(SGT_1); + inOrder.verify(epForwardingTemplateDao).read(IP_PREFIX_1); + inOrder.verify(epForwardingTemplateDao).read(IP_PREFIX_2); + inOrder.verify(sxpMapper).processTemplatesAndSxpMasterDB(EP_PL_TEMPLATE_VALUE, epForwardingTemplate1, masterDBBinding1); + inOrder.verify(sxpMapper).processTemplatesAndSxpMasterDB(EP_PL_TEMPLATE_VALUE, epForwardingTemplate2, masterDBBinding2); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testClose() throws Exception { + Mockito.verify(listenerRegistration, Mockito.never()).close(); + listener.close(); + Mockito.verify(listenerRegistration).close(); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImplTest.java new file mode 100644 index 000000000..49b0f0a52 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImplTest.java @@ -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.sxp.ep.provider.impl.listen; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.Futures; +import java.util.Collections; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +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.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener; +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.sxp.ep.provider.impl.DSAsyncDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.MasterDatabaseBindingListener; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao; +import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +/** + * Test for {@link MasterDatabaseBindingListenerImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class MasterDatabaseBindingListenerImplTest { + + private static final Sgt SGT_1 = new Sgt(1); + private static final IpPrefix IP_PREFIX = new IpPrefix(new Ipv4Prefix("1.2.3.4/32")); + private static final KeyedInstanceIdentifier MASTER_DB_PATH = + MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH + .child(Node.class, new NodeKey(new NodeId("utNodeId"))) + .augmentation(SxpNodeIdentity.class) + .child(SxpDomains.class) + .child(SxpDomain.class, new SxpDomainKey("global")) + .child(MasterDatabase.class) + .child(MasterDatabaseBinding.class, new MasterDatabaseBindingKey(IP_PREFIX)); + private static final DataTreeIdentifier MASTER_DB_BINDING_TREE_PATH = + new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, MASTER_DB_PATH); + private final MasterDatabaseBinding MASTER_DB_BINDING_VALUE; + + @Mock + private DataBroker dataBroker; + @Mock + private SxpMapperReactor sxpMapper; + @Mock + private DSAsyncDao epPolicyTemplateDao; + @Mock + private DSAsyncDao epForwardingTemplateDao; + @Mock + private SimpleCachedDao cachedDao; + @Mock + private ListenerRegistration listenerRegistration; + @Mock + private DataTreeModification dataTreeModification; + @Mock + private DataObjectModification dataObjectModification; + + private MasterDatabaseBindingListenerImpl listener; + + public MasterDatabaseBindingListenerImplTest() { + MASTER_DB_BINDING_VALUE = new MasterDatabaseBindingBuilder() + .setSecurityGroupTag(SGT_1) + .setIpPrefix(IP_PREFIX) + .build(); + } + + + @Before + public void setUp() throws Exception { + Mockito.when(dataBroker.registerDataTreeChangeListener(Matchers.any(), + Matchers.any())).thenReturn(listenerRegistration); + listener = new MasterDatabaseBindingListenerImpl(dataBroker, sxpMapper, cachedDao, epPolicyTemplateDao, + epForwardingTemplateDao); + } + + @Test + public void testOnDataTreeChanged() throws Exception { + Mockito.when(dataTreeModification.getRootNode()).thenReturn(dataObjectModification); + Mockito.when(dataTreeModification.getRootPath()).thenReturn(MASTER_DB_BINDING_TREE_PATH); + Mockito.when(dataObjectModification.getDataAfter()).thenReturn(MASTER_DB_BINDING_VALUE); + + // prepare epPolicy template + final EndpointPolicyTemplateBySgt epPolicyTemplate = new EndpointPolicyTemplateBySgtBuilder() + .setSgt(SGT_1) + .build(); + Mockito.when(epPolicyTemplateDao.read(Matchers.any())).thenReturn( + Futures.immediateFuture(Optional.of(epPolicyTemplate))); + + // prepare epForwarding template + final IpPrefix ipPrefixSubnet = new IpPrefix(new Ipv4Prefix("1.2.3.0/24")); + final EndpointForwardingTemplateBySubnet epForwardingTemplate = new EndpointForwardingTemplateBySubnetBuilder() + .setIpPrefix(ipPrefixSubnet) + .build(); + Mockito.when(epForwardingTemplateDao.read(Matchers.any())).thenReturn( + Futures.immediateFuture(Optional.of(epForwardingTemplate))); + + listener.onDataTreeChanged(Collections.singleton(dataTreeModification)); + + final InOrder inOrder = Mockito.inOrder(cachedDao, epPolicyTemplateDao, epForwardingTemplateDao, sxpMapper); + inOrder.verify(cachedDao).update(IP_PREFIX, MASTER_DB_BINDING_VALUE); + inOrder.verify(epPolicyTemplateDao).read(SGT_1); + inOrder.verify(epForwardingTemplateDao).read(IP_PREFIX); + inOrder.verify(sxpMapper).processTemplatesAndSxpMasterDB(epPolicyTemplate, epForwardingTemplate, MASTER_DB_BINDING_VALUE); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testClose() throws Exception { + Mockito.verify(listenerRegistration, Mockito.never()).close(); + listener.close(); + Mockito.verify(listenerRegistration).close(); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtilTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtilTest.java new file mode 100644 index 000000000..63fe54158 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtilTest.java @@ -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.groupbasedpolicy.sxp.ep.provider.impl.util; + +import org.apache.commons.net.util.SubnetUtils; +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; + +/** + * Test for {@link EPTemplateUtil}. + */ +public class EPTemplateUtilTest { + + public static final IpPrefix IP_PREFIX_24 = new IpPrefix(new Ipv4Prefix("1.2.3.0/24")); + public static final IpPrefix IP_PREFIX_32 = new IpPrefix(new Ipv4Prefix("1.2.3.4/32")); + + @Test + public void testIsPlain() throws Exception { + Assert.assertFalse(EPTemplateUtil.isPlain(IP_PREFIX_24)); + Assert.assertTrue(EPTemplateUtil.isPlain(IP_PREFIX_32)); + } + + @Test + public void testBuildSubnetInfoKey() throws Exception { + checkSubnetInfoBuilder(IP_PREFIX_24, "1.2.3.1", "1.2.3.254", 254); + checkSubnetInfoBuilder(IP_PREFIX_32, "0.0.0.0", "0.0.0.0", 0); + } + + private void checkSubnetInfoBuilder(final IpPrefix ipPrefix, final String expectedLow, final String expectedHigh, final int expectedCount) { + final SubnetInfoKeyDecorator subnetInfoKey = EPTemplateUtil.buildSubnetInfoKey(ipPrefix); + final SubnetUtils.SubnetInfo subnetInfo = subnetInfoKey.getDelegate(); + Assert.assertEquals(expectedLow, subnetInfo.getLowAddress()); + Assert.assertEquals(expectedHigh, subnetInfo.getHighAddress()); + Assert.assertEquals(expectedCount, subnetInfo.getAddressCount()); + Assert.assertEquals(ipPrefix.getIpv4Prefix().getValue(), subnetInfo.getCidrSignature()); + } +} \ No newline at end of file diff --git a/sxp-integration/sxp-ep-provider/src/test/resources/log4j.xml b/sxp-integration/sxp-ep-provider/src/test/resources/log4j.xml new file mode 100644 index 000000000..024a8db76 --- /dev/null +++ b/sxp-integration/sxp-ep-provider/src/test/resources/log4j.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +