2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.groupbasedpolicy.neutron.ovsdb.util;
10 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.DataStore.getLongFromDpid;
11 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.DataStore.readFromDs;
12 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.DataStore.submitToDs;
13 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getOvsdbBridgeFromTerminationPoint;
14 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getOvsdbTerminationPoint;
16 import java.util.ArrayList;
17 import java.util.List;
19 import org.apache.commons.lang3.StringUtils;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.groupbasedpolicy.neutron.ovsdb.AbstractTunnelType;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfig;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.ExternalInterfaces;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.ExternalInterfacesBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.ExternalInterfacesKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.Tunnel;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.TunnelBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 import com.google.common.base.Optional;
47 public class InventoryHelper {
48 private static final Logger LOG = LoggerFactory.getLogger(InventoryHelper.class);
50 private static final Long MAX_OF_PORT=65534L;
52 * Construct a String that can be used to create a
54 * The String is constructed by getting the Datapath ID from the OVSDB bridge
55 * augmentation, converting that to a Long, and prepending it with the
58 * @param ovsdbBridge The OVSDB bridge augmentation
59 * @return String representation of the Inventory NodeId, null if it fails
61 public static String getInventoryNodeIdString(OvsdbBridgeAugmentation ovsdbBridge,
62 InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid, DataBroker dataBroker) {
63 DatapathId dpid = ovsdbBridge.getDatapathId();
65 OvsdbBridgeAugmentation bridgeData = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker);
66 dpid = bridgeData.getDatapathId();
68 LOG.error("No Data Path ID for OVSDB Bridge {}", ovsdbBridge);
72 Long macLong = getLongFromDpid(ovsdbBridge.getDatapathId().getValue());
73 String nodeIdString = "openflow:" + String.valueOf(macLong);
74 if(StringUtils.countMatches(nodeIdString, ":") != 1) {
75 LOG.error("{} is not correct format for NodeId.",nodeIdString);
82 * Construct a string that can be used to create a
83 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId}.
84 * The String is constructed by first getting the inventory Node ID string, and then
85 * adding the port number obtained by the OVSDB augmentation.
87 * @param inventoryNodeId The string representation of the Inventory NodeId
88 * @param ovsdbTp The {@link OvsdbTerminationPointAugmentation}
89 * @return String representation of the Inventory NodeConnectorId, null if it fails
91 public static String getInventoryNodeConnectorIdString(String inventoryNodeId,
92 OvsdbTerminationPointAugmentation ovsdbTp,
93 InstanceIdentifier<OvsdbTerminationPointAugmentation> tpIid,
94 DataBroker dataBroker) {
96 if (ovsdbTp.getOfport() != null && ovsdbTp.getOfport()>MAX_OF_PORT) {
97 LOG.debug("Invalid OpenFlow port {} for {}",ovsdbTp.getOfport(), ovsdbTp);
100 if (ovsdbTp.getOfport() == null) {
101 OvsdbTerminationPointAugmentation readOvsdbTp =
102 getOvsdbTerminationPoint(tpIid, dataBroker);
103 if (readOvsdbTp == null
104 || readOvsdbTp.getOfport() == null
105 || readOvsdbTp.getOfport() >MAX_OF_PORT) {
106 LOG.debug("Couldn't get OpenFlow port for {}",ovsdbTp);
109 ofport = readOvsdbTp.getOfport();
111 ofport = ovsdbTp.getOfport();
113 String nodeConnectorIdString = inventoryNodeId + ":" + String.valueOf(ofport);
115 if(StringUtils.countMatches(nodeConnectorIdString, ":") != 2) {
116 LOG.error("{} is not correct format for NodeConnectorId.",nodeConnectorIdString);
119 return nodeConnectorIdString;
123 * Read the {@link OfOverlayNodeConfig} augmentation from the
124 * Inventory Node, and verify that the tunnel types we need
127 * @return true if tunnel types are present, false otherwise
129 public static boolean checkOfOverlayConfig(String nodeIdString,
130 List<AbstractTunnelType> requiredTunnelTypes, DataBroker dataBroker) {
131 OfOverlayNodeConfig config = getOfOverlayConfig(nodeIdString, dataBroker);
132 if (config == null || config.getTunnel() == null) {
133 LOG.debug("No OfOverlay config for {}",nodeIdString);
138 * See if the OfOverlayNodeConfig has the
139 * tunnel type information.
141 for (AbstractTunnelType tunnelType: requiredTunnelTypes) {
142 boolean tunnelPresent = false;
143 for (Tunnel tunnel: config.getTunnel()) {
144 if (tunnelType.getTunnelType().equals(tunnel.getTunnelType())) {
145 tunnelPresent = true;
149 if (tunnelPresent == false) {
156 public static void addOfOverlayExternalPort(String nodeIdString, NodeConnectorId ncId, DataBroker dataBroker) {
157 InstanceIdentifier<ExternalInterfaces> nodeExternalInterfacesIid = InstanceIdentifier.builder(
159 .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
160 .augmentation(OfOverlayNodeConfig.class)
161 .child(ExternalInterfaces.class,new ExternalInterfacesKey(ncId))
164 ExternalInterfaces externalInterfaces = new ExternalInterfacesBuilder()
165 .setKey(new ExternalInterfacesKey(ncId))
166 .setNodeConnectorId(ncId)
168 WriteTransaction transaction = dataBroker.newReadWriteTransaction();
169 transaction.put(LogicalDatastoreType.CONFIGURATION, nodeExternalInterfacesIid, externalInterfaces, true);
170 submitToDs(transaction);
171 LOG.trace("Added external interface node connector {} to node {}", ncId.getValue(),nodeIdString);
174 public static OfOverlayNodeConfig getOfOverlayConfig(String nodeIdString, DataBroker dataBroker) {
175 InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(
177 .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
178 .augmentation(OfOverlayNodeConfig.class)
181 ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
182 Optional<OfOverlayNodeConfig> overlayConfig = readFromDs(LogicalDatastoreType.OPERATIONAL, ofOverlayNodeIid, transaction );
183 if (overlayConfig.isPresent()) {
184 return overlayConfig.get();
189 private static void addOfOverlayAugmentation(OfOverlayNodeConfig config, String nodeIdString, DataBroker dataBroker) {
190 InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(
192 .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
193 .augmentation(OfOverlayNodeConfig.class)
196 WriteTransaction transaction = dataBroker.newReadWriteTransaction();
197 transaction.put(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, config, true);
198 submitToDs(transaction);
202 * Update the {@link OfOverlayConfig} of an Inventory Node
203 * using the new tunnel state.
205 * @param nodeIdString
209 public static void updateOfOverlayConfig(IpAddress ip, String nodeIdString,
210 String nodeConnectorIdString, List<AbstractTunnelType> tunnels, DataBroker dataBroker) {
212 if ((ip == null) || (nodeIdString == null)
213 || (nodeConnectorIdString == null)) {
214 LOG.debug("Can't update OfOverlay: requisite information not present");
217 NodeConnectorId nodeConnectorId = new NodeConnectorId(nodeConnectorIdString);
218 List<Tunnel> tunnelList = new ArrayList<Tunnel>();
219 List<Tunnel> existingTunnels = new ArrayList<Tunnel>();
220 OfOverlayNodeConfig ofConfig = getOfOverlayConfig(nodeIdString, dataBroker);
221 if (ofConfig != null) {
222 existingTunnels = ofConfig.getTunnel();
224 boolean tunnelsUpdated = false;
225 for (AbstractTunnelType tunnelType: tunnels) {
226 boolean tunnelFound = false;
227 for (Tunnel currentTun: existingTunnels) {
228 if (tunnelType.getTunnelType().equals(currentTun.getTunnelType())) {
230 TunnelBuilder tunnelBuilder = new TunnelBuilder(currentTun);
231 tunnelBuilder.setIp(ip);
232 tunnelBuilder.setPort(tunnelType.getPortNumber());
233 tunnelBuilder.setNodeConnectorId(nodeConnectorId);
234 tunnelList.add(tunnelBuilder.build());
236 tunnelsUpdated = true;
240 if (tunnelFound == false) {
241 TunnelBuilder tunnelBuilder = new TunnelBuilder();
242 tunnelBuilder.setIp(ip);
243 tunnelBuilder.setPort(tunnelType.getPortNumber());
244 tunnelBuilder.setNodeConnectorId(nodeConnectorId);
245 tunnelBuilder.setTunnelType(tunnelType.getTunnelType());
246 tunnelList.add(tunnelBuilder.build());
247 tunnelsUpdated = true;
250 if (tunnelsUpdated == true) {
251 OfOverlayNodeConfigBuilder ofOverlayBuilder = null;
252 if (ofConfig == null) {
253 ofOverlayBuilder = new OfOverlayNodeConfigBuilder();
255 ofOverlayBuilder = new OfOverlayNodeConfigBuilder(ofConfig);
257 ofOverlayBuilder.setTunnel(tunnelList);
258 addOfOverlayAugmentation(ofOverlayBuilder.build(), nodeIdString, dataBroker);