2 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.vpnservice.interfacemgr;
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL3tunnel;
13 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
14 import java.math.BigInteger;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state._interface.StatisticsBuilder;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state._interface.Statistics;
20 import com.google.common.util.concurrent.Futures;
21 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
23 import com.google.common.util.concurrent.FutureCallback;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
32 import org.opendaylight.vpnservice.AbstractDataChangeListener;
33 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
34 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
35 import org.opendaylight.yangtools.concepts.ListenerRegistration;
36 import org.opendaylight.yangtools.yang.binding.DataObject;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
39 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
40 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
41 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47 import com.google.common.base.Optional;
49 public class InterfaceManager extends AbstractDataChangeListener<Interface> implements AutoCloseable{
50 private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class);
51 private ListenerRegistration<DataChangeListener> listenerRegistration;
52 private final DataBroker broker;
54 private static final FutureCallback<Void> DEFAULT_CALLBACK =
55 new FutureCallback<Void>() {
56 public void onSuccess(Void result) {
57 LOG.debug("Success in Datastore write operation");
60 public void onFailure(Throwable error) {
61 LOG.error("Error in Datastore write operation", error);
65 public InterfaceManager(final DataBroker db) {
66 super(Interface.class);
72 public void close() throws Exception {
73 if (listenerRegistration != null) {
75 listenerRegistration.close();
76 } catch (final Exception e) {
77 LOG.error("Error when cleaning up DataChangeListener.", e);
79 listenerRegistration = null;
81 LOG.info("Interface Manager Closed");
84 private void registerListener(final DataBroker db) {
86 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
87 getWildCardPath(), InterfaceManager.this, DataChangeScope.SUBTREE);
88 } catch (final Exception e) {
89 LOG.error("InterfaceManager DataChange listener registration fail!", e);
90 throw new IllegalStateException("InterfaceManager registration Listener failed.", e);
95 protected void add(final InstanceIdentifier<Interface> identifier,
96 final Interface imgrInterface) {
97 LOG.trace("key: " + identifier + ", value=" + imgrInterface );
98 addInterface(identifier, imgrInterface);
101 private InstanceIdentifier<Interface> buildId(final InstanceIdentifier<Interface> identifier) {
102 //TODO Make this generic and move to AbstractDataChangeListener or Utils.
103 final InterfaceKey key = identifier.firstKeyOf(Interface.class, InterfaceKey.class);
104 String interfaceName = key.getName();
105 InstanceIdentifierBuilder<Interface> idBuilder =
106 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
107 InstanceIdentifier<Interface> id = idBuilder.build();
111 private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
112 //TODO Make this generic and move to AbstractDataChangeListener or Utils.
113 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
114 InstanceIdentifier.builder(InterfacesState.class)
115 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
116 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
117 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
121 private void addInterface(final InstanceIdentifier<Interface> identifier,
122 final Interface imgrInterface) {
123 InstanceIdentifier<Interface> id = buildId(identifier);
124 Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
125 if(port.isPresent()) {
126 Interface interf = port.get();
127 NodeConnector nodeConn = getNodeConnectorFromInterface(interf);
128 updateInterfaceState(identifier, interf, nodeConn);
130 * 1. Get interface-id from id manager
131 * 2. Update interface-state with following:
132 * admin-status = set to enable value
133 * oper-status = Down [?]
134 * if-index = interface-id
136 * 1. Get operational data from node-connector-id?
142 private void updateInterfaceState(InstanceIdentifier<Interface> identifier,
143 Interface interf, NodeConnector nodeConn) {
144 /* Update InterfaceState
145 * 1. Get interfaces-state Identifier
146 * 2. Add interface to interfaces-state/interface
147 * 3. Get interface-id from id manager
148 * 4. Update interface-state with following:
149 * admin-status = set to enable value
150 * oper-status = Down [?]
151 * if-index = interface-id
153 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id =
154 buildStateInterfaceId(interf.getName());
155 Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> stateIf =
156 read(LogicalDatastoreType.OPERATIONAL, id);
157 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateIface;
158 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder =
159 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
160 if(!stateIf.isPresent()) {
161 // TODO: Get interface-id from IdManager
162 ifaceBuilder.setAdminStatus((interf.isEnabled()) ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up :
163 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Down);
164 ifaceBuilder.setOperStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down);
165 ifaceBuilder.setIfIndex(200).setName(interf.getName()).setType(interf.getType());
166 ifaceBuilder.setKey(getStateInterfaceKeyFromName(interf.getName()));
167 //ifaceBuilder.setStatistics(createStatistics(interf.getName(), nodeConn));
168 stateIface = ifaceBuilder.build();
169 LOG.trace("Adding stateIface {} and id {} to OPERATIONAL DS", stateIface, id);
170 asyncWrite(LogicalDatastoreType.OPERATIONAL, id, stateIface, DEFAULT_CALLBACK);
172 if(interf.isEnabled() != null) {
173 ifaceBuilder.setAdminStatus((interf.isEnabled()) ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up :
174 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Down);
176 if(interf.getType() != null) {
177 ifaceBuilder.setType(interf.getType());
180 stateIface = ifaceBuilder.build();
181 LOG.trace("updating OPERATIONAL data store with stateIface {} and id {}", stateIface, id);
182 asyncUpdate(LogicalDatastoreType.OPERATIONAL, id, stateIface, DEFAULT_CALLBACK);
187 private void setAugmentations(
188 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder,
189 InstanceIdentifier<Interface> identifier, Interface interf) {
190 // TODO Add code for all augmentations
191 InstanceIdentifier<IfL3tunnel> ifL3TunnelPath = identifier.augmentation(IfL3tunnel.class);
192 Optional<IfL3tunnel> l3Tunnel = read(LogicalDatastoreType.CONFIGURATION, ifL3TunnelPath);
193 String ifName = interf.getName();
194 if(l3Tunnel.isPresent()) {
200 private Statistics createStatistics(String name, NodeConnector nodeConn) {
201 Counter64 init64 = new Counter64(new BigInteger("0000000000000000"));
202 Counter32 init32 = new Counter32((long) 0);
203 StatisticsBuilder statBuilder = new StatisticsBuilder();
204 statBuilder.setDiscontinuityTime(new DateAndTime("2015-04-04T00:00:00Z"))
205 .setInBroadcastPkts(init64).setInDiscards(init32).setInErrors(init32).setInMulticastPkts(init64)
206 .setInOctets(init64).setInUnicastPkts(init64).setInUnknownProtos(init32).setOutBroadcastPkts(init64)
207 .setOutDiscards(init32).setOutErrors(init32).setOutMulticastPkts(init64).setOutOctets(init64)
208 .setOutUnicastPkts(init64);
209 return statBuilder.build();
212 private org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey getStateInterfaceKeyFromName(
214 return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(name);
217 private NodeConnector getNodeConnectorFromInterface(Interface interf) {
218 NodeConnectorId ncId = interf.getAugmentation(BaseIds.class).getOfPortId();
219 //TODO: Replace with MDSAL Util method
220 NodeId nodeId = new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":")));
221 InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
222 .child(Node.class, new NodeKey(nodeId))
223 .child(NodeConnector.class, new NodeConnectorKey(ncId)).build();
225 Optional<NodeConnector> nc = read(LogicalDatastoreType.OPERATIONAL, ncIdentifier);
227 NodeConnector nodeConn = nc.get();
228 LOG.trace("nodeConnector: {}",nodeConn);
234 private void delInterface(final InstanceIdentifier<Interface> identifier,
235 final Interface delInterface) {
236 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id =
237 buildStateInterfaceId(delInterface.getName());
238 Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> stateIf =
239 read(LogicalDatastoreType.OPERATIONAL, id);
240 if(!stateIf.isPresent()) {
241 LOG.trace("deleting interfaces:state OPERATIONAL data store with id {}", id);
242 asyncRemove(LogicalDatastoreType.OPERATIONAL, id, DEFAULT_CALLBACK);
246 private void updateInterface(final InstanceIdentifier<Interface> identifier,
247 final Interface original, final Interface udpate) {
248 InstanceIdentifier<Interface> id = buildId(identifier);
249 Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
250 if(port.isPresent()) {
251 Interface interf = port.get();
252 //TODO: Update operational data
256 private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
257 InstanceIdentifier<T> path) {
259 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
261 Optional<T> result = Optional.absent();
263 result = tx.read(datastoreType, path).get();
264 } catch (Exception e) {
265 throw new RuntimeException(e);
271 private InstanceIdentifier<Interface> getWildCardPath() {
272 return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
276 protected void remove(InstanceIdentifier<Interface> identifier, Interface del) {
277 LOG.trace("key: " + identifier + ", value=" + del );
278 delInterface(identifier, del);
282 protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
283 LOG.trace("key: " + identifier + ", original=" + original + ", update=" + update );
284 updateInterface(identifier, original, update);
287 private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
288 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
289 WriteTransaction tx = broker.newWriteOnlyTransaction();
290 tx.put(datastoreType, path, data, true);
291 Futures.addCallback(tx.submit(), callback);
294 private <T extends DataObject> void asyncUpdate(LogicalDatastoreType datastoreType,
295 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
296 WriteTransaction tx = broker.newWriteOnlyTransaction();
297 tx.merge(datastoreType, path, data, true);
298 Futures.addCallback(tx.submit(), callback);
301 private <T extends DataObject> void asyncRemove(LogicalDatastoreType datastoreType,
302 InstanceIdentifier<T> path, FutureCallback<Void> callback) {
303 WriteTransaction tx = broker.newWriteOnlyTransaction();
304 tx.delete(datastoreType, path);
305 Futures.addCallback(tx.submit(), callback);
308 public void processPortAdd(NodeConnector port) {
309 String strPortId = port.getId().getValue();
310 FlowCapableNodeConnector ofPort = port.getAugmentation(FlowCapableNodeConnector.class);
311 LOG.debug("PortAdd: PortId { "+strPortId+"} PortName {"+ofPort.getName()+"}");
314 public void processPortUpdate(NodeConnector oldPort, NodeConnector update) {
315 String oldPortId = oldPort.getId().getValue();
316 FlowCapableNodeConnector oldOfPort = oldPort.getAugmentation(FlowCapableNodeConnector.class);
317 String strPortId = update.getId().getValue();
318 FlowCapableNodeConnector ofPort = update.getAugmentation(FlowCapableNodeConnector.class);
319 LOG.debug("PortUpdate: { "+strPortId+", "+ofPort.getName()+"}");
322 public void processPortDelete(NodeConnector port) {
323 String strPortId = port.getId().getValue();
324 FlowCapableNodeConnector ofPort = port.getAugmentation(FlowCapableNodeConnector.class);
325 LOG.debug("PortDelete: PortId { "+strPortId+"} PortName {"+ofPort.getName()+"}");