Implemented SouthboundHandler#processInterfaceDelete()
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / SouthboundHandler.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 package org.opendaylight.ovsdb.openstack.netvirt;
9
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import java.util.concurrent.ConcurrentMap;
14
15 import org.opendaylight.neutron.spi.NeutronNetwork;
16 import org.opendaylight.ovsdb.lib.notation.Row;
17 import org.opendaylight.ovsdb.lib.notation.UUID;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.*;
19 import org.opendaylight.ovsdb.openstack.netvirt.impl.MdsalUtils;
20 import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter;
21 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
22 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
23 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
24 import org.opendaylight.ovsdb.schema.openvswitch.Port;
25 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
26 //import org.opendaylight.ovsdb.utils.mdsal.node.StringConvertor;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * @author Madhu Venugopal
37  * @author Brent Salisbury
38  * @author Dave Tucker
39  * @author Sam Hague (shague@redhat.com)
40  */
41 public class SouthboundHandler extends AbstractHandler
42         implements NodeCacheListener, OvsdbInventoryListener {
43     static final Logger logger = LoggerFactory.getLogger(SouthboundHandler.class);
44
45     // The implementation for each of these services is resolved by the OSGi Service Manager
46     private volatile ConfigurationService configurationService;
47     private volatile BridgeConfigurationManager bridgeConfigurationManager;
48     private volatile TenantNetworkManager tenantNetworkManager;
49     private volatile NetworkingProviderManager networkingProviderManager;
50     private volatile OvsdbConfigurationService ovsdbConfigurationService;
51     private volatile OvsdbConnectionService connectionService;
52     private volatile OvsdbInventoryService mdsalConsumer; // TODO SB_MIGRATION
53     private volatile NeutronL3Adapter neutronL3Adapter;
54
55     void start() {
56         //this.triggerUpdates(); // TODO SB_MIGRATION
57     }
58
59     @Override
60     public void ovsdbNodeAdded(Node node) {
61         logger.info("ovsdbNodeAdded: {}", node);
62         this.enqueueEvent(new SouthboundEvent(node, Action.ADD));
63     }
64
65     @Override
66     public void ovsdbNodeRemoved(Node node) {
67         this.enqueueEvent(new SouthboundEvent(node, Action.DELETE));
68     }
69
70     @Override
71     public void rowAdded(Node node, String tableName, String uuid, Row row) {
72         this.enqueueEvent(new SouthboundEvent(node, tableName, uuid, row, Action.ADD));
73     }
74
75     @Override
76     public void rowUpdated(Node node, String tableName, String uuid, Row oldRow, Row newRow) {
77         if (this.isUpdateOfInterest(node, oldRow, newRow)) {
78             this.enqueueEvent(new SouthboundEvent(node, tableName, uuid, newRow, Action.UPDATE));
79         }
80     }
81
82     /*
83      * Ignore unnecessary updates to be even considered for processing.
84      * (Especially stats update are fast and furious).
85      */
86
87     private boolean isUpdateOfInterest(Node node, Row oldRow, Row newRow) {
88         /* TODO SB_MIGRATION */
89         if (oldRow == null) return true;
90         if (newRow.getTableSchema().getName().equals(ovsdbConfigurationService.getTableName(node, Interface.class))) {
91             // We are NOT interested in Stats only updates
92             Interface oldIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, oldRow);
93             if (oldIntf.getName() == null && oldIntf.getExternalIdsColumn() == null && oldIntf.getMacColumn() == null &&
94                 oldIntf.getOpenFlowPortColumn() == null && oldIntf.getOptionsColumn() == null && oldIntf.getOtherConfigColumn() == null &&
95                 oldIntf.getTypeColumn() == null) {
96                 logger.trace("IGNORING Interface Update: node {}, row: {}", node, newRow);
97                 return false;
98             }
99         } else if (newRow.getTableSchema().getName().equals(ovsdbConfigurationService.getTableName(node, Port.class))) {
100             // We are NOT interested in Stats only updates
101             Port oldPort = ovsdbConfigurationService.getTypedRow(node, Port.class, oldRow);
102             if (oldPort.getName() == null && oldPort.getExternalIdsColumn() == null && oldPort.getMacColumn() == null &&
103                 oldPort.getInterfacesColumn() == null && oldPort.getTagColumn() == null && oldPort.getTrunksColumn() == null) {
104                 logger.trace("IGNORING Port Update: node {}, row: {}", node, newRow);
105                 return false;
106             }
107         } else if (newRow.getTableSchema().getName().equals(ovsdbConfigurationService.getTableName(node, OpenVSwitch.class))) {
108             OpenVSwitch oldOpenvSwitch = ovsdbConfigurationService.getTypedRow(node, OpenVSwitch.class, oldRow);
109             if (oldOpenvSwitch.getOtherConfigColumn()== null) {
110                 // we are only interested in other_config field change
111                 return false;
112             }
113         }
114         return true;
115     }
116
117     @Override
118     public void rowRemoved(Node node, String tableName, String uuid, Row row, Object context) {
119         this.enqueueEvent(new SouthboundEvent(node, tableName, uuid, row, context, Action.DELETE));
120     }
121
122     private SouthboundEvent.Type ovsdbTypeToSouthboundEventType(OvsdbType ovsdbType) {
123         SouthboundEvent.Type type = SouthboundEvent.Type.NODE;
124
125         switch (ovsdbType) {
126             case NODE:
127                 type = SouthboundEvent.Type.NODE;
128                 break;
129             case BRIDGE:
130                 type = SouthboundEvent.Type.BRIDGE;
131                 break;
132             case PORT:
133                 type = SouthboundEvent.Type.PORT;
134                 break;
135             case CONTROLLER:
136                 type = SouthboundEvent.Type.CONTROLLER;
137                 break;
138             case OPENVSWITCH:
139                 type = SouthboundEvent.Type.OPENVSWITCH;
140                 break;
141             default:
142                 logger.warn("Invalid OvsdbType: {}", ovsdbType);
143                 break;
144         }
145         return type;
146     }
147
148     @Override
149     public void ovsdbUpdate(Node node, OvsdbType ovsdbType, Action action) {
150         logger.info("ovsdbUpdate: {} - {} - {}", node, ovsdbType, action);
151         this.enqueueEvent(new SouthboundEvent(node, ovsdbTypeToSouthboundEventType(ovsdbType), action));
152     }
153
154     public void processOvsdbNodeUpdate(Node node, Action action) {
155         if (action == Action.ADD) {
156             logger.info("processOvsdbNodeUpdate {}", node);
157             bridgeConfigurationManager.prepareNode(node);
158         } else {
159             logger.info("Not implemented yet: {}", action);
160         }
161     }
162
163     private void processRowUpdate(Node node, String tableName, String uuid, Row row,
164                                   Object context, Action action) {
165         /* TODO SB_MIGRATION */
166         if (action == Action.DELETE) {
167             if (tableName.equalsIgnoreCase(ovsdbConfigurationService.getTableName(node, Interface.class))) {
168                 logger.debug("Processing update of {}. Deleted node: {}, uuid: {}, row: {}", tableName, node, uuid, row);
169                 Interface deletedIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
170                 NeutronNetwork network = null;
171                 if (context == null) {
172                     network = tenantNetworkManager.getTenantNetwork(deletedIntf);
173                 } else {
174                     network = (NeutronNetwork)context;
175                 }
176                 List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
177                 logger.info("Delete interface " + deletedIntf.getName());
178
179                 if (deletedIntf.getTypeColumn().getData().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
180                     deletedIntf.getTypeColumn().getData().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
181                     phyIfName.contains(deletedIntf.getName())) {
182                     /* delete tunnel interfaces or physical interfaces */
183                     //this.handleInterfaceDelete(node, uuid, deletedIntf, false, null);
184                 } else if (network != null && !network.getRouterExternal()) {
185                     logger.debug("Processing update of {}:{} node {} intf {} network {}",
186                             tableName, action, node, uuid, network.getNetworkUUID());
187                     try {
188                         ConcurrentMap<String, Row> interfaces = this.ovsdbConfigurationService
189                                 .getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
190                         if (interfaces != null) {
191                             boolean isLastInstanceOnNode = true;
192                             for (String intfUUID : interfaces.keySet()) {
193                                 if (intfUUID.equals(uuid)) continue;
194                                 Interface intf = this.ovsdbConfigurationService.getTypedRow(node, Interface.class, interfaces.get(intfUUID));
195                                 NeutronNetwork neutronNetwork = tenantNetworkManager.getTenantNetwork(intf);
196                                 if (neutronNetwork != null && neutronNetwork.equals(network)) isLastInstanceOnNode = false;
197                             }
198                             //this.handleInterfaceDelete(node, uuid, deletedIntf, isLastInstanceOnNode, network);
199                         }
200                     } catch (Exception e) {
201                         logger.error("Error fetching Interface Rows for node " + node, e);
202                     }
203                 }
204             }
205         }
206         else if (tableName.equalsIgnoreCase(ovsdbConfigurationService.getTableName(node, Interface.class))) {
207             logger.debug("Processing update of {}:{} node: {}, interface uuid: {}, row: {}",
208                     tableName, action, node, uuid, row);
209             Interface intf = this.ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
210             NeutronNetwork network = tenantNetworkManager.getTenantNetwork(intf);
211             if (network != null && !network.getRouterExternal()) {
212                 if (networkingProviderManager.getProvider(node).hasPerTenantTunneling()) {
213                     int vlan = tenantNetworkManager.networkCreated(node, network.getID());
214                     String portUUID = this.getPortIdForInterface(node, uuid, intf);
215                     if (portUUID != null) {
216                         logger.debug("Neutron Network {}:{} Created with Internal vlan {} port {}",
217                                  network.getNetworkUUID(), network.getNetworkName(), vlan, portUUID);
218                         tenantNetworkManager.programInternalVlan(node, portUUID, network);
219                     } else {
220                         logger.trace("Neutron Network {}:{} Created with Internal vlan {} but have no portUUID",
221                                  network.getNetworkUUID(), network.getNetworkName(), vlan);
222                     }
223                 }
224                 //this.handleInterfaceUpdate(node, uuid, intf);
225             }
226
227         } else if (tableName.equalsIgnoreCase(ovsdbConfigurationService.getTableName(node, Port.class))) {
228             logger.debug("Processing update of {}:{} node: {}, port uuid: {}, row: {}", tableName, action, node, uuid, row);
229             Port port = this.ovsdbConfigurationService.getTypedRow(node, Port.class, row);
230             Set<UUID> interfaceUUIDs = port.getInterfacesColumn().getData();
231             for (UUID intfUUID : interfaceUUIDs) {
232                 logger.trace("Scanning interface "+intfUUID);
233                 try {
234                     Row intfRow = this.ovsdbConfigurationService
235                             .getRow(node, ovsdbConfigurationService.getTableName(node, Interface.class),
236                                     intfUUID.toString());
237                     Interface intf = this.ovsdbConfigurationService.getTypedRow(node, Interface.class, intfRow);
238                     NeutronNetwork network = tenantNetworkManager.getTenantNetwork(intf);
239                     if (network != null && !network.getRouterExternal()) {
240                          logger.debug("Processing update of {}:{} node {} intf {} network {}",
241                                  tableName, action, node, intfUUID, network.getNetworkUUID());
242                         tenantNetworkManager.programInternalVlan(node, uuid, network);
243                         //this.handleInterfaceUpdate(node, intfUUID.toString(), intf);
244                     } else {
245                         logger.trace("Ignoring update because there is not a neutron network {} for port {}, interface {}",
246                                 network, uuid, intfUUID);
247                     }
248                 } catch (Exception e) {
249                     logger.error("Failed to process row update", e);
250                 }
251             }
252         } else if (tableName.equalsIgnoreCase(ovsdbConfigurationService.getTableName(node, OpenVSwitch.class))) {
253             logger.debug("Processing update of {}:{} node: {}, ovs uuid: {}, row: {}", tableName, action, node, uuid, row);
254             try {
255                 ConcurrentMap<String, Row> interfaces = this.ovsdbConfigurationService
256                         .getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
257                 if (interfaces != null) {
258                     for (String intfUUID : interfaces.keySet()) {
259                         Interface intf = ovsdbConfigurationService.getTypedRow(node, Interface.class, interfaces.get(intfUUID));
260                         //this.handleInterfaceUpdate(node, intfUUID, intf);
261                     }
262                 }
263             } catch (Exception e) {
264                 logger.error("Error fetching Interface Rows for node " + node, e);
265             }
266         } else if (tableName.equalsIgnoreCase(ovsdbConfigurationService.getTableName(node, Bridge.class))) {
267             logger.debug("Processing update of {}:{} node: {}, bridge uuid: {}, row: {}", tableName, action, node, uuid, row);
268             Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, row);
269             final Set<String> dpids = bridge.getDatapathIdColumn().getData();
270             if (dpids != null &&
271                     (bridge.getName().equals(configurationService.getIntegrationBridgeName()) ||
272                             bridge.getName().equals(configurationService.getExternalBridgeName()))) {
273                 NetworkingProvider networkingProvider = networkingProviderManager.getProvider(node);
274                 for (String dpid : dpids) {
275                     // TODO SB_MIGRATION
276                     // I don't think this is used anymore since adding NodeCacheManager to service dependency
277                     //networkingProvider.notifyFlowCapableNodeEvent(StringConvertor.dpidStringToLong(dpid), action);
278                 }
279             }
280         }
281     }
282
283     private void handleInterfaceUpdate (Node node, String portName) {
284         OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
285                 MdsalUtils.getTerminationPointAugmentation(node, portName);
286         logger.trace("Interface update of node: {}, portName: {}", node, portName);
287         NeutronNetwork network = tenantNetworkManager.getTenantNetwork(ovsdbTerminationPointAugmentation);
288         if (network != null) {
289             neutronL3Adapter.handleInterfaceEvent(node, ovsdbTerminationPointAugmentation, network, Action.UPDATE);
290             if (bridgeConfigurationManager.createLocalNetwork(node, network))
291                 networkingProviderManager.getProvider(node).handleInterfaceUpdate(network, node,
292                         ovsdbTerminationPointAugmentation);
293         } else {
294             logger.debug("No tenant network found on node: {}, portName: {} for interface: {}",
295                     node, portName, ovsdbTerminationPointAugmentation);
296         }
297     }
298
299     private void handleInterfaceDelete (Node node, OvsdbTerminationPointAugmentation intf, boolean isLastInstanceOnNode,
300                                         NeutronNetwork network) {
301         logger.debug("handleInterfaceDelete: node: {}, isLastInstanceOnNode: {}, interface: {}",
302                 node, isLastInstanceOnNode, intf);
303
304         neutronL3Adapter.handleInterfaceEvent(node, intf, network, Action.DELETE);
305         List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
306         if (isInterfaceOfInterest(intf, phyIfName)) {
307             /* delete tunnel or physical interfaces */
308             //networkingProviderManager.getProvider(node).handleInterfaceDelete(intf.getTypeColumn().getData(), null,
309             //        node, intf, isLastInstanceOnNode);
310         } else if (network != null) {
311             if (!network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) { /* vlan doesn't need a tunnel endpoint */
312                 if (configurationService.getTunnelEndPoint(node) == null) {
313                     logger.error("Tunnel end-point configuration missing. Please configure it in OpenVSwitch Table");
314                     return;
315                 }
316             }
317             if (isLastInstanceOnNode & networkingProviderManager.getProvider(node).hasPerTenantTunneling()) {
318                 tenantNetworkManager.reclaimInternalVlan(node, network);
319             }
320             networkingProviderManager.getProvider(node).handleInterfaceDelete(network.getProviderNetworkType(), network, node, intf, isLastInstanceOnNode);
321         }
322     }
323
324     private String getPortIdForInterface (Node node, String uuid, Interface intf) {
325         /* TODO SB_MIGRATION */
326         try {
327             Map<String, Row> ports = this.ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Port.class));
328             if (ports == null) return null;
329             for (String portUUID : ports.keySet()) {
330                 Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, ports.get(portUUID));
331                 Set<UUID> interfaceUUIDs = port.getInterfacesColumn().getData();
332                 logger.trace("Scanning Port {} to identify interface : {} ",port, uuid);
333                 for (UUID intfUUID : interfaceUUIDs) {
334                     if (intfUUID.toString().equalsIgnoreCase(uuid)) {
335                         logger.trace("Found Interface {} -> {}", uuid, portUUID);
336                         return portUUID;
337                     }
338                 }
339             }
340         } catch (Exception e) {
341             logger.debug("Failed to get Port tag for for Intf " + intf, e);
342         }
343         return null;
344     }
345
346     private void triggerUpdates() {
347         /* TODO SB_MIGRATION */
348         List<Node> nodes = connectionService.getNodes();
349         if (nodes == null) return;
350         for (Node node : nodes) {
351             try {
352                 List<String> tableNames = ovsdbConfigurationService.getTables(node);
353                 if (tableNames == null) continue;
354                 for (String tableName : tableNames) {
355                     Map<String, Row> rows = ovsdbConfigurationService.getRows(node, tableName);
356                     if (rows == null) continue;
357                     for (String uuid : rows.keySet()) {
358                         Row row = rows.get(uuid);
359                         this.rowAdded(node, tableName, uuid, row);
360                     }
361                 }
362             } catch (Exception e) {
363                 logger.error("Exception during OVSDB Southbound update trigger", e);
364             }
365         }
366     }
367
368     private void processBridgeUpdate(Node node, OvsdbBridgeAugmentation bridge, Action action) {
369         logger.debug("processBridgeUpdate {}: {}, {}", action, node, bridge);
370         final String dpid = bridge.getDatapathId().getValue();
371         if (dpid != null
372                 && (bridge.getBridgeName().equals(configurationService.getIntegrationBridgeName())
373                 || bridge.getBridgeName().equals(configurationService.getExternalBridgeName()))) {
374             NetworkingProvider networkingProvider = networkingProviderManager.getProvider(node);
375             // TODO SB_MIGRATION
376             // I don't think this is used anymore since adding NodeCacheManager to service dependency
377             //networkingProvider.notifyFlowCapableNodeEvent(StringConvertor.dpidStringToLong(dpid), action);
378         }
379     }
380
381     private void processInterfaceDelete(Node node, String portName, Object context, Action action) {
382         OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
383                 MdsalUtils.getTerminationPointAugmentation(node, portName);
384         logger.debug("processInterfaceDelete {}: {}", node, portName);
385         NeutronNetwork network = null;
386         if (context == null) {
387             network = tenantNetworkManager.getTenantNetwork(ovsdbTerminationPointAugmentation);
388         } else {
389             network = (NeutronNetwork)context;
390         }
391         List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
392         if (isInterfaceOfInterest(ovsdbTerminationPointAugmentation, phyIfName)) {
393             this.handleInterfaceDelete(node, ovsdbTerminationPointAugmentation, false, null);
394         } else if (network != null && !network.getRouterExternal()) {
395             logger.debug("Network {} : Delete interface {} attached to bridge {}", network.getNetworkUUID(),
396                     ovsdbTerminationPointAugmentation.getInterfaceUuid(), node);
397             try {
398                 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.getAugmentation(OvsdbBridgeAugmentation.class);
399                 if (ovsdbBridgeAugmentation != null) {
400                     List<TerminationPoint> terminationPoints = node.getTerminationPoint();
401                     if(!terminationPoints.isEmpty()){
402                         boolean isLastInstanceOnNode = true;
403                         for(TerminationPoint terminationPoint : terminationPoints) {
404                             OvsdbTerminationPointAugmentation tpAugmentation =
405                                     terminationPoint.getAugmentation( OvsdbTerminationPointAugmentation.class);
406                             if(tpAugmentation.getInterfaceUuid().equals(ovsdbTerminationPointAugmentation.getInterfaceUuid())) continue;
407                             NeutronNetwork neutronNetwork = tenantNetworkManager.getTenantNetwork(tpAugmentation);
408                             if (neutronNetwork != null && neutronNetwork.equals(network)) {
409                                 isLastInstanceOnNode = false;
410                                 break;
411                             }
412                         }
413                         this.handleInterfaceDelete(node, ovsdbTerminationPointAugmentation, isLastInstanceOnNode, network);
414                     }
415                 }
416             } catch (Exception e) {
417                 logger.error("Error fetching Interface Rows for node " + node, e);
418             }
419         }
420     }
421
422     private void processInterfaceUpdate(Node node, OvsdbTerminationPointAugmentation terminationPoint,
423                                         String portName, Object context, Action action) {
424         if (action == Action.DELETE) {
425             processInterfaceDelete(node, portName, context, action);
426         } else {
427
428         }
429     }
430
431     private boolean isInterfaceOfInterest(OvsdbTerminationPointAugmentation terminationPoint, List<String> phyIfName) {
432         return (SouthboundMapper.createOvsdbInterfaceType(
433                 terminationPoint.getInterfaceType()).equals(NetworkHandler.NETWORK_TYPE_VXLAN)
434                 ||
435                 SouthboundMapper.createOvsdbInterfaceType(
436                         terminationPoint.getInterfaceType()).equals(NetworkHandler.NETWORK_TYPE_GRE)
437                 ||
438                 phyIfName.contains(terminationPoint.getName()));
439     }
440
441     /**
442      * Notification about an OpenFlow Node
443      *
444      * @param openFlowNode the {@link Node Node} of interest in the notification
445      * @param action the {@link Action}
446      * @see NodeCacheListener#notifyNode
447      */
448     @Override
449     public void notifyNode (Node openFlowNode, Action action) {
450         logger.info("notifyNode: Node {} update {}", openFlowNode, action);
451
452         if (action.equals(Action.ADD)) {
453             networkingProviderManager.getProvider(openFlowNode).initializeOFFlowRules(openFlowNode);
454         }
455     }
456
457     /**
458      * Process the event.
459      *
460      * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
461      * @see EventDispatcher
462      */
463     @Override
464     public void processEvent(AbstractEvent abstractEvent) {
465         if (!(abstractEvent instanceof SouthboundEvent)) {
466             logger.error("Unable to process abstract event " + abstractEvent);
467             return;
468         }
469         SouthboundEvent ev = (SouthboundEvent) abstractEvent;
470         logger.info("processEvent: {}", ev);
471         switch (ev.getType()) {
472             case NODE:
473                 processOvsdbNodeUpdate(ev.getNode(), ev.getAction());
474                 break;
475             case BRIDGE:
476                 processBridgeUpdate(ev.getNode(), ev.getAction());
477                 break;
478
479             case PORT:
480                 processPortUpdate(ev.getNode(), ev.getAction());
481                 break;
482
483             case OPENVSWITCH:
484                 processOpenVSwitchUpdate(ev.getNode(), ev.getAction());
485                 break;
486             case ROW:
487                 try {
488                     processRowUpdate(ev.getNode(), ev.getTableName(), ev.getUuid(), ev.getRow(),
489                             ev.getContext(), ev.getAction());
490                 } catch (Exception e) {
491                     logger.error("Exception caught in ProcessRowUpdate for node " + ev.getNode(), e);
492                 }
493                 break;
494             default:
495                 logger.warn("Unable to process type " + ev.getType() +
496                         " action " + ev.getAction() + " for node " + ev.getNode());
497                 break;
498         }
499     }
500
501     private void processPortUpdate(Node node, Action action) {
502         switch (action) {
503             case ADD:
504             case UPDATE:
505                 processPortUpdate(node);
506                 break;
507             case DELETE:
508                 processPortDelete(node);
509                 break;
510         }
511     }
512
513     private void processPortDelete(Node node) {
514     }
515
516     private void processPortUpdate(Node node) {
517     }
518
519     private void processBridgeUpdate(Node node, Action action) {
520     }
521
522     private void processOpenVSwitchUpdate(Node node, Action action) {
523         //do the work that rowUpdate(table=openvswith) would have done
524     }
525 }