fc37e32a49d5bfcfb370f376cd820a835410ff69
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / ovsdb / transact / AutoAttachRemovedCommand.java
1 /*
2  * Copyright © 2016, 2017 Inocybe Technologies 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.southbound.ovsdb.transact;
9
10 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
11
12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Optional;
19 import java.util.concurrent.ExecutionException;
20 import org.opendaylight.mdsal.binding.api.DataTreeModification;
21 import org.opendaylight.mdsal.binding.api.ReadTransaction;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.ovsdb.lib.notation.Mutator;
24 import org.opendaylight.ovsdb.lib.notation.UUID;
25 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
26 import org.opendaylight.ovsdb.schema.openvswitch.AutoAttach;
27 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
28 import org.opendaylight.ovsdb.southbound.InstanceIdentifierCodec;
29 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
30 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Autoattach;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 @SuppressFBWarnings("UPM_UNCALLED_PRIVATE_METHOD")
44 public class AutoAttachRemovedCommand implements TransactCommand {
45     private static final Logger LOG = LoggerFactory.getLogger(AutoAttachRemovedCommand.class);
46
47     @Override
48     public void execute(final TransactionBuilder transaction, final BridgeOperationalState state,
49             final Collection<DataTreeModification<Node>> modifications,
50             final InstanceIdentifierCodec instanceIdentifierCodec) {
51         execute(transaction, state, TransactUtils.extractOriginal(modifications, OvsdbNodeAugmentation.class),
52                 TransactUtils.extractUpdated(modifications, OvsdbNodeAugmentation.class));
53     }
54
55     @Override
56     public void execute(final TransactionBuilder transaction, final BridgeOperationalState state,
57             final DataChangeEvent events, final InstanceIdentifierCodec instanceIdentifierCodec) {
58         execute(transaction, state, TransactUtils.extractOriginal(events, OvsdbNodeAugmentation.class),
59                 TransactUtils.extractUpdated(events, OvsdbNodeAugmentation.class));
60     }
61
62     private void execute(final TransactionBuilder transaction, final BridgeOperationalState state,
63                          final Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> original,
64                          final Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated) {
65
66         for (final Map.Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originalEntry :
67                 original.entrySet()) {
68             final InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid = originalEntry.getKey();
69             final OvsdbNodeAugmentation ovsdbNodeAugmentation = originalEntry.getValue();
70             final OvsdbNodeAugmentation deletedOvsdbNodeAugmentation = updated.get(ovsdbNodeIid);
71
72             if (ovsdbNodeAugmentation != null && deletedOvsdbNodeAugmentation != null) {
73                 final List<Autoattach> origAutoattachList = ovsdbNodeAugmentation.getAutoattach();
74                 final List<Autoattach> deletedAutoattachList = deletedOvsdbNodeAugmentation.getAutoattach();
75                 if (origAutoattachList != null && !origAutoattachList.isEmpty()
76                         && (deletedAutoattachList == null || deletedAutoattachList.isEmpty())) {
77
78                     if (true) {
79                         // FIXME: Remove if loop after ovs community supports external_ids column in AutoAttach Table
80                         LOG.info("UNSUPPORTED FUNCTIONALITY: Auto Attach related CRUD operations are not supported for"
81                                 + " this version of OVSDB schema due to missing external_ids column.");
82                         return;
83                     }
84                     final OvsdbNodeAugmentation currentOvsdbNode =
85                             state.getBridgeNode(ovsdbNodeIid).get().augmentation(OvsdbNodeAugmentation.class);
86                     final List<Autoattach> currentAutoAttach = currentOvsdbNode.getAutoattach();
87                     for (final Autoattach origAutoattach : origAutoattachList) {
88                         final Uri autoAttachId = origAutoattach.getAutoattachId();
89                         deleteAutoAttach(transaction, ovsdbNodeIid, getAutoAttachUuid(currentAutoAttach, autoAttachId));
90                     }
91                 }
92             }
93         }
94     }
95
96     private void deleteAutoAttach(final TransactionBuilder transaction,
97             final InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid,
98             final Uuid autoattachUuid) {
99
100         LOG.debug("Received request to delete Autoattach entry {}", autoattachUuid);
101         final OvsdbBridgeAugmentation bridgeAugmentation = getBridge(ovsdbNodeIid, autoattachUuid);
102         if (autoattachUuid != null && bridgeAugmentation != null) {
103             final UUID uuid = new UUID(autoattachUuid.getValue());
104             final AutoAttach autoattach = transaction.getTypedRowSchema(AutoAttach.class);
105             transaction.add(op.delete(autoattach.getSchema())
106                     .where(autoattach.getUuidColumn().getSchema().opEqual(uuid))
107                     .build());
108             transaction.add(op.comment("AutoAttach: Deleting {} " + uuid
109                     + " attached to " + bridgeAugmentation.getBridgeName().getValue()));
110
111             final Bridge bridge = transaction.getTypedRowSchema(Bridge.class);
112             transaction.add(op.mutate(bridge.getSchema())
113                     .addMutation(bridge.getAutoAttachColumn().getSchema(),
114                             Mutator.DELETE, Collections.singleton(uuid))
115                     .where(bridge.getNameColumn().getSchema()
116                             .opEqual(bridgeAugmentation.getBridgeName().getValue())).build());
117
118             transaction.add(op.comment("Bridge: Mutating " + bridgeAugmentation.getBridgeName().getValue()
119                     + " to remove autoattach column " + uuid));
120         } else {
121             LOG.debug("Unable to delete AutoAttach {} for node {} because it was not found in the operational store, "
122                     + "and thus we cannot retrieve its UUID", autoattachUuid, ovsdbNodeIid);
123         }
124     }
125
126     private Uuid getAutoAttachUuid(final List<Autoattach> currentAutoAttach, final Uri autoAttachId) {
127         if (currentAutoAttach != null && !currentAutoAttach.isEmpty()) {
128             for (final Autoattach autoAttach : currentAutoAttach) {
129                 if (autoAttach.getAutoattachId().equals(autoAttachId)) {
130                     return autoAttach.getAutoattachUuid();
131                 }
132             }
133         }
134         return null;
135     }
136
137     private OvsdbBridgeAugmentation getBridge(final InstanceIdentifier<OvsdbNodeAugmentation> key, final Uuid aaUuid) {
138         if (aaUuid == null) {
139             return null;
140         }
141         OvsdbBridgeAugmentation bridge = null;
142         final InstanceIdentifier<Node> nodeIid = key.firstIdentifierOf(Node.class);
143         try (ReadTransaction transaction = SouthboundProvider.getDb().newReadOnlyTransaction()) {
144             final Optional<Node> nodeOptional = SouthboundUtil.readNode(transaction, nodeIid);
145             if (nodeOptional.isPresent()) {
146                 final List<ManagedNodeEntry> managedNodes =
147                         nodeOptional.get().augmentation(OvsdbNodeAugmentation.class).getManagedNodeEntry();
148                 for (final ManagedNodeEntry managedNode : managedNodes) {
149                     final OvsdbBridgeRef ovsdbBridgeRef = managedNode.getBridgeRef();
150                     final InstanceIdentifier<OvsdbBridgeAugmentation> brIid = ovsdbBridgeRef.getValue()
151                             .firstIdentifierOf(Node.class).augmentation(OvsdbBridgeAugmentation.class);
152                     final Optional<OvsdbBridgeAugmentation> optionalBridge =
153                             transaction.read(LogicalDatastoreType.OPERATIONAL, brIid).get();
154                     bridge = optionalBridge.get();
155                     if (bridge != null && bridge.getAutoAttach() != null
156                             && bridge.getAutoAttach().equals(aaUuid)) {
157                         return bridge;
158                     }
159                 }
160             }
161         } catch (InterruptedException | ExecutionException e) {
162             LOG.warn("Error reading from datastore",e);
163         }
164         return null;
165     }
166 }