Added br-tun bridge installation code via InternalNetworkManager in cases when the...
[netvirt.git] / neutron / src / main / java / org / opendaylight / ovsdb / neutron / InternalNetworkManager.java
1 package org.opendaylight.ovsdb.neutron;
2
3 import java.util.List;
4 import java.util.Map;
5
6 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
7 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
8 import org.opendaylight.controller.sal.core.Node;
9 import org.opendaylight.controller.sal.utils.ServiceHelper;
10 import org.opendaylight.controller.sal.utils.Status;
11 import org.opendaylight.controller.sal.utils.StatusCode;
12 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
13 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
14 import org.opendaylight.ovsdb.lib.notation.UUID;
15 import org.opendaylight.ovsdb.lib.table.Bridge;
16 import org.opendaylight.ovsdb.lib.table.Interface;
17 import org.opendaylight.ovsdb.lib.table.Port;
18 import org.opendaylight.ovsdb.lib.table.internal.Table;
19 import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
20 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * OpenStack Neutron with the OpenVswitch data plan relies on a typical OVS bridge configurations that
26  * consists of br-int (Integration Bridge), br-tun (Tunnel bridge), br-ex (External bridge).
27  *
28  * In DevStack like setups, the br-tun is not automatically created on the controller nodes.
29  * Hence this class attempts to bring all the nodes to be elibible for OpenStack operations.
30  *
31  */
32 public class InternalNetworkManager {
33     static final Logger logger = LoggerFactory.getLogger(InternalNetworkManager.class);
34
35     private static InternalNetworkManager internalNetwork = new InternalNetworkManager();
36     private InternalNetworkManager() {
37     }
38
39     public static InternalNetworkManager getManager() {
40         return internalNetwork;
41     }
42
43     public boolean isInternalNetworkNeutronReady(Node node) throws Exception {
44         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
45         Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
46         if (bridgeTable != null) {
47             for (Table<?> row : bridgeTable.values()) {
48                 Bridge bridge = (Bridge)row;
49                 if (bridge.getName().equals(AdminConfigManager.getManager().getIntegrationBridgeName())) return true;
50             }
51         }
52         return false;
53     }
54
55     public boolean isInternalNetworkOverlayReady(Node node) throws Exception {
56         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
57         Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
58         if (bridgeTable != null) {
59             for (Table<?> row : bridgeTable.values()) {
60                 Bridge bridge = (Bridge)row;
61                 if (bridge.getName().equals(AdminConfigManager.getManager().getTunnelBridgeName())) return true;
62             }
63         }
64         return false;
65     }
66
67     public Status createInternalNetworkForOverlay(Node node) throws Exception {
68         if (!isInternalNetworkNeutronReady(node)) {
69             logger.error("Integration Bridge is not available in Node {}", node);
70             return new Status(StatusCode.NOTACCEPTABLE, "Integration Bridge is not avaialble in Node " + node);
71         }
72         if (isInternalNetworkOverlayReady(node)) {
73             logger.error("Network Overlay Bridge is already present in Node {}", node);
74             return new Status(StatusCode.NOTACCEPTABLE, "Network Overlay Bridge is already present in Node " + node);
75         }
76
77         /*
78          * Lets create this :
79          *
80          * Bridge br-tun
81                 Port patch-int
82                     Interface patch-int
83                         type: patch
84                         options: {peer=patch-tun}
85                 Port br-tun
86                     Interface br-tun
87                         type: internal
88          */
89
90         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
91         Bridge brTun = new Bridge();
92         brTun.setName(AdminConfigManager.getManager().getTunnelBridgeName());
93         // Create br-tun bridge
94         Status status = ovsdbTable.insertRow(node, Bridge.NAME.getName(), null, brTun);
95         if (!status.isSuccess()) return status;
96         String bridgeUUID = status.getDescription();
97
98         Port port = new Port();
99         port.setName(brTun.getName());
100         status = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
101
102         status = addPatchPort(node, bridgeUUID, "patch-int", "patch-tun");
103         if (!status.isSuccess()) return status;
104
105         // Create the corresponding patch-tun port in br-int
106         Map<String, Table<?>> bridges = ovsdbTable.getRows(node, Bridge.NAME.getName());
107         for (String brIntUUID : bridges.keySet()) {
108             Bridge brInt = (Bridge) bridges.get(brIntUUID);
109             if (brInt.getName().equalsIgnoreCase(AdminConfigManager.getManager().getIntegrationBridgeName())) {
110                 return addPatchPort(node, brIntUUID, "patch-tun", "patch-int");
111             }
112         }
113
114         return status;
115     }
116
117     private Status addPatchPort (Node node, String bridgeUUID, String portName, String patchName) throws Exception {
118         Status status = null;
119         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
120
121         Port patchPort = new Port();
122         patchPort.setName(portName);
123         // Create patch-int port and interface
124         status = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, patchPort);
125         if (!status.isSuccess()) return status;
126
127         String patchPortUUID = status.getDescription();
128
129         String interfaceUUID = null;
130         int timeout = 6;
131         while ((interfaceUUID == null) && (timeout > 0)) {
132             patchPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), status.getDescription());
133             OvsDBSet<UUID> interfaces = patchPort.getInterfaces();
134             if (interfaces == null || interfaces.size() == 0) {
135                 // Wait for the OVSDB update to sync up the Local cache.
136                 Thread.sleep(500);
137                 timeout--;
138                 continue;
139             }
140             interfaceUUID = interfaces.toArray()[0].toString();
141         }
142
143         if (interfaceUUID == null) {
144             return new Status(StatusCode.INTERNALERROR);
145         }
146
147         Interface tunInterface = new Interface();
148         tunInterface.setType("patch");
149         OvsDBMap<String, String> options = new OvsDBMap<String, String>();
150         options.put("peer", patchName);
151         tunInterface.setOptions(options);
152         status = ovsdbTable.updateRow(node, Interface.NAME.getName(), patchPortUUID, interfaceUUID, tunInterface);
153
154         return status;
155     }
156
157     private void prepareInternalNetwork (NeutronNetwork network, Node node) {
158         // vlan, vxlan, and gre
159         if (network.getProviderNetworkType().equalsIgnoreCase("gre") ||
160                 network.getProviderNetworkType().equalsIgnoreCase("vxlan") ||
161                 network.getProviderNetworkType().equalsIgnoreCase("vlan")) {
162
163             try {
164                 if (!this.isInternalNetworkOverlayReady(node)) {
165                     this.createInternalNetworkForOverlay(node);
166                 }
167             } catch (Exception e) {
168                 e.printStackTrace();
169             }
170         } else {
171             try {
172                 if (!this.isInternalNetworkNeutronReady(node)) {
173                     // TODO : FILL IN
174                     // this.createInternalNetworkForNeutron(node);
175                 }
176             } catch (Exception e) {
177                 e.printStackTrace();
178             }
179         }
180     }
181
182     public void prepareInternalNetwork(NeutronNetwork network) {
183         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
184         List<Node> nodes = connectionService.getNodes();
185         for (Node node : nodes) {
186             prepareInternalNetwork(network, node);
187         }
188     }
189
190     public void prepareInternalNetwork(Node node) {
191         INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
192         List <NeutronNetwork> networks = neutronNetworkService.getAllNetworks();
193         for (NeutronNetwork network : networks) {
194             prepareInternalNetwork(network, node);
195         }
196     }
197
198 }