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 * Authors : Madhu Venugopal, Brent Salisbury
10 package org.opendaylight.ovsdb.neutron;
14 import org.opendaylight.controller.sal.core.Node;
15 import org.opendaylight.controller.sal.utils.ServiceHelper;
16 import org.opendaylight.controller.sal.utils.Status;
17 import org.opendaylight.controller.sal.utils.StatusCode;
18 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
19 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
20 import org.opendaylight.ovsdb.lib.notation.UUID;
21 import org.opendaylight.ovsdb.lib.table.Bridge;
22 import org.opendaylight.ovsdb.lib.table.Interface;
23 import org.opendaylight.ovsdb.lib.table.Port;
24 import org.opendaylight.ovsdb.lib.table.internal.Table;
25 import org.opendaylight.ovsdb.neutron.provider.ProviderNetworkManager;
26 import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
27 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
28 import org.opendaylight.ovsdb.plugin.StatusWithUuid;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * OpenStack Neutron with the OpenVswitch data plan relies on a typical OVS bridge configurations that
34 * consists of br-int (Integration Bridge), br-tun (Tunnel bridge), br-ex (External bridge).
36 * In DevStack like setups, the br-tun is not automatically created on the controller nodes.
37 * Hence this class attempts to bring all the nodes to be elibible for OpenStack operations.
40 public class InternalNetworkManager {
41 static final Logger logger = LoggerFactory.getLogger(InternalNetworkManager.class);
42 private static final int LLDP_PRIORITY = 1000;
43 private static final int NORMAL_PRIORITY = 0;
45 private static InternalNetworkManager internalNetwork = new InternalNetworkManager();
46 private InternalNetworkManager() {
49 public static InternalNetworkManager getManager() {
50 return internalNetwork;
53 public String getInternalBridgeUUID (Node node, String bridgeName) {
55 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
56 Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
57 if (bridgeTable == null) return null;
58 for (String key : bridgeTable.keySet()) {
59 Bridge bridge = (Bridge)bridgeTable.get(key);
60 if (bridge.getName().equals(bridgeName)) return key;
62 } catch (Exception e) {
63 logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
68 public boolean isInternalNetworkNeutronReady(Node node) {
69 if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getIntegrationBridgeName()) != null) {
76 public boolean isInternalNetworkOverlayReady(Node node) {
77 if (!this.isInternalNetworkNeutronReady(node)) {
80 if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()) != null) {
88 * Lets create these if not already present :
94 options: {peer=patch-int}
102 options: {peer=patch-tun}
107 public void createInternalNetworkForOverlay(Node node) throws Exception {
108 String brTun = AdminConfigManager.getManager().getTunnelBridgeName();
109 String brInt = AdminConfigManager.getManager().getIntegrationBridgeName();
110 String patchInt = AdminConfigManager.getManager().getPatchToIntegration();
111 String patchTun = AdminConfigManager.getManager().getPatchToTunnel();
113 Status status = this.addInternalBridge(node, brInt, patchTun, patchInt);
114 if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
115 if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
116 status = this.addInternalBridge(node, brTun, patchInt, patchTun);
117 if (!status.isSuccess()) logger.debug("Tunnel Bridge Creation Status : "+status.toString());
122 * Lets create these if not already present :
129 public void createInternalNetworkForNeutron(Node node) throws Exception {
130 String brInt = AdminConfigManager.getManager().getIntegrationBridgeName();
132 Status status = this.addInternalBridge(node, brInt, null, null);
133 if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
136 private Status addInternalBridge (Node node, String bridgeName, String localPathName, String remotePatchName) throws Exception {
137 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
139 String bridgeUUID = this.getInternalBridgeUUID(node, bridgeName);
140 Bridge bridge = new Bridge();
141 OvsDBSet<String> failMode = new OvsDBSet<String>();
142 failMode.add("secure");
143 bridge.setFail_mode(failMode);
145 OvsDBSet<String> protocols = new OvsDBSet<String>();
146 if (!ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
147 protocols.add("OpenFlow13");
149 protocols.add("OpenFlow10");
151 bridge.setProtocols(protocols);
153 if (bridgeUUID == null) {
154 bridge.setName(bridgeName);
156 StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Bridge.NAME.getName(), null, bridge);
157 if (!statusWithUuid.isSuccess()) return statusWithUuid;
158 bridgeUUID = statusWithUuid.getUuid().toString();
159 Port port = new Port();
160 port.setName(bridgeName);
161 Status status = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
162 logger.debug("addInternalBridge : Inserting Bridge {} with protocols {} and status {}", bridgeUUID, protocols, status);
164 Status status = ovsdbTable.updateRow(node, Bridge.NAME.getName(), null, bridgeUUID, bridge);
165 logger.debug("addInternalBridge : Updating Bridge {} with protocols {} and status {}", bridgeUUID, protocols, status);
168 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
169 connectionService.setOFController(node, bridgeUUID);
171 if (localPathName != null && remotePatchName != null && ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
172 return addPatchPort(node, bridgeUUID, localPathName, remotePatchName);
174 return new Status(StatusCode.SUCCESS);
177 private Status addPatchPort (Node node, String bridgeUUID, String portName, String patchName) throws Exception {
178 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
180 Port patchPort = new Port();
181 patchPort.setName(portName);
182 // Create patch port and interface
183 StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, patchPort);
184 if (!statusWithUuid.isSuccess()) return statusWithUuid;
186 String patchPortUUID = statusWithUuid.getUuid().toString();
188 String interfaceUUID = null;
190 while ((interfaceUUID == null) && (timeout > 0)) {
191 patchPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), patchPortUUID);
192 OvsDBSet<UUID> interfaces = patchPort.getInterfaces();
193 if (interfaces == null || interfaces.size() == 0) {
194 // Wait for the OVSDB update to sync up the Local cache.
199 interfaceUUID = interfaces.toArray()[0].toString();
202 if (interfaceUUID == null) {
203 return new Status(StatusCode.INTERNALERROR);
206 Interface tunInterface = new Interface();
207 tunInterface.setType("patch");
208 OvsDBMap<String, String> options = new OvsDBMap<String, String>();
209 options.put("peer", patchName);
210 tunInterface.setOptions(options);
211 return ovsdbTable.updateRow(node, Interface.NAME.getName(), patchPortUUID, interfaceUUID, tunInterface);
214 public void prepareInternalNetwork(Node node) {
216 this.createInternalNetworkForOverlay(node);
217 } catch (Exception e) {
218 logger.error("Error creating internal network "+node.toString(), e);
220 ProviderNetworkManager.getManager().initializeFlowRules(node);