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.util.ArrayList;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.List;
16 import java.util.Objects;
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.mdsal.binding.api.DataBroker;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.NotHostedTransportZones;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZone;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZoneBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZoneKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVteps;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVtepsBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVtepsKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.VtepsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.VtepsKey;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.opendaylight.yangtools.yang.common.Uint64;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 public final class OvsdbTepAddConfigHelper {
47 private static final Logger LOG = LoggerFactory.getLogger(OvsdbTepAddConfigHelper.class);
49 private OvsdbTepAddConfigHelper() {
54 * Adds the TEP into ITM configuration/operational Datastore in one of the following cases.
55 * 1) default transport zone
56 * 2) Configured transport zone
57 * 3) Unhosted transport zone
59 * @param tepIp TEP-IP address in string
60 * @param strDpnId bridge datapath ID in string
61 * @param tzName transport zone name in string
62 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
63 * @param dataBroker data broker handle to perform operations on config/operational datastore
64 * @param txRunner ManagedTransactionRunner object
67 public static List<ListenableFuture<Void>> addTepReceivedFromOvsdb(String tepIp, String strDpnId, String tzName,
68 boolean ofTunnel, DataBroker dataBroker,
69 ManagedNewTransactionRunner txRunner)
71 Uint64 dpnId = Uint64.ZERO;
73 if (strDpnId != null && !strDpnId.isEmpty()) {
74 dpnId = MDSALUtil.getDpnId(strDpnId);
78 IpAddress tepIpAddress = IpAddressBuilder.getDefaultInstance(tepIp);
79 TransportZone tzone = null;
81 // check if TEP received is already present in any other TZ.
82 TransportZone transportZone = ItmUtils.getTransportZoneOfVtep(dpnId, dataBroker);
83 if (transportZone != null) {
84 LOG.trace("Vtep (tep-ip: {} and dpid: {}) is already present in transport-zone: {}",
85 tepIpAddress, dpnId, transportZone.getZoneName());
86 if (!transportZone.getZoneName().equals(tzName)) {
87 // remove TEP from TZ because TZ is updated for TEP from southbound in this case
88 OvsdbTepRemoveWorker ovsdbTepRemoveWorkerObj = new OvsdbTepRemoveWorker(tepIp, strDpnId,
89 transportZone.getZoneName(), dataBroker);
90 ovsdbTepRemoveWorkerObj.call();
94 // Case: TZ name is not given with OVS TEP.
96 tzName = ITMConstants.DEFAULT_TRANSPORT_ZONE;
97 // add TEP into default-TZ
98 tzone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
100 // Case: default-TZ is not yet created, then add TEP into "teps-in-not-hosted-transport-zone"
101 LOG.trace("Adding TEP with default TZ into teps-in-not-hosted-transport-zone.");
102 return addUnknownTzTepIntoTepsNotHostedAndReturnFutures(tzName, tepIpAddress, dpnId, ofTunnel,
103 dataBroker, txRunner);
105 LOG.trace("Add TEP into default-transport-zone.");
107 // Case: Add TEP into corresponding TZ created from Northbound.
108 tzone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
110 // Case: TZ is not configured from Northbound, then add TEP into "teps-in-not-hosted-transport-zone"
111 LOG.trace("Adding TEP with unknown TZ into teps-in-not-hosted-transport-zone.");
112 return addUnknownTzTepIntoTepsNotHostedAndReturnFutures(tzName, tepIpAddress, dpnId, ofTunnel,
113 dataBroker, txRunner);
115 LOG.trace("Add TEP into transport-zone already configured by Northbound.");
119 List<ListenableFuture<Void>> futures = new ArrayList<>();
120 final Uint64 id = dpnId;
121 final String name = tzName;
122 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION,
123 tx -> addConfig(name, id, tepIpAddress, ofTunnel, tx)));
128 * Adds the TEP into Vtep list in the subnet list in the transport zone list
129 * from ITM configuration Datastore by merge operation with write transaction.
131 * @param updatedVtepList updated Vteps list object which will have new TEP for addition
132 * @param tepIpAddress TEP IP address in IpAddress object
133 * @param tzName transport zone name in string
134 * @param dpid bridge datapath ID
135 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
136 * @param tx TypedWriteTransaction object
138 public static void addVtepInITMConfigDS(List<Vteps> updatedVtepList, IpAddress tepIpAddress, String tzName,
139 Uint64 dpid, boolean ofTunnel,
140 TypedWriteTransaction<Datastore.Configuration> tx) {
141 //Create TZ node path
142 InstanceIdentifier<TransportZone> tranzportZonePath =
143 InstanceIdentifier.builder(TransportZones.class)
144 .child(TransportZone.class, new TransportZoneKey(tzName)).build();
146 // this check is needed to reuse same function from TransportZoneListener
147 // when VTEP is moved from TepsNotHosted list to TZ configured from Northbound.
148 if (dpid.compareTo(Uint64.ZERO) > 0) {
150 VtepsKey vtepkey = new VtepsKey(dpid);
152 new VtepsBuilder().setDpnId(dpid).setIpAddress(tepIpAddress).withKey(vtepkey)
153 .setOptionOfTunnel(ofTunnel).build();
155 // Add vtep obtained from bridge into list
156 updatedVtepList.add(vtepObj);
158 LOG.trace("Adding TEP (TZ: {} TEP IP: {} DPID: {}, of-tunnel: {}) in ITM Config DS.", tzName,
159 tepIpAddress, dpid, ofTunnel);
161 // this is case when this function is called while TEPs movement from tepsNotHosted list when
162 // corresponding TZ is configured from northbound.
163 for (Vteps vtep: updatedVtepList) {
164 LOG.trace("Moving TEP (TEP IP: {} DPID: {}, of-tunnel: {})"
165 + "from not-hosted-transport-zone {} into ITM Config DS.",
166 vtep.getIpAddress(), vtep.getDpnId(), ofTunnel, tzName);
170 // create TZ node with updated subnet having new vtep
171 TransportZone updatedTzone =
172 new TransportZoneBuilder().withKey(new TransportZoneKey(tzName)).setVteps(updatedVtepList)
173 .setZoneName(tzName).build();
175 // Update TZ in Config DS to add vtep in TZ
176 tx.mergeParentStructureMerge(tranzportZonePath, updatedTzone);
180 * Adds the TEP into Vtep list in the subnet list in the transport zone list
181 * from ITM operational Datastore by merge operation with write transaction.
183 * @param tzName transport zone name in string
184 * @param tepIpAddress TEP IP address in IpAddress object
185 * @param dpid bridge datapath ID
186 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
187 * @param dataBroker data broker handle to perform operations on operational datastore
188 * @param tx TypedWriteTransaction object
190 protected static void addUnknownTzTepIntoTepsNotHosted(String tzName, IpAddress tepIpAddress,
191 Uint64 dpid, boolean ofTunnel, DataBroker dataBroker,
192 TypedWriteTransaction<Datastore.Operational> tx) {
193 Map<UnknownVtepsKey, UnknownVteps> vtepList;
194 TepsInNotHostedTransportZone tepsInNotHostedTransportZone =
195 ItmUtils.getUnknownTransportZoneFromITMOperDS(tzName, dataBroker);
196 if (tepsInNotHostedTransportZone == null) {
197 LOG.trace("Unhosted TransportZone ({}) does not exist in OperDS.", tzName);
198 vtepList = new HashMap<>();
199 addVtepIntoTepsNotHosted(addVtepToUnknownVtepsList(vtepList, tepIpAddress, dpid, ofTunnel), tzName, tx);
201 vtepList = tepsInNotHostedTransportZone.getUnknownVteps();
202 if (vtepList == null || vtepList.isEmpty()) {
203 // case: vtep list does not exist or it has no elements
204 if (vtepList == null) {
205 LOG.trace("Add TEP into unhosted TZ ({}) when no vtep-list in the TZ.", tzName);
206 vtepList = new HashMap<>();
208 LOG.trace("Add TEP into unhosted TZ ({}) when no vtep-list in the TZ.", tzName);
209 addVtepIntoTepsNotHosted(addVtepToUnknownVtepsList(vtepList, tepIpAddress, dpid, ofTunnel), tzName, tx);
211 // case: vtep list has elements
212 boolean vtepFound = false;
213 UnknownVteps oldVtep = null;
215 for (UnknownVteps vtep : vtepList.values()) {
216 if (Objects.equals(vtep.getDpnId(), dpid)) {
223 addVtepIntoTepsNotHosted(addVtepToUnknownVtepsList(vtepList,
224 tepIpAddress, dpid, ofTunnel), tzName, tx);
226 // vtep is found, update it with tep-ip
227 vtepList.remove(oldVtep.key());
228 addVtepIntoTepsNotHosted(addVtepToUnknownVtepsList(vtepList,
229 tepIpAddress, dpid, ofTunnel), tzName, tx);
236 * Adds the TEP into Unknown Vtep list under the transport zone in the TepsNotHosted list
237 * from ITM operational Datastore by merge operation with write transaction.
239 * @param updatedVtepList updated UnknownVteps list object which will have new TEP for addition
241 * @param tzName transport zone name in string
242 * @param tx TypedWriteTransaction object
244 protected static void addVtepIntoTepsNotHosted(Map<UnknownVtepsKey, UnknownVteps> updatedVtepList, String tzName,
245 TypedWriteTransaction<Datastore.Operational> tx) {
246 //Create TZ node path
247 InstanceIdentifier<TepsInNotHostedTransportZone> tepsInNotHostedTransportZoneIid =
248 InstanceIdentifier.builder(NotHostedTransportZones.class)
249 .child(TepsInNotHostedTransportZone.class,
250 new TepsInNotHostedTransportZoneKey(tzName)).build();
252 // create unknown TZ node with updated vtep list
253 TepsInNotHostedTransportZone updatedTzone = new TepsInNotHostedTransportZoneBuilder()
254 .withKey(new TepsInNotHostedTransportZoneKey(tzName)).setZoneName(tzName)
255 .setUnknownVteps(updatedVtepList).build();
257 // Update TZ in Oper DS.
258 tx.mergeParentStructureMerge(tepsInNotHostedTransportZoneIid, updatedTzone);
261 private static void addConfig(String tzName, Uint64 dpnId, IpAddress ipAdd,
262 boolean ofTunnel, TypedWriteTransaction<Datastore.Configuration> tx) {
263 List<Vteps> vtepList = new ArrayList<>();
265 LOG.trace("Add TEP in transport-zone when no vtep-list for specific subnet.");
266 addVtepInITMConfigDS(vtepList, ipAdd, tzName, dpnId, ofTunnel, tx);
269 private static List<ListenableFuture<Void>> addUnknownTzTepIntoTepsNotHostedAndReturnFutures(String tzName,
270 IpAddress tepIpAddress, Uint64 id, boolean ofTunnel,
271 DataBroker dataBroker, ManagedNewTransactionRunner txRunner) {
272 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.OPERATIONAL,
273 tx -> addUnknownTzTepIntoTepsNotHosted(tzName, tepIpAddress, id, ofTunnel, dataBroker, tx)));
276 private static Map<UnknownVtepsKey, UnknownVteps> addVtepToUnknownVtepsList(Map<UnknownVtepsKey,
277 UnknownVteps> updatedVtepList, IpAddress tepIpAddress, Uint64 dpid, boolean ofTunnel) {
279 UnknownVtepsKey vtepkey = new UnknownVtepsKey(dpid);
280 UnknownVteps vtepObj =
281 new UnknownVtepsBuilder().setDpnId(dpid).setIpAddress(tepIpAddress).withKey(vtepkey)
282 .setOfTunnel(ofTunnel).build();
284 // Add vtep obtained into unknown TZ tep list
285 updatedVtepList.put(vtepObj.key(),vtepObj);
286 LOG.trace("Adding TEP (DPID: {}, TEP IP: {}, of-tunnel: {}) into unhosted Transport Zone"
287 + "inside ITM Oper DS.", dpid, tepIpAddress, ofTunnel);
288 return updatedVtepList;