10e01044fd6ad47fdd5d7cf0e829aa4c33cdaeb7
[bgpcep.git] / bmp / bmp-impl / src / main / java / org / opendaylight / protocol / bmp / impl / app / BmpMonitoringStationImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bmp.impl.app;
9
10 import static java.util.Objects.requireNonNull;
11
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;
22 import java.util.Map;
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.common.api.ClusterSingletonService;
30 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
31 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
32 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
33 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
34 import org.opendaylight.protocol.bmp.api.BmpDispatcher;
35 import org.opendaylight.protocol.bmp.impl.spi.BmpMonitoringStation;
36 import org.opendaylight.protocol.concepts.KeyMapping;
37 import org.opendaylight.protocol.util.Ipv4Util;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.config.rev200120.odl.bmp.monitors.bmp.monitor.config.MonitoredRouter;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.BmpMonitor;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.MonitorId;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.bmp.monitor.Monitor;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.routers.Router;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.rfc2385.cfg.rev160324.Rfc2385Key;
45 import org.opendaylight.yangtools.yang.common.QName;
46 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
47 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 public final class BmpMonitoringStationImpl implements BmpMonitoringStation, ClusterSingletonService {
52
53     private static final Logger LOG = LoggerFactory.getLogger(BmpMonitoringStationImpl.class);
54
55     private static final QName MONITOR_ID_QNAME = QName.create(Monitor.QNAME, "monitor-id").intern();
56     private static final ServiceGroupIdentifier SERVICE_GROUP_IDENTIFIER =
57             ServiceGroupIdentifier.create("bmp-monitors-service-group");
58
59     private final DOMDataBroker domDataBroker;
60     private final InetSocketAddress address;
61     private final MonitorId monitorId;
62     private final Collection<MonitoredRouter> monitoredRouters;
63     private final BmpDispatcher dispatcher;
64     private final RouterSessionManager sessionManager;
65     private final YangInstanceIdentifier yangMonitorId;
66     private Channel channel;
67     private ClusterSingletonServiceRegistration singletonServiceRegistration;
68
69     public BmpMonitoringStationImpl(final DOMDataBroker domDataBroker, final BmpDispatcher dispatcher,
70             final RIBExtensionConsumerContext extensions, final BindingCodecTree codecTree,
71             final ClusterSingletonServiceProvider singletonProvider, final MonitorId monitorId,
72             final InetSocketAddress address, final Collection<MonitoredRouter> mrs) {
73         this.domDataBroker = requireNonNull(domDataBroker);
74         this.dispatcher = requireNonNull(dispatcher);
75         this.monitorId = monitorId;
76         monitoredRouters = mrs;
77         this.address = requireNonNull(address);
78
79         yangMonitorId = YangInstanceIdentifier.builder()
80                 .node(BmpMonitor.QNAME).node(Monitor.QNAME)
81                 .nodeWithKey(Monitor.QNAME, MONITOR_ID_QNAME, monitorId.getValue()).build();
82
83         sessionManager = new RouterSessionManager(yangMonitorId, this.domDataBroker, extensions, codecTree);
84
85         LOG.info("BMP Monitor Singleton Service {} registered, Monitor Id {}",
86                 getIdentifier().getName(), this.monitorId.getValue());
87         singletonServiceRegistration = singletonProvider.registerClusterSingletonService(this);
88     }
89
90     @Override
91     public synchronized void instantiateServiceInstance() {
92         LOG.info("BMP Monitor Singleton Service {} instantiated, Monitor Id {}",
93                 getIdentifier().getName(), monitorId.getValue());
94
95         final ChannelFuture channelFuture = dispatcher.createServer(address, sessionManager,
96                 constructKeys(monitoredRouters));
97         try {
98             channel = channelFuture.sync().channel();
99             createEmptyMonitor();
100             LOG.info("BMP Monitoring station {} started", monitorId.getValue());
101
102             connectMonitoredRouters(dispatcher);
103             LOG.info("Connecting to monitored routers completed.");
104         } catch (final InterruptedException e) {
105             LOG.error("Failed to instantiate BMP Monitor Singleton {}", monitorId.getValue(), e);
106         }
107
108     }
109
110     private static KeyMapping constructKeys(final Collection<MonitoredRouter> mrs) {
111         if (mrs == null || mrs.isEmpty()) {
112             return KeyMapping.of();
113         }
114
115         final Map<InetAddress, String> passwords = new HashMap<>();
116         for (MonitoredRouter mr : mrs) {
117             if (mr != null) {
118                 final Rfc2385Key password = mr.getPassword();
119                 if (password != null && !password.getValue().isEmpty()) {
120                     passwords.put(IetfInetUtil.inetAddressForNoZone(mr.getAddress()), password.getValue());
121                 }
122             }
123         }
124
125         return KeyMapping.of(passwords);
126     }
127
128     @Override
129     public synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
130         LOG.info("BMP Monitor Singleton Service {} instance closed, Monitor Id {}",
131                 getIdentifier().getName(), monitorId.getValue());
132         if (channel != null) {
133             channel.close().addListener((ChannelFutureListener) future -> {
134                 Preconditions.checkArgument(future.isSuccess(),
135                         "Channel failed to close: %s", future.cause());
136                 BmpMonitoringStationImpl.this.sessionManager.close();
137             });
138         }
139
140         final DOMDataTreeWriteTransaction wTx = domDataBroker.newWriteOnlyTransaction();
141         wTx.delete(LogicalDatastoreType.OPERATIONAL, yangMonitorId);
142         LOG.info("BMP monitoring station {} closed.", monitorId.getValue());
143         return wTx.commit();
144     }
145
146     @Override
147     public ServiceGroupIdentifier getIdentifier() {
148         return SERVICE_GROUP_IDENTIFIER;
149     }
150
151     private void connectMonitoredRouters(final BmpDispatcher pdispatcher) {
152         if (monitoredRouters != null) {
153             for (final MonitoredRouter mr : monitoredRouters) {
154                 if (mr.getActive()) {
155                     requireNonNull(mr.getAddress());
156                     requireNonNull(mr.getPort());
157                     final String s = mr.getAddress().getIpv4AddressNoZone().getValue();
158                     final InetAddress addr = InetAddresses.forString(s);
159                     final KeyMapping ret;
160                     final Rfc2385Key rfc2385KeyPassword = mr.getPassword();
161                     ret = KeyMapping.of(addr, rfc2385KeyPassword.getValue());
162                     pdispatcher.createClient(Ipv4Util.toInetSocketAddress(mr.getAddress(), mr.getPort()),
163                             sessionManager, ret);
164                 }
165             }
166         }
167     }
168
169     private synchronized void createEmptyMonitor() {
170         final DOMDataTreeWriteTransaction wTx = domDataBroker.newWriteOnlyTransaction();
171         wTx.put(LogicalDatastoreType.OPERATIONAL,
172                 YangInstanceIdentifier.builder().node(BmpMonitor.QNAME).node(Monitor.QNAME)
173                         .nodeWithKey(Monitor.QNAME, MONITOR_ID_QNAME, monitorId.getValue()).build(),
174                 ImmutableNodes.mapEntryBuilder(Monitor.QNAME, MONITOR_ID_QNAME, monitorId.getValue())
175                         .addChild(ImmutableNodes.leafNode(MONITOR_ID_QNAME, monitorId.getValue()))
176                         .addChild(ImmutableNodes.mapNodeBuilder(Router.QNAME).build())
177                         .build());
178         try {
179             wTx.commit().get();
180         } catch (final ExecutionException | InterruptedException e) {
181             LOG.error("Failed to initiate BMP Monitor {}.", monitorId.getValue(), e);
182         }
183     }
184
185     @Override
186     public synchronized void close() throws Exception {
187         if (singletonServiceRegistration != null) {
188             singletonServiceRegistration.close();
189             singletonServiceRegistration = null;
190         }
191     }
192 }