Bump versions by x.(y+1).z
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / McastMacsRemoteUpdateCommand.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.annotations.VisibleForTesting;
13 import com.google.common.collect.Lists;
14 import com.google.common.collect.Sets;
15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Map.Entry;
22 import java.util.Objects;
23 import java.util.Set;
24 import org.opendaylight.mdsal.binding.api.DataTreeModification;
25 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
26 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
27 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
28 import org.opendaylight.ovsdb.lib.notation.UUID;
29 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
30 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
31 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class McastMacsRemoteUpdateCommand
43         extends AbstractTransactCommand<RemoteMcastMacs, RemoteMcastMacsKey, HwvtepGlobalAugmentation> {
44     private static final Logger LOG = LoggerFactory.getLogger(McastMacsRemoteUpdateCommand.class);
45
46     @VisibleForTesting
47     static final McastMacUnMetDependencyGetter MCAST_MAC_DATA_VALIDATOR = new McastMacUnMetDependencyGetter();
48
49     public McastMacsRemoteUpdateCommand(final HwvtepOperationalState state,
50             final Collection<DataTreeModification<Node>> changes) {
51         super(state, changes);
52     }
53
54     @Override
55     public void execute(final TransactionBuilder transaction) {
56         Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> updateds =
57                 extractUpdated(getChanges(),RemoteMcastMacs.class);
58         if (!updateds.isEmpty()) {
59             for (Entry<InstanceIdentifier<Node>, List<RemoteMcastMacs>> updated:
60                 updateds.entrySet()) {
61                 updateMcastMacRemote(transaction,  updated.getKey(), updated.getValue());
62             }
63         }
64     }
65
66     private void updateMcastMacRemote(final TransactionBuilder transaction,
67             final InstanceIdentifier<Node> instanceIdentifier, final List<RemoteMcastMacs> macList) {
68         for (RemoteMcastMacs mac: macList) {
69             //add / update only if locator set got changed
70             InstanceIdentifier<RemoteMcastMacs> macIid = instanceIdentifier
71                     .augmentation(HwvtepGlobalAugmentation.class)
72                     .child(RemoteMcastMacs.class, mac.key());
73             updateConfigData(RemoteMcastMacs.class, macIid, mac);
74             if (!HwvtepSouthboundUtil.isEmpty(mac.getLocatorSet())) {
75                 onConfigUpdate(transaction, instanceIdentifier, mac, null);
76             }
77         }
78     }
79
80     @Override
81     public void onConfigUpdate(final TransactionBuilder transaction,
82                                final InstanceIdentifier<Node> nodeIid,
83                                final RemoteMcastMacs remoteMcastMac,
84                                final InstanceIdentifier macKey,
85                                final Object... extraData) {
86         InstanceIdentifier<RemoteMcastMacs> macIid = nodeIid.augmentation(HwvtepGlobalAugmentation.class)
87                 .child(RemoteMcastMacs.class, remoteMcastMac.key());
88         processDependencies(MCAST_MAC_DATA_VALIDATOR, transaction, nodeIid, macIid, remoteMcastMac);
89     }
90
91     @Override
92     public void doDeviceTransaction(final TransactionBuilder transaction,
93                                        final InstanceIdentifier<Node> instanceIdentifier,
94                                        final RemoteMcastMacs mac,
95                                        final InstanceIdentifier macKey,
96                                        final Object... extraData) {
97
98         String nodeId = instanceIdentifier.firstKeyOf(Node.class).getNodeId().getValue();
99         LOG.debug("Creating remoteMcastMacs, mac address: {} {}", nodeId, mac.getMacEntryKey().getValue());
100
101         McastMacsRemote mcastMacsRemote = transaction.getTypedRowWrapper(McastMacsRemote.class);
102         setIpAddress(mcastMacsRemote, mac);
103         setLogicalSwitch(transaction, mcastMacsRemote, mac);
104         setMac(mcastMacsRemote, mac);
105         InstanceIdentifier<RemoteMcastMacs> macIid = instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class)
106                 .child(RemoteMcastMacs.class, mac.key());
107         HwvtepDeviceInfo.DeviceData deviceData = super.fetchDeviceData(RemoteMcastMacs.class, macIid);
108         if (deviceData == null) {
109             setLocatorSet(transaction, mcastMacsRemote, mac);
110             transaction.add(op.insert(mcastMacsRemote));
111             updateCurrentTxData(RemoteMcastMacs.class, macIid, new UUID("uuid"), mac);
112             updateControllerTxHistory(TransactionType.ADD, mcastMacsRemote);
113             LOG.info("CONTROLLER - {} {}", TransactionType.ADD, mcastMacsRemote);
114         } else if (deviceData.getUuid() != null) {
115             setLocatorSet(transaction, mcastMacsRemote, mac);
116             UUID macEntryUUID = deviceData.getUuid();
117             McastMacsRemote extraMac = transaction.getTypedRowSchema(McastMacsRemote.class);
118             extraMac.getUuidColumn().setData(macEntryUUID);
119             transaction.add(op.update(mcastMacsRemote)
120                     .where(extraMac.getUuidColumn().getSchema().opEqual(macEntryUUID))
121                     .build());
122             updateControllerTxHistory(TransactionType.UPDATE, mcastMacsRemote);
123             LOG.info("CONTROLLER - {} {}", TransactionType.UPDATE, mcastMacsRemote);
124             addToUpdates(macIid, mac);
125         } else {
126             LOG.error("Unable to update remoteMcastMacs {} {} because uuid not found in the operational"
127                     + " store txId: {}", mac, deviceData, getOperationalState().getTransactionId());
128         }
129         updateConfigData(RemoteMcastMacs.class, macIid, mac);
130     }
131
132     private void setLogicalSwitch(final TransactionBuilder transaction, final McastMacsRemote mcastMacsRemote,
133             final RemoteMcastMacs inputMac) {
134         if (inputMac.getLogicalSwitchRef() != null) {
135             @SuppressWarnings("unchecked")
136             InstanceIdentifier<LogicalSwitches> lswitchIid =
137                     (InstanceIdentifier<LogicalSwitches>) inputMac.getLogicalSwitchRef().getValue();
138             UUID logicalSwitchUUID = TransactUtils.getLogicalSwitchUUID(transaction, getOperationalState(), lswitchIid);
139             if (logicalSwitchUUID != null) {
140                 mcastMacsRemote.setLogicalSwitch(logicalSwitchUUID);
141             }
142         }
143     }
144
145     private void setLocatorSet(final TransactionBuilder transaction, final McastMacsRemote mcastMacsRemote,
146             final RemoteMcastMacs inputMac) {
147         if (inputMac.getLocatorSet() != null && !inputMac.getLocatorSet().isEmpty()) {
148             UUID locatorSetUuid = TransactUtils.createPhysicalLocatorSet(getOperationalState(),
149                     transaction, inputMac.getLocatorSet());
150             mcastMacsRemote.setLocatorSet(locatorSetUuid);
151         }
152     }
153
154     private static void setIpAddress(final McastMacsRemote mcastMacsRemote, final RemoteMcastMacs inputMac) {
155         if (inputMac.getIpaddr() != null) {
156             mcastMacsRemote.setIpAddress(inputMac.getIpaddr().getIpv4Address().getValue());
157         }
158     }
159
160     private static void setMac(final McastMacsRemote mcastMacsRemote, final RemoteMcastMacs inputMac) {
161         if (inputMac.getMacEntryKey() != null) {
162             if (inputMac.getMacEntryKey().equals(HwvtepSouthboundConstants.UNKNOWN_DST_MAC)) {
163                 mcastMacsRemote.setMac(HwvtepSouthboundConstants.UNKNOWN_DST_STRING);
164             } else {
165                 mcastMacsRemote.setMac(inputMac.getMacEntryKey().getValue());
166             }
167         }
168     }
169
170     @Override
171     protected Map<RemoteMcastMacsKey, RemoteMcastMacs> getData(final HwvtepGlobalAugmentation augmentation) {
172         return augmentation.getRemoteMcastMacs();
173     }
174
175     @Override
176     protected boolean areEqual(final RemoteMcastMacs macs1, final RemoteMcastMacs macs2) {
177         if (getOperationalState().isInReconciliation()) {
178             return Objects.equals(macs1.key(), macs2.key())
179                     && compareLocatorSets(macs1.getLocatorSet(), macs2.getLocatorSet());
180         }
181         return Objects.equals(macs1.key(), macs2.key())
182                 && Objects.equals(macs1.getLocatorSet(), macs2.getLocatorSet());
183     }
184
185     private static boolean compareLocatorSets(List<LocatorSet> locatorSet1, List<LocatorSet> locatorSet2) {
186         if (locatorSet1 == null) {
187             locatorSet1 = Collections.emptyList();
188         }
189         if (locatorSet2 == null) {
190             locatorSet2 = Collections.emptyList();
191         }
192         if (locatorSet1.size() != locatorSet2.size()) {
193             return false;
194         }
195         Set<LocatorSet> set1 = Sets.newHashSet(locatorSet1);
196         Set<LocatorSet> set2 = Sets.newHashSet(locatorSet2);
197         return set1.containsAll(set2);
198     }
199
200     static class McastMacUnMetDependencyGetter extends UnMetDependencyGetter<RemoteMcastMacs> {
201
202         @Override
203         public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(final RemoteMcastMacs data) {
204             if (data == null) {
205                 return Collections.emptyList();
206             }
207             return Lists.newArrayList(data.getLogicalSwitchRef().getValue());
208         }
209
210         @Override
211         public List<InstanceIdentifier<?>> getTerminationPointDependencies(final RemoteMcastMacs data) {
212             if (data == null || HwvtepSouthboundUtil.isEmpty(data.getLocatorSet())) {
213                 return Collections.emptyList();
214             }
215             List<InstanceIdentifier<?>> locators = new ArrayList<>();
216             for (LocatorSet locator: data.getLocatorSet()) {
217                 locators.add(locator.getLocatorRef().getValue());
218             }
219             return locators;
220         }
221     }
222
223     @SuppressFBWarnings("UC_USELESS_OBJECT")
224     private void updateLocatorRefCounts(final MdsalUpdate mdsalUpdate) {
225         //decrement the refcounts from old mcast mac
226         //increment the refcounts for new mcast mac
227         RemoteMcastMacs newMac = (RemoteMcastMacs) mdsalUpdate.getNewData();
228         RemoteMcastMacs oldMac = (RemoteMcastMacs) mdsalUpdate.getOldData();
229         InstanceIdentifier<RemoteMcastMacs> macIid = mdsalUpdate.getKey();
230
231         if (oldMac != null && !oldMac.equals(newMac)) {
232             if (oldMac.getLocatorSet() != null) {
233                 List<LocatorSet> removedLocators = new ArrayList<>(oldMac.getLocatorSet());
234                 if (newMac.getLocatorSet() != null) {
235                     removedLocators.removeAll(newMac.getLocatorSet());
236                 }
237                 removedLocators.forEach(iid -> getDeviceInfo().decRefCount(macIid, iid.getLocatorRef().getValue()));
238             }
239         }
240     }
241
242     @Override
243     public void onSuccess(final TransactionBuilder tx) {
244         for (MdsalUpdate mdsalUpdate : updates) {
245             updateLocatorRefCounts(mdsalUpdate);
246             RemoteMcastMacs mac = (RemoteMcastMacs) mdsalUpdate.getNewData();
247             InstanceIdentifier<RemoteMcastMacs> macIid = mdsalUpdate.getKey();
248             getDeviceInfo().updateRemoteMcast(
249                     (InstanceIdentifier<LogicalSwitches>) mac.getLogicalSwitchRef().getValue(), macIid, mac);
250         }
251     }
252
253     @Override
254     protected String getKeyStr(final InstanceIdentifier<RemoteMcastMacs> iid) {
255         return getLsKeyStr(iid.firstKeyOf(RemoteMcastMacs.class).getLogicalSwitchRef().getValue());
256     }
257 }