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