2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. 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.genius.itm.confighelpers;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.Objects;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.genius.infra.Datastore;
18 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
19 import org.opendaylight.genius.infra.TypedWriteTransaction;
20 import org.opendaylight.genius.itm.globals.ITMConstants;
21 import org.opendaylight.genius.itm.impl.ItmUtils;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.NotHostedTransportZones;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZone;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZoneBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZoneKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVteps;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVtepsBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVtepsKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.VtepsBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.VtepsKey;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 public final class OvsdbTepAddConfigHelper {
45 private static final Logger LOG = LoggerFactory.getLogger(OvsdbTepAddConfigHelper.class);
47 private OvsdbTepAddConfigHelper() { }
50 * Adds the TEP into ITM configuration/operational Datastore in one of the following cases.
51 * 1) default transport zone
52 * 2) Configured transport zone
53 * 3) Unhosted transport zone
55 * @param tepIp TEP-IP address in string
56 * @param strDpnId bridge datapath ID in string
57 * @param tzName transport zone name in string
58 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
59 * @param dataBroker data broker handle to perform operations on config/operational datastore
60 * @param txRunner ManagedTransactionRunner object
63 public static List<ListenableFuture<Void>> addTepReceivedFromOvsdb(String tepIp, String strDpnId, String tzName,
64 boolean ofTunnel, DataBroker dataBroker,
65 ManagedNewTransactionRunner txRunner) {
66 List<ListenableFuture<Void>> futures = new ArrayList<>();
67 BigInteger dpnId = BigInteger.valueOf(0);
69 if (strDpnId != null && !strDpnId.isEmpty()) {
70 dpnId = MDSALUtil.getDpnId(strDpnId);
74 IpAddress tepIpAddress = IpAddressBuilder.getDefaultInstance(tepIp);
75 TransportZone tzone = null;
77 // Case: TZ name is not given with OVS TEP.
79 tzName = ITMConstants.DEFAULT_TRANSPORT_ZONE;
80 // add TEP into default-TZ
81 tzone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
83 // Case: default-TZ is not yet created, then add TEP into "teps-in-not-hosted-transport-zone"
84 LOG.trace("Adding TEP with default TZ into teps-in-not-hosted-transport-zone.");
85 return addUnknownTzTepIntoTepsNotHostedAndReturnFutures(tzName, tepIpAddress, dpnId, ofTunnel,
86 dataBroker, txRunner);
88 LOG.trace("Add TEP into default-transport-zone.");
90 // Case: Add TEP into corresponding TZ created from Northbound.
91 tzone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
93 // Case: TZ is not configured from Northbound, then add TEP into "teps-in-not-hosted-transport-zone"
94 LOG.trace("Adding TEP with unknown TZ into teps-in-not-hosted-transport-zone.");
95 return addUnknownTzTepIntoTepsNotHostedAndReturnFutures(tzName, tepIpAddress, dpnId, ofTunnel,
96 dataBroker, txRunner);
98 LOG.trace("Add TEP into transport-zone already configured by Northbound.");
103 final BigInteger id = dpnId;
104 final String name = tzName;
105 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION,
106 tx -> addConfig(name, id, tepIpAddress, ofTunnel, tx)));
111 * Adds the TEP into Vtep list in the subnet list in the transport zone list
112 * from ITM configuration Datastore by merge operation with write transaction.
114 * @param updatedVtepList updated Vteps list object which will have new TEP for addition
115 * @param tepIpAddress TEP IP address in IpAddress object
116 * @param tzName transport zone name in string
117 * @param dpid bridge datapath ID in BigInteger
118 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
119 * @param tx TypedWriteTransaction object
121 public static void addVtepInITMConfigDS(List<Vteps> updatedVtepList, IpAddress tepIpAddress, String tzName,
122 BigInteger dpid, boolean ofTunnel,
123 TypedWriteTransaction<Datastore.Configuration> tx) {
124 //Create TZ node path
125 InstanceIdentifier<TransportZone> tranzportZonePath =
126 InstanceIdentifier.builder(TransportZones.class)
127 .child(TransportZone.class, new TransportZoneKey(tzName)).build();
129 // this check is needed to reuse same function from TransportZoneListener
130 // when VTEP is moved from TepsNotHosted list to TZ configured from Northbound.
131 if (dpid.compareTo(BigInteger.ZERO) > 0) {
133 VtepsKey vtepkey = new VtepsKey(dpid);
135 new VtepsBuilder().setDpnId(dpid).setIpAddress(tepIpAddress).withKey(vtepkey)
136 .setOptionOfTunnel(ofTunnel).build();
138 // Add vtep obtained from bridge into list
139 updatedVtepList.add(vtepObj);
141 LOG.trace("Adding TEP (TZ: {} TEP IP: {} DPID: {}, of-tunnel: {}) in ITM Config DS.", tzName,
142 tepIpAddress, dpid, ofTunnel);
144 // this is case when this function is called while TEPs movement from tepsNotHosted list when
145 // corresponding TZ is configured from northbound.
146 for (Vteps vtep: updatedVtepList) {
147 LOG.trace("Moving TEP (TEP IP: {} DPID: {}, of-tunnel: {})"
148 + "from not-hosted-transport-zone {} into ITM Config DS.",
149 vtep.getIpAddress(), vtep.getDpnId(), ofTunnel, tzName);
153 // create TZ node with updated subnet having new vtep
154 TransportZone updatedTzone =
155 new TransportZoneBuilder().withKey(new TransportZoneKey(tzName)).setVteps(updatedVtepList)
156 .setZoneName(tzName).build();
158 // Update TZ in Config DS to add vtep in TZ
159 tx.merge(tranzportZonePath, updatedTzone, true);
163 * Adds the TEP into Vtep list in the subnet list in the transport zone list
164 * from ITM operational Datastore by merge operation with write transaction.
166 * @param tzName transport zone name in string
167 * @param tepIpAddress TEP IP address in IpAddress object
168 * @param dpid bridge datapath ID in BigInteger
169 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
170 * @param dataBroker data broker handle to perform operations on operational datastore
171 * @param tx TypedWriteTransaction object
173 protected static void addUnknownTzTepIntoTepsNotHosted(String tzName, IpAddress tepIpAddress,
174 BigInteger dpid, boolean ofTunnel, DataBroker dataBroker,
175 TypedWriteTransaction<Datastore.Operational> tx) {
176 List<UnknownVteps> vtepList;
177 TepsInNotHostedTransportZone tepsInNotHostedTransportZone =
178 ItmUtils.getUnknownTransportZoneFromITMOperDS(tzName, dataBroker);
179 if (tepsInNotHostedTransportZone == null) {
180 LOG.trace("Unhosted TransportZone ({}) does not exist in OperDS.", tzName);
181 vtepList = new ArrayList<>();
182 addVtepIntoTepsNotHosted(addVtepToUnknownVtepsList(vtepList, tepIpAddress, dpid, ofTunnel), tzName, tx);
184 vtepList = tepsInNotHostedTransportZone.getUnknownVteps();
185 if (vtepList == null || vtepList.isEmpty()) {
186 // case: vtep list does not exist or it has no elements
187 if (vtepList == null) {
188 LOG.trace("Add TEP into unhosted TZ ({}) when no vtep-list in the TZ.", tzName);
189 vtepList = new ArrayList<>();
191 LOG.trace("Add TEP into unhosted TZ ({}) when no vtep-list in the TZ.", tzName);
192 addVtepIntoTepsNotHosted(addVtepToUnknownVtepsList(vtepList, tepIpAddress, dpid, ofTunnel), tzName, tx);
194 // case: vtep list has elements
195 boolean vtepFound = false;
196 UnknownVteps oldVtep = null;
198 for (UnknownVteps vtep : vtepList) {
199 if (Objects.equals(vtep.getDpnId(), dpid)) {
206 addVtepIntoTepsNotHosted(addVtepToUnknownVtepsList(vtepList,
207 tepIpAddress, dpid, ofTunnel), tzName, tx);
209 // vtep is found, update it with tep-ip
210 vtepList.remove(oldVtep);
211 addVtepIntoTepsNotHosted(addVtepToUnknownVtepsList(vtepList,
212 tepIpAddress, dpid, ofTunnel), tzName, tx);
219 * Adds the TEP into Unknown Vtep list under the transport zone in the TepsNotHosted list
220 * from ITM operational Datastore by merge operation with write transaction.
222 * @param updatedVtepList updated UnknownVteps list object which will have new TEP for addition
224 * @param tzName transport zone name in string
225 * @param tx TypedWriteTransaction object
227 protected static void addVtepIntoTepsNotHosted(List<UnknownVteps> updatedVtepList, String tzName,
228 TypedWriteTransaction<Datastore.Operational> tx) {
229 //Create TZ node path
230 InstanceIdentifier<TepsInNotHostedTransportZone> tepsInNotHostedTransportZoneIid =
231 InstanceIdentifier.builder(NotHostedTransportZones.class)
232 .child(TepsInNotHostedTransportZone.class,
233 new TepsInNotHostedTransportZoneKey(tzName)).build();
235 // create unknown TZ node with updated vtep list
236 TepsInNotHostedTransportZone updatedTzone = new TepsInNotHostedTransportZoneBuilder()
237 .withKey(new TepsInNotHostedTransportZoneKey(tzName)).setZoneName(tzName)
238 .setUnknownVteps(updatedVtepList).build();
240 // Update TZ in Oper DS.
241 tx.merge(tepsInNotHostedTransportZoneIid, updatedTzone, true);
244 private static void addConfig(String tzName, BigInteger dpnId, IpAddress ipAdd,
245 boolean ofTunnel, TypedWriteTransaction<Datastore.Configuration> tx) {
246 List<Vteps> vtepList = new ArrayList<>();
248 LOG.trace("Add TEP in transport-zone when no vtep-list for specific subnet.");
249 addVtepInITMConfigDS(vtepList, ipAdd, tzName, dpnId, ofTunnel, tx);
252 private static List<ListenableFuture<Void>> addUnknownTzTepIntoTepsNotHostedAndReturnFutures(String tzName,
253 IpAddress tepIpAddress, BigInteger id, boolean ofTunnel,
254 DataBroker dataBroker, ManagedNewTransactionRunner txRunner) {
255 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.OPERATIONAL,
256 tx -> addUnknownTzTepIntoTepsNotHosted(tzName, tepIpAddress, id, ofTunnel, dataBroker, tx)));
259 private static List<UnknownVteps> addVtepToUnknownVtepsList(List<UnknownVteps> updatedVtepList,
260 IpAddress tepIpAddress, BigInteger dpid,
263 UnknownVtepsKey vtepkey = new UnknownVtepsKey(dpid);
264 UnknownVteps vtepObj =
265 new UnknownVtepsBuilder().setDpnId(dpid).setIpAddress(tepIpAddress).withKey(vtepkey)
266 .setOfTunnel(ofTunnel).build();
268 // Add vtep obtained into unknown TZ tep list
269 updatedVtepList.add(vtepObj);
270 LOG.trace("Adding TEP (DPID: {}, TEP IP: {}, of-tunnel: {}) into unhosted Transport Zone"
271 + "inside ITM Oper DS.", dpid, tepIpAddress, ofTunnel);
272 return updatedVtepList;