2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.bmp.impl.app;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.base.Preconditions;
13 import com.google.common.net.InetAddresses;
14 import com.google.common.util.concurrent.FluentFuture;
15 import io.netty.channel.Channel;
16 import io.netty.channel.ChannelFuture;
17 import io.netty.channel.ChannelFutureListener;
18 import java.net.InetAddress;
19 import java.net.InetSocketAddress;
20 import java.util.Collection;
21 import java.util.HashMap;
23 import java.util.concurrent.ExecutionException;
24 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
25 import org.opendaylight.mdsal.common.api.CommitInfo;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
28 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
29 import org.opendaylight.mdsal.singleton.api.ClusterSingletonService;
30 import org.opendaylight.mdsal.singleton.api.ClusterSingletonServiceProvider;
31 import org.opendaylight.mdsal.singleton.api.ServiceGroupIdentifier;
32 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
33 import org.opendaylight.protocol.bmp.api.BmpDispatcher;
34 import org.opendaylight.protocol.bmp.impl.spi.BmpMonitoringStation;
35 import org.opendaylight.protocol.concepts.KeyMapping;
36 import org.opendaylight.protocol.util.Ipv4Util;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.config.rev200120.odl.bmp.monitors.bmp.monitor.config.MonitoredRouter;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.BmpMonitor;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.MonitorId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.bmp.monitor.Monitor;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.routers.Router;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.rfc2385.cfg.rev160324.Rfc2385Key;
44 import org.opendaylight.yangtools.concepts.Registration;
45 import org.opendaylight.yangtools.yang.common.QName;
46 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
47 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
48 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
49 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 public final class BmpMonitoringStationImpl implements BmpMonitoringStation, ClusterSingletonService {
55 private static final Logger LOG = LoggerFactory.getLogger(BmpMonitoringStationImpl.class);
57 private static final QName MONITOR_ID_QNAME = QName.create(Monitor.QNAME, "monitor-id").intern();
58 private static final ServiceGroupIdentifier SERVICE_GROUP_IDENTIFIER =
59 new ServiceGroupIdentifier("bmp-monitors-service-group");
61 private final DOMDataBroker domDataBroker;
62 private final InetSocketAddress address;
63 private final MonitorId monitorId;
64 private final Collection<MonitoredRouter> monitoredRouters;
65 private final BmpDispatcher dispatcher;
66 private final RouterSessionManager sessionManager;
67 private final YangInstanceIdentifier yangMonitorId;
68 private Channel channel;
69 private Registration singletonServiceRegistration;
71 public BmpMonitoringStationImpl(final DOMDataBroker domDataBroker, final BmpDispatcher dispatcher,
72 final RIBExtensionConsumerContext extensions, final BindingCodecTree codecTree,
73 final ClusterSingletonServiceProvider singletonProvider, final MonitorId monitorId,
74 final InetSocketAddress address, final Collection<MonitoredRouter> mrs) {
75 this.domDataBroker = requireNonNull(domDataBroker);
76 this.dispatcher = requireNonNull(dispatcher);
77 this.monitorId = monitorId;
78 monitoredRouters = mrs;
79 this.address = requireNonNull(address);
81 yangMonitorId = YangInstanceIdentifier.builder()
82 .node(BmpMonitor.QNAME).node(Monitor.QNAME)
83 .nodeWithKey(Monitor.QNAME, MONITOR_ID_QNAME, monitorId.getValue()).build();
85 sessionManager = new RouterSessionManager(yangMonitorId, this.domDataBroker, extensions, codecTree);
87 LOG.info("BMP Monitor Singleton Service {} registered, Monitor Id {}",
88 getIdentifier().value(), this.monitorId.getValue());
89 singletonServiceRegistration = singletonProvider.registerClusterSingletonService(this);
93 public synchronized void instantiateServiceInstance() {
94 LOG.info("BMP Monitor Singleton Service {} instantiated, Monitor Id {}",
95 getIdentifier().value(), monitorId.getValue());
97 final ChannelFuture channelFuture = dispatcher.createServer(address, sessionManager,
98 constructKeys(monitoredRouters));
100 channel = channelFuture.sync().channel();
101 createEmptyMonitor();
102 LOG.info("BMP Monitoring station {} started", monitorId.getValue());
104 connectMonitoredRouters(dispatcher);
105 LOG.info("Connecting to monitored routers completed.");
106 } catch (final InterruptedException e) {
107 LOG.error("Failed to instantiate BMP Monitor Singleton {}", monitorId.getValue(), e);
112 private static KeyMapping constructKeys(final Collection<MonitoredRouter> mrs) {
113 if (mrs == null || mrs.isEmpty()) {
114 return KeyMapping.of();
117 final Map<InetAddress, String> passwords = new HashMap<>();
118 for (MonitoredRouter mr : mrs) {
120 final Rfc2385Key password = mr.getPassword();
121 if (password != null && !password.getValue().isEmpty()) {
122 passwords.put(IetfInetUtil.inetAddressForNoZone(mr.getAddress()), password.getValue());
127 return KeyMapping.of(passwords);
131 public synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
132 LOG.info("BMP Monitor Singleton Service {} instance closed, Monitor Id {}",
133 getIdentifier().value(), monitorId.getValue());
134 if (channel != null) {
135 channel.close().addListener((ChannelFutureListener) future -> {
136 Preconditions.checkArgument(future.isSuccess(),
137 "Channel failed to close: %s", future.cause());
138 BmpMonitoringStationImpl.this.sessionManager.close();
142 final DOMDataTreeWriteTransaction wTx = domDataBroker.newWriteOnlyTransaction();
143 wTx.delete(LogicalDatastoreType.OPERATIONAL, yangMonitorId);
144 LOG.info("BMP monitoring station {} closed.", monitorId.getValue());
149 public ServiceGroupIdentifier getIdentifier() {
150 return SERVICE_GROUP_IDENTIFIER;
153 private void connectMonitoredRouters(final BmpDispatcher pdispatcher) {
154 if (monitoredRouters != null) {
155 for (final MonitoredRouter mr : monitoredRouters) {
156 if (mr.getActive()) {
157 requireNonNull(mr.getAddress());
158 requireNonNull(mr.getPort());
159 final String s = mr.getAddress().getIpv4AddressNoZone().getValue();
160 final InetAddress addr = InetAddresses.forString(s);
161 final KeyMapping ret;
162 final Rfc2385Key rfc2385KeyPassword = mr.getPassword();
163 ret = KeyMapping.of(addr, rfc2385KeyPassword.getValue());
164 pdispatcher.createClient(Ipv4Util.toInetSocketAddress(mr.getAddress(), mr.getPort()),
165 sessionManager, ret);
171 private synchronized void createEmptyMonitor() {
172 final DOMDataTreeWriteTransaction wTx = domDataBroker.newWriteOnlyTransaction();
173 wTx.put(LogicalDatastoreType.OPERATIONAL,
174 YangInstanceIdentifier.builder().node(BmpMonitor.QNAME).node(Monitor.QNAME)
175 .nodeWithKey(Monitor.QNAME, MONITOR_ID_QNAME, monitorId.getValue()).build(),
176 ImmutableNodes.newMapEntryBuilder()
177 .withNodeIdentifier(NodeIdentifierWithPredicates.of(Monitor.QNAME, MONITOR_ID_QNAME,
178 monitorId.getValue()))
179 .withChild(ImmutableNodes.leafNode(MONITOR_ID_QNAME, monitorId.getValue()))
180 .withChild(ImmutableNodes.newSystemMapBuilder()
181 .withNodeIdentifier(new NodeIdentifier(Router.QNAME))
186 } catch (final ExecutionException | InterruptedException e) {
187 LOG.error("Failed to initiate BMP Monitor {}.", monitorId.getValue(), e);
192 public synchronized void close() throws Exception {
193 if (singletonServiceRegistration != null) {
194 singletonServiceRegistration.close();
195 singletonServiceRegistration = null;