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