Merge "GBP UI fixes"
[groupbasedpolicy.git] / neutron-ovsdb / src / main / java / org / opendaylight / groupbasedpolicy / neutron / ovsdb / util / OvsdbHelper.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.neutron.ovsdb.util;
10
11 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.DataStore.readFromDs;
12 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.DataStore.submitToDs;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.groupbasedpolicy.neutron.ovsdb.AbstractTunnelType;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import com.google.common.base.Optional;
46
47 public class OvsdbHelper {
48     private static final Logger LOG = LoggerFactory.getLogger(DataStore.class);
49     private static final String OF_PORT = "6653";
50
51     /**
52      * Look up the {@link OvsdbBridgeAugmentation} from the data store
53      * given a child {@link InstanceIdentifier<OvsdbTerminationPointAugmentation>}
54      *
55      * @param tpId The InstanceIdentifier for a child TerminationPoint augmentation
56      * @return the {@link OvsdbBridgeAugmentation}, null if the augmentation isn't present
57      */
58     public static OvsdbBridgeAugmentation getOvsdbBridgeFromTerminationPoint(
59             InstanceIdentifier<OvsdbTerminationPointAugmentation> tpIid, DataBroker dataBroker) {
60         InstanceIdentifier<OvsdbBridgeAugmentation> ovsdbBridgeIid =
61                 tpIid.firstIdentifierOf(Node.class).augmentation(OvsdbBridgeAugmentation.class);
62         if (ovsdbBridgeIid == null) {
63             return null;
64         }
65         ReadTransaction transaction = dataBroker.newReadOnlyTransaction();
66         Optional<OvsdbBridgeAugmentation> ovsdbBridge =
67                 readFromDs(LogicalDatastoreType.OPERATIONAL, ovsdbBridgeIid, transaction );
68         if (ovsdbBridge.isPresent()) {
69             return ovsdbBridge.get();
70         }
71         return null;
72     }
73
74     public static Node getNodeFromBridgeRef(OvsdbBridgeRef bridgeRef, DataBroker dataBroker) {
75         InstanceIdentifier<Node> nodeIid = bridgeRef.getValue().firstIdentifierOf(Node.class);
76         ReadTransaction transaction = dataBroker.newReadOnlyTransaction();
77         Optional<?> node =
78                 readFromDs(LogicalDatastoreType.OPERATIONAL, nodeIid, transaction );
79         if (node.isPresent()) {
80             if (node.get() instanceof Node) {
81                 return (Node)node.get();
82             }
83         }
84         return null;
85     }
86
87     public static OvsdbTerminationPointAugmentation getOvsdbTerminationPoint(
88             InstanceIdentifier<OvsdbTerminationPointAugmentation> tpIid, DataBroker dataBroker) {
89         ReadTransaction transaction = dataBroker.newReadOnlyTransaction();
90         Optional<OvsdbTerminationPointAugmentation> ovsdbTp =
91                 readFromDs(LogicalDatastoreType.OPERATIONAL, tpIid, transaction );
92         if (ovsdbTp.isPresent()) {
93             return ovsdbTp.get();
94         }
95         return null;
96     }
97
98     public static Node getNode(Node node, List<TerminationPoint> tps,
99             OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
100         NodeBuilder nodeBuilder = new NodeBuilder();
101         nodeBuilder.setKey(node.getKey());
102
103         nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
104                 ovsdbBridgeAugmentation);
105
106         nodeBuilder.setTerminationPoint(tps);
107         return nodeBuilder.build();
108     }
109
110     public static OvsdbBridgeAugmentation buildOvsdbBridgeAugmentation(OvsdbBridgeAugmentation bridge,
111             OvsdbNodeAugmentation ovsdbNode) {
112         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentation = new OvsdbBridgeAugmentationBuilder();
113         IpAddress managerIp = getManagerIp(ovsdbNode);
114         if (managerIp != null) {
115             List<ControllerEntry> controllerEntries = buildControllerEntries(managerIp);
116             ovsdbBridgeAugmentation.setControllerEntry(controllerEntries);
117         }
118         ovsdbBridgeAugmentation.setBridgeName(bridge.getBridgeName());
119         ovsdbBridgeAugmentation.setManagedBy(bridge.getManagedBy());
120         return ovsdbBridgeAugmentation.build();
121     }
122
123     public static List<TerminationPoint> buildTerminationPoints(OvsdbBridgeAugmentation bridge,
124             OvsdbTerminationPointAugmentation ovsdbTp, AbstractTunnelType tunnelType) {
125         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
126         tpBuilder.setTpId(new TpId(new Uri(generateTpName(bridge, tunnelType))));
127         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, ovsdbTp);
128
129         List<TerminationPoint> tps = new ArrayList<TerminationPoint>();
130         tps.add(tpBuilder.build());
131         return tps;
132     }
133
134     public static String generateTpName(OvsdbBridgeAugmentation bridge, AbstractTunnelType tunnelType) {
135         return tunnelType.getTunnelPrefix() + bridge.getBridgeName().getValue();
136     }
137
138     public static OvsdbTerminationPointAugmentation buildOvsdbTerminationPointAugmentation(OvsdbBridgeAugmentation bridge,
139             List<Options> options, AbstractTunnelType tunnelType) {
140         OvsdbTerminationPointAugmentationBuilder ovsdbTpBuilder = new OvsdbTerminationPointAugmentationBuilder();
141         ovsdbTpBuilder.setName(generateTpName(bridge, tunnelType));
142         ovsdbTpBuilder.setOptions(options);
143         ovsdbTpBuilder.setInterfaceType(InterfaceTypeVxlan.class);
144         return ovsdbTpBuilder.build();
145     }
146
147     public static void setOption(List<Options> options, String key, String value) {
148         OptionsBuilder option = new OptionsBuilder();
149         option.setOption(key);
150         option.setValue(value);
151         options.add(option.build());
152     }
153
154     public static IpAddress getManagerIp(OvsdbNodeAugmentation ovsdbNode) {
155         if (ovsdbNode.getConnectionInfo() != null) {
156             return ovsdbNode.getConnectionInfo().getLocalIp();
157         }
158         return null;
159     }
160
161     public static IpAddress getNodeIp(OvsdbNodeAugmentation ovsdbNode) {
162         if (ovsdbNode.getConnectionInfo() != null) {
163             return ovsdbNode.getConnectionInfo().getRemoteIp();
164         }
165         return null;
166     }
167
168     public static List<ControllerEntry> buildControllerEntries(IpAddress ip) {
169         List<ControllerEntry> result = new ArrayList<ControllerEntry>();
170
171         if (ip != null) {
172             ControllerEntryBuilder controllerBuilder = new ControllerEntryBuilder();
173             String localIp = String.valueOf(ip.getValue());
174             String targetString = "tcp:" + localIp + ":" + OF_PORT;
175             controllerBuilder.setTarget(new Uri(targetString));
176             result.add(controllerBuilder.build());
177         }
178
179         return result;
180     }
181
182     /**
183      * Get the manager node for this bridge node
184      *
185      * @param bridge
186      * @param dataBroker
187      * @return The {@link OvsdbBridgAugmentation} for the manager node, null
188      *         if not found or if it already is the manager node
189      */
190     public static OvsdbNodeAugmentation getManagerNode(OvsdbBridgeAugmentation bridge, DataBroker dataBroker) {
191         OvsdbNodeRef bareIId = bridge.getManagedBy();
192         if(bareIId != null) {
193             if(bareIId.getValue().getTargetType().equals(Node.class)) {
194                 ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
195                 InstanceIdentifier<Node> iid = (InstanceIdentifier<Node>) bareIId.getValue();
196                 Optional<Node> nodeOptional = readFromDs(LogicalDatastoreType.OPERATIONAL, iid, transaction);
197                 if(nodeOptional.isPresent()
198                         && nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class) != null) {
199                     return nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class);
200                 } else {
201                     LOG.warn("Could not find ovsdb-node for connection for {}",bridge);
202                 }
203             } else {
204                 LOG.warn("Bridge 'managedBy' non-ovsdb-node.  bridge {} getManagedBy() {}",bridge,bareIId.getValue());
205             }
206         } else {
207             LOG.debug("Bridge 'managedBy' is null.  bridge {}",bridge);
208         }
209         return null;
210     }
211
212     public static Node getTopologyNode(InstanceIdentifier<Node> nodeIid, DataBroker dataBroker) {
213         ReadTransaction transaction = dataBroker.newReadOnlyTransaction();
214         Optional<Node> nodeOptional =
215                 readFromDs(LogicalDatastoreType.OPERATIONAL, nodeIid, transaction );
216         if (nodeOptional.isPresent()) {
217             return nodeOptional.get();
218         }
219         return null;
220     }
221
222     /**
223      * Use OVSDB CRUD to create any missing tunnels on a given
224      * Inventory Node.
225      *
226      * @param nodeIid
227      * @param node
228      * @param tunnelType
229      */
230     public static void createTunnelPort(InstanceIdentifier<Node> nodeIid,
231             Node node, AbstractTunnelType tunnelType, DataBroker dataBroker) {
232         ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
233         OvsdbBridgeAugmentation bridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
234         if (bridge == null) {
235             LOG.warn("No OvsdbBridgeAugmentationfor Node {}", node);
236             return;
237         }
238
239         OvsdbNodeAugmentation managerNode = getManagerNode(bridge, dataBroker);
240         if(managerNode == null) {
241             LOG.warn("Couldn't create tunnel port for Node {}, no manager", node);
242             return;
243         }
244         List<Options> options = tunnelType.getOptions();
245         OvsdbTerminationPointAugmentation ovsdbTp =
246                 buildOvsdbTerminationPointAugmentation(bridge,options, tunnelType);
247         List<TerminationPoint> tps = buildTerminationPoints(bridge,ovsdbTp, tunnelType);
248         OvsdbBridgeAugmentation ovsdbBridgeAugmentation =
249                 buildOvsdbBridgeAugmentation(bridge,managerNode);
250         Node configNode = getNode(node, tps,ovsdbBridgeAugmentation);
251         LOG.info("About to write nodeId {} node {}",nodeIid,configNode);
252         transaction.put(LogicalDatastoreType.CONFIGURATION, nodeIid, configNode);
253         submitToDs(transaction);
254     }
255
256
257 }