2 * Copyright (C) 2013 Red Hat, Inc.
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.ovsdb.openstack.netvirt;
10 import java.util.List;
12 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
13 import org.opendaylight.neutron.spi.NeutronNetwork;
14 import org.opendaylight.ovsdb.openstack.netvirt.api.*;
15 import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter;
16 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
20 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
21 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * @author Madhu Venugopal
29 * @author Brent Salisbury
31 * @author Sam Hague (shague@redhat.com)
33 public class SouthboundHandler extends AbstractHandler
34 implements NodeCacheListener, OvsdbInventoryListener {
35 static final Logger logger = LoggerFactory.getLogger(SouthboundHandler.class);
37 // The implementation for each of these services is resolved by the OSGi Service Manager
38 private volatile ConfigurationService configurationService;
39 private volatile BridgeConfigurationManager bridgeConfigurationManager;
40 private volatile TenantNetworkManager tenantNetworkManager;
41 private volatile NetworkingProviderManager networkingProviderManager;
42 private volatile OvsdbConnectionService connectionService;
43 private volatile NeutronL3Adapter neutronL3Adapter;
46 this.triggerUpdates();
50 logger.info(">>>>>> init {}", this.getClass());
53 private SouthboundEvent.Type ovsdbTypeToSouthboundEventType(OvsdbType ovsdbType) {
54 SouthboundEvent.Type type = SouthboundEvent.Type.NODE;
58 type = SouthboundEvent.Type.NODE;
61 type = SouthboundEvent.Type.BRIDGE;
64 type = SouthboundEvent.Type.PORT;
67 type = SouthboundEvent.Type.CONTROLLER;
70 type = SouthboundEvent.Type.OPENVSWITCH;
73 logger.warn("Invalid OvsdbType: {}", ovsdbType);
80 public void ovsdbUpdate(Node node, DataObject resourceAugmentationData, OvsdbType ovsdbType, Action action) {
81 logger.info("ovsdbUpdate: {} - {} - {}", node, ovsdbType, action);
82 this.enqueueEvent(new SouthboundEvent(node, resourceAugmentationData, ovsdbTypeToSouthboundEventType(ovsdbType), action));
85 public void processOvsdbNodeUpdate(Node node, Action action) {
88 logger.info("processOvsdbNodeUpdate {}", node);
89 bridgeConfigurationManager.prepareNode(node);
94 processNodeDelete(node);
97 if (action == Action.ADD) {
99 logger.info("Not implemented yet: {}", action);
103 private void processNodeDelete(Node node) {
104 OvsdbNodeAugmentation nodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class);
105 if(nodeAugmentation != null){
106 InstanceIdentifier<Node> bridgeNodeIid =
107 MdsalHelper.createInstanceIdentifier(nodeAugmentation.getConnectionInfo(), Constants.INTEGRATION_BRIDGE);
108 MdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid);
112 private void handleInterfaceUpdate (Node node, OvsdbTerminationPointAugmentation tp) {
113 logger.trace("handleInterfaceUpdate node: {}, tp: {}", node, tp);
114 NeutronNetwork network = tenantNetworkManager.getTenantNetwork(tp);
115 if (network != null && !network.getRouterExternal()) {
116 logger.trace("handleInterfaceUpdate node: {}, tp: {}, network: {}", node, tp, network.getNetworkUUID());
117 tenantNetworkManager.programInternalVlan(node, tp, network);
118 neutronL3Adapter.handleInterfaceEvent(node, tp, network, Action.UPDATE);
119 if (bridgeConfigurationManager.createLocalNetwork(node, network)) {
120 networkingProviderManager.getProvider(node).handleInterfaceUpdate(network, node, tp);
123 logger.debug("No tenant network found on node: {} for interface: {}", node, tp);
127 private void handleInterfaceDelete (Node node, OvsdbTerminationPointAugmentation intf,
128 boolean isLastInstanceOnNode, NeutronNetwork network) {
129 logger.debug("handleInterfaceDelete: node: {}, isLastInstanceOnNode: {}, interface: {}",
130 node, isLastInstanceOnNode, intf);
132 neutronL3Adapter.handleInterfaceEvent(node, intf, network, Action.DELETE);
133 List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
134 if (isInterfaceOfInterest(intf, phyIfName)) {
135 // delete tunnel or physical interfaces
136 networkingProviderManager.getProvider(node).handleInterfaceDelete(network.getProviderNetworkType(),
137 network, node, intf, isLastInstanceOnNode);
138 } else if (network != null) {
139 // vlan doesn't need a tunnel endpoint
140 if (!network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
141 if (configurationService.getTunnelEndPoint(node) == null) {
142 logger.error("Tunnel end-point configuration missing. Please configure it in OpenVSwitch Table");
146 if (isLastInstanceOnNode & networkingProviderManager.getProvider(node).hasPerTenantTunneling()) {
147 tenantNetworkManager.reclaimInternalVlan(node, network);
149 networkingProviderManager.getProvider(node).handleInterfaceDelete(network.getProviderNetworkType(),
150 network, node, intf, isLastInstanceOnNode);
154 private void triggerUpdates() {
155 List<Node> nodes = connectionService.getNodes();
156 if (nodes == null) return;
157 for (Node node : nodes) {
158 OvsdbBridgeAugmentation bridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
159 if (bridge != null) {
160 processBridgeUpdate(node, bridge);
163 List<TerminationPoint> tps = MdsalUtils.extractTerminationPoints(node);
164 for (TerminationPoint tp : tps) {
165 OvsdbTerminationPointAugmentation port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
167 processPortUpdate(node, port);
173 private void processPortDelete(Node node, OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation,
175 logger.debug("processportDelete {}: {}", node, ovsdbTerminationPointAugmentation);
176 NeutronNetwork network = null;
177 if (context == null) {
178 network = tenantNetworkManager.getTenantNetwork(ovsdbTerminationPointAugmentation);
180 network = (NeutronNetwork)context;
182 List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
183 if (isInterfaceOfInterest(ovsdbTerminationPointAugmentation, phyIfName)) {
184 this.handleInterfaceDelete(node, ovsdbTerminationPointAugmentation, false, null);
185 } else if (network != null && !network.getRouterExternal()) {
186 logger.debug("Network {} : Delete interface {} attached to bridge {}", network.getNetworkUUID(),
187 ovsdbTerminationPointAugmentation.getInterfaceUuid(), node);
189 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.getAugmentation(OvsdbBridgeAugmentation.class);
190 if (ovsdbBridgeAugmentation != null) {
191 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
192 if(!terminationPoints.isEmpty()){
193 boolean isLastInstanceOnNode = true;
194 for(TerminationPoint terminationPoint : terminationPoints) {
195 OvsdbTerminationPointAugmentation tpAugmentation =
196 terminationPoint.getAugmentation( OvsdbTerminationPointAugmentation.class);
197 if(tpAugmentation.getInterfaceUuid().equals(ovsdbTerminationPointAugmentation.getInterfaceUuid())) continue;
198 NeutronNetwork neutronNetwork = tenantNetworkManager.getTenantNetwork(tpAugmentation);
199 if (neutronNetwork != null && neutronNetwork.equals(network)) {
200 isLastInstanceOnNode = false;
204 this.handleInterfaceDelete(node, ovsdbTerminationPointAugmentation, isLastInstanceOnNode, network);
207 } catch (Exception e) {
208 logger.error("Error fetching Interface Rows for node " + node, e);
213 private boolean isInterfaceOfInterest(OvsdbTerminationPointAugmentation terminationPoint, List<String> phyIfName) {
214 return (SouthboundMapper.createOvsdbInterfaceType(
215 terminationPoint.getInterfaceType()).equals(NetworkHandler.NETWORK_TYPE_VXLAN)
217 SouthboundMapper.createOvsdbInterfaceType(
218 terminationPoint.getInterfaceType()).equals(NetworkHandler.NETWORK_TYPE_GRE)
220 phyIfName.contains(terminationPoint.getName()));
224 * Notification about an OpenFlow Node
226 * @param openFlowNode the {@link Node Node} of interest in the notification
227 * @param action the {@link Action}
228 * @see NodeCacheListener#notifyNode
231 public void notifyNode (Node openFlowNode, Action action) {
232 logger.info("notifyNode: Node {} update {}", openFlowNode, action);
234 if (action.equals(Action.ADD)) {
235 networkingProviderManager.getProvider(openFlowNode).initializeOFFlowRules(openFlowNode);
242 * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
243 * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
246 public void processEvent(AbstractEvent abstractEvent) {
247 if (!(abstractEvent instanceof SouthboundEvent)) {
248 logger.error("Unable to process abstract event " + abstractEvent);
251 SouthboundEvent ev = (SouthboundEvent) abstractEvent;
252 logger.info("processEvent: {}", ev);
253 switch (ev.getType()) {
255 processOvsdbNodeUpdate(ev.getNode(), ev.getAction());
258 processBridgeUpdate(ev.getNode(), ev.getAction());
262 processPortUpdate(ev.getNode(), ev.getAction());
266 processOpenVSwitchUpdate(ev.getNode(), ev.getAction());
270 logger.warn("Unable to process type " + ev.getType() +
271 " action " + ev.getAction() + " for node " + ev.getNode());
276 private void processPortUpdate(Node node, Action action) {
280 processPortUpdate(node);
283 processPortDelete(node);
288 private void processPortDelete(Node node) {
289 List<TerminationPoint> terminationPoints = MdsalUtils.extractTerminationPoints(node);
290 for (TerminationPoint terminationPoint : terminationPoints) {
291 processPortDelete(node, terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class), null);
295 private void processPortUpdate(Node node) {
296 List<TerminationPoint> terminationPoints = MdsalUtils.extractTerminationPoints(node);
297 for (TerminationPoint terminationPoint : terminationPoints) {
298 processPortUpdate(node, terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class));
302 private void processPortUpdate(Node node, OvsdbTerminationPointAugmentation port) {
303 logger.debug("processPortUpdate {} - {}", node, port);
304 NeutronNetwork network = tenantNetworkManager.getTenantNetwork(port);
305 if (network != null && !network.getRouterExternal()) {
306 this.handleInterfaceUpdate(node, port);
311 private void processOpenVSwitchUpdate(Node node, Action action) {
315 processOpenVSwitchUpdate(node);
322 private void processOpenVSwitchUpdate(Node node) {
323 // TODO this node might be the OvsdbNode and not have termination points
324 // Would need to change listener or grab tp nodes in here.
325 List<TerminationPoint> terminationPoints = MdsalUtils.extractTerminationPoints(node);
326 for (TerminationPoint terminationPoint : terminationPoints) {
327 processPortUpdate(node, terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class));
331 private void processBridgeUpdate(Node node, Action action) {
332 OvsdbBridgeAugmentation bridge = MdsalUtils.extractBridgeAugmentation(node);
336 processBridgeUpdate(node, bridge);
339 processBridgeDelete(node, bridge);
344 private void processBridgeDelete(Node bridgeNode, OvsdbBridgeAugmentation bridge) {
345 logger.debug("Delete bridge from config data store : {}", bridgeNode.getNodeId());
346 MdsalUtils.deleteBridge(bridgeNode);
349 private void processBridgeUpdate(Node node, OvsdbBridgeAugmentation bridge) {
350 logger.debug("processBridgeUpdate {}, {}", node, bridge);