Rename MdsalUtils to be Southbound and remove statics
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / impl / BridgeConfigurationManagerImpl.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 package org.opendaylight.ovsdb.openstack.netvirt.impl;
9
10 import org.opendaylight.neutron.spi.NeutronNetwork;
11 import org.opendaylight.ovsdb.openstack.netvirt.ConfigInterface;
12 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
13 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
14 import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
15 import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
16 import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbTables;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
18 import org.opendaylight.ovsdb.utils.config.ConfigProperties;
19 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
24
25 import com.google.common.base.Preconditions;
26 import com.google.common.collect.Lists;
27 import java.net.InetAddress;
28 import java.net.NetworkInterface;
29 import java.net.UnknownHostException;
30 import java.util.Enumeration;
31 import java.util.List;
32 import org.apache.commons.lang3.tuple.ImmutablePair;
33 import org.osgi.framework.BundleContext;
34 import org.osgi.framework.ServiceReference;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * @author Madhu Venugopal
40  * @author Brent Salisbury
41  * @author Sam Hague (shague@redhat.com)
42  */
43 public class BridgeConfigurationManagerImpl implements BridgeConfigurationManager, ConfigInterface {
44     static final Logger LOGGER = LoggerFactory.getLogger(BridgeConfigurationManagerImpl.class);
45
46     // The implementation for each of these services is resolved by the OSGi Service Manager
47     private volatile ConfigurationService configurationService;
48     private volatile NetworkingProviderManager networkingProviderManager;
49     private volatile Southbound southbound;
50
51     public void setConfigurationService(ConfigurationService configurationService) {
52         this.configurationService = configurationService;
53     }
54
55     public void setSouthbound(Southbound southbound) {
56         this.southbound = southbound;
57     }
58
59     @Override
60     public String getBridgeUuid(Node node, String bridgeName) {
61         return southbound.getBridgeUuid(node, bridgeName);
62     }
63
64     @Override
65     public boolean isNodeNeutronReady(Node node) {
66         Preconditions.checkNotNull(configurationService);
67         return southbound.getBridge(node, configurationService.getIntegrationBridgeName()) != null;
68     }
69
70     @Override
71     public boolean isNodeOverlayReady(Node node) {
72         Preconditions.checkNotNull(configurationService);
73         return isNodeNeutronReady(node)
74                 && southbound.getBridge(node, configurationService.getNetworkBridgeName()) != null;
75     }
76
77     @Override
78     public boolean isPortOnBridge (Node node, String portName) {
79         return southbound.extractTerminationPointAugmentation(node, portName) != null;
80     }
81
82     @Override
83     public boolean isNodeTunnelReady(Node node) {
84         Preconditions.checkNotNull(configurationService);
85         return southbound.getBridge(node, configurationService.getIntegrationBridgeName()) != null;
86     }
87
88     @Override
89     public boolean isNodeVlanReady(Node node, NeutronNetwork network) {
90         Preconditions.checkNotNull(configurationService);
91
92         /* is br-int created */
93         OvsdbBridgeAugmentation intBridge = southbound.getBridge(node, configurationService.getIntegrationBridgeName());
94         if (intBridge == null) {
95             LOGGER.trace("isNodeVlanReady: node: {}, br-int missing", node);
96             return false;
97         }
98
99         /* Check if physical device is added to br-int. */
100         String phyNetName = getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
101         if (southbound.extractTerminationPointAugmentation(node, phyNetName) == null) {
102             LOGGER.trace("isNodeVlanReady: node: {}, eth missing", node);
103             return false;
104         }
105
106         return true;
107     }
108
109     @Override
110     public void prepareNode(Node node) {
111         //Preconditions.checkNotNull(networkingProviderManager);
112
113         try {
114             createIntegrationBridge(node);
115         } catch (Exception e) {
116             LOGGER.error("Error creating Integration Bridge on {}", node, e);
117             return;
118         }
119         // this node is an ovsdb node so it doesn't have a bridge
120         // so either look up the bridges or just wait for the bridge update to come in
121         // and add the flows there.
122         //networkingProviderManager.getProvider(node).initializeFlowRules(node);
123     }
124
125     /**
126      * Check if the full network setup is available. If not, create it.
127      */
128     @Override
129     public boolean createLocalNetwork (Node node, NeutronNetwork network) {
130         boolean isCreated = false;
131         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
132             if (!isNodeVlanReady(node, network)) {
133                 try {
134                     isCreated = createBridges(node, network);
135                 } catch (Exception e) {
136                     LOGGER.error("Error creating internal net network " + node, e);
137                 }
138             } else {
139                 isCreated = true;
140             }
141         } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
142                    network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
143             if (!isNodeTunnelReady(node)) {
144                 try {
145                     isCreated = createBridges(node, network);
146                 } catch (Exception e) {
147                     LOGGER.error("Error creating internal net network " + node, e);
148                 }
149             } else {
150                 isCreated = true;
151             }
152         }
153         return isCreated;
154     }
155
156     @Override
157     public String getPhysicalInterfaceName (Node node, String physicalNetwork) {
158         String phyIf = null;
159         String providerMaps = southbound.getOtherConfig(node, OvsdbTables.OPENVSWITCH,
160                 configurationService.getProviderMappingsKey());
161         if (providerMaps == null) {
162             providerMaps = configurationService.getDefaultProviderMapping();
163         }
164
165         if (providerMaps != null) {
166             for (String map : providerMaps.split(",")) {
167                 String[] pair = map.split(":");
168                 if (pair[0].equals(physicalNetwork)) {
169                     phyIf = pair[1];
170                     break;
171                 }
172             }
173         }
174
175         if (phyIf == null) {
176             LOGGER.error("Physical interface not found for Node: {}, Network {}",
177                          node, physicalNetwork);
178         }
179
180         return phyIf;
181     }
182
183     @Override
184     public List<String> getAllPhysicalInterfaceNames(Node node) {
185         List<String> phyIfName = Lists.newArrayList();
186         String phyIf = null;
187         String providerMaps = southbound.getOtherConfig(node, OvsdbTables.OPENVSWITCH,
188                 configurationService.getProviderMappingsKey());
189         if (providerMaps == null) {
190             providerMaps = configurationService.getDefaultProviderMapping();
191         }
192
193         if (providerMaps != null) {
194             for (String map : providerMaps.split(",")) {
195                 String[] pair = map.split(":");
196                 phyIfName.add(pair[1]);
197             }
198         }
199
200         return phyIfName;
201     }
202
203     /**
204      * Returns true if a patch port exists between the Integration Bridge and Network Bridge
205      */
206     private boolean isNetworkPatchCreated(Node node, Node intBridge, Node netBridge) {
207         Preconditions.checkNotNull(configurationService);
208
209         boolean isPatchCreated = false;
210
211         String portName = configurationService.getPatchPortName(new ImmutablePair<>(intBridge, netBridge));
212         if (isPortOnBridge(intBridge, portName)) {
213             portName = configurationService.getPatchPortName(new ImmutablePair<>(netBridge, intBridge));
214             if (isPortOnBridge(netBridge, portName)) {
215                 isPatchCreated = true;
216             }
217         }
218
219         return isPatchCreated;
220     }
221
222     /**
223      * Creates the Integration Bridge
224      */
225     private void createIntegrationBridge(Node node) throws Exception {
226         Preconditions.checkNotNull(configurationService);
227
228         String brIntName = configurationService.getIntegrationBridgeName();
229
230         if (!addBridge(node, brIntName, null, null)) {
231             LOGGER.debug("Integration Bridge Creation failed");
232         }
233     }
234
235     /**
236      * Create and configure bridges for all network types and OpenFlow versions.
237      *
238        OF 1.0 vlan:
239        Bridge br-int
240             Port patch-net
241                 Interface patch-net
242                     type: patch
243                     options: {peer=patch-int}
244             Port br-int
245                 Interface br-int
246                     type: internal
247        Bridge br-net
248             Port "eth1"
249                 Interface "eth1"
250             Port patch-int
251                 Interface patch-int
252                     type: patch
253                     options: {peer=patch-net}
254             Port br-net
255                 Interface br-net
256                     type: internal
257
258        OF 1.0 tunnel:
259        Bridge br-int
260             Port patch-net
261                 Interface patch-net
262                     type: patch
263                     options: {peer=patch-int}
264             Port br-int
265                 Interface br-int
266                     type: internal
267        Bridge "br-net"
268             Port patch-int
269                 Interface patch-int
270                     type: patch
271                     options: {peer=patch-net}
272             Port br-net
273                 Interface br-net
274                     type: internal
275
276        OF 1.3 vlan:
277        Bridge br-int
278             Port "eth1"
279                 Interface "eth1"
280             Port br-int
281                 Interface br-int
282                     type: internal
283
284        OF 1.3 tunnel:
285        Bridge br-int
286             Port br-int
287                 Interface br-int
288                     type: internal
289      */
290     private boolean createBridges(Node node, NeutronNetwork network) throws Exception {
291         Preconditions.checkNotNull(configurationService);
292         Preconditions.checkNotNull(networkingProviderManager);
293
294         LOGGER.debug("createBridges: node: {}, network type: {}", node, network.getProviderNetworkType());
295
296         String brInt = configurationService.getIntegrationBridgeName();
297         if (!addBridge(node, brInt, null, null)) {
298             LOGGER.debug("{} Bridge creation failed", brInt);
299             return false;
300         }
301
302         /* For vlan network types add physical port to br-int. */
303         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
304             String phyNetName = this.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
305             if (!addPortToBridge(node, brInt, phyNetName)) {
306                 LOGGER.debug("Add Port {} to Bridge {} failed", phyNetName, brInt);
307                 return false;
308             }
309         }
310
311         LOGGER.debug("createBridges: node: {}, status: success", node);
312         return true;
313     }
314
315     /**
316      * Add a Port to a Bridge
317      */
318     private boolean addPortToBridge (Node node, String bridgeName, String portName) throws Exception {
319         boolean rv = true;
320
321         if (southbound.extractTerminationPointAugmentation(node, portName) == null) {
322             rv = southbound.addTerminationPoint(node, bridgeName, portName, null);
323         }
324
325         return rv;
326     }
327
328     /**
329      * Add a Patch Port to a Bridge
330      */
331     private boolean addPatchPort (Node node, String bridgeName, String portName, String peerPortName) throws Exception {
332         boolean rv = true;
333
334         if (southbound.extractTerminationPointAugmentation(node, portName) == null) {
335             rv = southbound.addPatchTerminationPoint(node, bridgeName, portName, peerPortName);
336         }
337
338         return rv;
339     }
340
341     /**
342      * Add Bridge to a Node
343      */
344     private boolean addBridge(Node node, String bridgeName,
345                               String localPatchName, String remotePatchName) throws Exception {
346         boolean rv = true;
347         if (southbound.getBridge(node, bridgeName) == null) {
348             rv = southbound.addBridge(node, bridgeName, getControllerTarget(node));
349         }
350         return rv;
351     }
352
353     private InetAddress getControllerIPAddress() {
354         InetAddress controllerIP = null;
355
356         String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
357         if (addressString != null) {
358             try {
359                 controllerIP = InetAddress.getByName(addressString);
360                 if (controllerIP != null) {
361                     return controllerIP;
362                 }
363             } catch (UnknownHostException e) {
364                 LOGGER.error("Host {} is invalid", addressString);
365             }
366         }
367
368         addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
369         if (addressString != null) {
370             try {
371                 controllerIP = InetAddress.getByName(addressString);
372                 if (controllerIP != null) {
373                     return controllerIP;
374                 }
375             } catch (UnknownHostException e) {
376                 LOGGER.error("Host {} is invalid", addressString);
377             }
378         }
379
380         /*
381         try {
382             controllerIP = connection.getClient().getConnectionInfo().getLocalAddress();
383             return controllerIP;
384         } catch (Exception e) {
385             LOGGER.debug("Invalid connection provided to getControllerIPAddresses", e);
386         }
387         */
388
389         if (addressString != null) {
390             try {
391                 controllerIP = InetAddress.getByName(addressString);
392                 if (controllerIP != null) {
393                     return controllerIP;
394                 }
395             } catch (UnknownHostException e) {
396                 LOGGER.error("Host {} is invalid", addressString);
397             }
398         }
399
400         return controllerIP;
401     }
402
403     private short getControllerOFPort() {
404         Short defaultOpenFlowPort = 6633;
405         Short openFlowPort = defaultOpenFlowPort;
406         String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
407         if (portString != null) {
408             try {
409                 openFlowPort = Short.decode(portString).shortValue();
410             } catch (NumberFormatException e) {
411                 LOGGER.warn("Invalid port:{}, use default({})", portString,
412                         openFlowPort);
413             }
414         }
415         return openFlowPort;
416     }
417
418     private String getControllerTarget(Node node) {
419         String target = null;
420         OvsdbNodeAugmentation ovsdbNodeAugmentation = southbound.extractOvsdbNode(node);
421         if (ovsdbNodeAugmentation != null) {
422             ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
423             String addressStr = new String(connectionInfo.getLocalIp().getValue());
424             target = "tcp:" + addressStr + ":6633";
425         } else{
426             target = getControllerTarget();
427         }
428         return target;
429     }
430
431     private String getControllerTarget() {
432         /* TODO SB_MIGRATION
433          * hardcoding value, need to find better way to get local ip
434          */
435         //String target = "tcp:" + getControllerIPAddress() + ":" + getControllerOFPort();
436         //TODO: dirty fix, need to remove it once we have proper solution
437         String ipaddress = null;
438         try{
439             for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces();ifaces.hasMoreElements();){
440                 NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
441
442                 for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
443                     InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
444                     if (!inetAddr.isLoopbackAddress()) {
445                         if (inetAddr.isSiteLocalAddress()) {
446                             ipaddress = inetAddr.getHostAddress();
447                             break;
448                         }
449                     }
450                 }
451             }
452         }catch (Exception e){
453             LOGGER.warn("ROYALLY SCREWED : Exception while fetching local host ip address ",e);
454         }
455         return "tcp:"+ipaddress+":6633";
456     }
457
458     @Override
459     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
460         configurationService =
461                 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
462         networkingProviderManager =
463                 (NetworkingProviderManager) ServiceHelper.getGlobalInstance(NetworkingProviderManager.class, this);
464         southbound =
465                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
466     }
467
468     @Override
469     public void setDependencies(Object impl) {}
470 }