From 3a36ce8ca3221ea9d5ecda53eda7896ff1e630c3 Mon Sep 17 00:00:00 2001 From: Milos Fabian Date: Wed, 23 Sep 2015 12:09:21 +0200 Subject: [PATCH] BUG-4197: BGP OpenConfig Implementation -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 --- artifacts/pom.xml | 5 + bgp/controller-config/pom.xml | 5 + .../resources/initial/43-bgp-openconfig.xml | 50 +++++ bgp/openconfig-impl/.project | 23 ++ bgp/openconfig-impl/pom.xml | 161 ++++++++++++++ .../openconfig/BgpOpenConfigImplModule.java | 36 +++ .../BgpOpenConfigImplModuleFactory.java | 13 ++ .../openconfig/impl/BGPConfigHolderImpl.java | 62 ++++++ .../impl/BGPConfigStateStoreImpl.java | 33 +++ .../bgp/openconfig/impl/BGPOpenConfig.java | 162 ++++++++++++++ .../impl/moduleconfig/BGPAppPeerProvider.java | 144 ++++++++++++ .../moduleconfig/BGPConfigModuleProvider.java | 54 +++++ .../moduleconfig/BGPOpenConfigListener.java | 150 +++++++++++++ .../impl/moduleconfig/BGPPeerProvider.java | 207 ++++++++++++++++++ .../impl/moduleconfig/BGPRibImplProvider.java | 113 ++++++++++ .../moduleconfig/RibInstanceFunction.java | 67 ++++++ .../impl/moduleconfig/TableTypesFunction.java | 127 +++++++++++ .../AbstractBGPNeighborProvider.java | 42 ++++ .../AbstractBGPOpenConfigMapper.java | 83 +++++++ .../BGPAppNeighborProviderImpl.java | 56 +++++ .../openconfig/BGPConfigMapperRegistry.java | 33 +++ .../BGPConfigModuleMapperProvider.java | 85 +++++++ .../openconfig/BGPGlobalProviderImpl.java | 69 ++++++ .../openconfig/BGPNeighborProviderImpl.java | 100 +++++++++ .../openconfig/impl/spi/BGPConfigHolder.java | 58 +++++ .../impl/spi/BGPConfigStateStore.java | 36 +++ .../impl/util/GlobalIdentifier.java | 55 +++++ .../openconfig/impl/util/OpenConfigUtil.java | 84 +++++++ .../src/main/yang/odl-openconfig-bgp-cfg.yang | 40 ++++ .../AbstractBGPNeighborProviderTest.java | 69 ++++++ .../AbstractBGPOpenConfigMapperTest.java | 103 +++++++++ .../BGPAppNeighborProviderImplTest.java | 67 ++++++ .../BGPConfigMapperRegistryTest.java | 40 ++++ .../openconfig/BGPGlobalProviderImplTest.java | 88 ++++++++ .../BGPNeighborProviderImplTest.java | 91 ++++++++ .../impl/util/OpenConfigUtilTest.java | 63 ++++++ bgp/pom.xml | 3 +- bgp/rib-impl/pom.xml | 3 +- features/bgp/pom.xml | 24 ++ features/bgp/src/main/features/features.xml | 14 ++ parent/pom.xml | 8 + 41 files changed, 2724 insertions(+), 2 deletions(-) create mode 100644 bgp/controller-config/src/main/resources/initial/43-bgp-openconfig.xml create mode 100644 bgp/openconfig-impl/.project create mode 100644 bgp/openconfig-impl/pom.xml create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModule.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModuleFactory.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigHolderImpl.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigStateStoreImpl.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPOpenConfig.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPAppPeerProvider.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPConfigModuleProvider.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPOpenConfigListener.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPPeerProvider.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPRibImplProvider.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/RibInstanceFunction.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/TableTypesFunction.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProvider.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapper.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImpl.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistry.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigModuleMapperProvider.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImpl.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImpl.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigHolder.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigStateStore.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/GlobalIdentifier.java create mode 100644 bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtil.java create mode 100644 bgp/openconfig-impl/src/main/yang/odl-openconfig-bgp-cfg.yang create mode 100644 bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProviderTest.java create mode 100644 bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapperTest.java create mode 100644 bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImplTest.java create mode 100644 bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistryTest.java create mode 100644 bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImplTest.java create mode 100644 bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImplTest.java create mode 100644 bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtilTest.java diff --git a/artifacts/pom.xml b/artifacts/pom.xml index 0e3d379eea..7f9844da88 100644 --- a/artifacts/pom.xml +++ b/artifacts/pom.xml @@ -378,6 +378,11 @@ bgp-openconfig-spi ${project.version} + + ${project.groupId} + bgp-openconfig-impl + ${project.version} + ${project.groupId} bgp-controller-config diff --git a/bgp/controller-config/pom.xml b/bgp/controller-config/pom.xml index 514d464dd3..8daa45839e 100644 --- a/bgp/controller-config/pom.xml +++ b/bgp/controller-config/pom.xml @@ -65,6 +65,11 @@ xml bmp-config-example + + ${project.build.directory}/classes/initial/43-bgp-openconfig.xml + xml + openconfig-config + 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 index 0000000000..1a24b15fd5 --- /dev/null +++ b/bgp/controller-config/src/main/resources/initial/43-bgp-openconfig.xml @@ -0,0 +1,50 @@ + + + + + + urn:opendaylight:params:xml:ns:yang:controller:bgp:openconfig?module=odl-openconfig-bgp-cfg&revision=2015-07-18 + urn:opendaylight:params:xml:ns:yang:controller:bgp-openconfig-spi?module=odl-bgp-openconfig-spi-cfg&revision=2015-09-25 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:bgp:rib:impl?module=odl-bgp-rib-impl-cfg&revision=2013-04-09 + + + + + + + prefix:openconfig-bgp + openconfig-bgp + + prefix:binding-broker-osgi-registry + binding-osgi-broker + + + + prefix:rib-impl + example-bgp-rib + + prefix:bgp-openconfig-provider + openconfig-bgp + + + + + + + prefix:bgp-openconfig-provider + + openconfig-bgp + /config/modules/module[name='openconfig-bgp']/instance[name='openconfig-bgp'] + + + + + + diff --git a/bgp/openconfig-impl/.project b/bgp/openconfig-impl/.project new file mode 100644 index 0000000000..48b788b021 --- /dev/null +++ b/bgp/openconfig-impl/.project @@ -0,0 +1,23 @@ + + + bgp-openconfig-impl + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bgp/openconfig-impl/pom.xml b/bgp/openconfig-impl/pom.xml new file mode 100644 index 0000000000..d213049f48 --- /dev/null +++ b/bgp/openconfig-impl/pom.xml @@ -0,0 +1,161 @@ + + + + + + + 4.0.0 + + scm:git:ssh://git.opendaylight.org:29418/bgpcep.git + scm:git:ssh://git.opendaylight.org:29418/bgpcep.git + https://wiki.opendaylight.org/view/BGP_LS_PCEP:Main + HEAD + + + org.opendaylight.bgpcep + bgp-parent + 0.5.0-SNAPSHOT + + + bgp-openconfig-impl + BGP OPENCONFIG IMPL + bundle + ${project.artifactId} + + + + ${project.groupId} + bgp-openconfig-api + + + ${project.groupId} + bgp-openconfig-spi + + + ${project.groupId} + bgp-parser-api + + + ${project.groupId} + bgp-rib-api + + + ${project.groupId} + bgp-rib-impl + + + ${project.groupId} + bgp-concepts + + + ${project.groupId} + bgp-linkstate + + + ${project.groupId} + bgp-flowspec + + + ${project.groupId} + bgp-labeled-unicast + + + org.opendaylight.controller + config-api + + + org.opendaylight.controller + sal-binding-api + + + org.opendaylight.controller + sal-binding-config + + + org.opendaylight.controller + sal-common-api + + + org.opendaylight.yangtools + yang-common + + + org.opendaylight.yangtools + concepts + + + org.opendaylight.mdsal + yang-binding + + + org.opendaylight.mdsal.model + ietf-inet-types + + + com.google.guava + guava + + + org.opendaylight.netconf + sal-netconf-connector + + + org.opendaylight.mdsal.model + ietf-topology + + + org.opendaylight.tcpmd5 + tcpmd5-api + + + org.osgi + org.osgi.core + + + org.slf4j + slf4j-api + + + com.google.code.findbugs + jsr305 + + + + junit + junit + test + + + org.mockito + mockito-core + + + org.opendaylight.yangtools + mockito-configuration + + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.groupId}.${project.artifactId} + + + + + + \ 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 index 0000000000..dc154eaaf9 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModule.java @@ -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 index 0000000000..c450d96fca --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/openconfig/BgpOpenConfigImplModuleFactory.java @@ -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 index 0000000000..41e9d8aced --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigHolderImpl.java @@ -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 implements BGPConfigHolder { + + @GuardedBy("this") + private final BiMap moduleToOpenConfig = HashBiMap.create(); + + @GuardedBy("this") + private final Map 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 index 0000000000..e1471054b7 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPConfigStateStoreImpl.java @@ -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, BGPConfigHolder> configHolderMap = new HashMap<>(); + + @SuppressWarnings("unchecked") + @Override + public BGPConfigHolder getBGPConfigHolder(final Class clazz) { + return (BGPConfigHolder) configHolderMap.get(clazz); + } + + @Override + public void registerBGPConfigHolder(final Class clazz, final BGPConfigHolder 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 index 0000000000..618bc05e10 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/BGPOpenConfig.java @@ -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, BGPOpenConfigProvider { + + private static final Logger LOG = LoggerFactory.getLogger(BGPOpenConfig.class); + + private static final InstanceIdentifier 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 CONTROLLER_CONFIG_IID = NETCONF_TOPOLOGY + .child(Node.class, CONFIG_NODE_KEY); + + private final BGPConfigStateStore configStateHolders; + private BGPConfigModuleMapperProvider configModuleListener; + private BGPOpenConfigListener openConfigListener; + private ListenerRegistration registration; + private MountPointService mountService; + private DataBroker dataBroker; + + public BGPOpenConfig() { + configStateHolders = new BGPConfigStateStoreImpl(); + configStateHolders.registerBGPConfigHolder(Global.class, new BGPConfigHolderImpl()); + configStateHolders.registerBGPConfigHolder(Neighbor.class, new BGPConfigHolderImpl()); + } + + @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> changes) { + for (final DataTreeModification dataTreeModification : changes) { + final DataObjectModification 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 callable = new Callable() { + @Override + public MountPoint call() { + Optional 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 BGPOpenconfigMapper getOpenConfigMapper(final Class 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 index 0000000000..32c49b522f --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPAppPeerProvider.java @@ -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 TO_RIB_FUNCTION = new Function() { + @Override + public TargetRib apply(final String name) { + return new TargetRibBuilder().setName(name).setType(RibInstance.class).build(); + } + }; + + private final BGPConfigHolder neighborState; + private final BGPConfigHolder 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 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 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 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 index 0000000000..74a02746f0 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPConfigModuleProvider.java @@ -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_IID = InstanceIdentifier.builder(Services.class).build(); + private static final InstanceIdentifier 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> readModuleConfiguration(final ModuleKey moduleKey, final ReadTransaction rTx) { + return rTx.read(LogicalDatastoreType.CONFIGURATION, MODULES_IID.child(Module.class, moduleKey)); + } + + ListenableFuture> 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 index 0000000000..cd54040b66 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPOpenConfigListener.java @@ -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, AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(BGPOpenConfigListener.class); + + private final BGPConfigModuleProvider configModuleWriter; + private final ListenerRegistration registerDataTreeChangeListener; + private final BGPRibImplProvider ribImplProvider; + private final BGPPeerProvider peerProvider; + private final BGPAppPeerProvider appPeerProvider; + private final Callable callable; + + public BGPOpenConfigListener(final DataBroker dataBroker, final Callable 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> changes) { + try { + final Optional databroker = callable.call().getService(DataBroker.class); + if (databroker.isPresent()) { + for (final DataTreeModification dataTreeModification : changes) { + final DataObjectModification rootNode = dataTreeModification.getRootNode(); + for (final DataObjectModification 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 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 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 index 0000000000..b9b2730daf --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPPeerProvider.java @@ -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 ADVERTIZED_TABLE_FUNCTION = new Function() { + @Override + public AdvertizedTable apply(final String instance) { + return new AdvertizedTableBuilder().setName(instance).setType(BgpTableType.class).build(); + } + }; + + private static final Function TO_RIB_FUNCTION = new Function() { + @Override + public Rib apply(final String name) { + return new RibBuilder().setName(name).setType(RibInstance.class).build(); + } + }; + + private final BGPConfigHolder neighborState; + private final BGPConfigHolder 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 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> advertizedTablesFuture = new TableTypesFunction(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 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 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 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 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 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 index 0000000000..9ea214eaf4 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/BGPRibImplProvider.java @@ -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 LOCAL_TABLE_FUNCTION = new Function() { + @Override + public LocalTable apply(final String input) { + return new LocalTableBuilder().setName(input).setType(BgpTableType.class).build(); + } + }; + + private final BGPConfigHolder 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 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 maybeModule = configModuleWriter.readModuleConfiguration(moduleKey, rTx).get(); + if (maybeModule.isPresent()) { + final ListenableFuture> localTablesFuture = new TableTypesFunction(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 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 index 0000000000..ec8e7a5ca5 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/RibInstanceFunction.java @@ -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> implements AsyncFunction { + + private final ReadTransaction rTx; + private final BGPConfigModuleProvider configModuleOp; + private final Function function; + + public RibInstanceFunction(final ReadTransaction rTx, final BGPConfigModuleProvider configModuleOp, final Function function) { + this.rTx = Preconditions.checkNotNull(rTx); + this.configModuleOp = Preconditions.checkNotNull(configModuleOp); + this.function = Preconditions.checkNotNull(function); + } + + @Override + public ListenableFuture apply(final String instanceName) { + final ListenableFuture> readFuture = configModuleOp.readConfigService(new ServiceKey(RibInstance.class), rTx); + return Futures.transform(readFuture, new Function, T>() { + @Override + public T apply(final Optional maybeService) { + if (maybeService.isPresent()) { + final Optional maybeInstance = Iterables.tryFind(maybeService.get().getInstance(), new Predicate() { + @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 index 0000000000..4c61faf16c --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/moduleconfig/TableTypesFunction.java @@ -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> implements AsyncFunction, List> { + + private final ReadTransaction rTx; + private final BGPConfigModuleProvider configModuleWriter; + private final Function function; + + public TableTypesFunction(final ReadTransaction rTx, final BGPConfigModuleProvider configModuleWriter, final Function function) { + this.rTx = Preconditions.checkNotNull(rTx); + this.configModuleWriter = Preconditions.checkNotNull(configModuleWriter); + this.function = Preconditions.checkNotNull(function); + } + + @Override + public ListenableFuture> apply(final List afiSafis) { + final ListenableFuture> readFuture = configModuleWriter.readConfigService(new ServiceKey(BgpTableType.class), rTx); + return Futures.transform(readFuture, new AsyncFunction, List>() { + + @Override + public ListenableFuture> apply(final Optional maybeService) { + if (maybeService.isPresent()) { + final Service service = maybeService.get(); + final List>> modulesFuture = new ArrayList<>(); + final Map 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> { + + private final List afiSafis; + private final Map moduleNameToService; + + public ModulesToLocalTablesFunction(final List afiSafis, final Map moduleNameToService) { + this.afiSafis = afiSafis; + this.moduleNameToService = moduleNameToService; + } + + @Override + public List apply(final List> maybeModules) { + final ImmutableList modules = FluentIterable.from(maybeModules) + .filter(new Predicate>() { + @Override + public boolean apply(final Optional input) { + return input.isPresent(); + } + }).transform(new Function, Module>() { + @Override + public Module apply(final Optional input) { + return input.get(); + } + }).toList(); + + return toTableTypes(afiSafiToModuleName(modules)); + } + + private Map, String> afiSafiToModuleName(final List modules) { + final Map, 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 = 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 toTableTypes(final Map, String> afiSafiToModuleName) { + final List 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 index 0000000000..f8c196531f --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProvider.java @@ -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 extends AbstractBGPOpenConfigMapper { + + protected AbstractBGPNeighborProvider(final BindingTransactionChain txChain, final BGPConfigStateStore stateHolders, + final Class clazz) { + super(txChain, stateHolders, clazz); + } + + private static final InstanceIdentifier NEIGHBORS_IID = BGP_IID.child(Neighbors.class); + + @Override + protected InstanceIdentifier 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 index 0000000000..bf61294388 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapper.java @@ -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 implements BGPOpenconfigMapper, Function { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractBGPOpenConfigMapper.class); + + private final BGPConfigHolder configHolder; + private final BindingTransactionChain txChain; + + protected AbstractBGPOpenConfigMapper(final BindingTransactionChain txChain, final BGPConfigStateStore stateHolders, final Class 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 getInstanceIdentifier(Identifier key); + + protected abstract Identifier keyForConfiguration(final T openConfig); + + protected abstract Class 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 index 0000000000..841395c492 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImpl.java @@ -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 { + + 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 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 index 0000000000..a958f63652 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistry.java @@ -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, AbstractBGPOpenConfigMapper> configMappers = new HashMap<>(); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void registerOpenConfigMapper(final AbstractBGPOpenConfigMapper openConfigMapper) { + configMappers.put(openConfigMapper.getInstanceConfigurationType(), openConfigMapper); + } + + @SuppressWarnings("unchecked") + @Override + public BGPOpenconfigMapper getOpenConfigMapper(final Class 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 index 0000000000..1fbc1496e5 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigModuleMapperProvider.java @@ -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 BGPOpenconfigMapper getOpenConfigMapper(final Class 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 index 0000000000..0cfd900490 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImpl.java @@ -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 { + + private static final InstanceIdentifier 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 getInstanceIdentifier(final Identifier key) { + return GLOBAL_IID; + } + + @Override + public Identifier keyForConfiguration(final Global global) { + return GlobalIdentifier.GLOBAL_IDENTIFIER; + } + + @Override + public Class 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 index 0000000000..cc0700c11c --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImpl.java @@ -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 { + + public BGPNeighborProviderImpl(final BindingTransactionChain txChain, final BGPConfigStateStore stateHolders) { + super(txChain, stateHolders, Neighbor.class); + } + + @Override + public Class 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 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 index 0000000000..a76dc5d1ca --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigHolder.java @@ -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 A type of DataBobject to which the configuration is binded. + */ +public interface BGPConfigHolder { + + /** + * 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 index 0000000000..99973dd79e --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/spi/BGPConfigStateStore.java @@ -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. + */ + void registerBGPConfigHolder(@Nonnull Class clazz, @Nonnull BGPConfigHolder 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. + */ + BGPConfigHolder getBGPConfigHolder(@Nonnull Class 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 index 0000000000..1af2d79512 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/GlobalIdentifier.java @@ -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 index 0000000000..f09626fe43 --- /dev/null +++ b/bgp/openconfig-impl/src/main/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtil.java @@ -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_IID = InstanceIdentifier.builder(Bgp.class).build(); + + public static final String APPLICATION_PEER_GROUP_NAME = "application-peers"; + + private static final Map 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 toAfiSafi(final BgpTableType tableType) { + return Optional.fromNullable(TABLETYPE_TO_AFISAFI.get(tableType)); + } + + public static List toAfiSafis(final List advertizedTables) { + final List afiSafis = new ArrayList<>(advertizedTables.size()); + for (final BgpTableType tableType : advertizedTables) { + final Optional 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 index 0000000000..ea920d3c2e --- /dev/null +++ b/bgp/openconfig-impl/src/main/yang/odl-openconfig-bgp-cfg.yang @@ -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 index 0000000000..d5c338c7dc --- /dev/null +++ b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPNeighborProviderTest.java @@ -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 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 configHolder = Mockito.mock(BGPConfigHolder.class); + Mockito.doReturn(configHolder).when(stateHolders).getBGPConfigHolder(Mockito.any(Class.class)); + absNeighborProvider = new AbstractBGPNeighborProvider(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 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 index 0000000000..32891eb0e8 --- /dev/null +++ b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/AbstractBGPOpenConfigMapperTest.java @@ -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 mapper; + @SuppressWarnings("unchecked") + private final BGPConfigHolder 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 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 index 0000000000..2f7b9a243a --- /dev/null +++ b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPAppNeighborProviderImplTest.java @@ -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 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 index 0000000000..efdee28027 --- /dev/null +++ b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPConfigMapperRegistryTest.java @@ -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 index 0000000000..d3342e84f3 --- /dev/null +++ b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPGlobalProviderImplTest.java @@ -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 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.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 index 0000000000..430f992e75 --- /dev/null +++ b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/openconfig/BGPNeighborProviderImplTest.java @@ -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 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.newArrayList(new BgpTableTypeImpl(Ipv6AddressFamily.class, FlowspecSubsequentAddressFamily.class)), + new AsNumber(10L), Optional.absent())); + final Neighbor expectedNeighbor = new NeighborBuilder() + .setAfiSafis(new AfiSafisBuilder().setAfiSafi(Lists.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 index 0000000000..de86d7a5ec --- /dev/null +++ b/bgp/openconfig-impl/src/test/java/org/opendaylight/protocol/bgp/openconfig/impl/util/OpenConfigUtilTest.java @@ -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 afiSafis = OpenConfigUtil.toAfiSafis(Lists.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 c = OpenConfigUtil.class.getDeclaredConstructor(); + c.setAccessible(true); + try { + c.newInstance(); + } catch (final InvocationTargetException e) { + throw e.getCause(); + } + } + +} \ No newline at end of file diff --git a/bgp/pom.xml b/bgp/pom.xml index f7c06bb858..dbd78eadfc 100644 --- a/bgp/pom.xml +++ b/bgp/pom.xml @@ -52,5 +52,6 @@ controller-config openconfig-api openconfig-spi - + openconfig-impl + diff --git a/bgp/rib-impl/pom.xml b/bgp/rib-impl/pom.xml index c1a569e2c9..88a15d0ea5 100644 --- a/bgp/rib-impl/pom.xml +++ b/bgp/rib-impl/pom.xml @@ -288,7 +288,8 @@ ${project.groupId}.${project.artifactId} 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.* diff --git a/features/bgp/pom.xml b/features/bgp/pom.xml index eb24c57c47..104230146a 100644 --- a/features/bgp/pom.xml +++ b/features/bgp/pom.xml @@ -30,6 +30,7 @@ 1.6.0-SNAPSHOT 0.7.0-SNAPSHOT 1.2.0-SNAPSHOT + 1.0.0-SNAPSHOT @@ -90,6 +91,15 @@ import pom + + + + org.opendaylight.netconf + netconf-artifacts + ${netconf.version} + import + pom + @@ -154,6 +164,12 @@ features xml + + org.opendaylight.netconf + features-netconf-connector + features + xml + ${project.groupId} bgp-concepts @@ -260,6 +276,14 @@ ${project.groupId} bgp-bmp-api + + ${project.groupId} + bgp-openconfig-api + + + ${project.groupId} + bgp-openconfig-impl + io.netty diff --git a/features/bgp/src/main/features/features.xml b/features/bgp/src/main/features/features.xml index 13f43ff160..2c2c7bb836 100644 --- a/features/bgp/src/main/features/features.xml +++ b/features/bgp/src/main/features/features.xml @@ -19,6 +19,7 @@ mvn:org.opendaylight.tcpmd5/features-tcpmd5/{{VERSION}}/xml/features mvn:org.opendaylight.mdsal.model/features-mdsal-model/{{VERSION}}/xml/features mvn:org.opendaylight.bgpcep/features-rsvp/{{VERSION}}/xml/features + mvn:org.opendaylight.netconf/features-netconf-connector/{{VERSION}}/xml/features @@ -33,8 +34,21 @@ odl-bgpcep-bgp-flowspec odl-bgpcep-bgp-labeled-unicast odl-bgpcep-bgp-topology + odl-bgpcep-bgp-openconfig mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/config mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/config-example + mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/openconfig-config + + + + odl-bgpcep-bgp-rib-impl + odl-bgpcep-bgp-linkstate + odl-bgpcep-bgp-flowspec + odl-bgpcep-bgp-labeled-unicast + odl-bgpcep-bgp-topology + odl-netconf-connector + mvn:org.opendaylight.bgpcep/bgp-openconfig-api/{{VERSION}} + mvn:org.opendaylight.bgpcep/bgp-openconfig-impl/{{VERSION}} diff --git a/parent/pom.xml b/parent/pom.xml index 3443ca235b..cf35e4b5c2 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -137,6 +137,14 @@ test-jar test + + + org.opendaylight.netconf + netconf-artifacts + ${netconf.version} + import + pom + -- 2.36.6