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