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