<artifactId>ovssfc-renderer</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ne-location-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>neutron-mapper</artifactId>
<type>xml</type>
<classifier>config</classifier>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ne-location-provider</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>neutron-mapper</artifactId>
<groupId>org.opendaylight.groupbasedpolicy</groupId>
<artifactId>iovisor-renderer</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>ne-location-provider</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.groupbasedpolicy</groupId>
<artifactId>neutron-mapper</artifactId>
<type>xml</type>
<classifier>config</classifier>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>ne-location-provider</artifactId>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </dependency>
<dependency>
<groupId>org.opendaylight.groupbasedpolicy</groupId>
<artifactId>neutron-mapper</artifactId>
<feature version="${controller.mdsal.version}">odl-mdsal-broker</feature>
<feature version='${mdsal.version}'>odl-mdsal-binding-base</feature>
<feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+ <bundle>mvn:commons-net/commons-net/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy/{{VERSION}}</bundle>
<configfile finalname="${config.configfile.directory}/15-groupbasedpolicy-base.xml">mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy/{{VERSION}}/xml/config</configfile>
</feature>
<bundle>mvn:org.opendaylight.groupbasedpolicy/sxp-mapper/{{VERSION}}</bundle>
<configfile finalname="${config.configfile.directory}/15-groupbasedpolicy-sxp-mapper.xml">mvn:org.opendaylight.groupbasedpolicy/sxp-mapper/{{VERSION}}/xml/config</configfile>
</feature>
+
+ <!--
+ NE Location Provider
+ -->
+ <feature name='odl-groupbasedpolicy-ne-location-provider' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: NE location provider'>
+ <feature version="${project.version}">odl-groupbasedpolicy-base</feature>
+ <bundle>mvn:org.opendaylight.groupbasedpolicy/ne-location-provider/{{VERSION}}</bundle>
+ <configfile finalname="${config.configfile.directory}/15-ne-location-provider.xml">mvn:org.opendaylight.groupbasedpolicy/ne-location-provider/{{VERSION}}/xml/config</configfile>
+ </feature>
</features>
<groupId>org.opendaylight.mdsal.model</groupId>
<artifactId>yang-ext</artifactId>
</dependency>
+ <!-- net utils dependencies -->
+ <dependency>
+ <groupId>com.googlecode.java-ipv6</groupId>
+ <artifactId>java-ipv6</artifactId>
+ <version>0.16</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-net</groupId>
+ <artifactId>commons-net</artifactId>
+ </dependency>
<!-- testing dependencies -->
<dependency>
<groupId>junit</groupId>
org.opendaylight.groupbasedpolicy.dto,
org.opendaylight.groupbasedpolicy.util,
</Export-Package>
+ <Embed-Dependency>java-ipv6</Embed-Dependency>
</instructions>
</configuration>
</plugin>
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.ContainmentEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
-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.endpoint_location_provider.rev160419.LocationProviders;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.ProviderName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProviderKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecord;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecordKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
public class IidFactory {
.build();
}
+ public static InstanceIdentifierBuilder<ProviderAddressEndpointLocation> providerAddressEndpointLocationIid(String provider,
+ Class<? extends AddressType> addrType, String addr, Class<? extends ContextType> cType,
+ ContextId containment) {
+ return InstanceIdentifier.builder(LocationProviders.class)
+ .child(LocationProvider.class, new LocationProviderKey(new ProviderName(provider)))
+ .child(ProviderAddressEndpointLocation.class, new ProviderAddressEndpointLocationKey(addr, addrType, containment, cType));
+ }
}
--- /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.util;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.commons.net.util.SubnetUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+
+import com.google.common.base.Strings;
+import com.googlecode.ipv6.IPv6NetworkMask;
+
+public final class NetUtils {
+
+ /**
+ * Extract prefix length from prefix form
+ * Works for both IPv4 and IPv6
+ *
+ * @param prefix {@code String} to extract prefix length from
+ * @return prefix length as {@code int}
+ */
+ public static int getMaskFromPrefix(@Nullable String prefix) {
+ String newPrefix = Strings.nullToEmpty(prefix);
+ int slashIndex = newPrefix.indexOf("/");
+ if (slashIndex == -1) {
+ slashIndex = newPrefix.length() - 1;
+ }
+ return Integer.parseInt(newPrefix.substring(slashIndex + 1));
+ }
+
+ /**
+ * Extract IP adress from prefix form
+ * Works for both IPv4 and IPv6
+ *
+ * @param prefix {@code String} to extract IP address from
+ * @return IP address as a {@code String}
+ */
+ public static @Nonnull String getIpAddrFromPrefix(@Nullable String prefix) {
+ String newPrefix = Strings.nullToEmpty(prefix);
+ int slashIndex = newPrefix.indexOf("/");
+ if (slashIndex == -1) {
+ slashIndex = newPrefix.length();
+ }
+ return newPrefix.substring(0, slashIndex);
+ }
+
+ /**
+ * Mask IPv6 address from prefix with provided prefix length
+ *
+ * @param ipv6Prefix {@link Ipv6Prefix} to apply mask on
+ * @param ipv6MaskLength prefix length
+ * @return resulting network IP address as {@link Ipv6Address}
+ */
+ public static @Nullable Ipv6Address applyMaskOnIpv6Prefix(@Nullable Ipv6Prefix ipv6Prefix, int ipv6MaskLength) {
+ if (ipv6Prefix == null) {
+ return null;
+ }
+ return applyMaskOnIpv6Address(new Ipv6Address(getIpAddrFromPrefix(ipv6Prefix.getValue())), ipv6MaskLength);
+ }
+
+ /**
+ * Mask IPv6 address with provided prefix length
+ *
+ * @param ipv6Address {@link Ipv6Prefix} to apply mask on
+ * @param ipv6MaskLength prefix length
+ * @return resulting network address as {@link Ipv6Address}, {@code null} if provided address is null
+ */
+ public static @Nullable Ipv6Address applyMaskOnIpv6Address(@Nullable Ipv6Address ipv6Address, int ipv6MaskLength) {
+ if (ipv6Address == null) {
+ return null;
+ }
+ com.googlecode.ipv6.IPv6Address ip = com.googlecode.ipv6.IPv6Address.fromString(ipv6Address.getValue());
+ IPv6NetworkMask mask = IPv6NetworkMask.fromPrefixLength(ipv6MaskLength);
+ ip = ip.maskWithNetworkMask(mask);
+ return new Ipv6Address(ip.toString());
+ }
+
+ /**
+ * Check if two IpPrefixes represents same network. Must be identical in network address and prefix length.
+ * Works for both IPv4 and IPv6
+ *
+ * @param prefix1 {@link IpPrefix} to compare
+ * @param prefix2 {@link IpPrefix} to compare
+ * @return {@code true} if provided prefixes are identical, otherwise return {@code false}
+ */
+ public static boolean samePrefix(@Nullable IpPrefix prefix1, @Nullable IpPrefix prefix2) {
+ if (prefix1 == null || prefix2 == null) {
+ return false;
+ }
+ if (prefix1.getIpv4Prefix() != null && prefix2.getIpv4Prefix() != null) {
+ SubnetUtils fromPrefix1 = new SubnetUtils(prefix1.getIpv4Prefix().getValue());
+ SubnetUtils fromPrefix2 = new SubnetUtils(prefix2.getIpv4Prefix().getValue());
+ if (fromPrefix1.getInfo().isInRange(fromPrefix2.getInfo().getHighAddress())
+ && fromPrefix2.getInfo().isInRange(fromPrefix1.getInfo().getHighAddress())) {
+ return true;
+ }
+ } else if (prefix1.getIpv6Prefix() != null && prefix2.getIpv6Prefix() != null) {
+ int ipv6MaskLength1 = getMaskFromPrefix(prefix1.getIpv6Prefix().getValue());
+ int ipv6MaskLength2 = getMaskFromPrefix(prefix2.getIpv6Prefix().getValue());
+ if (ipv6MaskLength1 != ipv6MaskLength2) {
+ return false;
+ }
+ Ipv6Address ipv6Network = applyMaskOnIpv6Prefix(prefix1.getIpv6Prefix(), ipv6MaskLength1);
+ Ipv6Address hostv6Network = applyMaskOnIpv6Prefix(prefix2.getIpv6Prefix(), ipv6MaskLength1);
+ if (ipv6Network.getValue().equals(hostv6Network.getValue())) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
grouping has-location {
container real-location {
choice location-type {
- case regular-location {
+ case regular-location-case {
uses has-regular-location;
}
- case external-location {
+ case external-location-case {
uses has-external-location;
}
}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+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.common.rev140421.ActionDefinitionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
public class IidFactoryTest {
+ private final String LOCATION_PROVIDER_NAME = "location-provider";
+ private final String IP_ADDRESS = "192.68.50.71";
+ private final String IP_PREFIX = "192.168.50.0/24";
+ private final String L3_CONTEXT_ID = "l3Context";
+
private TenantId tenantId;
private EndpointGroupId epgId;
private ContractId contractId;
Assert.assertEquals(epgId, identifier.firstKeyOf(ExternalImplicitGroup.class).getId());
}
+ @Test
+ public void testProviderAddressEndpointLocationIid() {
+ ContextId l3Context = new ContextId(L3_CONTEXT_ID);
+ InstanceIdentifier<ProviderAddressEndpointLocation> identifier = IidFactory
+ .providerAddressEndpointLocationIid(LOCATION_PROVIDER_NAME, IpPrefixType.class, IP_ADDRESS,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
+ l3Context)
+ .build();
+ Assert.assertEquals(LOCATION_PROVIDER_NAME,
+ identifier.firstKeyOf(LocationProvider.class).getProvider().getValue());
+ Assert.assertEquals(IP_ADDRESS, identifier.firstKeyOf(ProviderAddressEndpointLocation.class).getAddress());
+ Assert.assertEquals(l3Context, identifier.firstKeyOf(ProviderAddressEndpointLocation.class).getContextId());
+ }
+
+ @Test
+ public void testAddressEndpointIid() {
+ ContextId l3Context = new ContextId(L3_CONTEXT_ID);
+ InstanceIdentifier<AddressEndpoint> identifier =
+ IidFactory.addressEndpointIid(new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(l3Context),
+ org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class
+ ));
+ Assert.assertEquals(IpPrefixType.class, identifier.firstKeyOf(AddressEndpoint.class).getAddressType());
+ Assert.assertEquals(IP_ADDRESS, identifier.firstKeyOf(AddressEndpoint.class).getAddress());
+ Assert.assertEquals(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context.class,
+ identifier.firstKeyOf(AddressEndpoint.class).getContextType());
+ Assert.assertEquals(l3Context, identifier.firstKeyOf(AddressEndpoint.class).getContextId());
+ }
}
--- /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.util;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+
+public class NetUtilsTest {
+
+ private final String IPV4_ADDRESS_1 = "192.168.50.20";
+ private final String IPV4_ADDRESS_2 = "10.0.0.1";
+ private final String IPV6_HOST_ADDRESS = "DEAD:BEEF::1";
+ private final String IPV6_NETWORK_ADDRESS_1 = "DEAD:BEEF::";
+ private final String IPV6_NETWORK_ADDRESS_2 = "DEAF:BABE::";
+ private final String MASK_16 = "/16";
+ private final String MASK_24 = "/24";
+ private final String MASK_32 = "/32";
+ private final String MASK_64 = "/64";
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testGetMaskFromPrefix_FromNull () {
+ thrown.expect(NumberFormatException.class);
+ NetUtils.getMaskFromPrefix(null);
+ }
+
+ @Test
+ public void testGetMaskFromPrefix_StringWithouPrefix () {
+ thrown.expect(NumberFormatException.class);
+ NetUtils.getMaskFromPrefix(IPV4_ADDRESS_1);
+ }
+
+ @Test
+ public void testGetMaskFromPrefix_Correct () {
+ int result = NetUtils.getMaskFromPrefix(IPV4_ADDRESS_1 + MASK_24);
+ Assert.assertEquals(24, result);
+ }
+
+ @Test
+ public void testGetIpAddrFromPrefix_FromNull () {
+ String result = NetUtils.getIpAddrFromPrefix(null);
+ Assert.assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testGetIpAddrFromPrefix_StringWithouPrefixLength () {
+ String result = NetUtils.getIpAddrFromPrefix(IPV4_ADDRESS_1);
+ Assert.assertEquals(IPV4_ADDRESS_1, result);
+ }
+
+ @Test
+ public void testGetIpAddrFromPrefix_Ipv4Prefix () {
+ String result = NetUtils.getIpAddrFromPrefix(IPV4_ADDRESS_1 + MASK_24);
+ Assert.assertEquals(IPV4_ADDRESS_1, result);
+ }
+
+ @Test
+ public void testGetIpAddrFromPrefix_Ipv6Prefix () {
+ String result = NetUtils.getIpAddrFromPrefix(IPV6_HOST_ADDRESS + MASK_64);
+ Assert.assertEquals(IPV6_HOST_ADDRESS, result);
+ }
+
+ @Test
+ public void testApplyMaskOnIpv6Prefix_NullPrefix () {
+ Ipv6Address result = NetUtils.applyMaskOnIpv6Prefix(null, 0);
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void testApplyMaskOnIpv6Prefix_PrefixLengthOutOfRange () {
+ Ipv6Prefix prefix = new Ipv6Prefix(IPV6_HOST_ADDRESS + MASK_64);
+ thrown.expect(IllegalArgumentException.class);
+ NetUtils.applyMaskOnIpv6Prefix(prefix, 130);
+ }
+
+ @Test
+ public void testApplyMaskOnIpv6Prefix_Correct () {
+ Ipv6Prefix prefix = new Ipv6Prefix(IPV6_HOST_ADDRESS + MASK_64);
+ Ipv6Address result = NetUtils.applyMaskOnIpv6Prefix(prefix, 64);
+ Assert.assertTrue(IPV6_NETWORK_ADDRESS_1.equalsIgnoreCase(result.getValue()));
+ }
+
+ @Test
+ public void testApplyMaskOnIpv6Address_NullAddress () {
+ Ipv6Address result = NetUtils.applyMaskOnIpv6Address(null, 0);
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void testApplyMaskOnIpv6Address_PrefixLengthOutOfRange () {
+ Ipv6Address prefix = new Ipv6Address(IPV6_HOST_ADDRESS);
+ thrown.expect(IllegalArgumentException.class);
+ NetUtils.applyMaskOnIpv6Address(prefix, 130);
+ }
+
+ @Test
+ public void testApplyMaskOnIpv6Address_Correct () {
+ Ipv6Address prefix = new Ipv6Address(IPV6_HOST_ADDRESS);
+ Ipv6Address result = NetUtils.applyMaskOnIpv6Address(prefix, 64);
+ Assert.assertTrue(IPV6_NETWORK_ADDRESS_1.equalsIgnoreCase(result.getValue()));
+ }
+
+ @Test
+ public void testSamePrefix_NullInput () {
+ Ipv4Prefix prefix = new Ipv4Prefix(IPV4_ADDRESS_1 + MASK_24);
+ boolean result = NetUtils.samePrefix(new IpPrefix(prefix), null);
+ Assert.assertFalse(result);
+ result = NetUtils.samePrefix(null, new IpPrefix(prefix));
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void testSamePrefix_Ipv6AndIpv4 () {
+ Ipv4Prefix prefix4 = new Ipv4Prefix(IPV4_ADDRESS_1 + MASK_24);
+ Ipv6Prefix prefix6 = new Ipv6Prefix(IPV6_HOST_ADDRESS + MASK_64);
+ boolean result = NetUtils.samePrefix(new IpPrefix(prefix4), new IpPrefix(prefix6));
+ Assert.assertFalse(result);
+ result = NetUtils.samePrefix(new IpPrefix(prefix6), new IpPrefix(prefix4));
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void testSamePrefix_Ipv4DifferentNetwork () {
+ Ipv4Prefix prefix1 = new Ipv4Prefix(IPV4_ADDRESS_1 + MASK_24);
+ Ipv4Prefix prefix2 = new Ipv4Prefix(IPV4_ADDRESS_2 + MASK_24);
+ boolean result = NetUtils.samePrefix(new IpPrefix(prefix1), new IpPrefix(prefix2));
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void testSamePrefix_Ipv6DifferentNetwork () {
+ Ipv6Prefix prefix1 = new Ipv6Prefix(IPV6_HOST_ADDRESS + MASK_64);
+ Ipv6Prefix prefix2 = new Ipv6Prefix(IPV6_NETWORK_ADDRESS_2 + MASK_64);
+ boolean result = NetUtils.samePrefix(new IpPrefix(prefix1), new IpPrefix(prefix2));
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void testSamePrefix_Ipv4DifferentPrefix () {
+ Ipv4Prefix prefix1 = new Ipv4Prefix(IPV4_ADDRESS_1 + MASK_24);
+ Ipv4Prefix prefix2 = new Ipv4Prefix(IPV4_ADDRESS_1 + MASK_16);
+ boolean result = NetUtils.samePrefix(new IpPrefix(prefix1), new IpPrefix(prefix2));
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void testSamePrefix_Ipv6DifferentPrefix () {
+ Ipv6Prefix prefix1 = new Ipv6Prefix(IPV6_HOST_ADDRESS + MASK_64);
+ Ipv6Prefix prefix2 = new Ipv6Prefix(IPV6_NETWORK_ADDRESS_2 + MASK_32);
+ boolean result = NetUtils.samePrefix(new IpPrefix(prefix1), new IpPrefix(prefix2));
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void testSamePrefix_Ipv4SamePrefix () {
+ Ipv6Prefix prefix = new Ipv6Prefix(IPV6_HOST_ADDRESS + MASK_24);
+ boolean result = NetUtils.samePrefix(new IpPrefix(prefix), new IpPrefix(prefix));
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testSamePrefix_Ipv6SamePrefix () {
+ Ipv6Prefix prefix = new Ipv6Prefix(IPV6_HOST_ADDRESS + MASK_64);
+ boolean result = NetUtils.samePrefix(new IpPrefix(prefix), new IpPrefix(prefix));
+ Assert.assertTrue(result);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy-location-providers</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <artifactId>ne-location-provider</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.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <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.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <!-- project build -->
+ <build>
+ <!-- We use the maven-resources-plugin to copy a class from the groupbasepolicy
+ bundle that we need in order to run some unit tests in the renderer (classes
+ in the test directory aren't packaged in bundles, and instead of keeping
+ separate copies, we just copy the file(s) needed in order to run the test). -->
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ne.location.provider.rev160421.*
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+ <configuration>
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:ne-location="urn:opendaylight:params:xml:ns:yang:controller:config:ne:location:provider:cfg">
+ ne-location:ne-location-provider
+ </type>
+ <name>ne-location-provider</name>
+
+ <data-broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+ <name>binding-data-broker</name>
+ </data-broker>
+ </module>
+ </modules>
+ </data>
+
+ </configuration>
+
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:ne:location:provider:cfg?module=ne-location-provider-cfg&revision=2016-04-21</capability>
+ </required-capabilities>
+
+</snapshot>
--- /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.controller.config.yang.config.ne.location.provider.cfg;
+
+import org.opendaylight.groupbasedpolicy.ne.location.provider.NeLocationProvider;
+
+public class NeLocationProviderModule extends org.opendaylight.controller.config.yang.config.ne.location.provider.cfg.AbstractNeLocationProviderModule {
+ public NeLocationProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public NeLocationProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.ne.location.provider.cfg.NeLocationProviderModule 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 NeLocationProvider(getDataBrokerDependency());
+ }
+
+}
--- /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.controller.config.yang.config.ne.location.provider.cfg;
+public class NeLocationProviderModuleFactory extends org.opendaylight.controller.config.yang.config.ne.location.provider.cfg.AbstractNeLocationProviderModuleFactory {
+
+}
--- /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.ne.location.provider;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EndpointsListener implements DataTreeChangeListener<AddressEndpoint>{
+
+ private static final Logger LOG = LoggerFactory.getLogger(EndpointsListener.class);
+
+ private NeLocationProvider listener;
+ private ListenerRegistration<EndpointsListener> listenerRegistration;
+
+ public EndpointsListener (DataBroker dataBroker, NeLocationProvider listener) {
+ this.listener = listener;
+ this.listenerRegistration = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(Endpoints.class)
+ .child(AddressEndpoints.class).child(AddressEndpoint.class).build()), this);
+ LOG.info("NE location provider registered for Endpoints listening");
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<AddressEndpoint>> changes) {
+ listener.onEndpointsChange(changes);
+ }
+
+ public void close() {
+ this.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.ne.location.provider;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+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.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.util.NetUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.location.RealLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.location.RealLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.location.real.location.location.type.RegularLocationCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElements;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElementsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.NetworkElement;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetwork;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class NeLocationProvider implements DataTreeChangeListener<NetworkElements>, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeLocationProvider.class);
+ public static final String NE_LOCATION_PROVIDER_NAME = "ne-location-provider";
+
+ private List<AddressEndpoint> endpoints;
+ private NetworkElements networkElements;
+ private DataBroker dataBroker;
+ private ListenerRegistration<NeLocationProvider> listenerRegistration;
+ private EndpointsListener endpointsListener;
+
+ public NeLocationProvider(DataBroker dataBroker) {
+ this.listenerRegistration =
+ dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.builder(NetworkElements.class).build()), this);
+ this.endpoints = new ArrayList<>();
+ this.networkElements = new NetworkElementsBuilder().build();
+ this.dataBroker = dataBroker;
+ this.endpointsListener = new EndpointsListener(dataBroker, this);
+ LOG.info("NE location provider created");
+ }
+
+ @Override
+ public void close() {
+ this.listenerRegistration.close();
+ this.endpointsListener.close();
+ }
+
+ public synchronized void onEndpointsChange(Collection<DataTreeModification<AddressEndpoint>> changes) {
+ for (DataTreeModification<AddressEndpoint> change : changes) {
+ switch (change.getRootNode().getModificationType()) {
+ case DELETE: {
+ AddressEndpoint endpoint = change.getRootNode().getDataBefore();
+ removeLocationForEndpoint(endpoint);
+ this.endpoints.remove(endpoint);
+ break;
+ }
+ case WRITE: {
+ AddressEndpoint endpoint = change.getRootNode().getDataBefore();
+ if (endpoint != null) {
+ this.endpoints.remove(endpoint);
+ this.endpoints.add(change.getRootNode().getDataAfter());
+ break;
+ }
+ endpoint = change.getRootNode().getDataAfter();
+ createLocationForEndpoint(endpoint);
+ this.endpoints.add(endpoint);
+ break;
+ }
+ case SUBTREE_MODIFIED: {
+ this.endpoints.remove(change.getRootNode().getDataBefore());
+ this.endpoints.add(change.getRootNode().getDataAfter());
+ break;
+ }
+ }
+ }
+ }
+
+ private void createLocationForEndpoint(AddressEndpoint endpoint) {
+ for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
+ for (Interface iface : nullToEmpty(ne.getInterface())) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ if (endpoint.getContextType().isAssignableFrom(L3Context.class)
+ && endpoint.getContextId().equals(en.getL3ContextId())
+ && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
+ .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ InstanceIdentifier<RealLocation> iid = IidFactory
+ .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
+ endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
+ .child(RealLocation.class)
+ .build();
+ wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(ne.getIid(), iface.getIid()),
+ true);
+ wtx.submit();
+ LOG.debug("New location created for endpoint {}", endpoint);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private void removeLocationForEndpoint(AddressEndpoint endpoint) {
+ for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
+ for (Interface iface : nullToEmpty(ne.getInterface())) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ if (endpoint.getContextType().isAssignableFrom(L3Context.class)
+ && endpoint.getContextId().equals(en.getL3ContextId())
+ && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
+ .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ InstanceIdentifier<RealLocation> iid = IidFactory
+ .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
+ endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
+ .child(RealLocation.class)
+ .build();
+ wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+ wtx.submit();
+ LOG.debug("Location deleted for endpoint {}", endpoint);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public synchronized void onDataTreeChanged(Collection<DataTreeModification<NetworkElements>> changes) {
+ for (DataTreeModification<NetworkElements> change : changes) {
+ switch (change.getRootNode().getModificationType()) {
+ case DELETE: {
+ NetworkElements nes = change.getRootNode().getDataBefore();
+ for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
+ for (Interface iface : nullToEmpty(ne.getInterface())) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processDeletedEN(en, ne.getIid(), iface.getIid());
+ }
+ }
+ }
+ networkElements = new NetworkElementsBuilder().build();
+ LOG.debug("Network elements removed");
+ break;
+ }
+ case WRITE: {
+ NetworkElements nes = change.getRootNode().getDataBefore();
+ if (nes != null) {
+ for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
+ for (Interface iface : nullToEmpty(ne.getInterface())) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processDeletedEN(en, ne.getIid(), iface.getIid());
+ }
+ }
+ }
+ }
+ nes = change.getRootNode().getDataAfter();
+ for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
+ for (Interface iface : nullToEmpty(ne.getInterface())) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processCreatedEN(en, ne.getIid(), iface.getIid());
+ }
+ }
+ }
+ networkElements = nes;
+ LOG.debug("New Network elements created {}", change.getRootNode().getDataAfter());
+ break;
+ }
+ case SUBTREE_MODIFIED: {
+ List<DataObjectModification<NetworkElement>> modifiedNetworkElements =
+ getModifiedNetworkElements(change.getRootNode());
+ for (DataObjectModification<NetworkElement> netElement : modifiedNetworkElements) {
+ processNetworkElementChange(netElement);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private List<DataObjectModification<NetworkElement>> getModifiedNetworkElements(
+ DataObjectModification<NetworkElements> modifiedNEs) {
+ Collection<DataObjectModification<? extends DataObject>> potentialModifiedNetworkElements =
+ modifiedNEs.getModifiedChildren();
+ if (potentialModifiedNetworkElements == null) {
+ return Collections.emptyList();
+ }
+ List<DataObjectModification<NetworkElement>> nes = new ArrayList<>();
+ for (DataObjectModification<? extends DataObject> potentialModifiedNetworkElement : potentialModifiedNetworkElements) {
+ if (potentialModifiedNetworkElement.getDataType().isAssignableFrom(NetworkElement.class)) {
+ nes.add((DataObjectModification<NetworkElement>) potentialModifiedNetworkElement);
+ }
+ }
+ return nes;
+ }
+
+ private void processNetworkElementChange(DataObjectModification<NetworkElement> netElement) {
+ switch (netElement.getModificationType()) {
+ case DELETE: {
+ NetworkElement ne = netElement.getDataBefore();
+ for (Interface iface : nullToEmpty(ne.getInterface())) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processDeletedEN(en, ne.getIid(), iface.getIid());
+ }
+ }
+ networkElements.getNetworkElement().remove(ne);
+ LOG.debug("Netowrk element {} removed", netElement.getDataBefore());
+ break;
+ }
+ case WRITE: {
+ NetworkElement ne = netElement.getDataBefore();
+ if (ne != null) {
+ for (Interface iface : nullToEmpty(ne.getInterface())) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processDeletedEN(en, ne.getIid(), iface.getIid());
+ }
+ }
+ networkElements.getNetworkElement().remove(ne);
+ }
+ ne = netElement.getDataAfter();
+ for (Interface iface : nullToEmpty(ne.getInterface())) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processCreatedEN(en, ne.getIid(), iface.getIid());
+ }
+ }
+ networkElements.getNetworkElement().add(ne);
+ LOG.debug("Created new Network element {}", netElement.getDataAfter());
+ break;
+ }
+ case SUBTREE_MODIFIED: {
+ List<DataObjectModification<Interface>> modifiedInterfaces = getModifiedInterfaces(netElement);
+ for (DataObjectModification<Interface> modifiedInterface : modifiedInterfaces) {
+ processInterfaceChange(modifiedInterface, netElement.getDataBefore());
+ }
+ break;
+ }
+ }
+ }
+
+ private List<DataObjectModification<Interface>> getModifiedInterfaces(
+ DataObjectModification<NetworkElement> netElement) {
+ Collection<DataObjectModification<? extends DataObject>> potentialModifiedInterfaces =
+ netElement.getModifiedChildren();
+ if (potentialModifiedInterfaces == null) {
+ return Collections.emptyList();
+ }
+ List<DataObjectModification<Interface>> interfaces = new ArrayList<>();
+ for (DataObjectModification<? extends DataObject> potentialModifiedInterface : potentialModifiedInterfaces) {
+ if (potentialModifiedInterface.getDataType().isAssignableFrom(Interface.class)) {
+ interfaces.add((DataObjectModification<Interface>) potentialModifiedInterface);
+ }
+ }
+ return interfaces;
+ }
+
+ private void processInterfaceChange(DataObjectModification<Interface> modifiedInterface,
+ NetworkElement nodeBefore) {
+ switch (modifiedInterface.getModificationType()) {
+ case DELETE: {
+ Interface iface = modifiedInterface.getDataBefore();
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processDeletedEN(en, nodeBefore.getIid(), iface.getIid());
+ }
+ int nodeIndex = getIndexOf(nodeBefore);
+ networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
+ LOG.debug("Interface {} removed", modifiedInterface.getDataBefore());
+ break;
+ }
+ case WRITE: {
+ Interface iface = modifiedInterface.getDataBefore();
+ int nodeIndex = getIndexOf(nodeBefore);
+ if (iface != null) {
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processDeletedEN(en, nodeBefore.getIid(), iface.getIid());
+ }
+ networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
+ }
+ iface = modifiedInterface.getDataAfter();
+ for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
+ processCreatedEN(en, nodeBefore.getIid(), iface.getIid());
+ }
+ networkElements.getNetworkElement().get(nodeIndex).getInterface().add(iface);
+ LOG.debug("Created new Interface {}", modifiedInterface.getDataAfter());
+ break;
+ }
+ case SUBTREE_MODIFIED: {
+ List<DataObjectModification<EndpointNetwork>> modifiedENs =
+ getModifiedEndpointNetworks(modifiedInterface);
+ for (DataObjectModification<EndpointNetwork> modifiedEN : modifiedENs) {
+ processEndpointNetworkChange(modifiedEN, nodeBefore, modifiedInterface.getDataBefore());
+ }
+ break;
+ }
+ }
+ }
+
+ private List<DataObjectModification<EndpointNetwork>> getModifiedEndpointNetworks(
+ DataObjectModification<Interface> modifiedInterface) {
+ Collection<DataObjectModification<? extends DataObject>> potentialModifiedEPs =
+ modifiedInterface.getModifiedChildren();
+ if (potentialModifiedEPs == null) {
+ return Collections.emptyList();
+ }
+ List<DataObjectModification<EndpointNetwork>> eps = new ArrayList<>();
+ for (DataObjectModification<? extends DataObject> potentialModifiedEP : potentialModifiedEPs) {
+ if (potentialModifiedEP.getDataType().isAssignableFrom(EndpointNetwork.class)) {
+ eps.add((DataObjectModification<EndpointNetwork>) potentialModifiedEP);
+ }
+ }
+ return eps;
+ }
+
+ private void processEndpointNetworkChange(DataObjectModification<EndpointNetwork> modifiedEN,
+ NetworkElement nodeBefore, Interface ifaceBefore) {
+ switch (modifiedEN.getModificationType()) {
+ case DELETE: {
+ processDeletedEN(modifiedEN.getDataBefore(), nodeBefore.getIid(), ifaceBefore.getIid());
+ int nodeIndex = getIndexOf(nodeBefore);
+ int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
+ networkElements.getNetworkElement()
+ .get(nodeIndex)
+ .getInterface()
+ .get(ifaceIndex)
+ .getEndpointNetwork()
+ .remove(modifiedEN.getDataBefore());
+ LOG.debug("Endpoint network {} removed", modifiedEN.getDataBefore());
+ break;
+ }
+ case WRITE: {
+ processCreatedEN(modifiedEN.getDataAfter(), nodeBefore.getIid(), ifaceBefore.getIid());
+ int nodeIndex = getIndexOf(nodeBefore);
+ int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
+ networkElements.getNetworkElement()
+ .get(nodeIndex)
+ .getInterface()
+ .get(ifaceIndex)
+ .getEndpointNetwork()
+ .add(modifiedEN.getDataAfter());
+ LOG.debug("Created new Endpoint network {}", modifiedEN.getDataAfter());
+ break;
+ }
+ case SUBTREE_MODIFIED: {
+ LOG.debug("EndpointNetwork {} changed", modifiedEN.getDataAfter().getKey());
+ break;
+ }
+ }
+ }
+
+ private void processCreatedEN(EndpointNetwork en, InstanceIdentifier<?> nodeIID,
+ InstanceIdentifier<?> connectorIID) {
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ for (AddressEndpoint endpoint : endpoints) {
+ if (endpoint.getContextType().isAssignableFrom(L3Context.class)
+ && endpoint.getContextId().equals(en.getL3ContextId())
+ && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class)
+ && NetUtils.samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
+ InstanceIdentifier<RealLocation> iid = IidFactory
+ .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
+ endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
+ .child(RealLocation.class)
+ .build();
+ wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(nodeIID, connectorIID), true);
+ wtx.submit();
+ LOG.debug("New location created for endpoint {}", endpoint);
+ return;
+ }
+ }
+ }
+
+ private void processDeletedEN(EndpointNetwork en, InstanceIdentifier<?> nodeIID,
+ InstanceIdentifier<?> connectorIID) {
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ for (AddressEndpoint endpoint : endpoints) {
+ if (endpoint.getContextType().isAssignableFrom(L3Context.class)
+ && endpoint.getContextId().equals(en.getL3ContextId())
+ && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class)
+ && NetUtils.samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
+ InstanceIdentifier<RealLocation> iid = IidFactory
+ .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
+ endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
+ .child(RealLocation.class)
+ .build();
+ wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+ wtx.submit();
+ LOG.debug("Location deleted for endpoint {}", endpoint);
+ return;
+ }
+ }
+ }
+
+ private RealLocation createRealLocation(InstanceIdentifier<?> node, InstanceIdentifier<?> iface) {
+ return new RealLocationBuilder()
+ .setLocationType(new RegularLocationCaseBuilder().setNode(node).setNodeConnector(iface).build()).build();
+ }
+
+ private <T> List<T> nullToEmpty(@Nullable List<T> list) {
+ return list == null ? Collections.emptyList() : list;
+ }
+
+ private int getIndexOf(NetworkElement ne) {
+ for (NetworkElement listNE : networkElements.getNetworkElement()) {
+ if (ne.getIid().equals(listNE.getIid())) {
+ return networkElements.getNetworkElement().indexOf(listNE);
+ }
+ }
+ return -1;
+ }
+
+ private int getIndexOf(Interface iface, int nodeIndex) {
+ for (Interface listIface : networkElements.getNetworkElement().get(nodeIndex).getInterface()) {
+ if (iface.getIid().equals(listIface.getIid())) {
+ return networkElements.getNetworkElement().get(nodeIndex).getInterface().indexOf(listIface);
+ }
+ }
+ return -1;
+ }
+
+ @VisibleForTesting
+ synchronized List<AddressEndpoint> getEndpoints() {
+ return endpoints;
+ }
+
+ @VisibleForTesting
+ synchronized NetworkElements getNetworkElements() {
+ return networkElements;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+module ne-location-provider-cfg {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:config:ne:location:provider:cfg";
+ prefix "ne-location-provider-cfg";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+
+ description
+ "This module contains the base YANG definitions for
+ ne location provider implementation.";
+
+ revision "2016-04-21" {
+ description
+ "Initial revision.";
+ }
+
+ identity ne-location-provider {
+ base "config:module-type";
+
+ config:java-name-prefix NeLocationProvider;
+ }
+
+ // Augments the 'configuration' choice node under modules/module.
+ augment "/config:modules/config:module/config:configuration" {
+ case ne-location-provider {
+ when "/config:modules/config:module/config:type = 'ne-location-provider'";
+
+ // 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;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+ module network-elements {
+ yang-version 1;
+
+ namespace "urn:opendaylight:groupbasedpolicy:endpoint:network:elements";
+ prefix "network-elements";
+
+ import gbp-common {
+ prefix gbp-common;
+ revision-date 2014-04-21;
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date 2010-09-24;
+ }
+
+ description
+ "This module defines network element structure for location provider.";
+
+ revision "2016-04-07" {
+ description
+ "Initial revision.";
+ }
+
+ container network-elements {
+ list network-element {
+ key iid;
+ leaf iid {
+ description "Path to the network element
+ represented in topology of southbound plugin.";
+ type instance-identifier;
+ }
+ list interface {
+ key "iid";
+ leaf iid {
+ description "Path to the interface
+ represented in topology of southbound plugin.
+ This should be more like RelativeSchemaPath
+ from network-element's IID to interface.";
+ type instance-identifier;
+ }
+ list endpoint-network {
+ description "Set of networks somewhere behind the interface.
+ Networks where an endpoint can be connected.";
+ key "l3-context-id ip-prefix";
+ leaf l3-context-id {
+ type gbp-common:context-id;
+ }
+ leaf ip-prefix {
+ type inet:ip-prefix;
+ description
+ "The IP prefix where an endpoint can be connected.";
+ }
+ }
+ }
+ }
+ }
+
+}
\ 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.ne.location.provider;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.endpoints.AddressEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EndpointsListenerTest {
+
+ private EndpointsListener endpointsListener;
+ private NeLocationProvider listener;
+ private DataBroker dataBroker;
+ private ListenerRegistration<EndpointsListener> listenerRegistration;
+
+ @Before
+ public void init () {
+ dataBroker = mock(DataBroker.class);
+ listenerRegistration = mock(ListenerRegistration.class);
+ when(dataBroker.registerDataTreeChangeListener(any(), Matchers.any(EndpointsListener.class)))
+ .thenReturn(listenerRegistration);
+ listener = mock(NeLocationProvider.class);
+ endpointsListener = new EndpointsListener(dataBroker, listener);
+ }
+
+ @Test
+ public void test_RegistrationDone () {
+ verify(dataBroker).registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(Endpoints.class).child(AddressEndpoints.class)
+ .child(AddressEndpoint.class).build()), endpointsListener);
+ }
+
+ @Test
+ public void test_ListenerNotification () {
+ endpointsListener.onDataTreeChanged(null);
+ verify(listener).onEndpointsChange(any());
+ }
+
+ @Test
+ public void test_UnregiserOnClose () {
+ endpointsListener.close();
+ verify(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.ne.location.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
+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.AddressEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElements;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElementsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.NetworkElement;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.NetworkElementBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.NetworkElementKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetwork;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetworkKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.CheckedFuture;
+
+public class NeLocationProviderTest extends CustomDataBrokerTest {
+
+ private DataBroker dataBroker;
+ private NeLocationProvider neProvider;
+ private String L3_CONTEXT_ID = "l3Context";
+ private String IPv4_HOST_ADDRESS_1 = "192.168.50.71";
+ private String IPv4_HOST_ADDRESS_2 = "192.168.50.72";
+ private String IPv4_NETWORK_ADDRESS_1 = "192.168.50.0/24";
+ private String IPv4_NETWORK_ADDRESS_2 = "192.168.51.0/24";
+ private String NODE_ID_1 = "node1";
+ private String NODE_ID_2 = "node2";
+ private String CONNECTOR_ID_1 = "connector:1";
+ private String CONNECTOR_ID_2 = "connector:2";
+
+ @Override
+ public Collection<Class<?>> getClassesFromModules() {
+ return ImmutableList.<Class<?>>of(NetworkElements.class, EndpointLocations.class, Endpoints.class, L3Context.class, Nodes.class);
+ }
+
+ @Before
+ public void init() {
+ dataBroker = getDataBroker();
+ neProvider = new NeLocationProvider(dataBroker);
+ }
+
+ @Test
+ public void test_NetworkElementsListenerRegistration() {
+ DataBroker dataBroker = mock(DataBroker.class);
+ NeLocationProvider provider = new NeLocationProvider(dataBroker);
+ verify(dataBroker).registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.builder(NetworkElements.class).build()), provider);
+ }
+
+ @Test
+ public void test_EndpointsListenerRegistration() {
+ DataBroker dataBroker = mock(DataBroker.class);
+ new NeLocationProvider(dataBroker);
+ verify(dataBroker)
+ .registerDataTreeChangeListener(eq(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(Endpoints.class).child(AddressEndpoints.class)
+ .child(AddressEndpoint.class).build())), isA(EndpointsListener.class));
+ }
+
+ @Test
+ public void test_ListenersUnregistration() {
+ DataBroker dataBroker = mock(DataBroker.class);
+ ListenerRegistration<EndpointsListener> endpointsListenerRegistration = mock(ListenerRegistration.class);
+ when(dataBroker.registerDataTreeChangeListener(any(), isA(EndpointsListener.class)))
+ .thenReturn(endpointsListenerRegistration);
+ ListenerRegistration<NeLocationProvider> NEListenerRegistration = mock(ListenerRegistration.class);
+ when(dataBroker.registerDataTreeChangeListener(any(), isA(NeLocationProvider.class)))
+ .thenReturn(NEListenerRegistration);
+ NeLocationProvider provider = new NeLocationProvider(dataBroker);
+ provider.close();
+ verify(endpointsListenerRegistration).close();
+ verify(NEListenerRegistration).close();
+ }
+
+ @Test
+ public void test_AddressEndpointWrite_NoNE_NoOverwrite() throws Exception {
+ AddressEndpoint endpoint =
+ createAddressEndpoint(IPv4_HOST_ADDRESS_1, IpPrefixType.class, L3_CONTEXT_ID, L3Context.class);
+ InstanceIdentifier<AddressEndpoint> iid = IidFactory.addressEndpointIid(endpoint.getKey());
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.put(LogicalDatastoreType.OPERATIONAL, iid, endpoint, true);
+ wtx.submit().get();
+ List<AddressEndpoint> endpoints = neProvider.getEndpoints();
+ assertEquals(1, endpoints.size());
+ assertEquals(endpoint, endpoints.get(0));
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_AddressEndpointWrite_NoNE_Overwrite() throws Exception {
+ test_AddressEndpointWrite_NoNE_NoOverwrite();
+ NetworkContainment nc = new NetworkContainmentBuilder()
+ .setNetworkDomainId(new NetworkDomainId(L3_CONTEXT_ID))
+ .build();
+ InstanceIdentifier<NetworkContainment> iid = InstanceIdentifier
+ .builder(Endpoints.class)
+ .child(AddressEndpoints.class)
+ .child(AddressEndpoint.class, new AddressEndpointKey(IPv4_HOST_ADDRESS_1, IpPrefixType.class,
+ new ContextId(L3_CONTEXT_ID), L3Context.class))
+ .child(NetworkContainment.class)
+ .build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.put(LogicalDatastoreType.OPERATIONAL, iid, nc);
+ wtx.submit().get();
+ List<AddressEndpoint> l3Endpoint = neProvider.getEndpoints();
+ assertEquals(1, l3Endpoint.size());
+ assertNotNull(l3Endpoint.get(0).getNetworkContainment());
+ assertEquals(nc, l3Endpoint.get(0).getNetworkContainment());
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_EndpointsDelete_NoNE() throws Exception {
+ test_AddressEndpointWrite_NoNE_NoOverwrite();
+ InstanceIdentifier<Endpoints> iid = InstanceIdentifier.builder(Endpoints.class)
+ .build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+ wtx.submit().get();
+ List<AddressEndpoint> l3Endpoint = neProvider.getEndpoints();
+ assertEquals(0, l3Endpoint.size());
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_EndpointsModify_NoNE() throws Exception {
+ test_AddressEndpointWrite_NoNE_NoOverwrite();
+ InstanceIdentifier<Endpoints> iid = InstanceIdentifier.builder(Endpoints.class)
+ .build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+ wtx.submit().get();
+ List<AddressEndpoint> l3Endpoint = neProvider.getEndpoints();
+ assertEquals(0, l3Endpoint.size());
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_NetworkElementsWrite_NoEP_NoOverwrite() throws Exception {
+ NetworkElements nes = createNetworkElements(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_1);
+ InstanceIdentifier<NetworkElements> iid = InstanceIdentifier.builder(NetworkElements.class).build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.put(LogicalDatastoreType.CONFIGURATION, iid, nes);
+ wtx.submit().get();
+ NetworkElements networkElements = neProvider.getNetworkElements();
+ assertEquals(nes, networkElements);
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_NetworkElementsWrite_NoEP_Overwrite() throws Exception {
+ test_NetworkElementsWrite_NoEP_NoOverwrite();
+ NetworkElements nes = createNetworkElements(NODE_ID_2, CONNECTOR_ID_2, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_1);
+ InstanceIdentifier<NetworkElements> iid = InstanceIdentifier.builder(NetworkElements.class).build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.put(LogicalDatastoreType.CONFIGURATION, iid, nes);
+ wtx.submit().get();
+ NetworkElements networkElements = neProvider.getNetworkElements();
+ assertEquals(nes, networkElements);
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_NetworkElementWrite_NoEP_Overwrite() throws Exception {
+ test_NetworkElementsWrite_NoEP_NoOverwrite();
+ NetworkElement ne = createNetworkElement(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_2);
+ InstanceIdentifier<NetworkElement> iid = InstanceIdentifier.builder(NetworkElements.class)
+ .child(NetworkElement.class, new NetworkElementKey(ne.getKey()))
+ .build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.put(LogicalDatastoreType.CONFIGURATION, iid, ne);
+ wtx.submit().get();
+ NetworkElements nes = neProvider.getNetworkElements();
+ assertNotNull(nes.getNetworkElement());
+ assertEquals(1, nes.getNetworkElement().size());
+ assertEquals(ne, nes.getNetworkElement().get(0));
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_InterfaceWrite_NoEP_Overwrite() throws Exception {
+ test_NetworkElementsWrite_NoEP_NoOverwrite();
+ Interface iface = createInterface(NODE_ID_1, CONNECTOR_ID_1, L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_2);
+ InstanceIdentifier<Interface> iid = InstanceIdentifier.builder(NetworkElements.class)
+ .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
+ .child(Interface.class, new InterfaceKey(iface.getKey()))
+ .build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.put(LogicalDatastoreType.CONFIGURATION, iid, iface);
+ wtx.submit().get();
+ NetworkElements nes = neProvider.getNetworkElements();
+ assertNotNull(nes.getNetworkElement());
+ assertEquals(1, nes.getNetworkElement().size());
+ assertNotNull(nes.getNetworkElement().get(0).getInterface());
+ assertEquals(1, nes.getNetworkElement().get(0).getInterface().size());
+ assertEquals(iface, nes.getNetworkElement().get(0).getInterface().get(0));
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_EndpointNetworkChange_NoEP() throws Exception {
+ test_NetworkElementsWrite_NoEP_NoOverwrite();
+ EndpointNetwork en = createEndpointNetwork(L3_CONTEXT_ID, IPv4_NETWORK_ADDRESS_2);
+ InstanceIdentifier<EndpointNetwork> iid = InstanceIdentifier.builder(NetworkElements.class)
+ .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
+ .child(Interface.class, new InterfaceKey(createInterfaceIid(NODE_ID_1, CONNECTOR_ID_1)))
+ .child(EndpointNetwork.class, new EndpointNetworkKey(en.getKey()))
+ .build();
+ InstanceIdentifier<EndpointNetwork> removeIid =
+ InstanceIdentifier.builder(NetworkElements.class)
+ .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
+ .child(Interface.class, new InterfaceKey(createInterfaceIid(NODE_ID_1, CONNECTOR_ID_1)))
+ .child(EndpointNetwork.class, new EndpointNetworkKey(
+ new IpPrefix(new Ipv4Prefix(IPv4_NETWORK_ADDRESS_1)),new ContextId(L3_CONTEXT_ID)))
+ .build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.delete(LogicalDatastoreType.CONFIGURATION, removeIid);
+ wtx.put(LogicalDatastoreType.CONFIGURATION, iid, en);
+ wtx.submit().get();
+ NetworkElements nes = neProvider.getNetworkElements();
+ assertNotNull(nes.getNetworkElement());
+ assertEquals(1, nes.getNetworkElement().size());
+ assertNotNull(nes.getNetworkElement().get(0).getInterface());
+ assertEquals(1, nes.getNetworkElement().get(0).getInterface().size());
+ assertNotNull(nes.getNetworkElement().get(0).getInterface().get(0).getEndpointNetwork());
+ assertEquals(1, nes.getNetworkElement().get(0).getInterface().get(0).getEndpointNetwork().size());
+ assertEquals(en, nes.getNetworkElement().get(0).getInterface().get(0).getEndpointNetwork().get(0));
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_NetworkElementsDelete() throws Exception {
+ test_NetworkElementsWrite_NoEP_NoOverwrite();
+ InstanceIdentifier<NetworkElements> iid = InstanceIdentifier.builder(NetworkElements.class).build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
+ wtx.submit().get();
+ NetworkElements nes = neProvider.getNetworkElements();
+ assertEquals(new NetworkElementsBuilder().build(), nes);
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_NetworkElementDelete() throws Exception {
+ test_NetworkElementsWrite_NoEP_NoOverwrite();
+ InstanceIdentifier<NetworkElement> iid = InstanceIdentifier.builder(NetworkElements.class)
+ .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
+ .build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
+ wtx.submit().get();
+ NetworkElements nes = neProvider.getNetworkElements();
+ assertNotNull(nes.getNetworkElement());
+ assertTrue(nes.getNetworkElement().isEmpty());
+ verifyEmptyLocations();
+ }
+
+ @Test
+ public void test_InterfaceDelete() throws Exception {
+ test_NetworkElementsWrite_NoEP_NoOverwrite();
+ InstanceIdentifier<Interface> iid = InstanceIdentifier.builder(NetworkElements.class)
+ .child(NetworkElement.class, new NetworkElementKey(createNetworkElementIid(NODE_ID_1)))
+ .child(Interface.class, new InterfaceKey(createInterfaceIid(NODE_ID_1, CONNECTOR_ID_1)))
+ .build();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
+ wtx.submit().get();
+ NetworkElements nes = neProvider.getNetworkElements();
+ assertNotNull(nes.getNetworkElement());
+ assertEquals(1, nes.getNetworkElement().size());
+ assertNotNull(nes.getNetworkElement().get(0).getInterface());
+ assertTrue(nes.getNetworkElement().get(0).getInterface().isEmpty());
+ verifyEmptyLocations();
+ }
+
+ private AddressEndpoint createAddressEndpoint(String ipAddr, Class<? extends AddressType> addrType,
+ String context, Class<? extends ContextType> cType) {
+ return new AddressEndpointBuilder().setAddress(ipAddr).setAddressType(addrType)
+ .setContextId(new ContextId(context)).setContextType(cType).build();
+ }
+
+ private NetworkElements createNetworkElements(String node, String iface, String l3c, String prefix) {
+ return new NetworkElementsBuilder()
+ .setNetworkElement(Collections.singletonList(createNetworkElement(node, iface, l3c, prefix))).build();
+ }
+
+ private NetworkElement createNetworkElement(String node, String iface, String l3c, String prefix) {
+ return new NetworkElementBuilder().setIid(createNetworkElementIid(node))
+ .setInterface(Collections.singletonList(createInterface(node, iface, l3c, prefix)))
+ .build();
+ }
+
+ private Interface createInterface(String node, String iface, String l3c, String prefix) {
+ return new InterfaceBuilder().setIid(createInterfaceIid(node, iface))
+ .setEndpointNetwork(Collections.singletonList(createEndpointNetwork(l3c, prefix)))
+ .build();
+ }
+
+ private EndpointNetwork createEndpointNetwork(String l3c, String prefix) {
+ return new EndpointNetworkBuilder().setIpPrefix(new IpPrefix(new Ipv4Prefix(prefix)))
+ .setL3ContextId(new ContextId(l3c))
+ .build();
+ }
+
+ private InstanceIdentifier<?> createNetworkElementIid(String node) {
+ return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId(node))).build();
+ }
+
+ private InstanceIdentifier<?> createInterfaceIid(String node, String connector) {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId(node)))
+ .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(connector)))
+ .build();
+ }
+
+ private void verifyEmptyLocations() throws Exception {
+ ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
+ InstanceIdentifier<EndpointLocations> locationIid = InstanceIdentifier.builder(EndpointLocations.class).build();
+ CheckedFuture<Optional<EndpointLocations>, ReadFailedException> read =
+ rtx.read(LogicalDatastoreType.OPERATIONAL, locationIid);
+ assertFalse(read.get().isPresent());
+ rtx.close();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy-location-providers</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>ne-location-provider</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
<module>artifacts</module>
<module>groupbasedpolicy</module>
<module>renderers</module>
+ <module>location-providers</module>
<module>neutron-mapper</module>
<module>neutron-ovsdb</module>
<module>ui-backend</module>