Merge "Revert "Spec for Counter Framework bundle""
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / confighelpers / OvsdbTepAddConfigHelper.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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 package org.opendaylight.genius.itm.confighelpers;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.itm.globals.ITMConstants;
18 import org.opendaylight.genius.itm.impl.ItmUtils;
19 import org.opendaylight.genius.mdsalutil.MDSALUtil;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.*;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.tepsnothostedintransportzone.UnknownVteps;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.tepsnothostedintransportzone.UnknownVtepsBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.tepsnothostedintransportzone.UnknownVtepsKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsKey;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 public class OvsdbTepAddConfigHelper {
38
39     private static final Logger LOG = LoggerFactory.getLogger(OvsdbTepAddConfigHelper.class);
40
41     /**
42      * Adds the TEP into ITM configuration Datastore in one of the following cases:
43      * 1) default transport zone
44      * 2) Configured transport zone
45      * 3) Unhosted transport zone
46      *
47      * @param tepIp TEP-IP address in string
48      * @param strDpid bridge datapath ID in string
49      * @param tzName transport zone name in string
50      * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
51      * @param dataBroker data broker handle to perform operations on config datastore
52      * @param wrTx WriteTransaction object
53      */
54     public static void addTepReceivedFromOvsdb(String tepIp, String strDpid, String tzName,
55         boolean ofTunnel, DataBroker dataBroker, WriteTransaction wrTx) {
56         BigInteger dpid = BigInteger.valueOf(0);
57
58         if (strDpid != null && !strDpid.isEmpty()) {
59             dpid = MDSALUtil.getDpnId(strDpid);
60         }
61
62         // Get tep IP
63         IpAddress tepIpAddress = new IpAddress(tepIp.toCharArray());
64         TransportZone tZone = null;
65
66         // Case: TZ name is not given with CSS TEP.
67         if (tzName == null) {
68             tzName = ITMConstants.DEFAULT_TRANSPORT_ZONE;
69             // add TEP into default-TZ
70             tZone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
71             if (tZone == null) {
72                 LOG.error("Error: default-transport-zone is not yet created.");
73                 return;
74             }
75             LOG.trace("Add TEP into default-transport-zone.");
76         } else {
77             // Case: Add TEP into corresponding TZ created from Northbound.
78             tZone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
79             if (tZone == null) {
80                 // Case: TZ is not configured from Northbound, then add TEP into "teps-not-hosted-in-transport-zone"
81                 LOG.trace("Adding TEP with unknown TZ into teps-not-hosted-in-transport-zone.");
82                 addUnknownTzTepIntoTepsNotHosted(tzName, tepIpAddress, dpid, ofTunnel,
83                     dataBroker, wrTx);
84                 return;
85             } else {
86                 LOG.trace("Add TEP into transport-zone already configured by Northbound.");
87             }
88         }
89
90         // Get subnet list of corresponding TZ created from Northbound.
91         List<Subnets> subnetList = tZone.getSubnets();
92         String portName = ITMConstants.DUMMY_PORT;
93
94         IpPrefix subnetMaskObj = ItmUtils.getDummySubnet();
95
96         if (subnetList == null || subnetList.isEmpty()) {
97             if (subnetList == null) {
98                 subnetList = new ArrayList<Subnets>();
99             }
100             List<Vteps> vtepList = new ArrayList<Vteps>();
101             LOG.trace("Add TEP in transport-zone when no subnet-list.");
102             addVtepInITMConfigDS(subnetList, subnetMaskObj, vtepList, tepIpAddress, tzName, dpid,
103                 portName, ofTunnel, wrTx);
104         } else {
105             List<Vteps> vtepList = null;
106
107             // subnet list already exists case; check for dummy-subnet
108             for (Subnets subnet : subnetList) {
109                 if (subnet.getKey().getPrefix().equals(subnetMaskObj)) {
110                     LOG.trace("Subnet exists in the subnet list of transport-zone {}.", tzName);
111                     // get vtep list of existing subnet
112                     vtepList = subnet.getVteps();
113                     break;
114                 }
115             }
116
117             if (vtepList == null || vtepList.isEmpty()) {
118                 //  case: vtep list does not exist or it has no elements
119                 if (vtepList == null) {
120                     vtepList = new ArrayList<Vteps>();
121                 }
122                 LOG.trace("Add TEP in transport-zone when no vtep-list for specific subnet.");
123                 addVtepInITMConfigDS(subnetList, subnetMaskObj, vtepList, tepIpAddress, tzName,
124                     dpid, portName, ofTunnel, wrTx);
125             } else {
126                 //  case: vtep list has elements
127                 boolean vtepFound = false;
128                 Vteps oldVtep = null;
129
130                 for (Vteps vtep : vtepList) {
131                     if (vtep.getDpnId().equals(dpid)) {
132                         vtepFound = true;
133                         oldVtep = vtep;
134                         // get portName of existing vtep
135                         portName = vtep.getPortname();
136                         break;
137                     }
138                 }
139                 if (!vtepFound) {
140                     addVtepInITMConfigDS(subnetList, subnetMaskObj, vtepList, tepIpAddress, tzName,
141                         dpid, portName, ofTunnel, wrTx);
142                 } else {
143                     // vtep is found, update it with tep-ip
144                     vtepList.remove(oldVtep);
145                     addVtepInITMConfigDS(subnetList, subnetMaskObj, vtepList, tepIpAddress, tzName,
146                         dpid, portName, ofTunnel, wrTx);
147                 }
148             }
149         }
150     }
151
152     /**
153      * Adds the TEP into Vtep list in the subnet list in the transport zone list
154      * from ITM configuration Datastore by merge operation with write transaction.
155      *
156      * @param subnetList subnets list object
157      * @param subnetMaskObj subnet mask in IpPrefix object
158      * @param updatedVtepList updated Vteps list object which will have new TEP for addition
159      * @param tepIpAddress TEP IP address in IpAddress object
160      * @param tzName transport zone name in string
161      * @param dpid bridge datapath ID in BigInteger
162      * @param portName port name as a part of VtepsKey
163      * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
164      * @param wrTx WriteTransaction object
165      */
166     public static void addVtepInITMConfigDS(List<Subnets> subnetList, IpPrefix subnetMaskObj,
167         List<Vteps> updatedVtepList, IpAddress tepIpAddress, String tzName, BigInteger dpid,
168         String portName, boolean ofTunnel, WriteTransaction wrTx) {
169         //Create TZ node path
170         InstanceIdentifier<TransportZone> tZonepath =
171             InstanceIdentifier.builder(TransportZones.class)
172                 .child(TransportZone.class, new TransportZoneKey(tzName)).build();
173
174         // this check is needed to reuse same function from TransportZoneListener
175         // when VTEP is moved from TepsNotHosted list to TZ configured from Northbound.
176         if (dpid.compareTo(BigInteger.ZERO) > 0) {
177             // create vtep
178             VtepsKey vtepkey = new VtepsKey(dpid, portName);
179             Vteps vtepObj =
180                 new VtepsBuilder().setDpnId(dpid).setIpAddress(tepIpAddress).setKey(vtepkey).
181                     setPortname(portName).setOptionOfTunnel(ofTunnel).build();
182
183             // Add vtep obtained from bridge into list
184             updatedVtepList.add(vtepObj);
185
186             LOG.trace("Adding TEP (TZ: {} Subnet: {} TEP IP: {} DPID: {}, of-tunnel: {})"
187                     + "in ITM Config DS.", tzName, subnetMaskObj.getValue().toString(), tepIpAddress,
188                 dpid, ofTunnel);
189         } else {
190             // this is case when this function is called while TEPs movement from tepsNotHosted list when
191             // corresponding TZ is configured from northbound.
192             for (Vteps vtep: updatedVtepList) {
193                 LOG.trace("Moving TEP (TEP IP: {} DPID: {}, of-tunnel: {})"
194                         + "from tepNotHosted list into transport-zone {} in  ITM Config DS.",
195                     vtep.getIpAddress().getValue().toString(), vtep.getDpnId(), ofTunnel, tzName);
196             }
197         }
198
199         // Create subnet object
200         SubnetsKey subKey = new SubnetsKey(subnetMaskObj);
201         IpAddress gatewayIP = new IpAddress(ITMConstants.DUMMY_GATEWAY_IP.toCharArray());
202         int vlanID = ITMConstants.DUMMY_VLANID;
203
204         Subnets subnet =
205             new SubnetsBuilder().setGatewayIp(gatewayIP)
206                 .setKey(subKey).setPrefix(subnetMaskObj)
207                 .setVlanId(vlanID).setVteps(updatedVtepList).build();
208
209         // add subnet into subnet list
210         subnetList.add(subnet);
211
212         // create TZ node with updated subnet having new vtep
213         TransportZone updatedTzone =
214             new TransportZoneBuilder().setKey(new TransportZoneKey(tzName)).setSubnets(subnetList)
215                 .setZoneName(tzName).build();
216
217         // Update TZ in Config DS to add vtep in TZ
218         wrTx.merge(LogicalDatastoreType.CONFIGURATION, tZonepath, updatedTzone, true);
219     }
220
221     /**
222      * Adds the TEP into Vtep list in the subnet list in the transport zone list
223      * from ITM configuration Datastore by merge operation with write transaction.
224      *
225      * @param tzName transport zone name in string
226      * @param tepIpAddress TEP IP address in IpAddress object
227      * @param dpid bridge datapath ID in BigInteger
228      * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
229      * @param dataBroker data broker handle to perform operations on config datastore
230      * @param wrTx WriteTransaction object
231      */
232     protected static void addUnknownTzTepIntoTepsNotHosted(String tzName, IpAddress tepIpAddress,
233         BigInteger dpid, boolean ofTunnel, DataBroker dataBroker, WriteTransaction wrTx) {
234         List<UnknownVteps> vtepList = null;
235
236         TepsNotHostedInTransportZone unknownTz =
237             ItmUtils.getUnknownTransportZoneFromITMConfigDS(tzName, dataBroker);
238         if (unknownTz == null) {
239             LOG.trace("Unhosted TransportZone does not exist.");
240             vtepList = new ArrayList<UnknownVteps>();
241             addVtepIntoTepsNotHosted(vtepList, tepIpAddress, tzName, dpid, ofTunnel, wrTx);
242         } else {
243             vtepList = unknownTz.getUnknownVteps();
244             if (vtepList == null || vtepList.isEmpty()) {
245                 //  case: vtep list does not exist or it has no elements
246                 if (vtepList == null) {
247                     vtepList = new ArrayList<UnknownVteps>();
248                 }
249                 LOG.trace("Add TEP in unhosted TZ ({}) when no vtep-list in the TZ.", tzName);
250                 addVtepIntoTepsNotHosted(vtepList, tepIpAddress, tzName, dpid, ofTunnel, wrTx);
251             } else {
252                 //  case: vtep list has elements
253                 boolean vtepFound = false;
254                 UnknownVteps oldVtep = null;
255
256                 for (UnknownVteps vtep : vtepList) {
257                     if (vtep.getDpnId().equals(dpid)) {
258                         vtepFound = true;
259                         oldVtep = vtep;
260                         break;
261                     }
262                 }
263                 if (!vtepFound) {
264                     addVtepIntoTepsNotHosted(vtepList, tepIpAddress, tzName, dpid,
265                         ofTunnel, wrTx);
266                 } else {
267                     // vtep is found, update it with tep-ip
268                     vtepList.remove(oldVtep);
269                     addVtepIntoTepsNotHosted(vtepList, tepIpAddress, tzName, dpid,
270                         ofTunnel, wrTx);
271                 }
272             }
273         }
274     }
275
276     /**
277      * Adds the TEP into Unknown Vtep list under the transport zone in the TepsNotHosted list
278      * from ITM configuration Datastore by merge operation with write transaction.
279      *
280      * @param updatedVtepList updated UnknownVteps list object which will have new TEP for addition
281      *                        into TepsNotHosted
282      * @param tepIpAddress TEP IP address in IpAddress object
283      * @param tzName transport zone name in string
284      * @param dpid bridge datapath ID in BigInteger
285      * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
286      * @param wrTx WriteTransaction object
287      */
288     protected static void addVtepIntoTepsNotHosted(List<UnknownVteps> updatedVtepList,
289         IpAddress tepIpAddress, String tzName, BigInteger dpid, boolean ofTunnel,
290         WriteTransaction wrTx) {
291         //Create TZ node path
292         InstanceIdentifier<TepsNotHostedInTransportZone> tZonepath =
293             InstanceIdentifier.builder(TransportZones.class)
294                 .child(TepsNotHostedInTransportZone.class,
295                     new TepsNotHostedInTransportZoneKey(tzName)).build();
296
297         // create vtep
298         UnknownVtepsKey vtepkey = new UnknownVtepsKey(dpid);
299         UnknownVteps vtepObj =
300             new UnknownVtepsBuilder().setDpnId(dpid).setIpAddress(tepIpAddress).setKey(vtepkey)
301                 .setOfTunnel(ofTunnel).build();
302
303         // Add vtep obtained into unknown TZ tep list
304         updatedVtepList.add(vtepObj);
305
306         // create unknown TZ node with updated vtep list
307         TepsNotHostedInTransportZone updatedTzone = new TepsNotHostedInTransportZoneBuilder()
308             .setKey(new TepsNotHostedInTransportZoneKey(tzName)).setZoneName(tzName)
309             .setUnknownVteps(updatedVtepList).build();
310
311         LOG.trace("Adding TEP into unhosted (TZ: {}, DPID: {}, TEP IP: {}, of-tunnel: {})"
312                 + "in ITM Config DS.", tzName, dpid, tepIpAddress, ofTunnel);
313
314         // Update TZ in Config DS.
315         wrTx.merge(LogicalDatastoreType.CONFIGURATION, tZonepath, updatedTzone, true);
316     }
317 }