BUG-4197: BGP OpenConfig Implementation 94/28394/12
authorMilos Fabian <milfabia@cisco.com>
Wed, 23 Sep 2015 10:09:21 +0000 (12:09 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 5 Nov 2015 15:44:07 +0000 (15:44 +0000)
-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>
41 files changed:
artifacts/pom.xml
bgp/controller-config/pom.xml
bgp/controller-config/src/main/resources/initial/43-bgp-openconfig.xml [new file with mode: 0644]
bgp/openconfig-impl/.project [new file with mode: 0644]
bgp/openconfig-impl/pom.xml [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModule.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModuleFactory.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigHolderImpl.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigStateStoreImpl.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPOpenConfig.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPAppPeerProvider.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPConfigModuleProvider.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPOpenConfigListener.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPPeerProvider.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPRibImplProvider.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/RibInstanceFunction.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/TableTypesFunction.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProvider.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapper.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImpl.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistry.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigModuleMapperProvider.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImpl.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImpl.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigHolder.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigStateStore.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/GlobalIdentifier.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtil.java [new file with mode: 0644]
bgp/openconfig-impl/src/main/yang/odl-openconfig-bgp-cfg.yang [new file with mode: 0644]
bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProviderTest.java [new file with mode: 0644]
bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapperTest.java [new file with mode: 0644]
bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImplTest.java [new file with mode: 0644]
bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistryTest.java [new file with mode: 0644]
bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImplTest.java [new file with mode: 0644]
bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImplTest.java [new file with mode: 0644]
bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtilTest.java [new file with mode: 0644]
bgp/pom.xml
bgp/rib-impl/pom.xml
features/bgp/pom.xml
features/bgp/src/main/features/features.xml
parent/pom.xml

index 0e3d379eeadf908fd3504b01ab0fdde3511f040b..7f9844da88c1edb0779ec6d2ded27d881ebf583c 100644 (file)
                 <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>
index 514d464dd364674b4b75559f0fa387f61c146b74..8daa45839e98d06f563a2b0f7882ad0c891b7f11 100644 (file)
                                     <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>
diff --git a/bgp/controller-config/src/main/resources/initial/43-bgp-openconfig.xml b/bgp/controller-config/src/main/resources/initial/43-bgp-openconfig.xml
new file mode 100644 (file)
index 0000000..1a24b15
--- /dev/null
@@ -0,0 +1,50 @@
+<?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&amp;revision=2015-07-18</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:bgp-openconfig-spi?module=odl-bgp-openconfig-spi-cfg&amp;revision=2015-09-25</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:bgp:rib:impl?module=odl-bgp-rib-impl-cfg&amp;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>
diff --git a/bgp/openconfig-impl/.project b/bgp/openconfig-impl/.project
new file mode 100644 (file)
index 0000000..48b788b
--- /dev/null
@@ -0,0 +1,23 @@
+<?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>
diff --git a/bgp/openconfig-impl/pom.xml b/bgp/openconfig-impl/pom.xml
new file mode 100644 (file)
index 0000000..d213049
--- /dev/null
@@ -0,0 +1,161 @@
+<?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
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModule.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModule.java
new file mode 100644 (file)
index 0000000..dc154ea
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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;
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModuleFactory.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModuleFactory.java
new file mode 100644 (file)
index 0000000..c450d96
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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 {
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigHolderImpl.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigHolderImpl.java
new file mode 100644 (file)
index 0000000..41e9d8a
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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);
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigStateStoreImpl.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigStateStoreImpl.java
new file mode 100644 (file)
index 0000000..e147105
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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);
+    }
+
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPOpenConfig.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPOpenConfig.java
new file mode 100644 (file)
index 0000000..618bc05
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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);
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPAppPeerProvider.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPAppPeerProvider.java
new file mode 100644 (file)
index 0000000..32c49b5
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * 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();
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPConfigModuleProvider.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPConfigModuleProvider.java
new file mode 100644 (file)
index 0000000..74a0274
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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));
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPOpenConfigListener.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPOpenConfigListener.java
new file mode 100644 (file)
index 0000000..cd54040
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * 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;
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPPeerProvider.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPPeerProvider.java
new file mode 100644 (file)
index 0000000..b9b2730
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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;
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPRibImplProvider.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPRibImplProvider.java
new file mode 100644 (file)
index 0000000..9ea214e
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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();
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/RibInstanceFunction.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/RibInstanceFunction.java
new file mode 100644 (file)
index 0000000..ec8e7a5
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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;
+            }
+
+        });
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/TableTypesFunction.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/TableTypesFunction.java
new file mode 100644 (file)
index 0000000..4c61faf
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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;
+        }
+
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProvider.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProvider.java
new file mode 100644 (file)
index 0000000..f8c1965
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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();
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapper.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapper.java
new file mode 100644 (file)
index 0000000..bf61294
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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();
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImpl.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImpl.java
new file mode 100644 (file)
index 0000000..841395c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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();
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistry.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistry.java
new file mode 100644 (file)
index 0000000..a958f63
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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);
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigModuleMapperProvider.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigModuleMapperProvider.java
new file mode 100644 (file)
index 0000000..1fbc149
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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();
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImpl.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImpl.java
new file mode 100644 (file)
index 0000000..0cfd900
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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();
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImpl.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImpl.java
new file mode 100644 (file)
index 0000000..cc0700c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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;
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigHolder.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigHolder.java
new file mode 100644 (file)
index 0000000..a76dc5d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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);
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigStateStore.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigStateStore.java
new file mode 100644 (file)
index 0000000..99973dd
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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);
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/GlobalIdentifier.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/GlobalIdentifier.java
new file mode 100644 (file)
index 0000000..1af2d79
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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;
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtil.java b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtil.java
new file mode 100644 (file)
index 0000000..f09626f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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);
+    }
+}
diff --git a/bgp/openconfig-impl/src/main/yang/odl-openconfig-bgp-cfg.yang b/bgp/openconfig-impl/src/main/yang/odl-openconfig-bgp-cfg.yang
new file mode 100644 (file)
index 0000000..ea920d3
--- /dev/null
@@ -0,0 +1,40 @@
+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
diff --git a/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProviderTest.java b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProviderTest.java
new file mode 100644 (file)
index 0000000..d5c338c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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()));
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapperTest.java b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapperTest.java
new file mode 100644 (file)
index 0000000..32891eb
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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));
+
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImplTest.java b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImplTest.java
new file mode 100644 (file)
index 0000000..2f7b9a2
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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);
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistryTest.java b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistryTest.java
new file mode 100644 (file)
index 0000000..efdee28
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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));
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImplTest.java b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImplTest.java
new file mode 100644 (file)
index 0000000..d3342e8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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());
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImplTest.java b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImplTest.java
new file mode 100644 (file)
index 0000000..430f992
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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);
+    }
+
+}
diff --git a/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtilTest.java b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtilTest.java
new file mode 100644 (file)
index 0000000..de86d7a
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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
index f7c06bb858ebac09d44f37e6e883711398f127b8..dbd78eadfc37067b8394a7a6002e720902390802 100644 (file)
@@ -52,5 +52,6 @@
         <module>controller-config</module>
         <module>openconfig-api</module>
         <module>openconfig-spi</module>
-    </modules>
+        <module>openconfig-impl</module>
+  </modules>
 </project>
index c1a569e2c9f59639495e88972a9b09246055215a..88a15d0ea5fff2fa77c6dfbbc2d6ed06e7dd2e79 100644 (file)
                         <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>
index eb24c57c47b523f756aa74c6b54b1e9eac34bec1..104230146af7ef606989805dd8b5a41b4e7ba219 100644 (file)
@@ -30,6 +30,7 @@
         <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>
index 13f43ff160ab89d336ae34cf3eb33c915595a27b..2c2c7bb83649730c0216a2156fb1268158bb84f4 100644 (file)
@@ -19,6 +19,7 @@
     <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}'>
index 3443ca235bfe1b42ce39c64485451bb45887ab04..cf35e4b5c27256e3cedf62b6c5baa2c29edfa93c 100644 (file)
                 <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>