82430f2279984d221d1bd6441d425c106b95411e
[ovsdb.git] / neutron / src / main / java / org / opendaylight / ovsdb / neutron / InternalNetworkManager.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.neutron;
11
12 import java.util.Map;
13
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;
31
32 /**
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).
35  *
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.
38  *
39  */
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;
44
45     private static InternalNetworkManager internalNetwork = new InternalNetworkManager();
46     private InternalNetworkManager() {
47     }
48
49     public static InternalNetworkManager getManager() {
50         return internalNetwork;
51     }
52
53     public String getInternalBridgeUUID (Node node, String bridgeName) {
54         try {
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;
61             }
62         } catch (Exception e) {
63             logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
64         }
65         return null;
66     }
67
68     public boolean isInternalNetworkNeutronReady(Node node) {
69         if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getIntegrationBridgeName()) != null) {
70             return true;
71         } else {
72             return false;
73         }
74     }
75
76     public boolean isInternalNetworkOverlayReady(Node node) {
77         if (!this.isInternalNetworkNeutronReady(node)) {
78             return false;
79         }
80         if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()) != null) {
81             return true;
82         } else {
83             return false;
84         }
85     }
86
87     /*
88      * Lets create these if not already present :
89      *
90        Bridge br-int
91             Port patch-tun
92                 Interface patch-tun
93                     type: patch
94                     options: {peer=patch-int}
95             Port br-int
96                 Interface br-int
97                     type: internal
98       Bridge br-tun
99             Port patch-int
100                 Interface patch-int
101                     type: patch
102                     options: {peer=patch-tun}
103             Port br-tun
104                 Interface br-tun
105                     type: internal
106      */
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();
112
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());
118         }
119     }
120
121     /*
122      * Lets create these if not already present :
123      *
124        Bridge br-int
125             Port br-int
126                 Interface br-int
127                     type: internal
128      */
129     public void createInternalNetworkForNeutron(Node node) throws Exception {
130         String brInt = AdminConfigManager.getManager().getIntegrationBridgeName();
131
132         Status status = this.addInternalBridge(node, brInt, null, null);
133         if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
134     }
135
136     private Status addInternalBridge (Node node, String bridgeName, String localPathName, String remotePatchName) throws Exception {
137         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
138
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);
144
145         OvsDBSet<String> protocols = new OvsDBSet<String>();
146         if (!ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
147             protocols.add("OpenFlow13");
148         } else {
149             protocols.add("OpenFlow10");
150         }
151         bridge.setProtocols(protocols);
152
153         if (bridgeUUID == null) {
154             bridge.setName(bridgeName);
155
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);
163         } else {
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);
166         }
167
168         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
169         connectionService.setOFController(node, bridgeUUID);
170
171         if (localPathName != null && remotePatchName != null && ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
172             return addPatchPort(node, bridgeUUID, localPathName, remotePatchName);
173         }
174         return new Status(StatusCode.SUCCESS);
175     }
176
177     private Status addPatchPort (Node node, String bridgeUUID, String portName, String patchName) throws Exception {
178         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
179
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;
185
186         String patchPortUUID = statusWithUuid.getUuid().toString();
187
188         String interfaceUUID = null;
189         int timeout = 6;
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.
195                 Thread.sleep(500);
196                 timeout--;
197                 continue;
198             }
199             interfaceUUID = interfaces.toArray()[0].toString();
200         }
201
202         if (interfaceUUID == null) {
203             return new Status(StatusCode.INTERNALERROR);
204         }
205
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);
212     }
213
214     public void prepareInternalNetwork(Node node) {
215         try {
216             this.createInternalNetworkForOverlay(node);
217         } catch (Exception e) {
218             logger.error("Error creating internal network "+node.toString(), e);
219         }
220         ProviderNetworkManager.getManager().initializeFlowRules(node);
221     }
222 }