Bump upstreams for 2022.09 Chlorine
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / TransactUtils.java
1 /*
2  * Copyright © 2015, 2017 China Telecom Beijing Research Institute 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.ovsdb.hwvtepsouthbound.transact;
9
10 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
11
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import org.opendaylight.mdsal.binding.api.DataObjectModification;
19 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
20 import org.opendaylight.mdsal.binding.api.DataTreeModification;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
23 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
24 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundMapper;
25 import org.opendaylight.ovsdb.lib.notation.UUID;
26 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
27 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
28 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocatorSet;
29 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
30 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Acls;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalRouters;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 public final class TransactUtils {
49     private static final Logger LOG = LoggerFactory.getLogger(TransactUtils.class);
50
51     private TransactUtils() {
52         // Hidden on purpose
53     }
54
55     public static Node getCreated(final DataObjectModification<Node> mod) {
56         if (mod.getModificationType() == ModificationType.WRITE
57                         && mod.getDataBefore() == null) {
58             return mod.getDataAfter();
59         }
60         return null;
61     }
62
63     public static Node getRemoved(final DataObjectModification<Node> mod) {
64         if (mod.getModificationType() == ModificationType.DELETE) {
65             return mod.getDataBefore();
66         }
67         return null;
68     }
69
70     public static Node getUpdated(final DataObjectModification<Node> mod) {
71         Node node = null;
72         switch (mod.getModificationType()) {
73             case SUBTREE_MODIFIED:
74                 node = mod.getDataAfter();
75                 break;
76             case WRITE:
77                 if (mod.getDataBefore() != null) {
78                     node = mod.getDataAfter();
79                 }
80                 break;
81             default:
82                 break;
83         }
84         return node;
85     }
86
87     public static Node getOriginal(final DataObjectModification<Node> mod) {
88         Node node = null;
89         switch (mod.getModificationType()) {
90             case SUBTREE_MODIFIED:
91             case DELETE:
92                 node = mod.getDataBefore();
93                 break;
94             case WRITE:
95                 if (mod.getDataBefore() !=  null) {
96                     node = mod.getDataBefore();
97                 }
98                 break;
99             default:
100                 break;
101         }
102         return node;
103     }
104
105     //TODO: change this function to be generic
106     public static Map<InstanceIdentifier<Node>, Node> extractCreatedOrUpdatedOrRemoved(
107             final Collection<DataTreeModification<Node>> changes, final Class<Node> class1) {
108         Map<InstanceIdentifier<Node>, Node> result = new HashMap<>();
109         for (DataTreeModification<Node> change : changes) {
110             final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
111             final DataObjectModification<Node> mod = change.getRootNode();
112             Node created = getCreated(mod);
113             if (created != null) {
114                 result.put(key, created);
115             }
116             Node updated = getUpdated(mod);
117             if (updated != null) {
118                 result.put(key, updated);
119             }
120             Node deleted = getRemoved(mod);
121             if (deleted != null) {
122                 result.put(key, deleted);
123             }
124         }
125         return result;
126     }
127
128     public static UUID createPhysicalLocatorSet(final HwvtepOperationalState hwvtepOperationalState,
129             final TransactionBuilder transaction, final List<LocatorSet> locatorList) {
130         Set<UUID> locators = new HashSet<>();
131         Set<String> locatorsInfo = new HashSet<>();
132         for (LocatorSet locator: locatorList) {
133             @SuppressWarnings("unchecked")
134             InstanceIdentifier<TerminationPoint> iid =
135                     (InstanceIdentifier<TerminationPoint>) locator.getLocatorRef().getValue();
136             UUID locatorUuid = createPhysicalLocator(transaction, hwvtepOperationalState, iid);
137             if (locatorUuid != null) {
138                 locators.add(locatorUuid);
139                 addLocatorToTransactionHistory(hwvtepOperationalState, locatorsInfo, iid);
140             }
141         }
142         PhysicalLocatorSet physicalLocatorSet = transaction.getTypedRowWrapper(PhysicalLocatorSet.class);
143         physicalLocatorSet.setLocators(locators);
144         String locatorSetUuid = "PhysicalLocatorSet_" + HwvtepSouthboundMapper.getRandomUUID();
145         transaction.add(op.insert(physicalLocatorSet).withId(locatorSetUuid));
146         hwvtepOperationalState.getDeviceInfo().addToControllerTx(TransactionType.ADD,
147                 new StringBuilder(physicalLocatorSet.toString()).append(" Uuid ").append(locatorSetUuid)
148                         .append(" ").append(locatorsInfo.toString()));
149         return new UUID(locatorSetUuid);
150     }
151
152     public static UUID createPhysicalLocator(final TransactionBuilder transaction,
153                                              final HwvtepOperationalState operationalState,
154                                              final InstanceIdentifier<TerminationPoint> iid) {
155         UUID locatorUuid = null;
156         HwvtepDeviceInfo.DeviceData deviceData = operationalState.getDeviceInfo().getDeviceOperData(
157                 TerminationPoint.class, iid);
158         if (deviceData != null && deviceData.getUuid() != null) {
159             locatorUuid = deviceData.getUuid();
160             return locatorUuid;
161         }
162         locatorUuid = operationalState.getUUIDFromCurrentTx(TerminationPoint.class, iid);
163         if (locatorUuid != null) {
164             return locatorUuid;
165         }
166         HwvtepPhysicalLocatorAugmentationBuilder builder = new HwvtepPhysicalLocatorAugmentationBuilder();
167         HwvtepPhysicalLocatorAugmentation locatorAugmentation = null;
168         builder.setEncapsulationType(EncapsulationTypeVxlanOverIpv4.VALUE);
169         String tepKey = iid.firstKeyOf(TerminationPoint.class).getTpId().getValue();
170         String ip = tepKey.substring(tepKey.indexOf(":") + 1);
171         builder.setDstIp(parseIpAddress(ip));
172         locatorAugmentation = builder.build();
173         locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation, operationalState);
174         operationalState.updateCurrentTxData(TerminationPoint.class, iid, locatorUuid);
175         operationalState.getDeviceInfo().markKeyAsInTransit(TerminationPoint.class, iid);
176         return locatorUuid;
177     }
178
179     public static UUID createPhysicalLocator(final TransactionBuilder transaction,
180                                              final HwvtepPhysicalLocatorAugmentation inputLocator,
181                                              final HwvtepOperationalState hwvtepOperationalState) {
182         LOG.debug("Creating a physical locator: {}", inputLocator.getDstIp());
183         PhysicalLocator physicalLocator = transaction.getTypedRowWrapper(PhysicalLocator.class);
184         setEncapsulationType(physicalLocator, inputLocator);
185         setDstIp(physicalLocator, inputLocator);
186         String locatorUuid = "PhysicalLocator_" + HwvtepSouthboundMapper.getRandomUUID();
187         transaction.add(op.insert(physicalLocator).withId(locatorUuid));
188         hwvtepOperationalState.getDeviceInfo().addToControllerTx(TransactionType.ADD,
189                 new StringBuilder(physicalLocator.toString()).append(" Uuid ").append(locatorUuid));
190         LOG.info("CONTROLLER - {} {}", TransactionType.ADD,
191             new StringBuilder(physicalLocator.toString()).append(" Uuid ").append(locatorUuid));
192         return new UUID(locatorUuid);
193     }
194
195     public static IpAddress parseIpAddress(final String ipAddress) {
196         try {
197             return new IpAddress(new Ipv4Address(ipAddress));
198         } catch (IllegalArgumentException e) {
199             LOG.debug("Failed to interpret {} as an Ipv4Address", ipAddress, e);
200         }
201         return new IpAddress(new Ipv6Address(ipAddress));
202     }
203
204     private static void setEncapsulationType(final PhysicalLocator physicalLocator,
205             final HwvtepPhysicalLocatorAugmentation inputLocator) {
206         if (inputLocator.getEncapsulationType() != null) {
207             String encapType = HwvtepSouthboundConstants.ENCAPS_TYPE_MAP.get(
208                     HwvtepSouthboundMapper.createEncapsulationType(""));
209             physicalLocator.setEncapsulationType(encapType);
210         }
211     }
212
213     private static void setDstIp(final PhysicalLocator physicalLocator,
214             final HwvtepPhysicalLocatorAugmentation inputLocator) {
215         if (inputLocator.getDstIp() != null) {
216             physicalLocator.setDstIp(inputLocator.getDstIp().getIpv4Address().getValue());
217         }
218     }
219
220     static String sanitizeUUID(final HwvtepNodeName hwvtepNodeName) {
221         return sanitizeUUID(hwvtepNodeName.getValue());
222     }
223
224     static String sanitizeUUID(final String nodeName) {
225         //ovs is not accepting '-' in the named uuids
226         return nodeName.replace('-', '_');
227     }
228
229     public static String getLogicalSwitchId(final LogicalSwitches lswitch) {
230         return HwvtepSouthboundConstants.LOGICALSWITCH_UUID_PREFIX + sanitizeUUID(lswitch.getHwvtepNodeName());
231     }
232
233     public static UUID getLogicalSwitchUUID(final InstanceIdentifier<LogicalSwitches> lswitchIid) {
234         return new UUID(HwvtepSouthboundConstants.LOGICALSWITCH_UUID_PREFIX
235                 + sanitizeUUID(lswitchIid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName()));
236     }
237
238     public static UUID getLogicalSwitchUUID(final TransactionBuilder transaction,
239                                             final HwvtepOperationalState operationalState,
240                                             final InstanceIdentifier<LogicalSwitches> lswitchIid) {
241         HwvtepDeviceInfo hwvtepDeviceInfo = operationalState.getDeviceInfo();
242         HwvtepDeviceInfo.DeviceData lsData = hwvtepDeviceInfo.getDeviceOperData(LogicalSwitches.class, lswitchIid);
243         if (lsData != null) {
244             if (lsData.getUuid() != null) {
245                 return lsData.getUuid();
246             }
247             if (lsData.isInTransitState()) {
248                 return getLogicalSwitchUUID(lswitchIid);
249             }
250             return null;
251         }
252         LogicalSwitchUpdateCommand cmd = new LogicalSwitchUpdateCommand(operationalState, List.of());
253         MdsalUtils mdsalUtils = new MdsalUtils(operationalState.getDataBroker());
254         LogicalSwitches ls = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, lswitchIid);
255         if (ls != null) {
256             cmd.updateLogicalSwitch(transaction, lswitchIid.firstIdentifierOf(Node.class), List.of(ls));
257         } else {
258             LOG.error("Could not find logical switch in config ds {}", lswitchIid);
259             return null;
260         }
261         return getLogicalSwitchUUID(lswitchIid);
262     }
263
264     public static String getLogicalRouterId(final LogicalRouters lrouter) {
265         return HwvtepSouthboundConstants.LOGICALROUTER_UUID_PREFIX + sanitizeUUID(lrouter.getHwvtepNodeName());
266     }
267
268     public static UUID getAclUUID(final InstanceIdentifier<Acls> aclIid) {
269         return new UUID(HwvtepSouthboundConstants.ACL_UUID_PREFIX
270                 + sanitizeUUID(aclIid.firstKeyOf(Acls.class).getAclName()));
271     }
272
273     @SuppressWarnings("checkstyle:IllegalCatch")
274     private static void addLocatorToTransactionHistory(final HwvtepOperationalState hwvtepOperationalState,
275             final Set<String> locatorsInfo, final InstanceIdentifier<TerminationPoint> iid) {
276         try {
277             HwvtepDeviceInfo.DeviceData deviceData = hwvtepOperationalState.getDeviceInfo().getDeviceOperData(
278                     TerminationPoint.class, iid);
279             if (deviceData != null) {
280                 Object data = deviceData.getData();
281                 if (data instanceof PhysicalLocator locator) {
282                     locatorsInfo.add(new StringBuilder(locator.getUuid().toString()).append(" ")
283                             .append(locator.getDstIpColumn().getData()).toString());
284                 } else {
285                     LOG.debug("Ignoring unknown data {}", data);
286                 }
287             }
288         } catch (Exception exp) {
289             LOG.warn("Failed to add to Transaction History", exp);
290         }
291     }
292 }