-BGP OpenConfig for ODL BGP RIB and peer/app-peer configuration (config-subsystem) and vice-versa
*RIBImpl <-> Global
*BGPPeer <-> Neighbor
*BGPApplicationPeer <-> Neighbor (belonging to special neighbors grupup "application-peers")
-support BGP configuration module to BGP OpenConfig mapping:
*once configuration of a particular BGP config module is created, the attributes
are mapped to OpenConfig API, configuration is stored and written do configuration DS
*once configuration of a particular BGP Configuration module is closed, a stored OpenConfig DTO
is removed and deleted from configuration DS
-support BGP OpenConfig API to BGP configuration module mapping
-application is listening to the changes in BGP OpenConfig DS subtree:
*when a new data are created or modified, the new BGP OpenConfig DTO is mapped to
BGP config module, the DTO is stored and config module is written to
controller-config's Modules subtree.
*when data is removed, the DTO is removed from inner store and BGP config module is removed
from controller-config's Modules subtree.
Motivation: Simplify configuration of the main ODL BGP components (mainly in programatic way) in a most used use-cases.
Limitations: BGP OpenConfig Yang data model is composed for configuration of one BGP speaker, ODL may have multiple instances of BGP Speaker
The change brings a dependecy on netconf's sal-nectonf-connector ot BGP project.
Change-Id: If245bd54d844bd9965637c83f382e82c6a5b9a53
Signed-off-by: Milos Fabian <milfabia@cisco.com>
<artifactId>bgp-openconfig-spi</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-openconfig-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-controller-config</artifactId>
<type>xml</type>
<classifier>bmp-config-example</classifier>
</artifact>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/43-bgp-openconfig.xml</file>
+ <type>xml</type>
+ <classifier>openconfig-config</classifier>
+ </artifact>
</artifacts>
</configuration>
</execution>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:bgp:openconfig?module=odl-openconfig-bgp-cfg&revision=2015-07-18</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:bgp-openconfig-spi?module=odl-bgp-openconfig-spi-cfg&revision=2015-09-25</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:bgp:rib:impl?module=odl-bgp-rib-impl-cfg&revision=2013-04-09</capability>
+ </required-capabilities>
+
+ <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:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgp:openconfig">prefix:openconfig-bgp</type>
+ <name>openconfig-bgp</name>
+ <binding-broker>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>
+ <name>binding-osgi-broker</name>
+ </binding-broker>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgp:rib:impl">prefix:rib-impl</type>
+ <name>example-bgp-rib</name>
+ <openconfig-provider>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgp-openconfig-spi">prefix:bgp-openconfig-provider</type>
+ <name>openconfig-bgp</name>
+ </openconfig-provider>
+ </module>
+ </modules>
+
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgp-openconfig-spi">prefix:bgp-openconfig-provider</type>
+ <instance>
+ <name>openconfig-bgp</name>
+ <provider>/config/modules/module[name='openconfig-bgp']/instance[name='openconfig-bgp']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-openconfig-impl</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/bgpcep.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/bgpcep.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/BGP_LS_PCEP:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>bgp-openconfig-impl</artifactId>
+ <description>BGP OPENCONFIG IMPL</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-openconfig-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-openconfig-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-rib-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-rib-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-concepts</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-linkstate</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-flowspec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-labeled-unicast</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>concepts</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>sal-netconf-connector</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-topology</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.tcpmd5</groupId>
+ <artifactId>tcpmd5-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId> org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </dependency>
+ <!-- test scope dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
--- /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
+ */
+
+package org.opendaylight.controller.config.yang.bgp.openconfig;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.protocol.bgp.openconfig.impl.BGPOpenConfig;
+
+public class BgpOpenConfigImplModule extends AbstractBgpOpenConfigImplModule {
+ public BgpOpenConfigImplModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public BgpOpenConfigImplModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver, final BgpOpenConfigImplModule oldModule, final AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ final BGPOpenConfig bgpOpenConfigProvider = new BGPOpenConfig();
+ getBindingBrokerDependency().registerConsumer(bgpOpenConfigProvider);
+ return bgpOpenConfigProvider;
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.controller.config.yang.bgp.openconfig;
+
+public class BgpOpenConfigImplModuleFactory extends AbstractBgpOpenConfigImplModuleFactory {
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yangtools.concepts.Identifier;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+final class BGPConfigHolderImpl<V extends DataObject> implements BGPConfigHolder<V> {
+
+ @GuardedBy("this")
+ private final BiMap<ModuleKey, Identifier> moduleToOpenConfig = HashBiMap.<ModuleKey, Identifier>create();
+
+ @GuardedBy("this")
+ private final Map<Identifier, V> bgpOpenConfigConfig = new HashMap<>();
+
+ @Override
+ public synchronized boolean remove(final ModuleKey moduleKey) {
+ final Identifier key = getKey(moduleKey);
+ if (key != null) {
+ bgpOpenConfigConfig.remove(key);
+ moduleToOpenConfig.remove(moduleKey);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized boolean addOrUpdate(final ModuleKey moduleKey, final Identifier key, final V newValue) {
+ if (!moduleToOpenConfig.containsKey(moduleKey)) {
+ moduleToOpenConfig.put(moduleKey, key);
+ bgpOpenConfigConfig.put(key, newValue);
+ return true;
+ } else if (!bgpOpenConfigConfig.get(key).equals(newValue)) {
+ bgpOpenConfigConfig.put(key, newValue);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public ModuleKey getModuleKey(final Identifier key) {
+ return this.moduleToOpenConfig.inverse().get(key);
+ }
+
+ @Override
+ public Identifier getKey(final ModuleKey moduleKey) {
+ return this.moduleToOpenConfig.get(moduleKey);
+ }
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+final class BGPConfigStateStoreImpl implements BGPConfigStateStore {
+
+ final Map<Class<? extends DataObject>, BGPConfigHolder<? extends DataObject>> configHolderMap = new HashMap<>();
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends DataObject> BGPConfigHolder<T> getBGPConfigHolder(final Class<T> clazz) {
+ return (BGPConfigHolder<T>) configHolderMap.get(clazz);
+ }
+
+ @Override
+ public <T extends DataObject> void registerBGPConfigHolder(final Class<T> clazz, final BGPConfigHolder<T> configHolder) {
+ configHolderMap.put(clazz, configHolder);
+ }
+
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl;
+
+import com.google.common.base.Optional;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+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.MountPoint;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
+import org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig.BGPOpenConfigListener;
+import org.opendaylight.protocol.bgp.openconfig.impl.openconfig.BGPConfigModuleMapperProvider;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider;
+import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenconfigMapper;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfiguration;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Global;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BGPOpenConfig implements BindingAwareConsumer, AutoCloseable, DataTreeChangeListener<Node>, BGPOpenConfigProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BGPOpenConfig.class);
+
+ private static final InstanceIdentifier<Topology> NETCONF_TOPOLOGY = InstanceIdentifier
+ .builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))).build();
+
+ private static final NodeKey CONFIG_NODE_KEY = new NodeKey(new NodeId("controller-config"));
+
+ private static final InstanceIdentifier<Node> CONTROLLER_CONFIG_IID = NETCONF_TOPOLOGY
+ .child(Node.class, CONFIG_NODE_KEY);
+
+ private final BGPConfigStateStore configStateHolders;
+ private BGPConfigModuleMapperProvider configModuleListener;
+ private BGPOpenConfigListener openConfigListener;
+ private ListenerRegistration<BGPOpenConfig> registration;
+ private MountPointService mountService;
+ private DataBroker dataBroker;
+
+ public BGPOpenConfig() {
+ configStateHolders = new BGPConfigStateStoreImpl();
+ configStateHolders.registerBGPConfigHolder(Global.class, new BGPConfigHolderImpl<Global>());
+ configStateHolders.registerBGPConfigHolder(Neighbor.class, new BGPConfigHolderImpl<Neighbor>());
+ }
+
+ @Override
+ public void onSessionInitialized(final ConsumerContext session) {
+ dataBroker = session.getSALService(DataBroker.class);
+ try {
+ configModuleListener = new BGPConfigModuleMapperProvider(dataBroker, configStateHolders);
+ } catch (final TransactionCommitFailedException e) {
+ LOG.error("Failed to initialize application.", e);
+ throw new IllegalStateException(e);
+ }
+ mountService = session.getSALService(MountPointService.class);
+ registration = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+ NETCONF_TOPOLOGY.child(Node.class)), this);
+ }
+
+ @Override
+ public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
+ for (final DataTreeModification<Node> dataTreeModification : changes) {
+ final DataObjectModification<Node> rootNode = dataTreeModification.getRootNode();
+ if (dataTreeModification.getRootPath().getRootIdentifier().firstKeyOf(Node.class).equals(CONFIG_NODE_KEY)) {
+ switch (rootNode.getModificationType()) {
+ case DELETE:
+ closeOpenConfigListener();
+ break;
+ case SUBTREE_MODIFIED:
+ closeOpenConfigListener();
+ getConfigMountPoint();
+ break;
+ case WRITE:
+ getConfigMountPoint();
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled modification type " + rootNode.getModificationType());
+ }
+ }
+ }
+ }
+
+ private void getConfigMountPoint() {
+ final Callable<MountPoint> callable = new Callable<MountPoint>() {
+ @Override
+ public MountPoint call() {
+ Optional<MountPoint> mp;
+ do {
+ mp = mountService.getMountPoint(CONTROLLER_CONFIG_IID);
+ } while (!mp.isPresent());
+ return mp.get();
+ }
+ };
+ openConfigListener = new BGPOpenConfigListener(dataBroker, callable, configStateHolders);
+ }
+
+ @Override
+ public void close() {
+ closeConfigModuleListener();
+ closeOpenConfigListener();
+ if (registration != null) {
+ registration.close();
+ registration = null;
+ }
+ }
+
+ private void closeOpenConfigListener() {
+ if (openConfigListener != null) {
+ try {
+ openConfigListener.close();
+ } catch (final Exception e) {
+ LOG.warn("Failed to close OpenConfigProperly properly.", e);
+ } finally {
+ openConfigListener = null;
+ }
+ }
+ }
+
+ private void closeConfigModuleListener() {
+ if (configModuleListener != null) {
+ try {
+ configModuleListener.close();
+ } catch (final Exception e) {
+ LOG.warn("Failed to close ConfigModuleListener properly.", e);
+ } finally {
+ configModuleListener = null;
+ }
+ }
+ }
+
+ @Override
+ public <T extends InstanceConfiguration> BGPOpenconfigMapper<T> getOpenConfigMapper(final Class<T> clazz) {
+ return configModuleListener.getOpenConfigMapper(clazz);
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.GlobalIdentifier;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Global;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.RibInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpApplicationPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpApplicationPeerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.bgp.application.peer.TargetRib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.bgp.application.peer.TargetRibBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class BGPAppPeerProvider {
+
+ private static final String APPLICATION_RIB = "application-rib_";
+
+ private static final String APPLICATION_PEER = "application-peer_";
+
+ private static final Logger LOG = LoggerFactory.getLogger(BGPAppPeerProvider.class);
+
+ private static final Function<String, TargetRib> TO_RIB_FUNCTION = new Function<String, TargetRib>() {
+ @Override
+ public TargetRib apply(final String name) {
+ return new TargetRibBuilder().setName(name).setType(RibInstance.class).build();
+ }
+ };
+
+ private final BGPConfigHolder<Neighbor> neighborState;
+ private final BGPConfigHolder<Global> globalState;
+ private final BGPConfigModuleProvider configModuleOp;
+
+ public BGPAppPeerProvider(final BGPConfigStateStore configHolders, final BGPConfigModuleProvider configModuleWriter) {
+ this.configModuleOp = Preconditions.checkNotNull(configModuleWriter);
+ this.globalState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Global.class));
+ this.neighborState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Neighbor.class));
+ }
+
+ public void onNeighborRemoved(final Neighbor removedNeighbor, final DataBroker dataBroker) {
+ final ModuleKey moduleKey = neighborState.getModuleKey(removedNeighbor.getKey());
+ if (moduleKey != null) {
+ try {
+ globalState.remove(moduleKey);
+ final Optional<Module> maybeModule = configModuleOp.readModuleConfiguration(moduleKey, dataBroker.newReadOnlyTransaction()).get();
+ if (maybeModule.isPresent()) {
+ configModuleOp.removeModuleConfiguration(moduleKey, dataBroker.newWriteOnlyTransaction());
+ }
+ } catch (final Exception e) {
+ LOG.error("Failed to remove a configuration module: {}", moduleKey, e);
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ public void onNeighborModified(final Neighbor modifiedAppNeighbor, final DataBroker dataBroker) {
+ final ModuleKey moduleKey = neighborState.getModuleKey(modifiedAppNeighbor.getKey());
+ final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+ if (moduleKey != null) {
+ //update an existing peer configuration
+ try {
+ if (neighborState.addOrUpdate(moduleKey, modifiedAppNeighbor.getKey(), modifiedAppNeighbor)) {
+ final Optional<Module> maybeModule = configModuleOp.readModuleConfiguration(moduleKey, rTx).get();
+ if (maybeModule.isPresent()) {
+ final Module peerConfigModule = toPeerConfigModule(modifiedAppNeighbor, maybeModule.get());
+ configModuleOp.putModuleConfiguration(peerConfigModule, dataBroker.newWriteOnlyTransaction());
+ }
+ }
+ } catch (final Exception e) {
+ LOG.error("Failed to update a configuration module: {}", moduleKey, e);
+ throw new IllegalStateException(e);
+ }
+ } else {
+ //create new application peer configuration
+ final ModuleKey ribImplKey = globalState.getModuleKey(GlobalIdentifier.GLOBAL_IDENTIFIER);
+ if (ribImplKey != null) {
+ try {
+ final ListenableFuture<TargetRib> ribFuture = new RibInstanceFunction<>(rTx, configModuleOp, TO_RIB_FUNCTION).apply(ribImplKey.getName());
+ final Module peerConfigModule = toPeerConfigModule(modifiedAppNeighbor, ribFuture.get());
+ configModuleOp.putModuleConfiguration(peerConfigModule, dataBroker.newWriteOnlyTransaction());
+ neighborState.addOrUpdate(peerConfigModule.getKey(), modifiedAppNeighbor.getKey(), modifiedAppNeighbor);
+ } catch (final Exception e) {
+ LOG.error("Failed to create a configuration module: {}", moduleKey, e);
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+
+ private static Module toPeerConfigModule(final Neighbor neighbor, final Module currentModule) {
+ final BgpApplicationPeer appPeerConfig = (BgpApplicationPeer) currentModule.getConfiguration();
+ final BgpApplicationPeerBuilder bgpPeerConfigBuilder = toBgpPeerConfig(neighbor, appPeerConfig.getTargetRib());
+ bgpPeerConfigBuilder.setApplicationRibId(appPeerConfig.getApplicationRibId());
+ final ModuleBuilder mBuilder = new ModuleBuilder();
+ mBuilder.setConfiguration(bgpPeerConfigBuilder.build());
+ return mBuilder.build();
+ }
+
+ private static Module toPeerConfigModule(final Neighbor neighbor, final TargetRib rib) {
+ final ModuleBuilder mBuilder = new ModuleBuilder();
+ mBuilder.setName(createAppPeerName(neighbor.getNeighborAddress().getIpv4Address()));
+ mBuilder.setType(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpApplicationPeer.class);
+ mBuilder.setConfiguration(toBgpPeerConfig(neighbor, rib).build());
+ mBuilder.setKey(new ModuleKey(mBuilder.getName(), mBuilder.getType()));
+ return mBuilder.build();
+ }
+
+ private static BgpApplicationPeerBuilder toBgpPeerConfig(final Neighbor neighbor, final TargetRib rib) {
+ final BgpApplicationPeerBuilder bgpAppPeerBuilder = new BgpApplicationPeerBuilder();
+ bgpAppPeerBuilder.setTargetRib(rib);
+ final Ipv4Address address = neighbor.getNeighborAddress().getIpv4Address();
+ bgpAppPeerBuilder.setBgpPeerId(address);
+ bgpAppPeerBuilder.setApplicationRibId(new ApplicationRibId(createAppRibName(address)));
+ return bgpAppPeerBuilder;
+ }
+
+ private static String createAppPeerName(final Ipv4Address ipAddress) {
+ return APPLICATION_PEER + ipAddress.getValue();
+ }
+
+ private static String createAppRibName(final Ipv4Address ipAddress) {
+ return APPLICATION_RIB + ipAddress.getValue();
+ }
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.Modules;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.Services;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.services.Service;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.services.ServiceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class BGPConfigModuleProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BGPConfigModuleProvider.class);
+
+ private static final InstanceIdentifier<Services> SERVICES_IID = InstanceIdentifier.builder(Services.class).build();
+ private static final InstanceIdentifier<Modules> MODULES_IID = InstanceIdentifier.builder(Modules.class).build();
+
+ void putModuleConfiguration(final Module module, final WriteTransaction wTx) throws TransactionCommitFailedException {
+ LOG.debug("Adding/Updating configuration module: {}", module);
+ wTx.put(LogicalDatastoreType.CONFIGURATION, MODULES_IID.child(Module.class, module.getKey()), module);
+ wTx.submit().checkedGet();
+ }
+
+ void removeModuleConfiguration(final ModuleKey moduleKey, final WriteTransaction wTx) throws TransactionCommitFailedException {
+ LOG.debug("Removing configuration module with key: {}", moduleKey);
+ wTx.delete(LogicalDatastoreType.CONFIGURATION, MODULES_IID.child(Module.class, moduleKey));
+ wTx.submit().checkedGet();
+ }
+
+ ListenableFuture<Optional<Module>> readModuleConfiguration(final ModuleKey moduleKey, final ReadTransaction rTx) {
+ return rTx.read(LogicalDatastoreType.CONFIGURATION, MODULES_IID.child(Module.class, moduleKey));
+ }
+
+ ListenableFuture<Optional<Service>> readConfigService(final ServiceKey serviceKey, final ReadTransaction rTx) {
+ return rTx.read(LogicalDatastoreType.CONFIGURATION, SERVICES_IID.child(Service.class, serviceKey));
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+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.MountPoint;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Bgp;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Config1;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Global;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Neighbors;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BGPOpenConfigListener implements DataTreeChangeListener<Bgp>, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BGPOpenConfigListener.class);
+
+ private final BGPConfigModuleProvider configModuleWriter;
+ private final ListenerRegistration<BGPOpenConfigListener> registerDataTreeChangeListener;
+ private final BGPRibImplProvider ribImplProvider;
+ private final BGPPeerProvider peerProvider;
+ private final BGPAppPeerProvider appPeerProvider;
+ private final Callable<MountPoint> callable;
+
+ public BGPOpenConfigListener(final DataBroker dataBroker, final Callable<MountPoint> callable, final BGPConfigStateStore configStateHolders) {
+ this.callable = Preconditions.checkNotNull(callable);
+ this.configModuleWriter = new BGPConfigModuleProvider();
+ this.ribImplProvider = new BGPRibImplProvider(configStateHolders, configModuleWriter);
+ this.peerProvider = new BGPPeerProvider(configStateHolders, configModuleWriter);
+ this.appPeerProvider = new BGPAppPeerProvider(configStateHolders, configModuleWriter);
+ this.registerDataTreeChangeListener = dataBroker.registerDataTreeChangeListener(
+ new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, OpenConfigUtil.BGP_IID), this);
+ }
+
+ @Override
+ public synchronized void onDataTreeChanged(final Collection<DataTreeModification<Bgp>> changes) {
+ try {
+ final Optional<DataBroker> databroker = callable.call().getService(DataBroker.class);
+ if (databroker.isPresent()) {
+ for (final DataTreeModification<Bgp> dataTreeModification : changes) {
+ final DataObjectModification<Bgp> rootNode = dataTreeModification.getRootNode();
+ for (final DataObjectModification<? extends DataObject> dataObjectModification : rootNode.getModifiedChildren()) {
+ final DataBroker db = databroker.get();
+ switch (dataObjectModification.getModificationType()) {
+ case DELETE:
+ onOpenConfigRemoved(dataObjectModification.getDataBefore(), db);
+ break;
+ case SUBTREE_MODIFIED:
+ case WRITE:
+ onOpenConfigModified(dataObjectModification, db);
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled modification type " + rootNode.getModificationType());
+ }
+ }
+ }
+ }
+ } catch (final Exception e) {
+ LOG.error("Failed to obtain MountPoint.", e);
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public void close() {
+ registerDataTreeChangeListener.close();
+ }
+
+ private void onOpenConfigRemoved(final DataObject removedData, final DataBroker dataBroker) {
+ if (removedData instanceof Global) {
+ ribImplProvider.onGlobalRemoved((Global) removedData, dataBroker);
+ } else if (removedData instanceof Neighbors) {
+ final Neighbors neighbors = (Neighbors) removedData;
+ for (final Neighbor neighbor : neighbors.getNeighbor()) {
+ removeNeighbor(neighbor, dataBroker);
+ }
+ } else {
+ LOG.info("Skipping unhandled removed data: {}", removedData);
+ }
+ }
+
+ private void onOpenConfigModified(final DataObjectModification<? extends DataObject> dataObjectModification, final DataBroker dataBroker) {
+ final DataObject modifiedData = dataObjectModification.getDataAfter();
+ if (modifiedData instanceof Global) {
+ ribImplProvider.onGlobalModified((Global) modifiedData, dataBroker);
+ } else if (modifiedData instanceof Neighbors) {
+ for (final DataObjectModification<? extends DataObject> childModification : dataObjectModification.getModifiedChildren()) {
+ switch (childModification.getModificationType()) {
+ case DELETE:
+ final Neighbor before = (Neighbor) childModification.getDataBefore();
+ removeNeighbor(before, dataBroker);
+ break;
+ case SUBTREE_MODIFIED:
+ case WRITE:
+ final Neighbor after = (Neighbor) childModification.getDataAfter();
+ modifyNeighbor(after, dataBroker);
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ LOG.info("Skipping unhandled modified data: {}", modifiedData);
+ }
+ }
+
+ private void removeNeighbor(final Neighbor neighbor, final DataBroker dataBroker) {
+ if (isAppNeighbor(neighbor)) {
+ appPeerProvider.onNeighborRemoved(neighbor, dataBroker);
+ } else {
+ peerProvider.onNeighborRemoved(neighbor, dataBroker);
+ }
+ }
+
+ private void modifyNeighbor(final Neighbor neighbor, final DataBroker dataBroker) {
+ if (isAppNeighbor(neighbor)) {
+ appPeerProvider.onNeighborModified(neighbor, dataBroker);
+ } else {
+ peerProvider.onNeighborModified(neighbor, dataBroker);
+ }
+ }
+
+ private static boolean isAppNeighbor(final Neighbor neighbor) {
+ final Config1 config1 = neighbor.getConfig().getAugmentation(Config1.class);
+ if (config1 != null) {
+ return config1.getPeerGroup() != null && config1.getPeerGroup().equals(OpenConfigUtil.APPLICATION_PEER_GROUP_NAME);
+ }
+ return false;
+ }
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.GlobalIdentifier;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Global;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.RouteReflector;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.Timers;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.Transport;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.PeerType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.RibInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpPeerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.bgp.peer.AdvertizedTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.bgp.peer.AdvertizedTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.bgp.peer.Rib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.bgp.peer.RibBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.tcpmd5.cfg.rev140427.Rfc2385Key;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class BGPPeerProvider {
+
+ private static final String PEER = "peer_";
+
+ private static final Logger LOG = LoggerFactory.getLogger(BGPPeerProvider.class);
+
+ private static final Function<String, AdvertizedTable> ADVERTIZED_TABLE_FUNCTION = new Function<String, AdvertizedTable>() {
+ @Override
+ public AdvertizedTable apply(final String instance) {
+ return new AdvertizedTableBuilder().setName(instance).setType(BgpTableType.class).build();
+ }
+ };
+
+ private static final Function<String, Rib> TO_RIB_FUNCTION = new Function<String, Rib>() {
+ @Override
+ public Rib apply(final String name) {
+ return new RibBuilder().setName(name).setType(RibInstance.class).build();
+ }
+ };
+
+ private final BGPConfigHolder<Neighbor> neighborState;
+ private final BGPConfigHolder<Global> globalState;
+ private final BGPConfigModuleProvider configModuleOp;
+
+ public BGPPeerProvider(final BGPConfigStateStore configHolders, final BGPConfigModuleProvider configModuleWriter) {
+ this.configModuleOp = Preconditions.checkNotNull(configModuleWriter);
+ this.globalState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Global.class));
+ this.neighborState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Neighbor.class));
+ }
+
+ public void onNeighborRemoved(final Neighbor removedNeighbor, final DataBroker dataBroker) {
+ final ModuleKey moduleKey = neighborState.getModuleKey(removedNeighbor.getKey());
+ if (moduleKey != null) {
+ try {
+ globalState.remove(moduleKey);
+ final Optional<Module> maybeModule = configModuleOp.readModuleConfiguration(moduleKey, dataBroker.newReadOnlyTransaction()).get();
+ if (maybeModule.isPresent()) {
+ configModuleOp.removeModuleConfiguration(moduleKey, dataBroker.newWriteOnlyTransaction());
+ }
+ } catch (InterruptedException | ExecutionException | TransactionCommitFailedException e) {
+ LOG.error("Failed to remove a configuration module: {}", moduleKey, e);
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ public void onNeighborModified(final Neighbor modifiedNeighbor, final DataBroker dataBroker) {
+ final ModuleKey moduleKey = neighborState.getModuleKey(modifiedNeighbor.getKey());
+ final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+ final ListenableFuture<List<AdvertizedTable>> advertizedTablesFuture = new TableTypesFunction<AdvertizedTable>(rTx,
+ configModuleOp, ADVERTIZED_TABLE_FUNCTION).apply(modifiedNeighbor.getAfiSafis().getAfiSafi());
+ if (moduleKey != null) {
+ //update an existing peer configuration
+ try {
+ if (neighborState.addOrUpdate(moduleKey, modifiedNeighbor.getKey(), modifiedNeighbor)) {
+ final Optional<Module> maybeModule = configModuleOp.readModuleConfiguration(moduleKey, rTx).get();
+ if (maybeModule.isPresent()) {
+ final Module peerConfigModule = toPeerConfigModule(modifiedNeighbor, maybeModule.get(), advertizedTablesFuture.get());
+ configModuleOp.putModuleConfiguration(peerConfigModule, dataBroker.newWriteOnlyTransaction());
+ }
+ }
+ } catch (final Exception e) {
+ LOG.error("Failed to update a configuration module: {}", moduleKey, e);
+ throw new IllegalStateException(e);
+ }
+ } else {
+ //create new peer configuration
+ final ModuleKey ribImplKey = globalState.getModuleKey(GlobalIdentifier.GLOBAL_IDENTIFIER);
+ if (ribImplKey != null) {
+ try {
+ final ListenableFuture<Rib> ribFuture = new RibInstanceFunction<>(rTx, configModuleOp, TO_RIB_FUNCTION).apply(ribImplKey.getName());
+ final Module peerConfigModule = toPeerConfigModule(modifiedNeighbor, advertizedTablesFuture.get(), ribFuture.get());
+ configModuleOp.putModuleConfiguration(peerConfigModule, dataBroker.newWriteOnlyTransaction());
+ neighborState.addOrUpdate(peerConfigModule.getKey(), modifiedNeighbor.getKey(), modifiedNeighbor);
+ } catch (final Exception e) {
+ LOG.error("Failed to create a configuration module: {}", moduleKey, e);
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+
+ private static Module toPeerConfigModule(final Neighbor neighbor, final Module oldBgpPeer, final List<AdvertizedTable> tableTypes) {
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpPeer bgpPeer =
+ (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpPeer) oldBgpPeer.getConfiguration();
+ final BgpPeerBuilder bgpPeerBuilder = toBgpPeerConfig(neighbor, tableTypes, bgpPeer.getRib());
+ bgpPeerBuilder.setPeerRegistry(((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpPeer)oldBgpPeer.getConfiguration()).getPeerRegistry());
+ bgpPeerBuilder.setPort(((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpPeer)oldBgpPeer.getConfiguration()).getPort());
+
+ final ModuleBuilder mBuilder = new ModuleBuilder(oldBgpPeer);
+ mBuilder.setConfiguration(bgpPeerBuilder.build());
+ return mBuilder.build();
+ }
+
+ private static Module toPeerConfigModule(final Neighbor neighbor, final List<AdvertizedTable> tableTypes, final Rib rib) {
+ final ModuleBuilder mBuilder = new ModuleBuilder();
+ mBuilder.setName(createPeerName(neighbor.getNeighborAddress()));
+ mBuilder.setType(BgpPeer.class);
+ mBuilder.setConfiguration(toBgpPeerConfig(neighbor, tableTypes, rib).build());
+ mBuilder.setKey(new ModuleKey(mBuilder.getName(), mBuilder.getType()));
+ return mBuilder.build();
+ }
+
+ private static BgpPeerBuilder toBgpPeerConfig(final Neighbor neighbor, final List<AdvertizedTable> tableTypes, final Rib rib) {
+ final BgpPeerBuilder bgpPeerBuilder = new BgpPeerBuilder();
+ bgpPeerBuilder.setAdvertizedTable(tableTypes);
+ bgpPeerBuilder.setRib(rib);
+ bgpPeerBuilder.setHost(neighbor.getNeighborAddress());
+ final Timers timers = neighbor.getTimers();
+ if (timers != null && timers.getConfig() != null && timers.getConfig().getHoldTime() != null) {
+ bgpPeerBuilder.setHoldtimer(neighbor.getTimers().getConfig().getHoldTime().shortValue());
+ }
+ final Transport transport = neighbor.getTransport();
+ if (transport != null && transport.getConfig() != null && transport.getConfig().isPassiveMode() != null) {
+ bgpPeerBuilder.setInitiateConnection(!neighbor.getTransport().getConfig().isPassiveMode());
+ }
+ if (neighbor.getConfig() != null) {
+ if (neighbor.getConfig().getAuthPassword() != null) {
+ bgpPeerBuilder.setPassword(new Rfc2385Key(neighbor.getConfig().getAuthPassword()));
+ }
+ if (neighbor.getConfig().getPeerAs() != null) {
+ bgpPeerBuilder.setRemoteAs(neighbor.getConfig().getPeerAs().getValue());
+ }
+ if (neighbor.getConfig().getPeerType() != null) {
+ bgpPeerBuilder.setPeerRole(toPeerRole(neighbor));
+ }
+ }
+ return bgpPeerBuilder;
+ }
+
+ private static String createPeerName(final IpAddress ipAddress) {
+ final String address = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
+ return PEER + address;
+ }
+
+ private static PeerRole toPeerRole(final Neighbor neighbor) {
+ if (isRrClient(neighbor)) {
+ return PeerRole.RrClient;
+ }
+
+ if (neighbor.getConfig() != null) {
+ final PeerType peerType = neighbor.getConfig().getPeerType();
+ if (peerType == PeerType.INTERNAL) {
+ return PeerRole.Ibgp;
+ }
+ if (peerType == PeerType.EXTERNAL) {
+ return PeerRole.Ebgp;
+ }
+ }
+ LOG.info("Unknown peer role, setting peer {} role to iBGP", neighbor.getKey());
+ return PeerRole.Ibgp;
+ }
+
+ private static boolean isRrClient(final Neighbor neighbor) {
+ final RouteReflector routeReflector = neighbor.getRouteReflector();
+ if (routeReflector != null && routeReflector.getConfig() != null) {
+ return routeReflector.getConfig().isRouteReflectorClient();
+ }
+ return false;
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.GlobalIdentifier;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Global;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.RibImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.RibImplBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.rib.impl.LocalTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.rib.impl.LocalTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class BGPRibImplProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BGPRibImplProvider.class);
+
+ private static final Function<String, LocalTable> LOCAL_TABLE_FUNCTION = new Function<String, LocalTable>() {
+ @Override
+ public LocalTable apply(final String input) {
+ return new LocalTableBuilder().setName(input).setType(BgpTableType.class).build();
+ }
+ };
+
+ private final BGPConfigHolder<Global> globalState;
+ private final BGPConfigModuleProvider configModuleWriter;
+
+ public BGPRibImplProvider(final BGPConfigStateStore configHolders, final BGPConfigModuleProvider configModuleWriter) {
+ this.globalState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Global.class));
+ this.configModuleWriter = Preconditions.checkNotNull(configModuleWriter);
+ }
+
+ public void onGlobalRemoved(final Global removedGlobal, final DataBroker dataBroker) {
+ final ModuleKey moduleKey = globalState.getModuleKey(GlobalIdentifier.GLOBAL_IDENTIFIER);
+ if (moduleKey != null) {
+ try {
+ globalState.remove(moduleKey);
+ final Optional<Module> maybeModule = configModuleWriter.readModuleConfiguration(moduleKey, dataBroker.newReadOnlyTransaction()).get();
+ if (maybeModule.isPresent()) {
+ configModuleWriter.removeModuleConfiguration(moduleKey, dataBroker.newWriteOnlyTransaction());
+ }
+ } catch (final Exception e) {
+ LOG.error("Failed to remove a configuration module: {}", moduleKey, e);
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ public void onGlobalModified(final Global modifiedGlobal, final DataBroker dataBroker) {
+ final ModuleKey moduleKey = globalState.getModuleKey(GlobalIdentifier.GLOBAL_IDENTIFIER);
+ if (moduleKey != null) {
+ //update existing RIB configuration
+ if (globalState.addOrUpdate(moduleKey, GlobalIdentifier.GLOBAL_IDENTIFIER, modifiedGlobal)) {
+ final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+ try {
+ final Optional<Module> maybeModule = configModuleWriter.readModuleConfiguration(moduleKey, rTx).get();
+ if (maybeModule.isPresent()) {
+ final ListenableFuture<List<LocalTable>> localTablesFuture = new TableTypesFunction<LocalTable>(rTx, configModuleWriter, LOCAL_TABLE_FUNCTION).apply(modifiedGlobal.getAfiSafis().getAfiSafi());
+ final Module newModule = toRibImplConfigModule(modifiedGlobal, maybeModule.get(), localTablesFuture.get());
+ configModuleWriter.putModuleConfiguration(newModule, dataBroker.newWriteOnlyTransaction());
+ }
+ } catch (final Exception e) {
+ LOG.error("Failed to update a configuration module: {}", moduleKey, e);
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+
+ private static Module toRibImplConfigModule(final Global globalConfig, final Module module, final List<LocalTable> tableTypes) {
+ final RibImpl ribImpl = (RibImpl) module.getConfiguration();
+ final RibImplBuilder ribImplBuilder = new RibImplBuilder();
+ if (globalConfig.getConfig() != null) {
+ ribImplBuilder.setBgpRibId(globalConfig.getConfig().getRouterId());
+ ribImplBuilder.setLocalAs(globalConfig.getConfig().getAs().getValue());
+ }
+ ribImplBuilder.setLocalTable(tableTypes);
+ ribImplBuilder.setBgpDispatcher(ribImpl.getBgpDispatcher());
+ ribImplBuilder.setClusterId(ribImpl.getClusterId());
+ ribImplBuilder.setCodecTreeFactory(ribImpl.getCodecTreeFactory());
+ ribImplBuilder.setDataProvider(ribImpl.getDataProvider());
+ ribImplBuilder.setDomDataProvider(ribImpl.getDomDataProvider());
+ ribImplBuilder.setExtensions(ribImpl.getExtensions());
+ ribImplBuilder.setRibId(ribImpl.getRibId());
+ ribImplBuilder.setSessionReconnectStrategy(ribImpl.getSessionReconnectStrategy());
+ ribImplBuilder.setTcpReconnectStrategy(ribImpl.getTcpReconnectStrategy());
+ ribImplBuilder.setOpenconfigProvider(ribImpl.getOpenconfigProvider());
+
+ final ModuleBuilder mBuilder = new ModuleBuilder(module);
+ mBuilder.setConfiguration(ribImplBuilder.build());
+ return mBuilder.build();
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.RibInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.ServiceRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.services.Service;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.services.ServiceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.services.service.Instance;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+
+final class RibInstanceFunction<T extends ServiceRef & ChildOf<Module>> implements AsyncFunction<String, T> {
+
+ private final ReadTransaction rTx;
+ private final BGPConfigModuleProvider configModuleOp;
+ private final Function<String, T> function;
+
+ public RibInstanceFunction(final ReadTransaction rTx, final BGPConfigModuleProvider configModuleOp, final Function<String, T> function) {
+ this.rTx = Preconditions.checkNotNull(rTx);
+ this.configModuleOp = Preconditions.checkNotNull(configModuleOp);
+ this.function = Preconditions.checkNotNull(function);
+ }
+
+ @Override
+ public ListenableFuture<T> apply(final String instanceName) {
+ final ListenableFuture<Optional<Service>> readFuture = configModuleOp.readConfigService(new ServiceKey(RibInstance.class), rTx);
+ return Futures.transform(readFuture, new Function<Optional<Service>, T>() {
+ @Override
+ public T apply(final Optional<Service> maybeService) {
+ if (maybeService.isPresent()) {
+ final Optional<Instance> maybeInstance = Iterables.tryFind(maybeService.get().getInstance(), new Predicate<Instance>() {
+ @Override
+ public boolean apply(final Instance instance) {
+ final String moduleName = OpenConfigUtil.getModuleName(instance.getProvider());
+ if (moduleName.equals(instanceName)) {
+ return true;
+ }
+ return false;
+ }
+ });
+ if (maybeInstance.isPresent()) {
+ return function.apply(maybeInstance.get().getName());
+ }
+ }
+ return null;
+ }
+
+ });
+ }
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev150515.bgp.common.afi.safi.list.AfiSafi;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.AfiSafiType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpTableTypeImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.ServiceRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.services.Service;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.services.ServiceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.services.service.Instance;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+
+final class TableTypesFunction<T extends ServiceRef & ChildOf<Module>> implements AsyncFunction<List<AfiSafi>, List<T>> {
+
+ private final ReadTransaction rTx;
+ private final BGPConfigModuleProvider configModuleWriter;
+ private final Function<String, T> function;
+
+ public TableTypesFunction(final ReadTransaction rTx, final BGPConfigModuleProvider configModuleWriter, final Function<String, T> function) {
+ this.rTx = Preconditions.checkNotNull(rTx);
+ this.configModuleWriter = Preconditions.checkNotNull(configModuleWriter);
+ this.function = Preconditions.checkNotNull(function);
+ }
+
+ @Override
+ public ListenableFuture<List<T>> apply(final List<AfiSafi> afiSafis) {
+ final ListenableFuture<Optional<Service>> readFuture = configModuleWriter.readConfigService(new ServiceKey(BgpTableType.class), rTx);
+ return Futures.transform(readFuture, new AsyncFunction<Optional<Service>, List<T>>() {
+
+ @Override
+ public ListenableFuture<List<T>> apply(final Optional<Service> maybeService) {
+ if (maybeService.isPresent()) {
+ final Service service = maybeService.get();
+ final List<ListenableFuture<Optional<Module>>> modulesFuture = new ArrayList<>();
+ final Map<String, String> moduleNameToService = new HashMap<>();
+ for (final Instance instance : service.getInstance()) {
+ final String moduleName = OpenConfigUtil.getModuleName(instance.getProvider());
+ modulesFuture.add(configModuleWriter.readModuleConfiguration(new ModuleKey(moduleName, BgpTableTypeImpl.class), rTx));
+ moduleNameToService.put(moduleName, instance.getName());
+ }
+ return Futures.transform(Futures.successfulAsList(modulesFuture), new ModulesToLocalTablesFunction(afiSafis, moduleNameToService));
+ }
+ return Futures.immediateFailedFuture(new IllegalStateException("No BgpTableType service present in configuration."));
+ }
+
+ });
+ }
+
+ private final class ModulesToLocalTablesFunction implements Function<List<Optional<Module>>, List<T>> {
+
+ private final List<AfiSafi> afiSafis;
+ private final Map<String, String> moduleNameToService;
+
+ public ModulesToLocalTablesFunction(final List<AfiSafi> afiSafis, final Map<String, String> moduleNameToService) {
+ this.afiSafis = afiSafis;
+ this.moduleNameToService = moduleNameToService;
+ }
+
+ @Override
+ public List<T> apply(final List<Optional<Module>> maybeModules) {
+ final ImmutableList<Module> modules = FluentIterable.from(maybeModules)
+ .filter(new Predicate<Optional<Module>>() {
+ @Override
+ public boolean apply(final Optional<Module> input) {
+ return input.isPresent();
+ }
+ }).transform(new Function<Optional<Module>, Module>() {
+ @Override
+ public Module apply(final Optional<Module> input) {
+ return input.get();
+ }
+ }).toList();
+
+ return toTableTypes(afiSafiToModuleName(modules));
+ }
+
+ private Map<Class<? extends AfiSafiType>, String> afiSafiToModuleName(final List<Module> modules) {
+ final Map<Class<? extends AfiSafiType>, String> afiSafiToModuleName = new HashMap<>(afiSafis.size());
+ for (final Module module : modules) {
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpTableTypeImpl config =
+ ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.modules.module.configuration.BgpTableTypeImpl) module.getConfiguration());
+ final Optional<AfiSafi> afiSafi = OpenConfigUtil.toAfiSafi(new org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl(config.getAfi(), config.getSafi()));
+ if (afiSafi.isPresent()) {
+ afiSafiToModuleName.put(afiSafi.get().getAfiSafiName(), module.getName());
+ }
+ }
+ return afiSafiToModuleName;
+ }
+
+ private List<T> toTableTypes(final Map<Class<? extends AfiSafiType>, String> afiSafiToModuleName) {
+ final List<T> tableTypes = new ArrayList<>(afiSafis.size());
+ for (final AfiSafi afiSafi : afiSafis) {
+ final String moduleName = afiSafiToModuleName.get(afiSafi.getAfiSafiName());
+ if (moduleName != null) {
+ tableTypes.add(function.apply(moduleNameToService.get(moduleName)));
+ }
+ }
+ return tableTypes;
+ }
+
+ }
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import static org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil.BGP_IID;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfiguration;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Neighbors;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborKey;
+import org.opendaylight.yangtools.concepts.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+abstract class AbstractBGPNeighborProvider<T extends InstanceConfiguration> extends AbstractBGPOpenConfigMapper<T, Neighbor> {
+
+ protected AbstractBGPNeighborProvider(final BindingTransactionChain txChain, final BGPConfigStateStore stateHolders,
+ final Class<Neighbor> clazz) {
+ super(txChain, stateHolders, clazz);
+ }
+
+ private static final InstanceIdentifier<Neighbors> NEIGHBORS_IID = BGP_IID.child(Neighbors.class);
+
+ @Override
+ protected InstanceIdentifier<Neighbor> getInstanceIdentifier(final Identifier key) {
+ Preconditions.checkArgument((org.opendaylight.yangtools.yang.binding.Identifier<?>)key instanceof NeighborKey);
+ return NEIGHBORS_IID.child(Neighbor.class, (NeighborKey) key);
+ }
+
+ @Override
+ public final NeighborKey keyForConfiguration(final Neighbor neighbor) {
+ return neighbor.getKey();
+ }
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenconfigMapper;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfiguration;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfigurationIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yangtools.concepts.Identifier;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractBGPOpenConfigMapper<F extends InstanceConfiguration, T extends DataObject> implements BGPOpenconfigMapper<F>, Function<F, T> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractBGPOpenConfigMapper.class);
+
+ private final BGPConfigHolder<T> configHolder;
+ private final BindingTransactionChain txChain;
+
+ protected AbstractBGPOpenConfigMapper(final BindingTransactionChain txChain, final BGPConfigStateStore stateHolders, final Class<T> clazz) {
+ this.txChain = Preconditions.checkNotNull(txChain);
+ this.configHolder = Preconditions.checkNotNull(stateHolders.getBGPConfigHolder(clazz));
+ }
+
+ @Override
+ public final void writeConfiguration(final F instanceConfiguration) {
+ final T openConfig = apply(instanceConfiguration);
+ LOG.debug("Update configuration candidate: {} mapped to: {}", instanceConfiguration, openConfig);
+ final Identifier key = keyForConfiguration(openConfig);
+ final ModuleKey moduleKey = createModuleKey(instanceConfiguration.getIdentifier().getName());
+ if (configHolder.addOrUpdate(moduleKey, key, openConfig)) {
+ writeConfiguration(key, openConfig);
+ LOG.debug("Configuration [{} <-> {}] updated.", key, moduleKey);
+ }
+ }
+
+ @Override
+ public final void removeConfiguration(final InstanceConfigurationIdentifier identifier) {
+ LOG.debug("Remove configuration candidate: {}", identifier);
+ final ModuleKey moduleKey = createModuleKey(identifier.getName());
+ final Identifier key = configHolder.getKey(moduleKey);
+ if (configHolder.remove(moduleKey)) {
+ removeConfiguration(key);
+ LOG.debug("Configuration [{} <-> {}] removed", key, moduleKey);
+ }
+ }
+
+ private void writeConfiguration(final Identifier key, final T openConfig) {
+ final WriteTransaction wTx = txChain.newWriteOnlyTransaction();
+ wTx.put(LogicalDatastoreType.CONFIGURATION, getInstanceIdentifier(key), openConfig);
+ wTx.submit();
+ }
+
+ private void removeConfiguration(final Identifier key) {
+ final WriteTransaction wTx = txChain.newWriteOnlyTransaction();
+ wTx.delete(LogicalDatastoreType.CONFIGURATION, getInstanceIdentifier(key));
+ wTx.submit();
+ }
+
+ protected abstract ModuleKey createModuleKey(String instanceName);
+
+ protected abstract InstanceIdentifier<T> getInstanceIdentifier(Identifier key);
+
+ protected abstract Identifier keyForConfiguration(final T openConfig);
+
+ protected abstract Class<F> getInstanceConfigurationType();
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil;
+import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPAppPeerInstanceConfiguration;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Config1;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Config1Builder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpApplicationPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+
+final class BGPAppNeighborProviderImpl extends AbstractBGPNeighborProvider<BGPAppPeerInstanceConfiguration> {
+
+ public BGPAppNeighborProviderImpl(final BindingTransactionChain txChain, final BGPConfigStateStore stateHolders) {
+ super(txChain, stateHolders, Neighbor.class);
+ }
+
+ @Override
+ public ModuleKey createModuleKey(final String instanceName) {
+ return new ModuleKey(instanceName, BgpApplicationPeer.class);
+ }
+
+ @Override
+ public Neighbor apply(final BGPAppPeerInstanceConfiguration config) {
+ return toAppNeighbor(config);
+ }
+
+ @Override
+ public Class<BGPAppPeerInstanceConfiguration> getInstanceConfigurationType() {
+ return BGPAppPeerInstanceConfiguration.class;
+ }
+
+ private static Neighbor toAppNeighbor(final BGPAppPeerInstanceConfiguration config) {
+ final IpAddress ipAddress = new IpAddress(config.getBgpId());
+ return new NeighborBuilder()
+ .setNeighborAddress(ipAddress)
+ .setKey(new NeighborKey(ipAddress))
+ .setConfig(
+ new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.ConfigBuilder()
+ .addAugmentation(Config1.class, new Config1Builder().setPeerGroup(OpenConfigUtil.APPLICATION_PEER_GROUP_NAME).build())
+ .build())
+ .build();
+ }
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider;
+import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenconfigMapper;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfiguration;
+
+final class BGPConfigMapperRegistry implements BGPOpenConfigProvider {
+
+ @SuppressWarnings("rawtypes")
+ private final Map<Class<? extends InstanceConfiguration>, AbstractBGPOpenConfigMapper> configMappers = new HashMap<>();
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public void registerOpenConfigMapper(final AbstractBGPOpenConfigMapper openConfigMapper) {
+ configMappers.put(openConfigMapper.getInstanceConfigurationType(), openConfigMapper);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends InstanceConfiguration> BGPOpenconfigMapper<T> getOpenConfigMapper(final Class<T> clazz) {
+ return configMappers.get(clazz);
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import static org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil.APPLICATION_PEER_GROUP_NAME;
+import static org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil.BGP_IID;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider;
+import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenconfigMapper;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfiguration;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.BgpBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.NeighborsBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.PeerGroupsBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.peer.group.PeerGroup;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.peer.group.PeerGroupBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.peer.group.PeerGroupKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BGPConfigModuleMapperProvider implements BGPOpenConfigProvider, TransactionChainListener, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BGPConfigModuleMapperProvider.class);
+
+ private static final PeerGroup APP_PEER_GROUP = new PeerGroupBuilder().setPeerGroupName(APPLICATION_PEER_GROUP_NAME)
+ .setKey(new PeerGroupKey(APPLICATION_PEER_GROUP_NAME)).build();
+
+ private final BindingTransactionChain txChain;
+ private final BGPConfigMapperRegistry configMapperRegistry = new BGPConfigMapperRegistry();
+
+ public BGPConfigModuleMapperProvider(final DataBroker dataBroker, final BGPConfigStateStore configStateHolders) throws TransactionCommitFailedException {
+ Preconditions.checkNotNull(configStateHolders);
+ this.txChain = Preconditions.checkNotNull(dataBroker).createTransactionChain(this);
+ final WriteTransaction wTx = this.txChain.newWriteOnlyTransaction();
+ wTx.put(LogicalDatastoreType.CONFIGURATION, BGP_IID,
+ new BgpBuilder().setNeighbors(new NeighborsBuilder().build()).setPeerGroups(
+ new PeerGroupsBuilder().setPeerGroup(Collections.singletonList(APP_PEER_GROUP)).build()).build());
+ wTx.submit().checkedGet();
+ configMapperRegistry.registerOpenConfigMapper(new BGPGlobalProviderImpl(txChain, configStateHolders));
+ configMapperRegistry.registerOpenConfigMapper(new BGPNeighborProviderImpl(txChain, configStateHolders));
+ configMapperRegistry.registerOpenConfigMapper(new BGPAppNeighborProviderImpl(txChain, configStateHolders));
+ }
+
+ @Override
+ public <T extends InstanceConfiguration> BGPOpenconfigMapper<T> getOpenConfigMapper(final Class<T> clazz) {
+ return configMapperRegistry.getOpenConfigMapper(clazz);
+ }
+
+ @Override
+ public void onTransactionChainFailed(final TransactionChain<?, ?> transactionChain, final AsyncTransaction<?, ?> asyncTransaction,
+ final Throwable throwable) {
+ LOG.error("Transaction chain {} failed.", transactionChain, throwable);
+ txChain.close();
+ }
+
+ @Override
+ public void onTransactionChainSuccessful(final TransactionChain<?, ?> transactionChain) {
+ LOG.debug("Transaction chain {} successful.", transactionChain);
+ }
+
+ @Override
+ public void close() throws Exception {
+ final WriteTransaction wTx = txChain.newWriteOnlyTransaction();
+ wTx.delete(LogicalDatastoreType.CONFIGURATION, BGP_IID);
+ wTx.submit().checkedGet();
+ txChain.close();
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import static org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil.BGP_IID;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.GlobalIdentifier;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil;
+import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPRibInstanceConfiguration;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Global;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.GlobalBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.global.base.AfiSafisBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.global.base.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.RibImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yangtools.concepts.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+final class BGPGlobalProviderImpl extends AbstractBGPOpenConfigMapper<BGPRibInstanceConfiguration, Global> {
+
+ private static final InstanceIdentifier<Global> GLOBAL_IID = BGP_IID.child(Global.class);
+
+ public BGPGlobalProviderImpl(final BindingTransactionChain txChain, final BGPConfigStateStore stateHolders) {
+ super(txChain, stateHolders, Global.class);
+ }
+
+ @Override
+ public Global apply(final BGPRibInstanceConfiguration configuration) {
+ return toGlobalConfiguration(configuration);
+ }
+
+ @Override
+ public ModuleKey createModuleKey(final String instanceName) {
+ return new ModuleKey(instanceName, RibImpl.class);
+ }
+
+ @Override
+ protected InstanceIdentifier<Global> getInstanceIdentifier(final Identifier key) {
+ return GLOBAL_IID;
+ }
+
+ @Override
+ public Identifier keyForConfiguration(final Global global) {
+ return GlobalIdentifier.GLOBAL_IDENTIFIER;
+ }
+
+ @Override
+ public Class<BGPRibInstanceConfiguration> getInstanceConfigurationType() {
+ return BGPRibInstanceConfiguration.class;
+ }
+
+ private static Global toGlobalConfiguration(final BGPRibInstanceConfiguration config) {
+ return new GlobalBuilder()
+ .setAfiSafis(new AfiSafisBuilder().setAfiSafi(OpenConfigUtil.toAfiSafis(config.getTableTypes())).build())
+ .setConfig(
+ new ConfigBuilder()
+ .setAs(config.getLocalAs())
+ .setRouterId(config.getBgpRibId()).build()).build();
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import com.google.common.base.Optional;
+import java.math.BigDecimal;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil;
+import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPPeerInstanceConfiguration;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.RouteReflectorBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.TimersBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.TransportBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborKey;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.PeerType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.tcpmd5.cfg.rev140427.Rfc2385Key;
+
+final class BGPNeighborProviderImpl extends AbstractBGPNeighborProvider<BGPPeerInstanceConfiguration> {
+
+ public BGPNeighborProviderImpl(final BindingTransactionChain txChain, final BGPConfigStateStore stateHolders) {
+ super(txChain, stateHolders, Neighbor.class);
+ }
+
+ @Override
+ public Class<BGPPeerInstanceConfiguration> getInstanceConfigurationType() {
+ return BGPPeerInstanceConfiguration.class;
+ }
+
+ @Override
+ public Neighbor apply(final BGPPeerInstanceConfiguration config) {
+ return toNeighborConfiguration(config);
+ }
+
+ @Override
+ public ModuleKey createModuleKey(final String instanceName) {
+ return new ModuleKey(instanceName, BgpPeer.class);
+ }
+
+ private static Neighbor toNeighborConfiguration(final BGPPeerInstanceConfiguration config) {
+ return new NeighborBuilder()
+ .setNeighborAddress(config.getHost())
+ .setKey(new NeighborKey(config.getHost()))
+ .setTransport(new TransportBuilder().setConfig(
+ new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.transport.ConfigBuilder()
+ .setPassiveMode(!config.isActive())
+ .build()).build())
+ .setConfig(
+ new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.ConfigBuilder()
+ .setAuthPassword(getPasswor(config.getPassword()))
+ .setPeerAs(config.getAsNumber())
+ .setPeerType(toPeerTye(config.getPeerRole()))
+ .build())
+ .setAfiSafis(
+ new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.AfiSafisBuilder()
+ .setAfiSafi(OpenConfigUtil.toAfiSafis(config.getAdvertizedTables()))
+ .build())
+ .setTimers(new TimersBuilder().setConfig(
+ new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.timers.ConfigBuilder()
+ .setHoldTime(BigDecimal.valueOf(config.getHoldTimer()))
+ .build()).build())
+ .setRouteReflector(new RouteReflectorBuilder().setConfig(
+ new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.route.reflector.ConfigBuilder()
+ .setRouteReflectorClient(config.getPeerRole() == PeerRole.RrClient)
+ .build()).build())
+ .build();
+ }
+
+ private static PeerType toPeerTye(final PeerRole peerRole) {
+ switch(peerRole) {
+ case Ibgp:
+ case RrClient:
+ return PeerType.INTERNAL;
+ case Ebgp:
+ return PeerType.EXTERNAL;
+ case Internal:
+ break;
+ default:
+ break;
+ }
+ return null;
+ }
+
+ private static String getPasswor(final Optional<Rfc2385Key> maybePassword) {
+ if (maybePassword.isPresent()) {
+ return maybePassword.get().getValue();
+ }
+ return null;
+ }
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.spi;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yangtools.concepts.Identifier;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Holds current configuration state for a particular DataObject type.
+ * Each configuration object is identified by a ModuleKey of mapped
+ * configuration module and an Identifier of the DataObject.
+ *
+ * @param <V> A type of DataBobject to which the configuration is binded.
+ */
+public interface BGPConfigHolder<V extends DataObject> {
+
+ /**
+ * Remove configuration stored configuration state. The stored configuration
+ * is removed when configuration with such ModuleKey is present.
+ * @param moduleKey ModuleKey identifies configuration to be removed.
+ * @return True if configuration was removed successfully, otherwise false.
+ */
+ boolean remove(@Nonnull ModuleKey moduleKey);
+
+ /**
+ * Update or add a new configuration object. If configuration object is present for
+ * such ModuleKey, current state is compared (equality) with proposed newValue. If not
+ * equals, current configuration state is updated (replaced) with newValue.
+ * If configuration object is not present for such ModuleKey, new configuration state is added.
+ * @param moduleKey ModuleKey identifies configuration to be add/updated.
+ * @param key ModuleKey identifies configuration to be added/updated.
+ * @param newValue Proposed configuration state.
+ * @return True if configuration was added/updated successfully, otherwise false.
+ */
+ boolean addOrUpdate(@Nonnull ModuleKey moduleKey, @Nonnull Identifier key, @Nonnull V newValue);
+
+ /**
+ * Retrieves ModuleKey for an input configuration object Identifier.
+ * @param key A Configuration data object Identifier.
+ * @return ModuleKey for an input Identifier, or null if not present.
+ */
+ ModuleKey getModuleKey(@Nonnull Identifier key);
+
+ /**
+ * Retrieves a configuration object Identifier for an input ModuleKey.
+ * @param moduleKey A ModuleKey of data object.
+ * @return Identifier for an input ModuleKey, or null if not present.
+ */
+ Identifier getKey(@Nonnull ModuleKey moduleKey);
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.spi;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * BGPConfigStateStore serves as store for BGP configuration holders.
+ *
+ */
+public interface BGPConfigStateStore {
+
+ /**
+ * Register BGP configuration holder and store it future use.
+ * @param clazz the type BGP configuration holder
+ * @param configHolder BGPConfigHolder
+ * @throws NullPointerException when input parameters are null.
+ */
+ <T extends DataObject> void registerBGPConfigHolder(@Nonnull Class<T> clazz, @Nonnull BGPConfigHolder<T> configHolder);
+
+ /**
+ * Retrieve BGPConfigHolder by input parameter class type.
+ * @param clazz Type of BGPConfigHolder which the consumer wants to load from store.
+ * @return BGPConfigHolder or null if holder for such type was not registered.
+ * @throws NullPointerException when input parameter is null.
+ */
+ <T extends DataObject> BGPConfigHolder<T> getBGPConfigHolder(@Nonnull Class<T> clazz);
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.util;
+
+import com.google.common.base.Preconditions;
+import java.util.Objects;
+import org.opendaylight.yangtools.concepts.Identifier;
+
+public final class GlobalIdentifier implements Identifier {
+
+ private static final long serialVersionUID = 1L;
+ private static final String BGP_GLOBAL_ID = "GLOBAL";
+
+ public static final GlobalIdentifier GLOBAL_IDENTIFIER = new GlobalIdentifier(BGP_GLOBAL_ID);
+
+ private final String name;
+
+ private GlobalIdentifier(final String name) {
+ this.name = Preconditions.checkNotNull(name);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Objects.hashCode(name);
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof GlobalIdentifier)) {
+ return false;
+ }
+ final GlobalIdentifier other = (GlobalIdentifier) obj;
+ if (!Objects.equals(name, other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.util;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev150515.bgp.common.afi.safi.list.AfiSafi;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev150515.bgp.common.afi.safi.list.AfiSafiBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Bgp;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.Ipv4LabelledUnicast;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.Ipv4Unicast;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.Ipv6LabelledUnicast;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.Ipv6Unicast;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.FlowspecSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.LabeledUnicastSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.LinkstateAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.LinkstateSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev150930.Ipv4Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev150930.Ipv6Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev150930.Linkstate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv6AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class OpenConfigUtil {
+
+ public static final InstanceIdentifier<Bgp> BGP_IID = InstanceIdentifier.builder(Bgp.class).build();
+
+ public static final String APPLICATION_PEER_GROUP_NAME = "application-peers";
+
+ private static final Map<BgpTableType, AfiSafi> TABLETYPE_TO_AFISAFI = Maps.newHashMap();
+
+ static {
+ TABLETYPE_TO_AFISAFI.put(new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class),
+ new AfiSafiBuilder().setAfiSafiName(Ipv4Unicast.class).build());
+ TABLETYPE_TO_AFISAFI.put(new BgpTableTypeImpl(Ipv6AddressFamily.class, UnicastSubsequentAddressFamily.class),
+ new AfiSafiBuilder().setAfiSafiName(Ipv6Unicast.class).build());
+ TABLETYPE_TO_AFISAFI.put(new BgpTableTypeImpl(Ipv4AddressFamily.class, LabeledUnicastSubsequentAddressFamily.class),
+ new AfiSafiBuilder().setAfiSafiName(Ipv4LabelledUnicast.class).build());
+ TABLETYPE_TO_AFISAFI.put(new BgpTableTypeImpl(Ipv6AddressFamily.class, LabeledUnicastSubsequentAddressFamily.class),
+ new AfiSafiBuilder().setAfiSafiName(Ipv6LabelledUnicast.class).build());
+ TABLETYPE_TO_AFISAFI.put(new BgpTableTypeImpl(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class),
+ new AfiSafiBuilder().setAfiSafiName(Linkstate.class).build());
+ TABLETYPE_TO_AFISAFI.put(new BgpTableTypeImpl(Ipv4AddressFamily.class, FlowspecSubsequentAddressFamily.class),
+ new AfiSafiBuilder().setAfiSafiName(Ipv4Flow.class).build());
+ TABLETYPE_TO_AFISAFI.put(new BgpTableTypeImpl(Ipv6AddressFamily.class, FlowspecSubsequentAddressFamily.class),
+ new AfiSafiBuilder().setAfiSafiName(Ipv6Flow.class).build());
+ }
+
+ private OpenConfigUtil() {
+ throw new UnsupportedOperationException();
+ }
+
+ public static Optional<AfiSafi> toAfiSafi(final BgpTableType tableType) {
+ return Optional.fromNullable(TABLETYPE_TO_AFISAFI.get(tableType));
+ }
+
+ public static List<AfiSafi> toAfiSafis(final List<BgpTableType> advertizedTables) {
+ final List<AfiSafi> afiSafis = new ArrayList<>(advertizedTables.size());
+ for (final BgpTableType tableType : advertizedTables) {
+ final Optional<AfiSafi> afiSafi = toAfiSafi(new BgpTableTypeImpl(tableType.getAfi(), tableType.getSafi()));
+ if (afiSafi.isPresent()) {
+ afiSafis.add(afiSafi.get());
+ }
+ }
+ return afiSafis;
+ }
+
+ public static String getModuleName(final String provider) {
+ return provider.substring(provider.lastIndexOf("=") + 2, provider.length() - 2);
+ }
+}
--- /dev/null
+module odl-openconfig-bgp-cfg {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:bgp:openconfig";
+ prefix "bgp-oc";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+ import odl-bgp-openconfig-spi-cfg { prefix bgp-oc-spi; revision-date 2015-09-25; }
+
+ description
+ "This module contains the base YANG definitions for
+ BGP openconfig application implementation.
+ Copyright (c)2015 Cisco Systems, Inc. All rights reserved.";
+
+ revision "2015-07-18" {
+ description
+ "Initial revision";
+ }
+
+ identity openconfig-bgp {
+ base config:module-type;
+ config:provided-service bgp-oc-spi:bgp-openconfig-provider;
+ config:java-name-prefix: BgpOpenConfigImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case openconfig-bgp {
+ when "/config:modules/config:module/config:type = 'openconfig-bgp'";
+
+ container binding-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-broker-osgi-registry;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfiguration;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Bgp;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Neighbors;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AbstractBGPNeighborProviderTest {
+
+ private AbstractBGPNeighborProvider<InstanceConfiguration> absNeighborProvider;
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() throws Exception {
+ final BindingTransactionChain txChain = Mockito.mock(BindingTransactionChain.class);
+ final BGPConfigStateStore stateHolders = Mockito.mock(BGPConfigStateStore.class);
+ final BGPConfigHolder<Neighbor> configHolder = Mockito.mock(BGPConfigHolder.class);
+ Mockito.doReturn(configHolder).when(stateHolders).getBGPConfigHolder(Mockito.any(Class.class));
+ absNeighborProvider = new AbstractBGPNeighborProvider<InstanceConfiguration>(txChain, stateHolders, Neighbor.class) {
+ @Override
+ public Neighbor apply(final InstanceConfiguration input) {
+ return null;
+ }
+ @Override
+ public ModuleKey createModuleKey(final String instanceName) {
+ return null;
+ }
+ @Override
+ public Class<InstanceConfiguration> getInstanceConfigurationType() {
+ return null;
+ }
+ };
+ }
+
+ @Test
+ public void testGetInstanceIdentifierNeighborKey() {
+ assertEquals(InstanceIdentifier.builder(Bgp.class).child(Neighbors.class).child(Neighbor.class, new NeighborKey(new IpAddress(new Ipv4Address("1.2.3.4")))).build(),
+ absNeighborProvider.getInstanceIdentifier(new NeighborKey(new IpAddress(new Ipv4Address("1.2.3.4")))));
+ }
+
+ @Test
+ public void testKeyForConfigurationNeighbor() {
+ assertEquals(new NeighborKey(new IpAddress(new Ipv4Address("1.2.3.4"))),
+ absNeighborProvider.keyForConfiguration(new NeighborBuilder().setKey(new NeighborKey((new IpAddress(new Ipv4Address("1.2.3.4"))))).build()));
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfiguration;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfigurationIdentifier;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yangtools.concepts.Identifier;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AbstractBGPOpenConfigMapperTest {
+
+ private static final InstanceConfigurationIdentifier IDENTIFIER = new InstanceConfigurationIdentifier("instanceName");
+
+ private static final InstanceConfiguration INSTANCE_CONFIGURATION = new InstanceConfiguration() {
+ @Override
+ public InstanceConfigurationIdentifier getIdentifier() {
+ return IDENTIFIER;
+ }
+ };
+
+ private AbstractBGPOpenConfigMapper<InstanceConfiguration, DataObject> mapper;
+ @SuppressWarnings("unchecked")
+ private final BGPConfigHolder<Neighbor> configHolder = Mockito.mock(BGPConfigHolder.class);
+ final WriteTransaction wTx = Mockito.mock(WriteTransaction.class);
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Before
+ public void setUp() throws Exception {
+ final BindingTransactionChain txChain = Mockito.mock(BindingTransactionChain.class);
+ Mockito.doNothing().when(wTx).put(Mockito.any(LogicalDatastoreType.class), Mockito.any(InstanceIdentifier.class), Mockito.any(DataObject.class));
+ Mockito.doNothing().when(wTx).delete(Mockito.any(LogicalDatastoreType.class), Mockito.any(InstanceIdentifier.class));
+ Mockito.doReturn(null).when(wTx).submit();
+ Mockito.doReturn(wTx).when(txChain).newWriteOnlyTransaction();
+ final BGPConfigStateStore stateHolders = Mockito.mock(BGPConfigStateStore.class);
+ Mockito.doReturn(configHolder).when(stateHolders).getBGPConfigHolder(Mockito.any(Class.class));
+ Mockito.doReturn(null).when(configHolder).getKey(Mockito.any(ModuleKey.class));
+ mapper = new AbstractBGPOpenConfigMapper(txChain, stateHolders, DataObject.class) {
+ @Override
+ public ModuleKey createModuleKey(final String instanceName) {
+ return null;
+ }
+ @Override
+ public Class<InstanceConfiguration> getInstanceConfigurationType() {
+ return null;
+ }
+ @Override
+ public Object apply(final Object input) {
+ return null;
+ }
+ @Override
+ protected org.opendaylight.yangtools.concepts.Identifier keyForConfiguration(final DataObject openConfig) {
+ return null;
+ }
+ @Override
+ protected InstanceIdentifier getInstanceIdentifier(final Identifier key) {
+ return null;
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testWriteConfiguration() {
+ Mockito.doReturn(true).when(this.configHolder).addOrUpdate(Mockito.any(ModuleKey.class), Mockito.any(NeighborKey.class), Mockito.any(Neighbor.class));
+ mapper.writeConfiguration(INSTANCE_CONFIGURATION);
+ Mockito.verify(wTx, Mockito.times(1)).put(Mockito.any(LogicalDatastoreType.class), Mockito.any(InstanceIdentifier.class), Mockito.any(DataObject.class));
+
+ Mockito.doReturn(false).when(this.configHolder).addOrUpdate(Mockito.any(ModuleKey.class), Mockito.any(NeighborKey.class), Mockito.any(Neighbor.class));
+ mapper.writeConfiguration(INSTANCE_CONFIGURATION);
+ Mockito.verify(wTx, Mockito.times(1)).put(Mockito.any(LogicalDatastoreType.class), Mockito.any(InstanceIdentifier.class), Mockito.any(DataObject.class));
+ }
+
+ @Test
+ public void testRemoveConfiguration() {
+ Mockito.doReturn(true).when(this.configHolder).remove(Mockito.any(ModuleKey.class));
+ mapper.removeConfiguration(IDENTIFIER);
+ Mockito.verify(wTx, Mockito.times(1)).delete(Mockito.any(LogicalDatastoreType.class), Mockito.any(InstanceIdentifier.class));
+
+ Mockito.doReturn(false).when(this.configHolder).remove(Mockito.any(ModuleKey.class));
+ mapper.removeConfiguration(IDENTIFIER);
+ Mockito.verify(wTx, Mockito.times(1)).delete(Mockito.any(LogicalDatastoreType.class), Mockito.any(InstanceIdentifier.class));
+
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfigurationIdentifier;
+import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPAppPeerInstanceConfiguration;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Config1;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Config1Builder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpApplicationPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+
+public class BGPAppNeighborProviderImplTest {
+
+ private BGPAppNeighborProviderImpl neighborProvider;
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() throws Exception {
+ final BindingTransactionChain txChain = Mockito.mock(BindingTransactionChain.class);
+ final BGPConfigStateStore stateHolders = Mockito.mock(BGPConfigStateStore.class);
+ final BGPConfigHolder<Neighbor> configHolder = Mockito.mock(BGPConfigHolder.class);
+ Mockito.doReturn(configHolder).when(stateHolders).getBGPConfigHolder(Mockito.any(Class.class));
+ neighborProvider = new BGPAppNeighborProviderImpl(txChain, stateHolders);
+ }
+
+ @Test
+ public void testCreateModuleKey() {
+ assertEquals(new ModuleKey("instanceName", BgpApplicationPeer.class), neighborProvider.createModuleKey("instanceName"));
+ }
+
+ @Test
+ public void testGetInstanceConfigurationType() {
+ assertEquals(BGPAppPeerInstanceConfiguration.class, neighborProvider.getInstanceConfigurationType());
+ }
+
+ @Test
+ public void testApply() {
+ final Neighbor neighbor = neighborProvider.apply(new BGPAppPeerInstanceConfiguration(new InstanceConfigurationIdentifier("instanceName"), "app-rib", new Ipv4Address("1.2.3.4")));
+ final Neighbor expectedNeighbor = new NeighborBuilder()
+ .setNeighborAddress(new IpAddress(new Ipv4Address("1.2.3.4")))
+ .setKey(new NeighborKey(new IpAddress(new Ipv4Address("1.2.3.4"))))
+ .setConfig(new ConfigBuilder().addAugmentation(Config1.class, new Config1Builder().setPeerGroup("application-peers").build()).build())
+ .build();
+ assertEquals(expectedNeighbor, neighbor);
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfiguration;
+import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPAppPeerInstanceConfiguration;
+import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPPeerInstanceConfiguration;
+
+public class BGPConfigMapperRegistryTest {
+
+ @SuppressWarnings("rawtypes")
+ final AbstractBGPOpenConfigMapper mapper = Mockito.mock(AbstractBGPOpenConfigMapper.class);
+
+ @Before
+ public void setup() {
+ Mockito.doReturn(BGPPeerInstanceConfiguration.class).when(mapper).getInstanceConfigurationType();
+ }
+
+ @Test
+ public void testBGPConfigMapperRegistry() {
+ final BGPConfigMapperRegistry registry = new BGPConfigMapperRegistry();
+ registry.registerOpenConfigMapper(mapper);
+ assertNotNull(registry.getOpenConfigMapper(BGPPeerInstanceConfiguration.class));
+ assertNull(registry.getOpenConfigMapper(BGPAppPeerInstanceConfiguration.class));
+ assertNull(registry.getOpenConfigMapper(InstanceConfiguration.class));
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.Lists;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.impl.util.GlobalIdentifier;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfigurationIdentifier;
+import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPRibInstanceConfiguration;
+import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev150515.bgp.common.afi.safi.list.AfiSafiBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.Bgp;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.Global;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.GlobalBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.global.base.AfiSafisBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.global.base.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.LinkstateAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.LinkstateSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev150930.Linkstate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.RibImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class BGPGlobalProviderImplTest {
+
+ private BGPGlobalProviderImpl globalProvider;
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setup() {
+ final BindingTransactionChain txChain = Mockito.mock(BindingTransactionChain.class);
+ final BGPConfigStateStore stateHolders = Mockito.mock(BGPConfigStateStore.class);
+ final BGPConfigHolder<Global> configHolder = Mockito.mock(BGPConfigHolder.class);
+ Mockito.doReturn(configHolder).when(stateHolders).getBGPConfigHolder(Mockito.any(Class.class));
+ globalProvider = new BGPGlobalProviderImpl(txChain, stateHolders);
+ }
+
+ @Test
+ public void testCreateModuleKey() {
+ assertEquals(new ModuleKey("instanceName", RibImpl.class), globalProvider.createModuleKey("instanceName"));
+ }
+
+ @Test
+ public void testApply() {
+ final Global global = globalProvider.apply(new BGPRibInstanceConfiguration(new InstanceConfigurationIdentifier("instanceName"), new AsNumber(1L),
+ new Ipv4Address("1.2.3.4"), null,
+ Lists.<BgpTableType>newArrayList(new BgpTableTypeImpl(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class))));
+ final Global expectedGlobal = new GlobalBuilder()
+ .setAfiSafis(
+ new AfiSafisBuilder().setAfiSafi(Collections.singletonList(new AfiSafiBuilder().setAfiSafiName(Linkstate.class).build())).build())
+ .setConfig(new ConfigBuilder().setRouterId(new Ipv4Address("1.2.3.4")).setAs(new AsNumber(1L)).build())
+ .build();
+ assertEquals(expectedGlobal, global);
+ }
+
+ @Test
+ public void testGetInstanceIdentifierString() {
+ assertEquals(InstanceIdentifier.builder(Bgp.class).child(Global.class).build(), globalProvider.getInstanceIdentifier(null));
+ }
+
+ @Test
+ public void testKeyForConfigurationGlobal() {
+ assertEquals(GlobalIdentifier.GLOBAL_IDENTIFIER, globalProvider.keyForConfiguration(new GlobalBuilder().build()));
+ }
+
+ @Test
+ public void testGetInstanceConfigurationType() {
+ assertEquals(BGPRibInstanceConfiguration.class, globalProvider.getInstanceConfigurationType());
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.openconfig;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import java.math.BigDecimal;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
+import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
+import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfigurationIdentifier;
+import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPPeerInstanceConfiguration;
+import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev150515.bgp.common.afi.safi.list.AfiSafi;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev150515.bgp.common.afi.safi.list.AfiSafiBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.AfiSafisBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.RouteReflectorBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.TimersBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.TransportBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbors.NeighborKey;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.PeerType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.FlowspecSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev150930.Ipv6Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv6AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.BgpPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.tcpmd5.cfg.rev140427.Rfc2385Key;
+
+public class BGPNeighborProviderImplTest {
+
+ private BGPNeighborProviderImpl neighborProvider;
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() throws Exception {
+ final BindingTransactionChain txChain = Mockito.mock(BindingTransactionChain.class);
+ final BGPConfigStateStore stateHolders = Mockito.mock(BGPConfigStateStore.class);
+ final BGPConfigHolder<Neighbor> configHolder = Mockito.mock(BGPConfigHolder.class);
+ Mockito.doReturn(configHolder).when(stateHolders).getBGPConfigHolder(Mockito.any(Class.class));
+ neighborProvider = new BGPNeighborProviderImpl(txChain, stateHolders);
+ }
+
+ @Test
+ public void testCreateModuleKey() {
+ assertEquals(new ModuleKey("instanceName", BgpPeer.class), neighborProvider.createModuleKey("instanceName"));
+ }
+
+ @Test
+ public void testGetInstanceConfigurationType() {
+ assertEquals(BGPPeerInstanceConfiguration.class, neighborProvider.getInstanceConfigurationType());
+ }
+
+ @Test
+ public void testApply() {
+ final Neighbor neighbor = neighborProvider.apply(new BGPPeerInstanceConfiguration(new InstanceConfigurationIdentifier("instanceName"),
+ new IpAddress(new Ipv4Address("1.2.3.4")), new PortNumber(123), (short) 10, PeerRole.RrClient, false,
+ Lists.<BgpTableType>newArrayList(new BgpTableTypeImpl(Ipv6AddressFamily.class, FlowspecSubsequentAddressFamily.class)),
+ new AsNumber(10L), Optional.<Rfc2385Key>absent()));
+ final Neighbor expectedNeighbor = new NeighborBuilder()
+ .setAfiSafis(new AfiSafisBuilder().setAfiSafi(Lists.<AfiSafi>newArrayList(new AfiSafiBuilder().setAfiSafiName(Ipv6Flow.class).build())).build())
+ .setNeighborAddress(new IpAddress(new Ipv4Address("1.2.3.4")))
+ .setKey(new NeighborKey(new IpAddress(new Ipv4Address("1.2.3.4"))))
+ .setConfig(new ConfigBuilder().setPeerAs(new AsNumber(10L)).setPeerType(PeerType.INTERNAL).build())
+ .setRouteReflector(new RouteReflectorBuilder().setConfig(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.route.reflector.ConfigBuilder().setRouteReflectorClient(true).build()).build())
+ .setTimers(new TimersBuilder().setConfig(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.timers.ConfigBuilder().setHoldTime(BigDecimal.valueOf(10)).build()).build())
+ .setTransport(new TransportBuilder().setConfig(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev150515.bgp.neighbor.group.transport.ConfigBuilder().setPassiveMode(true).build()).build())
+ .build();
+ assertEquals(expectedNeighbor, neighbor);
+ }
+
+}
--- /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
+ */
+
+package org.opendaylight.protocol.bgp.openconfig.impl.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil.getModuleName;
+import static org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil.toAfiSafi;
+
+import com.google.common.collect.Lists;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev150515.bgp.common.afi.safi.list.AfiSafi;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev150515.bgp.common.afi.safi.list.AfiSafiBuilder;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev150515.Ipv4Unicast;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
+
+public class OpenConfigUtilTest {
+
+ private static final String TEST = "/modules/module[type='dom-concurrent-data-broker'][name='concurrent-data-broker']";
+
+ @Test
+ public void test() {
+ final String moduleName = getModuleName(TEST);
+ assertEquals("concurrent-data-broker", moduleName);
+ }
+
+ @Test
+ public void testToAfiSafi() {
+ assertEquals(toAfiSafi(new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class)).get(),
+ new AfiSafiBuilder().setAfiSafiName(Ipv4Unicast.class).build());
+ }
+
+ @Test
+ public void testToAfiSafis() {
+ final List<AfiSafi> afiSafis = OpenConfigUtil.toAfiSafis(Lists.<BgpTableType>newArrayList(new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class)));
+ Assert.assertEquals(Collections.singletonList(new AfiSafiBuilder().setAfiSafiName(Ipv4Unicast.class).build()), afiSafis);
+ }
+
+ @Test(expected=UnsupportedOperationException.class)
+ public void testPrivateConstructor() throws Throwable {
+ final Constructor<OpenConfigUtil> c = OpenConfigUtil.class.getDeclaredConstructor();
+ c.setAccessible(true);
+ try {
+ c.newInstance();
+ } catch (final InvocationTargetException e) {
+ throw e.getCause();
+ }
+ }
+
+}
\ No newline at end of file
<module>controller-config</module>
<module>openconfig-api</module>
<module>openconfig-spi</module>
- </modules>
+ <module>openconfig-impl</module>
+ </modules>
</project>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<Export-Package>
org.opendaylight.protocol.bgp.rib.impl.*,
- org.opendaylight.controller.config.yang.bgp.rib.impl
+ org.opendaylight.controller.config.yang.bgp.rib.impl,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev130409.*
</Export-Package>
</instructions>
</configuration>
<commons.opendaylight.version>1.6.0-SNAPSHOT</commons.opendaylight.version>
<protocol-framework.version>0.7.0-SNAPSHOT</protocol-framework.version>
<tcpmd5.version>1.2.0-SNAPSHOT</tcpmd5.version>
+ <netconf.version>1.0.0-SNAPSHOT</netconf.version>
</properties>
<dependencyManagement>
<scope>import</scope>
<type>pom</type>
</dependency>
+
+ <!-- NETCONF -->
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-artifacts</artifactId>
+ <version>${netconf.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
</dependencies>
</dependencyManagement>
<classifier>features</classifier>
<type>xml</type>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>features-netconf-connector</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-concepts</artifactId>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-bmp-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-openconfig-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-openconfig-impl</artifactId>
+ </dependency>
<dependency>
<groupId>io.netty</groupId>
<repository>mvn:org.opendaylight.tcpmd5/features-tcpmd5/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.bgpcep/features-rsvp/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.netconf/features-netconf-connector/{{VERSION}}/xml/features</repository>
<feature name='odl-bgpcep-bgp-all' version='${project.version}'>
<feature version='${project.version}'>odl-bgpcep-bgp-flowspec</feature>
<feature version='${project.version}'>odl-bgpcep-bgp-labeled-unicast</feature>
<feature version='${project.version}'>odl-bgpcep-bgp-topology</feature>
+ <feature version='${project.version}'>odl-bgpcep-bgp-openconfig</feature>
<configfile finalname="etc/opendaylight/karaf/31-bgp.xml">mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/config</configfile>
<configfile finalname="etc/opendaylight/karaf/41-bgp-example.xml">mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/config-example</configfile>
+ <configfile finalname="etc/opendaylight/karaf/43-bgp-openconfig.xml">mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/openconfig-config</configfile>
+ </feature>
+
+ <feature name="odl-bgpcep-bgp-openconfig" version='${project.version}'>
+ <feature version='${project.version}'>odl-bgpcep-bgp-rib-impl</feature>
+ <feature version='${project.version}'>odl-bgpcep-bgp-linkstate</feature>
+ <feature version='${project.version}'>odl-bgpcep-bgp-flowspec</feature>
+ <feature version='${project.version}'>odl-bgpcep-bgp-labeled-unicast</feature>
+ <feature version='${project.version}'>odl-bgpcep-bgp-topology</feature>
+ <feature version='${netconf.version}'>odl-netconf-connector</feature>
+ <bundle>mvn:org.opendaylight.bgpcep/bgp-openconfig-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.bgpcep/bgp-openconfig-impl/{{VERSION}}</bundle>
</feature>
<feature name='odl-bgpcep-bgp-dependencies' version='${project.version}'>
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <!-- Netconf -->
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-artifacts</artifactId>
+ <version>${netconf.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
</dependencies>
</dependencyManagement>