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.getOvsdbBridge;
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.Tunnel;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.TunnelBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 import com.google.common.base.Optional;
44 public class InventoryHelper {
45 private static final Logger LOG = LoggerFactory.getLogger(InventoryHelper.class);
47 private static final Long MAX_OF_PORT=65534L;
49 * Construct a String that can be used to create a
51 * The String is constructed by getting the Datapath ID from the OVSDB bridge
52 * augmentation, converting that to a Long, and prepending it with the
55 * @param ovsdbBridge The OVSDB bridge augmentation
56 * @return String representation of the Inventory NodeId, null if it fails
58 public static String getInventoryNodeIdString(OvsdbBridgeAugmentation ovsdbBridge,
59 InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid, DataBroker dataBroker) {
60 DatapathId dpid = ovsdbBridge.getDatapathId();
62 OvsdbBridgeAugmentation bridgeData = getOvsdbBridge(ovsdbTpIid, dataBroker);
63 dpid = bridgeData.getDatapathId();
65 LOG.error("No Data Path ID for OVSDB Bridge {}", ovsdbBridge);
69 Long macLong = getLongFromDpid(ovsdbBridge.getDatapathId().getValue());
70 String nodeIdString = "openflow:" + String.valueOf(macLong);
71 if(StringUtils.countMatches(nodeIdString, ":") != 1) {
72 LOG.error("{} is not correct format for NodeId.",nodeIdString);
79 * Construct a string that can be used to create a
80 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId}.
81 * The String is constructed by first getting the inventory Node ID string, and then
82 * adding the port number obtained by the OVSDB augmentation.
84 * @param inventoryNodeId The string representation of the Inventory NodeId
85 * @param ovsdbTp The {@link OvsdbTerminationPointAugmentation}
86 * @return String representation of the Inventory NodeConnectorId, null if it fails
88 public static String getInventoryNodeConnectorIdString(String inventoryNodeId,
89 OvsdbTerminationPointAugmentation ovsdbTp,
90 InstanceIdentifier<OvsdbTerminationPointAugmentation> tpIid,
91 DataBroker dataBroker) {
93 if (ovsdbTp.getOfport() != null && ovsdbTp.getOfport()>MAX_OF_PORT) {
94 LOG.debug("Invalid OpenFlow port {} for {}",ovsdbTp.getOfport(), ovsdbTp);
97 if (ovsdbTp.getOfport() == null) {
98 OvsdbTerminationPointAugmentation readOvsdbTp =
99 getOvsdbTerminationPoint(tpIid, dataBroker);
100 if (readOvsdbTp == null
101 || readOvsdbTp.getOfport() == null
102 || readOvsdbTp.getOfport() >MAX_OF_PORT) {
103 LOG.debug("Couldn't get OpenFlow port for {}",ovsdbTp);
106 ofport = readOvsdbTp.getOfport();
108 ofport = ovsdbTp.getOfport();
110 String nodeConnectorIdString = inventoryNodeId + ":" + String.valueOf(ofport);
112 if(StringUtils.countMatches(nodeConnectorIdString, ":") != 2) {
113 LOG.error("{} is not correct format for NodeConnectorId.",nodeConnectorIdString);
116 return nodeConnectorIdString;
120 * Read the {@link OfOverlayNodeConfig} augmentation from the
121 * Inventory Node, and verify that the tunnel types we need
124 * @return true if tunnel types are present, false otherwise
126 public static boolean checkOfOverlayConfig(String nodeIdString,
127 List<AbstractTunnelType> requiredTunnelTypes, DataBroker dataBroker) {
128 OfOverlayNodeConfig config = getOfOverlayConfig(nodeIdString, dataBroker);
129 if (config == null || config.getTunnel() == null) {
130 LOG.debug("No OfOverlay config for {}",nodeIdString);
135 * See if the OfOverlayNodeConfig has the
136 * tunnel type information.
138 for (AbstractTunnelType tunnelType: requiredTunnelTypes) {
139 boolean tunnelPresent = false;
140 for (Tunnel tunnel: config.getTunnel()) {
141 if (tunnelType.getTunnelType().equals(tunnel.getTunnelType())) {
142 tunnelPresent = true;
146 if (tunnelPresent == false) {
153 public static OfOverlayNodeConfig getOfOverlayConfig(String nodeIdString, DataBroker dataBroker) {
154 InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(
156 .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
157 .augmentation(OfOverlayNodeConfig.class)
160 ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
161 Optional<OfOverlayNodeConfig> overlayConfig = readFromDs(LogicalDatastoreType.OPERATIONAL, ofOverlayNodeIid, transaction );
162 if (overlayConfig.isPresent()) {
163 return overlayConfig.get();
168 private static void addOfOverlayAugmentation(OfOverlayNodeConfig config, String nodeIdString, DataBroker dataBroker) {
169 InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(
171 .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
172 .augmentation(OfOverlayNodeConfig.class)
175 WriteTransaction transaction = dataBroker.newReadWriteTransaction();
176 transaction.put(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, config, true);
177 submitToDs(transaction);
181 * Update the {@link OfOverlayConfig} of an Inventory Node
182 * using the new tunnel state.
184 * @param nodeIdString
188 public static void updateOfOverlayConfig(IpAddress ip, String nodeIdString,
189 String nodeConnectorIdString, List<AbstractTunnelType> tunnels, DataBroker dataBroker) {
191 if ((ip == null) || (nodeIdString == null)
192 || (nodeConnectorIdString == null)) {
193 LOG.debug("Can't update OfOverlay: requisite information not present");
196 NodeConnectorId nodeConnectorId = new NodeConnectorId(nodeConnectorIdString);
197 List<Tunnel> tunnelList = new ArrayList<Tunnel>();
198 List<Tunnel> existingTunnels = new ArrayList<Tunnel>();
199 OfOverlayNodeConfig ofConfig = getOfOverlayConfig(nodeIdString, dataBroker);
200 if (ofConfig != null) {
201 existingTunnels = ofConfig.getTunnel();
203 boolean tunnelsUpdated = false;
204 for (AbstractTunnelType tunnelType: tunnels) {
205 boolean tunnelFound = false;
206 for (Tunnel currentTun: existingTunnels) {
207 if (tunnelType.getTunnelType().equals(currentTun.getTunnelType())) {
209 TunnelBuilder tunnelBuilder = new TunnelBuilder(currentTun);
210 tunnelBuilder.setIp(ip);
211 tunnelBuilder.setPort(tunnelType.getPortNumber());
212 tunnelBuilder.setNodeConnectorId(nodeConnectorId);
213 tunnelList.add(tunnelBuilder.build());
215 tunnelsUpdated = true;
219 if (tunnelFound == false) {
220 TunnelBuilder tunnelBuilder = new TunnelBuilder();
221 tunnelBuilder.setIp(ip);
222 tunnelBuilder.setPort(tunnelType.getPortNumber());
223 tunnelBuilder.setNodeConnectorId(nodeConnectorId);
224 tunnelBuilder.setTunnelType(tunnelType.getTunnelType());
225 tunnelList.add(tunnelBuilder.build());
226 tunnelsUpdated = true;
229 if (tunnelsUpdated == true) {
230 OfOverlayNodeConfigBuilder ofOverlayBuilder = null;
231 if (ofConfig == null) {
232 ofOverlayBuilder = new OfOverlayNodeConfigBuilder();
234 ofOverlayBuilder = new OfOverlayNodeConfigBuilder(ofConfig);
236 ofOverlayBuilder.setTunnel(tunnelList);
237 addOfOverlayAugmentation(ofOverlayBuilder.build(), nodeIdString, dataBroker);