Initial code to handle changes to DS
[vpnservice.git] / interfacemgr / interfacemgr-impl / src / main / java / org / opendaylight / vpnservice / interfacemgr / InterfaceManager.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.vpnservice.interfacemgr;
9
10 import com.google.common.util.concurrent.FutureCallback;
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
19 import org.opendaylight.vpnservice.AbstractDataChangeListener;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
22 import org.opendaylight.yangtools.concepts.ListenerRegistration;
23 import org.opendaylight.yangtools.yang.binding.DataObject;
24 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
26 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34 import com.google.common.base.Optional;
35
36 public class InterfaceManager extends AbstractDataChangeListener<Interface> implements AutoCloseable{
37     private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class);
38     private ListenerRegistration<DataChangeListener> listenerRegistration;
39     private final DataBroker broker;
40
41     private static final FutureCallback<Void> DEFAULT_CALLBACK =
42                     new FutureCallback<Void>() {
43                         public void onSuccess(Void result) {
44                             LOG.debug("Success in Datastore write operation");
45                         }
46
47                         public void onFailure(Throwable error) {
48                             LOG.error("Error in Datastore write operation", error);
49                         };
50                     };
51
52     public InterfaceManager(final DataBroker db) {
53         super(Interface.class);
54         broker = db;
55         registerListener(db);
56     }
57
58     @Override
59     public void close() throws Exception {
60         if (listenerRegistration != null) {
61             try {
62                 listenerRegistration.close();
63             } catch (final Exception e) {
64                 LOG.error("Error when cleaning up DataChangeListener.", e);
65             }
66             listenerRegistration = null;
67         }
68         LOG.info("Interface Manager Closed");
69     }
70     
71     private void registerListener(final DataBroker db) {
72         try {
73             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
74                     getWildCardPath(), InterfaceManager.this, DataChangeScope.SUBTREE);
75         } catch (final Exception e) {
76             LOG.error("InterfaceManager DataChange listener registration fail!", e);
77             throw new IllegalStateException("InterfaceManager registration Listener failed.", e);
78         }
79     }
80
81     @Override
82     protected void add(final InstanceIdentifier<Interface> identifier,
83             final Interface imgrInterface) {
84         LOG.trace("key: " + identifier + ", value=" + imgrInterface );
85         addInterface(identifier, imgrInterface);
86     }
87
88     private InstanceIdentifier<Interface> buildId(final InstanceIdentifier<Interface> identifier) {
89         //TODO Make this generic and move to AbstractDataChangeListener or Utils.
90         final InterfaceKey key = identifier.firstKeyOf(Interface.class, InterfaceKey.class);
91         String interfaceName = key.getName();
92         InstanceIdentifierBuilder<Interface> idBuilder = 
93                 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
94         InstanceIdentifier<Interface> id = idBuilder.build();
95         return id;
96     }
97
98     private void addInterface(final InstanceIdentifier<Interface> identifier,
99                               final Interface imgrInterface) {
100         InstanceIdentifier<Interface> id = buildId(identifier);
101         Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
102         if(port.isPresent()) {
103             Interface interf = port.get();
104             NodeConnector nodeConn = getNodeConnectorFromInterface(interf);
105             updateInterfaceState(identifier, imgrInterface, interf);
106             /* TODO:
107              *  1. Get interface-id from id manager
108              *  2. Update interface-state with following:
109              *    admin-status = set to enable value
110              *    oper-status = Down [?]
111              *    if-index = interface-id
112              *    
113              * FIXME:
114              *  1. Get operational data from node-connector-id?
115              *
116              */
117         }
118     }
119
120     private void updateInterfaceState(InstanceIdentifier<Interface> identifier, Interface imgrInterface,
121                     Interface interf) {
122         // TODO Update InterfaceState
123         
124     }
125
126     private NodeConnector getNodeConnectorFromInterface(Interface interf) {
127         NodeConnectorId ncId = interf.getAugmentation(BaseIds.class).getOfPortId();
128         NodeId nodeId = new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":")));
129         InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
130                         .child(Node.class, new NodeKey(nodeId))
131                         .child(NodeConnector.class, new NodeConnectorKey(ncId)).build();
132
133         Optional<NodeConnector> nc = read(LogicalDatastoreType.OPERATIONAL, ncIdentifier);
134         if(nc.isPresent()) {
135             NodeConnector nodeConn = nc.get();
136             LOG.trace("nodeConnector: {}",nodeConn);
137             return nodeConn;
138         }
139         return null;
140     }
141
142     private void delInterface(final InstanceIdentifier<Interface> identifier,
143                               final Interface del) {
144         InstanceIdentifier<Interface> id = buildId(identifier);
145         Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
146         if(port.isPresent()) {
147             Interface interf = port.get();
148             // TODO: Update operational data
149         }
150     }
151
152     private void updateInterface(final InstanceIdentifier<Interface> identifier,
153                               final Interface original, final Interface udpate) {
154         InstanceIdentifier<Interface> id = buildId(identifier);
155         Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
156         if(port.isPresent()) {
157             Interface interf = port.get();
158             //TODO: Update operational data
159         }
160     }
161
162     private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
163             InstanceIdentifier<T> path) {
164
165         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
166
167         Optional<T> result = Optional.absent();
168         try {
169             result = tx.read(datastoreType, path).get();
170         } catch (Exception e) {
171             throw new RuntimeException(e);
172         }
173
174         return result;
175     }
176
177     private InstanceIdentifier<Interface> getWildCardPath() {
178         return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
179     }
180
181     @Override
182     protected void remove(InstanceIdentifier<Interface> identifier, Interface del) {
183         LOG.trace("key: " + identifier + ", value=" + del );
184         delInterface(identifier, del);
185     }
186
187     @Override
188     protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
189         LOG.trace("key: " + identifier + ", original=" + original + ", update=" + update );
190         updateInterface(identifier, original, update);
191         
192     }
193
194 }