Unwanted commit to non candidate device fix
[netconf.git] / netconf / messagebus-netconf / src / main / java / org / opendaylight / netconf / messagebus / eventsources / netconf / NetconfEventSourceRegistration.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.netconf.messagebus.eventsources.netconf;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
12
13 import java.util.List;
14 import java.util.Optional;
15 import org.opendaylight.controller.messagebus.spi.EventSourceRegistration;
16 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
17 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
22 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * Helper class to keep connection status of netconf node  and event source registration object.
34  */
35 final class NetconfEventSourceRegistration implements AutoCloseable {
36
37     private static final Logger LOG = LoggerFactory.getLogger(NetconfEventSourceRegistration.class);
38     private static final YangInstanceIdentifier NETCONF_DEVICE_DOM_PATH = YangInstanceIdentifier.builder()
39             .node(NetworkTopology.QNAME).node(Topology.QNAME)
40             .nodeWithKey(Topology.QNAME, QName.create(Topology.QNAME, "topology-id"), TopologyNetconf.QNAME
41                     .getLocalName())
42             .node(Node.QNAME).build();
43     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "node-id");
44     private static final String NOTIFICATION_CAPABILITY_PREFIX = "(urn:ietf:params:xml:ns:netconf:notification";
45
46     private final Node node;
47     private final NetconfEventSourceManager netconfEventSourceManager;
48     private final BindingNormalizedNodeSerializer serializer;
49
50     private ConnectionStatus currentNetconfConnStatus;
51     private EventSourceRegistration<NetconfEventSource> eventSourceRegistration;
52
53     private NetconfEventSourceRegistration(final BindingNormalizedNodeSerializer serializer, final Node node,
54             final NetconfEventSourceManager netconfEventSourceManager) {
55         this.serializer = requireNonNull(serializer);
56         this.node = node;
57         this.netconfEventSourceManager = netconfEventSourceManager;
58         this.eventSourceRegistration = null;
59         this.currentNetconfConnStatus = ConnectionStatus.Connecting;
60     }
61
62     static NetconfEventSourceRegistration create(final BindingNormalizedNodeSerializer serializer,
63             final InstanceIdentifier<?> instanceIdent, final Node node,
64             final NetconfEventSourceManager netconfEventSourceManager) {
65         requireNonNull(instanceIdent);
66         requireNonNull(netconfEventSourceManager);
67         if (!isEventSource(node)) {
68             return null;
69         }
70         NetconfEventSourceRegistration nesr = new NetconfEventSourceRegistration(serializer, node,
71             netconfEventSourceManager);
72         nesr.updateStatus();
73         LOG.debug("NetconfEventSourceRegistration for node {} has been initialized...", node.getNodeId().getValue());
74         return nesr;
75     }
76
77     private static boolean isEventSource(final Node node) {
78         final NetconfNode netconfNode = node.augmentation(NetconfNode.class);
79         if (netconfNode == null) {
80             return false;
81         }
82         if (netconfNode.getAvailableCapabilities() == null) {
83             return false;
84         }
85         final List<AvailableCapability> capabilities = netconfNode.getAvailableCapabilities().getAvailableCapability();
86         if (capabilities == null || capabilities.isEmpty()) {
87             return false;
88         }
89         for (final AvailableCapability capability : netconfNode.getAvailableCapabilities().getAvailableCapability()) {
90             if (capability.getCapability().startsWith(NOTIFICATION_CAPABILITY_PREFIX)) {
91                 return true;
92             }
93         }
94
95         return false;
96     }
97
98     Optional<EventSourceRegistration<NetconfEventSource>> getEventSourceRegistration() {
99         return Optional.ofNullable(eventSourceRegistration);
100     }
101
102     NetconfNode getNetconfNode() {
103         return node.augmentation(NetconfNode.class);
104     }
105
106     void updateStatus() {
107         ConnectionStatus netconfConnStatus = getNetconfNode().getConnectionStatus();
108         LOG.info("Change status on node {}, new status is {}", this.node.getNodeId().getValue(), netconfConnStatus);
109         if (netconfConnStatus.equals(currentNetconfConnStatus)) {
110             return;
111         }
112         changeStatus(netconfConnStatus);
113     }
114
115     private static boolean checkConnectionStatusType(final ConnectionStatus status) {
116         return status == ConnectionStatus.Connected || status == ConnectionStatus.Connecting
117                 || status == ConnectionStatus.UnableToConnect;
118     }
119
120     private void changeStatus(final ConnectionStatus newStatus) {
121         requireNonNull(newStatus);
122         checkState(this.currentNetconfConnStatus != null);
123         if (!checkConnectionStatusType(newStatus)) {
124             throw new IllegalStateException("Unknown new Netconf Connection Status");
125         }
126         switch (this.currentNetconfConnStatus) {
127             case Connecting:
128             case UnableToConnect:
129                 if (newStatus == ConnectionStatus.Connected) {
130                     if (this.eventSourceRegistration == null) {
131                         registrationEventSource();
132                     } else {
133                         // reactivate stream on registered event source (invoke publish notification about connection)
134                         this.eventSourceRegistration.getInstance().reActivateStreams();
135                     }
136                 }
137                 break;
138             case Connected:
139                 if (newStatus == ConnectionStatus.Connecting || newStatus == ConnectionStatus.UnableToConnect) {
140                     // deactivate streams on registered event source (invoke publish notification about connection)
141                     this.eventSourceRegistration.getInstance().deActivateStreams();
142                 }
143                 break;
144             default:
145                 throw new IllegalStateException("Unknown current Netconf Connection Status");
146         }
147         this.currentNetconfConnStatus = newStatus;
148     }
149
150     private void registrationEventSource() {
151         final Optional<DOMMountPoint> domMountPoint = netconfEventSourceManager.getDomMounts()
152                 .getMountPoint(domMountPath(node.getNodeId()));
153         EventSourceRegistration<NetconfEventSource> registration = null;
154         if (domMountPoint.isPresent()/* && mountPoint.isPresent()*/) {
155             NetconfEventSourceMount mount = new NetconfEventSourceMount(serializer, node, domMountPoint.get());
156             final NetconfEventSource netconfEventSource = new NetconfEventSource(
157                     netconfEventSourceManager.getStreamMap(),
158                     mount,
159                     netconfEventSourceManager.getPublishService());
160             registration = netconfEventSourceManager.getEventSourceRegistry().registerEventSource(netconfEventSource);
161             LOG.info("Event source {} has been registered", node.getNodeId().getValue());
162         }
163         this.eventSourceRegistration = registration;
164     }
165
166     private static YangInstanceIdentifier domMountPath(final NodeId nodeId) {
167         return YangInstanceIdentifier.builder(NETCONF_DEVICE_DOM_PATH)
168                 .nodeWithKey(Node.QNAME, NODE_ID_QNAME, nodeId.getValue()).build();
169     }
170
171     private void closeEventSourceRegistration() {
172         if (getEventSourceRegistration().isPresent()) {
173             getEventSourceRegistration().get().close();
174         }
175     }
176
177     @Override
178     public void close() {
179         closeEventSourceRegistration();
180     }
181
182 }