Update MRI projects for Aluminium
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / LogicalSwitchUcastsRemoveCommand.java
1 /*
2  * Copyright (c) 2015 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.Map.Entry;
18 import java.util.Objects;
19 import java.util.Set;
20 import java.util.concurrent.atomic.AtomicInteger;
21 import java.util.stream.Collectors;
22 import org.opendaylight.mdsal.binding.api.DataTreeModification;
23 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
24 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
25 import org.opendaylight.ovsdb.lib.notation.UUID;
26 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
27 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
28 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
29 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
30 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsLocal;
31 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
32 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalPort;
33 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsLocal;
34 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
35 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class LogicalSwitchUcastsRemoveCommand
46         extends AbstractTransactCommand<LogicalSwitches, LogicalSwitchesKey, HwvtepGlobalAugmentation> {
47
48     private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchUcastsRemoveCommand.class);
49
50     private final AtomicInteger retryCount = new AtomicInteger(5);
51     private final LogicalSwitches logicalSwitches;
52     private final InstanceIdentifier<Node> nodeIid;
53     private final List<LogicalSwitches> deletedLs;
54
55     volatile Map<String, Map<Long, UUID>> updatedPortBindings = new HashMap<>();
56     private boolean firstAttempt = true;
57
58     public LogicalSwitchUcastsRemoveCommand(final HwvtepOperationalState state,
59                                             final Collection<DataTreeModification<Node>> changes,
60                                             final List<LogicalSwitches> deletedLs,
61                                             final LogicalSwitches logicalSwitches) {
62         super(state, changes);
63         this.deletedLs = deletedLs;
64         this.logicalSwitches = logicalSwitches;
65         this.nodeIid = getOperationalState().getConnectionInstance().getInstanceIdentifier();
66     }
67
68     @Override
69     public void execute(final TransactionBuilder transaction) {
70         InstanceIdentifier<LogicalSwitches> lsKey = nodeIid.augmentation(HwvtepGlobalAugmentation.class)
71                 .child(LogicalSwitches.class, logicalSwitches.key());
72         HwvtepDeviceInfo.DeviceData deviceData  = super.<LogicalSwitch>fetchDeviceData(LogicalSwitches.class, lsKey);
73         if (deviceData != null && deviceData.getUuid() != null) {
74
75             UUID logicalSwitchUuid = deviceData.getUuid();
76
77             UcastMacsRemote ucastMacsRemote = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
78                     UcastMacsRemote.class, null);
79             transaction.add(op.delete(ucastMacsRemote.getSchema())
80                     .where(ucastMacsRemote.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
81
82             UcastMacsLocal ucastMacsLocal = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
83                     UcastMacsLocal.class, null);
84             transaction.add(op.delete(ucastMacsLocal.getSchema())
85                     .where(ucastMacsLocal.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
86
87             McastMacsRemote mcastMacsRemote = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
88                     McastMacsRemote.class, null);
89             transaction.add(op.delete(mcastMacsRemote.getSchema())
90                     .where(mcastMacsRemote.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
91
92             McastMacsLocal mcastMacsLocal = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
93                     McastMacsLocal.class, null);
94             transaction.add(op.delete(mcastMacsLocal.getSchema())
95                     .where(mcastMacsLocal.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
96
97             if (firstAttempt) {
98                 LogicalSwitch logicalSwitch = TyperUtils.getTypedRowWrapper(
99                         transaction.getDatabaseSchema(), LogicalSwitch.class, null);
100                 transaction.add(op.delete(logicalSwitch.getSchema()).where(logicalSwitch.getNameColumn().getSchema()
101                         .opEqual(logicalSwitches.getHwvtepNodeName().getValue())).build());
102                 updateControllerTxHistory(TransactionType.DELETE, new StringBuilder(logicalSwitch.toString())
103                         .append(": ").append(logicalSwitches.getHwvtepNodeName()).append(" ")
104                         .append(logicalSwitches.getLogicalSwitchUuid()).append(" ")
105                         .append(logicalSwitches.getTunnelKey()));
106                 LOG.info("CONTROLLER - {} {} {} {} {}", TransactionType.DELETE, logicalSwitch,
107                         logicalSwitches.getHwvtepNodeName(), logicalSwitches.getLogicalSwitchUuid(),
108                         logicalSwitches.getTunnelKey());
109             } else {
110                 for (Entry<String, Map<Long, UUID>> entry : updatedPortBindings.entrySet()) {
111                     PhysicalPort physicalPort = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
112                             PhysicalPort.class);
113                     physicalPort.setName(entry.getKey());
114                     physicalPort.setVlanBindings(entry.getValue());
115                     transaction.add(op.update(physicalPort)
116                             .where(physicalPort.getNameColumn().getSchema().opEqual(physicalPort.getName())).build());
117                     updateControllerTxHistory(TransactionType.UPDATE, physicalPort);
118                     LOG.info("CONTROLLER - {} {}", TransactionType.UPDATE, physicalPort);
119                 }
120             }
121         } else {
122             firstAttempt = false;
123             onSuccess(transaction);
124         }
125     }
126
127     @Override
128     protected Map<LogicalSwitchesKey, LogicalSwitches> getData(final HwvtepGlobalAugmentation augmentation) {
129         return augmentation.getLogicalSwitches();
130     }
131
132     @Override
133     protected boolean areEqual(final LogicalSwitches logicalSwitches1 , final LogicalSwitches logicalSwitches2) {
134         return logicalSwitches1.key().equals(logicalSwitches2.key())
135                 && Objects.equals(logicalSwitches1.getTunnelKey(), logicalSwitches2.getTunnelKey());
136     }
137
138     @Override
139     public void onSuccess(final TransactionBuilder tx) {
140         if (firstAttempt) {
141             //LOG.error("check succeeded in deletion of logical swtich at first attempt ");
142             //succeed in removing the logical switch upon first attempt
143             return;
144         }
145         //LOG.error("check succeeded in deletion of logical swtich after first attempt ");
146         PlainLogicalSwitchRemoveCmd cmd = new PlainLogicalSwitchRemoveCmd(
147                 newOperState(), getChanges(), logicalSwitches, HwvtepSouthboundConstants.LS_REMOVE_RETRIES);
148         hwvtepOperationalState.getConnectionInstance().transact(cmd);
149     }
150
151     @Override
152     public void onFailure(final TransactionBuilder tx) {
153         //Failed to remove logical swith upon first attempt,
154         //will attempt to remove the local ucasts and vlan bindings alone in the next attemtps
155         firstAttempt = false;
156         getFreshPortBindingsExcludingDeleted();
157         super.onFailure(tx);
158     }
159
160     private void getFreshPortBindingsExcludingDeleted() {
161         Set<UUID> deletedLsUuids = new HashSet<>();
162         for (LogicalSwitches ls : deletedLs) {
163             InstanceIdentifier<LogicalSwitches> lsKey = nodeIid
164                     .augmentation(HwvtepGlobalAugmentation.class)
165                     .child(LogicalSwitches.class, ls.key());
166             HwvtepDeviceInfo.DeviceData deviceData  =
167                     super.<LogicalSwitch>fetchDeviceData(LogicalSwitches.class, lsKey);
168             if (deviceData.getUuid() != null) {
169                 deletedLsUuids.add(deviceData.getUuid());
170             }
171         }
172         updatedPortBindings = new HashMap<>();
173         List<TypedBaseTable> portsFromDevice = getOperationalState().getConnectionInstance()
174                 .getHwvtepTableReader().getHwvtepTableEntries(VlanBindings.class);
175         if (portsFromDevice == null || portsFromDevice.isEmpty()) {
176             LOG.debug("Check did not get any bindings from tor while doing failure of logical switch delete");
177             return;
178         }
179         portsFromDevice.stream()
180                 .map(row -> (PhysicalPort) row)
181                 .filter(port -> port.getVlanBindingsColumn() != null && port.getVlanBindingsColumn().getData() != null)
182                 .forEach(port -> {
183                     int originalBindingsSize = port.getVlanBindingsColumn().getData().size();
184                     Map<Long, UUID> bindingsAfterExclusion = excludeVlanBindings(deletedLsUuids, port);
185                     if (bindingsAfterExclusion.size() < originalBindingsSize) {
186                         updatedPortBindings.put(port.getName(), bindingsAfterExclusion);
187                     }
188                 });
189     }
190
191     private Map<Long, UUID> excludeVlanBindings(final Set<UUID> deletedLsUuids, final PhysicalPort port) {
192         return port.getVlanBindingsColumn().getData()
193                 .entrySet().stream()
194                 .peek(entry -> {
195                     if (deletedLsUuids.contains(entry.getValue())) {
196                         LOG.trace("check Excluding the vlan binding {}", entry.getValue());
197                     }
198                 })
199                 .filter(entry -> !deletedLsUuids.contains(entry.getValue()))
200                 .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue()));
201     }
202
203     @Override
204     public boolean retry() {
205         boolean ret = retryCount.decrementAndGet() > 0;
206         return ret;
207     }
208
209     @Override
210     protected boolean isDeleteCmd() {
211         return true;
212     }
213
214 }