Merge "BUG-4417 Program tunnel flows on new Neutron nodes"
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / ovsdb / transact / AutoAttachRemovedCommand.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.ovsdb.southbound.ovsdb.transact;
10
11 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
12
13 import java.util.List;
14 import java.util.Map;
15 import java.util.concurrent.ExecutionException;
16
17 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.ovsdb.lib.notation.Mutator;
21 import org.opendaylight.ovsdb.lib.notation.UUID;
22 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
23 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
24 import org.opendaylight.ovsdb.schema.openvswitch.AutoAttach;
25 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
26 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Autoattach;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
35 import org.opendaylight.yangtools.yang.binding.DataObject;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import com.google.common.base.Optional;
41 import com.google.common.base.Preconditions;
42 import com.google.common.collect.Sets;
43
44 public class AutoAttachRemovedCommand extends AbstractTransactCommand {
45     private static final Logger LOG = LoggerFactory.getLogger(AutoAttachRemovedCommand.class);
46
47     public AutoAttachRemovedCommand(BridgeOperationalState state,
48             AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
49         super(state, changes);
50     }
51
52     @Override
53     public void execute(TransactionBuilder transaction) {
54
55         // FIXME: Remove if loop after ovs community supports external_ids column in AutoAttach Table
56         if (true) {
57             try {
58                 throw new UnsupportedOperationException("CRUD operations not supported from ODL for auto_attach column for"
59                         + " this version of ovsdb schema due to missing external_ids column");
60             } catch (UnsupportedOperationException e) {
61                 LOG.debug(e.getMessage());
62             }
63             return;
64         }
65
66         @SuppressWarnings("unused")
67         Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> original =
68         TransactUtils.extractOriginal(getChanges(), OvsdbNodeAugmentation.class);
69
70         Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> deleted =
71                 TransactUtils.extractUpdated(getChanges(), OvsdbNodeAugmentation.class);
72
73         for (Map.Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originalEntry : original.entrySet()) {
74             InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid = originalEntry.getKey();
75             OvsdbNodeAugmentation ovsdbNodeAugmentation = originalEntry.getValue();
76             OvsdbNodeAugmentation deletedOvsdbNodeAugmentation = deleted.get(ovsdbNodeIid);
77
78             if (ovsdbNodeAugmentation != null && deletedOvsdbNodeAugmentation != null) {
79                 List<Autoattach> origAutoattachList = ovsdbNodeAugmentation.getAutoattach();
80                 List<Autoattach> deletedAutoattachList = deletedOvsdbNodeAugmentation.getAutoattach();
81                 if(origAutoattachList != null && !origAutoattachList.isEmpty() &&
82                         (deletedAutoattachList == null || deletedAutoattachList.isEmpty())) {
83
84                     OvsdbNodeAugmentation currentOvsdbNode =
85                             getOperationalState().getBridgeNode(ovsdbNodeIid).get().getAugmentation(OvsdbNodeAugmentation.class);
86                     List<Autoattach> currentAutoAttach = currentOvsdbNode.getAutoattach();
87                     for (Autoattach origAutoattach : origAutoattachList) {
88                         Uri autoAttachId = origAutoattach.getAutoattachId();
89                         deleteAutoAttach(transaction, ovsdbNodeIid, getAutoAttachUuid(currentAutoAttach, autoAttachId));
90                     }
91                 }
92             }
93         }
94     }
95
96     private void deleteAutoAttach(TransactionBuilder transaction,
97             InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid,
98             Uuid autoattachUuid) {
99
100         LOG.debug("Received request to delete Autoattach entry {}", autoattachUuid);
101         OvsdbBridgeAugmentation bridgeAugmentation = getBridge(ovsdbNodeIid, autoattachUuid);
102         if (autoattachUuid != null && bridgeAugmentation != null) {
103             UUID uuid = new UUID(autoattachUuid.getValue());
104             AutoAttach autoattach = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), AutoAttach.class, null);
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             Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
112                     Bridge.class,null);
113
114             transaction.add(op.mutate(bridge.getSchema())
115                     .addMutation(bridge.getAutoAttachColumn().getSchema(),
116                             Mutator.DELETE, Sets.newHashSet(uuid))
117                     .where(bridge.getNameColumn().getSchema()
118                             .opEqual(bridgeAugmentation.getBridgeName().getValue())).build());
119
120             transaction.add(op.comment("Bridge: Mutating " + bridgeAugmentation.getBridgeName().getValue()
121                     + " to remove autoattach column " + uuid));
122         } else {
123             LOG.debug("Unable to delete AutoAttach {} for node {} because it was not found in the operational store, "
124                     + "and thus we cannot retrieve its UUID", autoattachUuid, ovsdbNodeIid);
125         }
126     }
127
128     private Uuid getAutoAttachUuid(List<Autoattach> currentAutoAttach, Uri autoAttachId) {
129         if (currentAutoAttach != null && !currentAutoAttach.isEmpty()) {
130             for (Autoattach autoAttach : currentAutoAttach) {
131                 if (autoAttach.getAutoattachId().equals(autoAttachId)) {
132                     return autoAttach.getAutoattachUuid();
133                 }
134             }
135         }
136         return null;
137     }
138
139     private OvsdbBridgeAugmentation getBridge(InstanceIdentifier<OvsdbNodeAugmentation> key, Uuid aaUuid) {
140         Preconditions.checkNotNull(aaUuid);
141         OvsdbBridgeAugmentation bridge = null;
142         InstanceIdentifier<Node> nodeIid = key.firstIdentifierOf(Node.class);
143         try (ReadOnlyTransaction transaction = SouthboundProvider.getDb().newReadOnlyTransaction()) {
144             Optional<Node> nodeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid).get();
145             if (nodeOptional.isPresent()) {
146                 List<ManagedNodeEntry> managedNodes = nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class).getManagedNodeEntry();
147                 for (ManagedNodeEntry managedNode : managedNodes) {
148                     OvsdbBridgeRef ovsdbBridgeRef = managedNode.getBridgeRef();
149                     InstanceIdentifier<OvsdbBridgeAugmentation> brIid = ovsdbBridgeRef.getValue()
150                             .firstIdentifierOf(Node.class).augmentation(OvsdbBridgeAugmentation.class);
151                     Optional<OvsdbBridgeAugmentation> optionalBridge = transaction.read(LogicalDatastoreType.OPERATIONAL, brIid).get();
152                     bridge = optionalBridge.orNull();
153                     if(bridge != null && bridge.getAutoAttach() != null
154                             && bridge.getAutoAttach().equals(aaUuid)) {
155                         return bridge;
156                     }
157                 }
158             }
159         } catch (InterruptedException | ExecutionException e) {
160             LOG.warn("Error reading from datastore",e);
161         }
162         return null;
163     }
164 }