Added more ignorable files to .gitignore
[ovsdb.git] / ovsdb / src / main / java / org / opendaylight / ovsdb / plugin / InventoryService.java
1 /*
2  * Copyright (C) 2013 Red Hat, Inc.
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  * Authors : Madhu Venugopal, Brent Salisbury
9  */
10 package org.opendaylight.ovsdb.plugin;
11
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.concurrent.ConcurrentMap;
20 import java.util.concurrent.CopyOnWriteArraySet;
21 import java.util.concurrent.Executors;
22 import java.util.concurrent.ScheduledExecutorService;
23 import java.util.concurrent.TimeUnit;
24
25 import org.opendaylight.controller.sal.core.ConstructionException;
26 import org.opendaylight.controller.sal.core.Description;
27 import org.opendaylight.controller.sal.core.Node;
28 import org.opendaylight.controller.sal.core.NodeConnector;
29 import org.opendaylight.controller.sal.core.Property;
30 import org.opendaylight.controller.sal.core.UpdateType;
31 import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
32 import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
33 import org.opendaylight.controller.sal.utils.HexEncode;
34 import org.opendaylight.controller.sal.utils.ServiceHelper;
35 import org.opendaylight.ovsdb.lib.database.DatabaseSchema;
36 import org.opendaylight.ovsdb.lib.message.TableUpdate;
37 import org.opendaylight.ovsdb.lib.message.TableUpdate.Row;
38 import org.opendaylight.ovsdb.lib.message.TableUpdates;
39 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
40 import org.opendaylight.ovsdb.lib.table.Bridge;
41 import org.opendaylight.ovsdb.lib.table.internal.Table;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import com.google.common.collect.Maps;
46
47 /**
48  * Stub Implementation for IPluginInReadService used by SAL
49  *
50  *
51  */
52 public class InventoryService implements IPluginInInventoryService, InventoryServiceInternal {
53     private static final Logger logger = LoggerFactory
54             .getLogger(InventoryService.class);
55     private final Set<IPluginOutInventoryService> pluginOutInventoryServices =
56             new CopyOnWriteArraySet<IPluginOutInventoryService>();
57     private ConcurrentMap<Node, Map<String, Property>> nodeProps;
58     private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps;
59     private ConcurrentMap<Node, NodeDB> dbCache = Maps.newConcurrentMap();
60     private ScheduledExecutorService executor;
61
62     /**
63      * Function called by the dependency manager when all the required
64      * dependencies are satisfied
65      *
66      */
67     public void init() {
68         nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
69         nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
70         Node.NodeIDType.registerIDType("OVS", String.class);
71         NodeConnector.NodeConnectorIDType.registerIDType("OVS", String.class, "OVS");
72         this.executor = Executors.newSingleThreadScheduledExecutor();
73     }
74
75     /**
76      * Function called by the dependency manager when at least one dependency
77      * become unsatisfied or when the component is shutting down because for
78      * example bundle is being stopped.
79      *
80      */
81     public void destroy() {
82     }
83
84     /**
85      * Function called by dependency manager after "init ()" is called and after
86      * the services provided by the class are registered in the service registry
87      *
88      */
89     public void start() {
90     }
91
92     /**
93      * Function called by the dependency manager before the services exported by
94      * the component are unregistered, this will be followed by a "destroy ()"
95      * calls
96      *
97      */
98     public void stop() {
99         this.executor.shutdownNow();
100     }
101
102     public void setPluginOutInventoryServices(IPluginOutInventoryService service) {
103             this.pluginOutInventoryServices.add(service);
104     }
105
106     public void unsetPluginOutInventoryServices(IPluginOutInventoryService service) {
107             this.pluginOutInventoryServices.remove(service);
108     }
109
110     /**
111      * Retrieve nodes from openflow
112      */
113     @Override
114     public ConcurrentMap<Node, Map<String, Property>> getNodeProps() {
115         return nodeProps;
116     }
117
118     /**
119      * Retrieve nodeConnectors from openflow
120      */
121     @Override
122     public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps(
123             Boolean refresh) {
124         return nodeConnectorProps;
125     }
126
127
128     @Override
129     public ConcurrentMap<String, ConcurrentMap<String, Table<?>>> getCache(Node n) {
130         NodeDB db = dbCache.get(n);
131         if (db == null) return null;
132         return db.getTableCache();
133     }
134
135
136     @Override
137     public ConcurrentMap<String, Table<?>> getTableCache(Node n, String tableName) {
138         NodeDB db = dbCache.get(n);
139         if (db == null) return null;
140         return db.getTableCache(tableName);
141     }
142
143
144     @Override
145     public Table<?> getRow(Node n, String tableName, String uuid) {
146         NodeDB db = dbCache.get(n);
147         if (db == null) return null;
148         return db.getRow(tableName, uuid);
149     }
150
151     @Override
152     public void updateRow(Node n, String tableName, String uuid, Table<?> row) {
153         NodeDB db = dbCache.get(n);
154         if (db == null) {
155             db = new NodeDB();
156             dbCache.put(n, db);
157         }
158         db.updateRow(tableName, uuid, row);
159     }
160
161     @Override
162     public void removeRow(Node n, String tableName, String uuid) {
163         NodeDB db = dbCache.get(n);
164         if (db != null) db.removeRow(tableName, uuid);
165     }
166
167     @Override
168     public void processTableUpdates(Node n, TableUpdates tableUpdates) {
169         NodeDB db = dbCache.get(n);
170         if (db == null) {
171             db = new NodeDB();
172             dbCache.put(n, db);
173         }
174
175         OVSDBInventoryListener inventoryListener = (OVSDBInventoryListener)ServiceHelper.getGlobalInstance(OVSDBInventoryListener.class, this);
176         Set<Table.Name> available = tableUpdates.availableUpdates();
177         for (Table.Name name : available) {
178             TableUpdate tableUpdate = tableUpdates.getUpdate(name);
179             Collection<TableUpdate.Row<?>> rows = tableUpdate.getRows();
180             for (Row<?> row : rows) {
181                 String uuid = row.getId();
182                 Table<?> newRow = (Table<?>)row.getNew();
183                 Table<?> oldRow = (Table<?>)row.getOld();
184                 if (newRow != null) {
185                     db.updateRow(name.getName(), uuid, newRow);
186                     if (name.getName().equalsIgnoreCase("bridge")) {
187                         logger.debug("Received Bridge Table udpate for node {}", n);
188                         // OVSDB has the Bridge name info while OpenFlow Spec is not
189                         // Clear on that. From a user/manageability standpoint, it is easier
190                         // to handle Bridge names compared to dpids.
191                         // Updating the Openflow bridge name via the SAL Description update.
192
193                         // updateOFBridgeName(n, (Bridge)newRow);
194                     }
195                     if ((oldRow == null) && (inventoryListener != null)) {
196                         inventoryListener.rowAdded(n, name.getName(), uuid, newRow);
197                     } else if (inventoryListener != null) {
198                         inventoryListener.rowUpdated(n, name.getName(), uuid, oldRow, newRow);
199                     }
200                 } else if (oldRow != null) {
201                     if (inventoryListener != null) {
202                         inventoryListener.rowRemoved(n, name.getName(), uuid, oldRow);
203                     }
204                     db.removeRow(name.getName(), uuid);
205                 }
206             }
207         }
208     }
209
210     private void updateOFBridgeName(final Node node, final Bridge bridge) {
211         Runnable updateNameRunnable = new Runnable() {
212             @Override
213             public void run() {
214                 OvsDBSet<String> dpids = bridge.getDatapath_id();
215                 String bridgeName = bridge.getName();
216                 if (dpids == null || bridgeName == null) return;
217                 for (String dpid : dpids) {
218                     Long dpidLong = Long.valueOf(HexEncode.stringToLong(dpid));
219                     try {
220                         Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
221                         Description descProp = new Description(bridgeName);
222                         Set<Property> props = new HashSet<Property>();
223                         props.add(descProp);
224
225                         IPluginOutInventoryService salInventoryService = (IPluginOutInventoryService) ServiceHelper.getInstance(
226                                 IPluginOutInventoryService.class, "default", this);
227                         if (salInventoryService != null) {
228                             logger.debug("Updating Bridge Name {} on OF node {}", bridgeName, ofNode);
229                             salInventoryService.updateNode(ofNode, UpdateType.CHANGED, props);
230                         } else {
231                             logger.error("Error accessing SAL Inventory plugin");
232                         }
233                     } catch (ConstructionException e) {
234                         logger.error("Failed to construct node for " + dpid, e);
235                     }
236                 }
237             }
238         };
239         executor.execute(updateNameRunnable);
240         // Add a delay & re-execute to compensate for the current OpenFlow plugin bug of
241         // overriding the Description with a Null value after the first statistics timer.
242         // Hopefully this will be resolved in the newer version of the Openflow plugin.
243         executor.schedule(updateNameRunnable, 30, TimeUnit.SECONDS);
244     }
245
246     @Override
247     public void printCache(Node n) {
248         NodeDB db = dbCache.get(n);
249         if (db != null) db.printTableCache();
250     }
251
252     @Override
253     public void addNode(Node node, Set<Property> props) {
254         addNodeProperty(node, UpdateType.ADDED, props);
255     }
256
257     @Override
258     public void notifyNodeAdded(Node node) {
259         OVSDBInventoryListener inventoryListener = (OVSDBInventoryListener)ServiceHelper.getGlobalInstance(OVSDBInventoryListener.class, this);
260         if (inventoryListener != null) {
261             inventoryListener.nodeAdded(node);
262         }
263     }
264
265     @Override
266     public void addNodeProperty(Node node, UpdateType type, Set<Property> props) {
267         Map<String, Property> nProp = nodeProps.get(node);
268         if (nProp == null) nProp = new HashMap<String, Property>();
269         for (Property prop : props) {
270             nProp.put(prop.getName(), prop);
271         }
272         nodeProps.put(node, nProp);
273         for (IPluginOutInventoryService service : pluginOutInventoryServices) {
274             service.updateNode(node, type, props);
275         }
276     }
277
278     @Override
279     public DatabaseSchema getDatabaseSchema(Node n) {
280         NodeDB db = dbCache.get(n);
281         if (db != null) return db.getSchema();
282         return null;
283     }
284
285     @Override
286     public void updateDatabaseSchema(Node n, DatabaseSchema schema) {
287         NodeDB db = dbCache.get(n);
288         if (db == null) {
289             db = new NodeDB();
290             dbCache.put(n, db);
291         }
292         db.setSchema(schema);
293     }
294
295     @Override
296     public void removeNode(Node node) {
297         OVSDBInventoryListener inventoryListener = (OVSDBInventoryListener)ServiceHelper.getGlobalInstance(OVSDBInventoryListener.class, this);
298         if (inventoryListener != null) {
299             inventoryListener.nodeRemoved(node);
300         }
301
302         for (IPluginOutInventoryService service : pluginOutInventoryServices) {
303             service.updateNode(node, UpdateType.REMOVED, null);
304         }
305         nodeProps.remove(node);
306         dbCache.remove(node);
307     }
308
309     @Override
310     public Set<Node> getConfiguredNotConnectedNodes() {
311         return Collections.emptySet();
312     }
313 }