Add support for openflow node callbacks
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / impl / OvsdbDataChangeListener.java
1 /*
2  * Copyright (c) 2015 Red Hat, 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.ovsdb.openstack.netvirt.impl;
9
10 import java.util.Map;
11 import java.util.Set;
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
14 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
15 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbInventoryListener;
19 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
20 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
21 import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactUtils;
22 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
30 import org.opendaylight.yangtools.concepts.ListenerRegistration;
31 import org.opendaylight.yangtools.yang.binding.DataObject;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * MDSAL dataChangeListener for the OVSDB Southbound
39  *
40  * @author Sam Hague (shague@redhat.com)
41  */
42 public class OvsdbDataChangeListener implements DataChangeListener, AutoCloseable {
43     private static final Logger LOG = LoggerFactory.getLogger(OvsdbDataChangeListener.class);
44     private DataBroker dataBroker = null;
45     private ListenerRegistration<DataChangeListener> registration;
46     private NodeCacheManager nodeCacheManager = null;
47
48     public OvsdbDataChangeListener (DataBroker dataBroker) {
49         LOG.info(">>>>> Registering OvsdbNodeDataChangeListener: dataBroker= {}", dataBroker);
50         this.dataBroker = dataBroker;
51         InstanceIdentifier<Node> path = InstanceIdentifier
52                 .create(NetworkTopology.class)
53                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
54                 .child(Node.class);
55         registration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, path, this,
56                 DataChangeScope.SUBTREE);
57         LOG.info("netvirt OvsdbDataChangeListener: registration= {}", registration);
58     }
59
60     @Override
61     public void close () throws Exception {
62         registration.close();
63     }
64
65     /* TODO
66      * Recognize when netvirt added a bridge to config and then the operational update comes in
67      * can it be ignored or just viewed as a new switch? ports and interfaces can likely be mapped
68      * to the old path where there were updates for them for update and insert row.
69      */
70     @Override
71     public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
72         LOG.info(">>>>> onDataChanged: {}", changes);
73
74         updateConnections(changes);
75         updateOpenflowConnections(changes);
76     }
77
78     private void updateConnections(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
79         for (Map.Entry<InstanceIdentifier<?>, DataObject> created : changes.getCreatedData().entrySet()) {
80             LOG.info("updateConnections created: {}", created);
81             if (created.getValue() instanceof OvsdbNodeAugmentation) {
82                 Node ovsdbNode = getNode(changes, created);
83                 LOG.info("ovsdbNode: {}", ovsdbNode);
84                 notifyNodeAdded(ovsdbNode);
85             }
86         }
87     }
88
89     private void updateOpenflowConnections(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
90         for (Map.Entry<InstanceIdentifier<?>, DataObject> created : changes.getCreatedData().entrySet()) {
91             LOG.info("updateOpenflowConnections created: {}", created);
92             if (created.getValue() instanceof OvsdbBridgeAugmentation) {
93                 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = (OvsdbBridgeAugmentation)created.getValue();
94                 // This value is not being set right now - OvsdbBridgeupdateCommand
95                 //if (ovsdbBridgeAugmentation.getBridgeOpenflowNodeRef() != null) {
96                     nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
97                     nodeCacheManager.nodeAdded(getNode(changes, created));
98                 //}
99             }
100         }
101         for (Map.Entry<InstanceIdentifier<?>, DataObject> created : changes.getUpdatedData().entrySet()) {
102             LOG.info("updateOpenflowConnections updated: {}", created);
103             if (created.getValue() instanceof OvsdbBridgeAugmentation) {
104                 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = (OvsdbBridgeAugmentation)created.getValue();
105                 // This value is not being set right now - OvsdbBridgeupdateCommand
106                 // if (ovsdbBridgeAugmentation.getBridgeOpenflowNodeRef() != null) {
107                     nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
108                     nodeCacheManager.nodeAdded(getNode(changes, created));
109                 //}
110             }
111         }
112     }
113
114     private Node getNode(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
115                          Map.Entry<InstanceIdentifier<?>, DataObject> created) {
116         InstanceIdentifier<Node> nodeInstanceIdentifier = created.getKey().firstIdentifierOf(Node.class);
117         return (Node)changes.getCreatedData().get(nodeInstanceIdentifier);
118     }
119
120     private void notifyNodeAdded(Node node) {
121         Set<OvsdbInventoryListener> mdsalConsumerListeners = OvsdbInventoryServiceImpl.getMdsalConsumerListeners();
122         for (OvsdbInventoryListener mdsalConsumerListener : mdsalConsumerListeners) {
123             mdsalConsumerListener.ovsdbNodeAdded(node);
124         }
125     }
126 }