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