and is available at http://www.eclipse.org/legal/epl-v10.html -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
+ <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.groupbasedpolicy</groupId>
- <artifactId>groupbasedpolicy-renderers</artifactId>
- <version>0.4.0-SNAPSHOT</version>
- <relativePath>../</relativePath>
- </parent>
+ <parent>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy-renderers</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
- <artifactId>ios-xe-renderer</artifactId>
- <packaging>bundle</packaging>
+ <artifactId>ios-xe-renderer</artifactId>
+ <packaging>bundle</packaging>
- <dependencies>
- <!-- testing dependencies -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-broker-impl</artifactId>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.groupbasedpolicy</groupId>
- <artifactId>groupbasedpolicy</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
- </dependencies>
+ <dependencies>
+ <!-- model dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>sxp-mapper</artifactId>
+ </dependency>
- <build>
- <plugins>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>config</id>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- <configuration>
- <codeGenerators>
- <generator>
- <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
- <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
- <additionalConfiguration>
- <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
- <namespaceToPackage2>urn:opendaylight:params:xml:ns:yang:groupbasedpolicy:renderer==org.opendaylight.groupbasedpolicy.renderer</namespaceToPackage2>
- </additionalConfiguration>
- </generator>
- </codeGenerators>
- <inspectDependencies>true</inspectDependencies>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
+ <!-- testing dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>config</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+ <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+ <namespaceToPackage2>urn:opendaylight:params:xml:ns:yang:groupbasedpolicy:renderer==org.opendaylight.groupbasedpolicy.renderer</namespaceToPackage2>
+ </additionalConfiguration>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Purpose: specify a cache driven by {@link DataTreeModification} where lookup key might differ from key used in
+ * dataStore and retrieved value is expected to be subset of <T>
+ *
+ * @param <T> dataStore object type
+ * @param <K> lookup key type
+ * @param <V> lookup result type
+ */
+public interface DSTreeBasedCache<T extends DataObject, K, V> {
+
+ /**
+ * @param exSource to be removed from cache
+ */
+ void invalidate(T exSource);
+
+ /**
+ * @param newSource to be added to chache
+ */
+ void add(T newSource);
+
+ /**
+ * update existing value
+ *
+ * @param before old value
+ * @param after new value
+ */
+ void update(T before, T after);
+
+ /**
+ * @param key for finding cached value
+ * @return found value pair to given key or null
+ */
+ V lookupValue(K key);
+
+
+ /**
+ * dispose of all cached values
+ */
+ void invalidateAll();
+}
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.IosXeRendererProvider;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyCacheImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.EpPolicyTemplateBySgtListenerImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.RendererConfigurationListenerImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(IosXeRendererProviderImpl.class);
- private final DataBroker dataBrokerDependency;
+ private final DataBroker dataBroker;
+ private final RendererName rendererName;
+ private RendererConfigurationListenerImpl rendererConfigurationListener;
+ private EpPolicyTemplateBySgtListenerImpl epPolicyTemplateBySgtListener;
+ private EpPolicyCacheImpl epPolicyCache;
- public IosXeRendererProviderImpl(final DataBroker dataBrokerDependency, final BindingAwareBroker brokerDependency) {
+ public IosXeRendererProviderImpl(final DataBroker dataBroker, final BindingAwareBroker broker,
+ final RendererName rendererName) {
LOG.debug("ios-xe renderer bootstrap");
- this.dataBrokerDependency = Preconditions.checkNotNull(dataBrokerDependency, "missing dataBroker dependency");
- brokerDependency.registerProvider(this);
+ this.dataBroker = Preconditions.checkNotNull(dataBroker, "missing dataBroker dependency");
+ this.rendererName = Preconditions.checkNotNull(rendererName, "missing rendererName param");
+ broker.registerProvider(this);
}
@Override
public void close() {
//TODO
LOG.info("closing ios-xe renderer");
+ if (rendererConfigurationListener != null) {
+ rendererConfigurationListener.close();
+ }
+ if (epPolicyTemplateBySgtListener != null) {
+ epPolicyTemplateBySgtListener.close();
+ }
+ if (epPolicyCache != null) {
+ epPolicyCache.invalidateAll();
+ }
}
@Override
public void onSessionInitiated(final BindingAwareBroker.ProviderContext providerContext) {
LOG.info("starting ios-xe renderer");
//TODO register listeners:
- // renderer-configuration endpoints
// ep-policy-template-by-sgt
+ epPolicyCache = new EpPolicyCacheImpl();
+ epPolicyTemplateBySgtListener = new EpPolicyTemplateBySgtListenerImpl(dataBroker, epPolicyCache);
+ // renderer-configuration endpoints
+ rendererConfigurationListener = new RendererConfigurationListenerImpl(dataBroker, rendererName, epPolicyCache);
// supported node list maintenance
+ // TODO: upkeep of available renderer-nodes
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+
+/**
+ * Purpose: cache for {@link EndpointPolicyTemplateBySgt}
+ */
+public class EpPolicyCacheImpl implements DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> {
+
+ private final ConcurrentMap<EpPolicyTemplateCacheKey, Sgt> cache;
+ private final EpPolicyTemplateCacheKeyFactory keyFactory;
+
+ public EpPolicyCacheImpl() {
+ cache = new ConcurrentHashMap<>();
+ keyFactory = new EpPolicyTemplateCacheKeyFactory(RendererPolicyUtil.createEndpointGroupIdOrdering(),
+ RendererPolicyUtil.createConditionNameOrdering());
+ }
+
+ @Override
+ public void invalidate(final EndpointPolicyTemplateBySgt exSource) {
+ cache.remove(keyFactory.createKey(exSource));
+ }
+
+ @Override
+ public void add(final EndpointPolicyTemplateBySgt newSource) {
+ final EpPolicyTemplateCacheKey key = keyFactory.createKey(newSource);
+ cache.put(key, newSource.getSgt());
+ }
+
+ @Override
+ public void update(final EndpointPolicyTemplateBySgt before, final EndpointPolicyTemplateBySgt after) {
+ cache.remove(keyFactory.createKey(before));
+ cache.put(keyFactory.createKey(after), after.getSgt());
+ }
+
+ @Override
+ public Sgt lookupValue(final EpPolicyTemplateCacheKey key) {
+ return cache.get(keyFactory.createKey(key));
+ }
+
+ @Override
+ public void invalidateAll() {
+ cache.clear();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache;
+
+import java.util.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.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+
+/**
+ * Purpose: composite key holcer for {@link EndpointPolicyTemplateBySgt}
+ */
+public class EpPolicyTemplateCacheKey {
+
+ private final TenantId tenantId;
+ private final List<EndpointGroupId> epgId;
+ private final List<ConditionName> conditionName;
+
+ public EpPolicyTemplateCacheKey(final TenantId tenantId, final List<EndpointGroupId> epgId, final List<ConditionName> conditionName) {
+ this.tenantId = tenantId;
+ this.epgId = epgId;
+ this.conditionName = conditionName;
+ }
+
+ public EpPolicyTemplateCacheKey(AddressEndpointWithLocation endpoint) {
+ this(endpoint.getTenant(), endpoint.getEndpointGroup(), endpoint.getCondition());
+ }
+
+ public TenantId getTenantId() {
+ return tenantId;
+ }
+
+ public List<EndpointGroupId> getEpgId() {
+ return epgId;
+ }
+
+ public List<ConditionName> getConditionName() {
+ return conditionName;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final EpPolicyTemplateCacheKey that = (EpPolicyTemplateCacheKey) 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;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache;
+
+import com.google.common.collect.Ordering;
+import java.util.Collections;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+
+/**
+ * Purpose: create cache keys with ordered lists inside
+ */
+public class EpPolicyTemplateCacheKeyFactory {
+ private final Ordering<EndpointGroupId> epgIdOrdering;
+ private final Ordering<ConditionName> conditionOrdering;
+
+ public EpPolicyTemplateCacheKeyFactory(final Ordering<EndpointGroupId> epgIdOrdering,
+ final Ordering<ConditionName> conditionOrdering) {
+ this.epgIdOrdering = epgIdOrdering;
+ this.conditionOrdering = conditionOrdering;
+ }
+
+ public EpPolicyTemplateCacheKey createKey(final EndpointPolicyTemplateBySgt newSource) {
+ Collections.sort(newSource.getEndpointGroups(), epgIdOrdering);
+ Collections.sort(newSource.getConditions(), conditionOrdering);
+
+ return new EpPolicyTemplateCacheKey(
+ newSource.getTenant(), newSource.getEndpointGroups(), newSource.getConditions());
+ }
+
+ public EpPolicyTemplateCacheKey createKey(final EpPolicyTemplateCacheKey existingKey) {
+ Collections.sort(existingKey.getEpgId(), epgIdOrdering);
+ Collections.sort(existingKey.getConditionName(), conditionOrdering);
+ return existingKey;
+ }
+}
@Override
public java.lang.AutoCloseable createInstance() {
- return new IosXeRendererProviderImpl(getDataBrokerDependency(), getBrokerDependency());
+ return new IosXeRendererProviderImpl(getDataBrokerDependency(), getBrokerDependency(), getRendererName());
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener;
+
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.SxpMapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: listen to {@link EndpointPolicyTemplateBySgt} changes for caching purposes
+ */
+public class EpPolicyTemplateBySgtListenerImpl implements DataTreeChangeListener<EndpointPolicyTemplateBySgt>, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EpPolicyTemplateBySgtListenerImpl.class);
+
+ private final ListenerRegistration<EpPolicyTemplateBySgtListenerImpl> listenerRegistration;
+ private final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> cache;
+
+ public EpPolicyTemplateBySgtListenerImpl(final DataBroker dataBroker,
+ final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> cache) {
+ this.cache = Preconditions.checkNotNull(cache, "missing ep-policy-template cache");
+ final InstanceIdentifier<EndpointPolicyTemplateBySgt> templatePath = InstanceIdentifier.create(SxpMapper.class)
+ .child(EndpointPolicyTemplateBySgt.class);
+
+ final DataTreeIdentifier<EndpointPolicyTemplateBySgt> treePath = new DataTreeIdentifier<>(
+ LogicalDatastoreType.CONFIGURATION, templatePath);
+ listenerRegistration = dataBroker.registerDataTreeChangeListener(treePath, this);
+ LOG.info("ep-policy-template listener registered");
+ }
+
+ @Override
+ public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<EndpointPolicyTemplateBySgt>> collection) {
+ LOG.debug("ep-policy-template changed");
+ for (DataTreeModification<EndpointPolicyTemplateBySgt> epPolicyTemplateModification : collection) {
+ final DataObjectModification<EndpointPolicyTemplateBySgt> rootNode = epPolicyTemplateModification
+ .getRootNode();
+ final DataObjectModification.ModificationType modificationType = rootNode.getModificationType();
+ switch (modificationType) {
+ case DELETE:
+ // invalidate cache
+ cache.invalidate(rootNode.getDataBefore());
+ break;
+ case WRITE:
+ // extend cache
+ cache.add(rootNode.getDataAfter());
+ break;
+ case SUBTREE_MODIFIED:
+ // update cache
+ cache.update(rootNode.getDataBefore(), rootNode.getDataAfter());
+ break;
+ default:
+ LOG.warn("modification type not supported: {}", modificationType);
+ }
+ }
+ }
+
+ @Override
+ public void close() {
+ listenerRegistration.close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener;
+
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: process changes of configured renderer policies
+ */
+public class RendererConfigurationListenerImpl implements DataTreeChangeListener<RendererPolicy>, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RendererConfigurationListenerImpl.class);
+ private final ListenerRegistration<RendererConfigurationListenerImpl> listenerRegistration;
+ private final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> epPolicyCache;
+
+ public RendererConfigurationListenerImpl(final DataBroker dataBroker, final RendererName rendererName,
+ final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> epPolicyCache) {
+ this.epPolicyCache = Preconditions.checkNotNull(epPolicyCache, "missing endpoint template cache");
+ final InstanceIdentifier<RendererPolicy> policyPath = InstanceIdentifier.create(Renderers.class)
+ .child(Renderer.class, new RendererKey(rendererName))
+ .child(RendererPolicy.class);
+
+ final DataTreeIdentifier<RendererPolicy> treePath = new DataTreeIdentifier<>(
+ LogicalDatastoreType.CONFIGURATION,
+ policyPath);
+ listenerRegistration = dataBroker.registerDataTreeChangeListener(treePath, this);
+ LOG.info("renderer-policy listener registered");
+ }
+
+ @Override
+ public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<RendererPolicy>> collection) {
+ LOG.debug("renderer policy configuration changed");
+ for (DataTreeModification<RendererPolicy> rendererPolicyDataTreeModification : collection) {
+ final DataObjectModification<RendererPolicy> rootNode = rendererPolicyDataTreeModification.getRootNode();
+
+ final RendererPolicy dataAfter = rootNode.getDataAfter();
+ if (dataAfter != null && dataAfter.getConfiguration() != null) {
+ // find sgt
+ final Configuration configuration = dataAfter.getConfiguration();
+ for (RendererEndpoint rendererEndpoint : configuration.getRendererEndpoints().getRendererEndpoint()) {
+ // lookup endpoints 1 source | * destination
+ AddressEndpointWithLocation sourceEp = RendererPolicyUtil.lookupEndpoint(rendererEndpoint, configuration.getEndpoints().getAddressEndpointWithLocation());
+ //resolve sgt
+ final Sgt sourceSgt = epPolicyCache.lookupValue(new EpPolicyTemplateCacheKey(sourceEp));
+ for (PeerEndpointWithPolicy peerEndpoint : rendererEndpoint.getPeerEndpointWithPolicy()) {
+ AddressEndpointWithLocation destinationEp = RendererPolicyUtil.lookupEndpoint(peerEndpoint, configuration.getEndpoints().getAddressEndpointWithLocation());
+ //resolve sgt
+ final Sgt destinationSgt = epPolicyCache.lookupValue(new EpPolicyTemplateCacheKey(destinationEp));
+ // invoke policy manager
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void close() {
+ listenerRegistration.close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
+
+import com.google.common.base.Equivalence;
+import com.google.common.base.Objects;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
+
+/**
+ * Purpose: hashCode and equals wrapper for any child of {@link AddressEndpointKey}
+ */
+public class AddressEndpointKeyEquivalence extends Equivalence<AddressEndpointKey> {
+
+ @Override
+ protected boolean doEquivalent(final AddressEndpointKey a, final AddressEndpointKey b) {
+ if (!Objects.equal(a.getContextType(), b.getContextType())) {
+ return false;
+ }
+ if (!Objects.equal(a.getAddressType(), b.getAddressType())) {
+ return false;
+ }
+ if (!Objects.equal(a.getAddress(), b.getAddress())) {
+ return false;
+ }
+ if (!Objects.equal(a.getContextId(), b.getContextId())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ protected int doHash(final AddressEndpointKey addressEndpointKey) {
+ return Objects.hashCode(
+ addressEndpointKey.getAddress(),
+ addressEndpointKey.getAddressType(),
+ addressEndpointKey.getContextId(),
+ addressEndpointKey.getContextType());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
+
+import com.google.common.base.Function;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Ordering;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
+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.renderer.rev151103.renderers.renderer.RendererPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+
+/**
+ * Purpose: provide util methods handling {@link RendererPolicy}
+ */
+public final class RendererPolicyUtil {
+
+ private static final AddressEndpointKeyEquivalence ADDRESS_EP_KEY_EQUIVALENCE = new AddressEndpointKeyEquivalence();
+ private static final Comparable EMPTY_COMPARABLE = "";
+
+ private RendererPolicyUtil() {
+ throw new IllegalAccessError("Shall not instantiate util class.");
+ }
+
+
+ /**
+ * @param rendererEp lightweight endpoint key
+ * @param addressEndpointWithLocation collection of heavyweight endpoint definitions
+ * @return full address endpoint found by given key
+ */
+ public static AddressEndpointWithLocation lookupEndpoint(final AddressEndpointKey rendererEp, final List<AddressEndpointWithLocation> addressEndpointWithLocation) {
+ final Predicate<AddressEndpointKey> addressEndpointKeyPredicate = ADDRESS_EP_KEY_EQUIVALENCE.equivalentTo(rendererEp);
+ AddressEndpointWithLocation needle = null;
+
+ for (AddressEndpointWithLocation ep : addressEndpointWithLocation) {
+ if (addressEndpointKeyPredicate.apply(ep)) {
+ needle = ep;
+ break;
+ }
+ }
+ return needle;
+ }
+
+ public static Ordering<EndpointGroupId> createEndpointGroupIdOrdering() {
+ return Ordering.natural().onResultOf(new Function<EndpointGroupId, Comparable>() {
+ @Nullable
+ @Override
+ public Comparable apply(@Nullable final EndpointGroupId input) {
+ if (input == null) {
+ return EMPTY_COMPARABLE;
+ }
+ return MoreObjects.firstNonNull(input.getValue(), EMPTY_COMPARABLE);
+ }
+ });
+ }
+
+ public static Ordering<ConditionName> createConditionNameOrdering() {
+ return Ordering.natural().onResultOf(new Function<ConditionName, Comparable>() {
+ @Nullable
+ @Override
+ public Comparable apply(@Nullable final ConditionName input) {
+ if (input == null) {
+ return EMPTY_COMPARABLE;
+ }
+ return MoreObjects.firstNonNull(input.getValue(), EMPTY_COMPARABLE);
+ }
+ });
+ }
+}
import config { prefix config; revision-date 2013-04-05; }
import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
- import ietf-yang-types { prefix "yang"; revision-date 2010-09-24; }
- import opendaylight-sal-binding-broker-impl { prefix sal-broker; revision-date 2013-10-28;}
import groupbasedpolicy-cfg { prefix gbpcfg; revision-date 2015-11-06; }
+ import renderer { prefix gbprenderer; revision-date 2015-11-03; }
description
"This module contains the base YANG definitions for
}
}
}
+
+ leaf renderer-name {
+ type gbprenderer:renderer-name;
+ }
}
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+
+/**
+ * Test for {@link EpPolicyCacheImpl}.
+ */
+public class EpPolicyCacheImplTest {
+
+ private static final int SGT1 = 1;
+ private static final int SGT2 = 2;
+ private static final String TENANT1 = "tenant1";
+ private static final String TENANT2 = "tenant2";
+
+ private static final EpPolicyTemplateCacheKey KEY_1 = createKey(TENANT1, new String[]{"n1", "n2"});
+ private static final EpPolicyTemplateCacheKey KEY_2 = createKey(TENANT2, new String[]{"n3"});
+
+ private static final EndpointPolicyTemplateBySgt TEMPLATE_1 = createTemplate(SGT1, TENANT1, new String[]{"n1", "n2"});
+ private static final EndpointPolicyTemplateBySgt TEMPLATE_2 = createTemplate(SGT2, TENANT2, new String[]{"n3"});
+
+ private EpPolicyCacheImpl cache;
+
+ @Before
+ public void setUp() throws Exception {
+ cache = new EpPolicyCacheImpl();
+ }
+
+ @Test
+ public void testInvalidate() throws Exception {
+ cache.add(TEMPLATE_1);
+ cache.add(TEMPLATE_2);
+
+ checkValuePresence(KEY_1, SGT1);
+
+ checkValuePresence(KEY_2, SGT2);
+
+ cache.invalidate(TEMPLATE_1);
+ Assert.assertNull(cache.lookupValue(KEY_1));
+ Assert.assertNotNull(cache.lookupValue(KEY_2));
+ }
+
+ @Test
+ public void testAdd() throws Exception {
+ cache.add(TEMPLATE_1);
+ checkValuePresence(KEY_1, SGT1);
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ cache.add(TEMPLATE_1);
+ checkValuePresence(KEY_1, SGT1);
+
+ cache.update(TEMPLATE_1, TEMPLATE_2);
+
+ Assert.assertNull(cache.lookupValue(KEY_1));
+ checkValuePresence(KEY_2, SGT2);
+ }
+
+ @Test
+ public void testLookupValue() throws Exception {
+ cache.add(TEMPLATE_1);
+ checkValuePresence(KEY_1, SGT1);
+ }
+
+ private void checkValuePresence(final EpPolicyTemplateCacheKey key, final int expectedSgt) {
+ final Sgt sgt = cache.lookupValue(key);
+ Assert.assertNotNull(sgt);
+ Assert.assertEquals(expectedSgt, sgt.getValue().intValue());
+ }
+
+ @Test
+ public void testLookupValue_withChangedOrder() throws Exception {
+ Assert.assertNull(cache.lookupValue(KEY_1));
+ cache.add(TEMPLATE_1);
+ checkValuePresence(KEY_1, SGT1);
+
+ final EpPolicyTemplateCacheKey twistedKey1 = createKey(TENANT1, new String[]{"n1", "n2"}, new String[]{"n2", "n1"});
+ checkValuePresence(twistedKey1, SGT1);
+
+ final EpPolicyTemplateCacheKey twistedKey2 = createKey(TENANT1, new String[]{"n2", "n1"}, new String[]{"n1", "n2"});
+ checkValuePresence(twistedKey2, SGT1);
+ }
+
+ @Test
+ public void testInvalidateAll() throws Exception {
+ cache.add(TEMPLATE_1);
+ cache.add(TEMPLATE_2);
+ checkValuePresence(KEY_1, SGT1);
+
+ cache.invalidateAll();
+ Assert.assertNull(cache.lookupValue(KEY_1));
+ Assert.assertNull(cache.lookupValue(KEY_2));
+ }
+
+ private static EndpointPolicyTemplateBySgt createTemplate(final int sgt, final String tenant, final String[] names) {
+ final List<ConditionName> conditions = buildConditions(names);
+ final List<EndpointGroupId> endpointGroupIds = buildEndpointGroupIds(names);
+
+ return new EndpointPolicyTemplateBySgtBuilder()
+ .setSgt(new Sgt(sgt))
+ .setTenant(new TenantId(tenant))
+ .setConditions(conditions)
+ .setEndpointGroups(endpointGroupIds)
+ .build();
+ }
+
+ private static List<EndpointGroupId> buildEndpointGroupIds(final String[] names) {
+ final List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
+ for (String epgId : names) {
+ endpointGroupIds.add(new EndpointGroupId(epgId));
+ }
+ return endpointGroupIds;
+ }
+
+ private static List<ConditionName> buildConditions(final String[] names) {
+ final List<ConditionName> conditions = new ArrayList<>();
+ for (String condition : names) {
+ conditions.add(new ConditionName(condition));
+ }
+ return conditions;
+ }
+
+ private static EpPolicyTemplateCacheKey createKey(final String tenant, final String[] names) {
+ return createKey(tenant, names, names);
+ }
+
+ private static EpPolicyTemplateCacheKey createKey(final String tenant, final String[] epgIds, final String[] conditionNames) {
+ return new EpPolicyTemplateCacheKey(new AddressEndpointWithLocationBuilder()
+ .setTenant(new TenantId(tenant))
+ .setEndpointGroup(buildEndpointGroupIds(epgIds))
+ .setCondition(buildConditions(conditionNames))
+ .build());
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener;
+
+import com.google.common.collect.Lists;
+import java.util.Collections;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+/**
+ * Test for {@link EpPolicyTemplateBySgtListenerImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class EpPolicyTemplateBySgtListenerImplTest {
+
+ private static final Sgt SGT1 = new Sgt(1);
+ private static final TenantId TENANT1 = new TenantId("tenant1");
+ private static final TenantId TENANT2 = new TenantId("tenant2");
+ @Mock
+ private DataBroker dataBroker;
+ @Mock
+ private DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> cache;
+ @Mock
+ private ListenerRegistration<EpPolicyTemplateBySgtListenerImpl> listenerRegistration;
+ @Mock
+ private DataTreeModification<EndpointPolicyTemplateBySgt> dataTreeModification;
+ @Mock
+ private DataObjectModification<EndpointPolicyTemplateBySgt> rootNode;
+
+ private final EndpointPolicyTemplateBySgt template1;
+ private final EndpointPolicyTemplateBySgt template2;
+
+ private EpPolicyTemplateBySgtListenerImpl listener;
+
+ public EpPolicyTemplateBySgtListenerImplTest() {
+ this.template1 = new EndpointPolicyTemplateBySgtBuilder()
+ .setSgt(SGT1)
+ .setTenant(TENANT1)
+ .setEndpointGroups(Lists.newArrayList(new EndpointGroupId("epg1"), new EndpointGroupId("epg2")))
+ .setConditions(Lists.newArrayList(new ConditionName("condition1"), new ConditionName("condition2")))
+ .build();
+
+ this.template2 = new EndpointPolicyTemplateBySgtBuilder()
+ .setSgt(SGT1)
+ .setTenant(TENANT2)
+ .setEndpointGroups(Lists.newArrayList(new EndpointGroupId("epg3"), new EndpointGroupId("epg4")))
+ .setConditions(Lists.newArrayList(new ConditionName("condition2"), new ConditionName("condition3")))
+ .build();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ Mockito.when(dataBroker.registerDataTreeChangeListener(
+ Matchers.<DataTreeIdentifier<EndpointPolicyTemplateBySgt>>any(),
+ Matchers.<EpPolicyTemplateBySgtListenerImpl>any()))
+ .thenReturn(listenerRegistration);
+ listener = new EpPolicyTemplateBySgtListenerImpl(dataBroker, cache);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ Mockito.verifyNoMoreInteractions(cache);
+ }
+
+ @Test
+ public void testOnDataTreeChanged_add() throws Exception {
+ Mockito.when(rootNode.getDataAfter()).thenReturn(template1);
+ Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
+ Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
+
+ listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+ Mockito.verify(cache).add(template1);
+ }
+
+ @Test
+ public void testOnDataTreeChanged_remove() throws Exception {
+ Mockito.when(rootNode.getDataBefore()).thenReturn(template1);
+ Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
+ Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
+
+ listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+ Mockito.verify(cache).invalidate(template1);
+ }
+
+ @Test
+ public void testOnDataTreeChanged_update() throws Exception {
+ Mockito.when(rootNode.getDataBefore()).thenReturn(template1);
+ Mockito.when(rootNode.getDataAfter()).thenReturn(template2);
+ Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
+ Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
+
+ listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+ Mockito.verify(cache).update(template1, template2);
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ Mockito.verify(listenerRegistration, Mockito.never()).close();
+ listener.close();
+ Mockito.verify(listenerRegistration).close();
+ listener.close();
+ Mockito.verify(listenerRegistration, Mockito.times(2)).close();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener;
+
+import java.util.Collections;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+/**
+ * Test for {@link RendererConfigurationListenerImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class RendererConfigurationListenerImplTest {
+
+ private static final RendererName RENDERER_NAME = new RendererName("renderer1");
+ private final RendererPolicy policy1;
+ @Mock
+ private DataBroker dataBroker;
+ @Mock
+ private DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> cache;
+ @Mock
+ private ListenerRegistration<RendererConfigurationListenerImpl> listenerRegistration;
+ @Mock
+ private DataTreeModification<RendererPolicy> dataTreeModification;
+ @Mock
+ private DataObjectModification<RendererPolicy> rootNode;
+
+ private RendererConfigurationListenerImpl listener;
+
+ public RendererConfigurationListenerImplTest() {
+ policy1 = new RendererPolicyBuilder().build();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ Mockito.when(dataBroker.registerDataTreeChangeListener(
+ Matchers.<DataTreeIdentifier<RendererPolicy>>any(),
+ Matchers.<RendererConfigurationListenerImpl>any()))
+ .thenReturn(listenerRegistration);
+ listener = new RendererConfigurationListenerImpl(dataBroker, RENDERER_NAME, cache);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ Mockito.verifyNoMoreInteractions(listenerRegistration);
+ }
+
+ @Test
+ public void testOnDataTreeChanged_add() throws Exception {
+ Mockito.when(rootNode.getDataAfter()).thenReturn(policy1);
+ Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
+ Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
+
+ listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+ //TODO: verify on policy manager
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ Mockito.verify(listenerRegistration, Mockito.never()).close();
+ listener.close();
+ Mockito.verify(listenerRegistration).close();
+ listener.close();
+ Mockito.verify(listenerRegistration, Mockito.times(2)).close();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Ordering;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+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.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationBuilder;
+
+/**
+ * Test for {@link RendererPolicyUtil}.
+ */
+public class RendererPolicyUtilTest {
+
+ @Test
+ public void testLookupEndpoint() throws Exception {
+ final AddressEndpointKey key1 = new AddressEndpointBuilder()
+ .setAddress("address1")
+ .setAddressType(IpPrefixType.class)
+ .setContextId(new ContextId("context1"))
+ .setContextType(L3Context.class)
+ .build();
+
+ final AddressEndpointWithLocation addressEPWithLocation1 =
+ createAddressEPWithLocation("address1", IpPrefixType.class, "context1", L3Context.class);
+ final AddressEndpointWithLocation addressEPWithLocation2 =
+ createAddressEPWithLocation("address2", IpPrefixType.class, "context1", L3Context.class);
+ final AddressEndpointWithLocation addressEPWithLocation3 =
+ createAddressEPWithLocation("address1", MacAddressType.class, "context1", L3Context.class);
+ final AddressEndpointWithLocation addressEPWithLocation4 =
+ createAddressEPWithLocation("address1", IpPrefixType.class, "context2", L3Context.class);
+ final AddressEndpointWithLocation addressEPWithLocation5 =
+ createAddressEPWithLocation("address1", IpPrefixType.class, "context1", L2BridgeDomain.class);
+
+ final List<AddressEndpointWithLocation> endpoints = Lists.newArrayList(
+ addressEPWithLocation2, addressEPWithLocation3,
+ addressEPWithLocation4, addressEPWithLocation5,
+ addressEPWithLocation1
+ );
+
+ final AddressEndpointWithLocation actualEndpoint = RendererPolicyUtil.lookupEndpoint(key1, endpoints);
+ Assert.assertSame(addressEPWithLocation1, actualEndpoint);
+ }
+
+ @Test
+ public void testCreateEndpointGroupIdOrdering() throws Exception {
+ final Ordering<EndpointGroupId> endpointGroupIdOrdering = RendererPolicyUtil.createEndpointGroupIdOrdering();
+ final String epg1 = "epg1";
+ final ArrayList<EndpointGroupId> list = Lists.newArrayList(
+ new EndpointGroupId("epg3"), new EndpointGroupId(epg1), new EndpointGroupId("epg2"));
+
+ Collections.sort(list, endpointGroupIdOrdering);
+ Assert.assertEquals(epg1, list.get(0).getValue());
+
+ Collections.sort(list, endpointGroupIdOrdering.reversed());
+ Assert.assertEquals(epg1, list.get(2).getValue());
+ }
+
+ @Test
+ public void testCreateConditionNameOrdering() throws Exception {
+ final Ordering<ConditionName> conditionNameOrdering = RendererPolicyUtil.createConditionNameOrdering();
+ final String name1 = "name1";
+ final ArrayList<ConditionName> list = Lists.newArrayList(
+ new ConditionName("name3"), new ConditionName(name1), new ConditionName("name2"));
+
+ Collections.sort(list, conditionNameOrdering);
+ Assert.assertEquals(name1, list.get(0).getValue());
+
+ Collections.sort(list, conditionNameOrdering.reversed());
+ Assert.assertEquals(name1, list.get(2).getValue());
+ }
+
+ private AddressEndpointWithLocation createAddressEPWithLocation(final String address,
+ final Class<? extends AddressType> addressType,
+ final String context,
+ final Class<? extends ContextType> contextType) {
+ return new AddressEndpointWithLocationBuilder()
+ .setAddress(address)
+ .setAddressType(addressType)
+ .setContextId(new ContextId(context))
+ .setContextType(contextType)
+ .build();
+ }
+}
\ No newline at end of file