Moved all Openflow 1.0 specific flow programming away from InternalNetworkManager...
[netvirt.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         status = this.addInternalBridge(node, brTun, patchInt, patchTun);
116         if (!status.isSuccess()) logger.debug("Tunnel Bridge Creation Status : "+status.toString());
117     }
118
119     /*
120      * Lets create these if not already present :
121      *
122        Bridge br-int
123             Port br-int
124                 Interface br-int
125                     type: internal
126      */
127     public void createInternalNetworkForNeutron(Node node) throws Exception {
128         String brInt = AdminConfigManager.getManager().getIntegrationBridgeName();
129
130         Status status = this.addInternalBridge(node, brInt, null, null);
131         if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
132     }
133
134     private Status addInternalBridge (Node node, String bridgeName, String localPathName, String remotePatchName) throws Exception {
135         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
136
137         String bridgeUUID = this.getInternalBridgeUUID(node, bridgeName);
138         if (bridgeUUID == null) {
139             Bridge bridge = new Bridge();
140             bridge.setName(bridgeName);
141
142             StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Bridge.NAME.getName(), null, bridge);
143             if (!statusWithUuid.isSuccess()) return statusWithUuid;
144             bridgeUUID = statusWithUuid.getUuid().toString();
145             Port port = new Port();
146             port.setName(bridgeName);
147             ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
148         }
149
150         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
151         connectionService.setOFController(node, bridgeUUID);
152
153         if (localPathName != null && remotePatchName != null) {
154             return addPatchPort(node, bridgeUUID, localPathName, remotePatchName);
155         }
156         return new Status(StatusCode.SUCCESS);
157     }
158
159     private Status addPatchPort (Node node, String bridgeUUID, String portName, String patchName) throws Exception {
160         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
161
162         Port patchPort = new Port();
163         patchPort.setName(portName);
164         // Create patch port and interface
165         StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, patchPort);
166         if (!statusWithUuid.isSuccess()) return statusWithUuid;
167
168         String patchPortUUID = statusWithUuid.getUuid().toString();
169
170         String interfaceUUID = null;
171         int timeout = 6;
172         while ((interfaceUUID == null) && (timeout > 0)) {
173             patchPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), patchPortUUID);
174             OvsDBSet<UUID> interfaces = patchPort.getInterfaces();
175             if (interfaces == null || interfaces.size() == 0) {
176                 // Wait for the OVSDB update to sync up the Local cache.
177                 Thread.sleep(500);
178                 timeout--;
179                 continue;
180             }
181             interfaceUUID = interfaces.toArray()[0].toString();
182         }
183
184         if (interfaceUUID == null) {
185             return new Status(StatusCode.INTERNALERROR);
186         }
187
188         Interface tunInterface = new Interface();
189         tunInterface.setType("patch");
190         OvsDBMap<String, String> options = new OvsDBMap<String, String>();
191         options.put("peer", patchName);
192         tunInterface.setOptions(options);
193         return ovsdbTable.updateRow(node, Interface.NAME.getName(), patchPortUUID, interfaceUUID, tunInterface);
194     }
195
196     public void prepareInternalNetwork(Node node) {
197         try {
198             this.createInternalNetworkForOverlay(node);
199         } catch (Exception e) {
200             logger.error("Error creating internal network "+node.toString(), e);
201         }
202         ProviderNetworkManager.getManager().initializeFlowRules(node);
203     }
204 }