597e11dcd2ce24c543ff8ecfeb74644147f90a42
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / reconciliation / configuration / TerminationPointConfigReconciliationTask.java
1 /*
2  * Copyright (c) 2016, 2017 NEC Corporation 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.reconciliation.configuration;
9
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17
18 import org.opendaylight.ovsdb.southbound.InstanceIdentifierCodec;
19 import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
20 import org.opendaylight.ovsdb.southbound.OvsdbConnectionManager;
21 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
22 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
23 import org.opendaylight.ovsdb.southbound.ovsdb.transact.BridgeOperationalState;
24 import org.opendaylight.ovsdb.southbound.ovsdb.transact.DataChangeEvent;
25 import org.opendaylight.ovsdb.southbound.ovsdb.transact.TerminationPointCreateCommand;
26 import org.opendaylight.ovsdb.southbound.ovsdb.transact.TerminationPointDeleteCommand;
27 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationManager;
28 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationTask;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
32 import org.opendaylight.yangtools.yang.binding.DataObject;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * Reconciliation task to reconcile termination point configurations in the config datastore.
39  * When the OVS switch connects to the ODL, the list of all bridge and termination point
40  * configurations in the config datastore are obtained.
41  * We then listens for any new bridge show up in the operational data store.
42  * If the new bridge is in the list of bridges to be reconciled as described above
43  * termination point reconciliation is triggered for that bridge.
44  */
45 public class TerminationPointConfigReconciliationTask extends ReconciliationTask {
46
47     private static final Logger LOG = LoggerFactory.getLogger(TerminationPointConfigReconciliationTask.class);
48     private final OvsdbConnectionInstance connectionInstance;
49     private final InstanceIdentifierCodec instanceIdentifierCodec;
50     private final Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
51         operTerminationPoints;
52
53     public TerminationPointConfigReconciliationTask(final ReconciliationManager reconciliationManager,
54             final OvsdbConnectionManager connectionManager, final Node bridgeNode,
55             final InstanceIdentifier<?> bridgeIid, final OvsdbConnectionInstance connectionInstance,
56             final Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
57                 operTerminationPoints,
58             final InstanceIdentifierCodec instanceIdentifierCodec) {
59         super(reconciliationManager, connectionManager, bridgeIid, bridgeNode);
60         this.connectionInstance = connectionInstance;
61         this.instanceIdentifierCodec = instanceIdentifierCodec;
62         this.operTerminationPoints = operTerminationPoints;
63     }
64
65     @Override
66     public boolean reconcileConfiguration(final OvsdbConnectionManager connectionManager) {
67         final Map<InstanceIdentifier<?>, DataObject> changes = new HashMap<>();
68         final Node configNodeData = ((Node) configData);
69         LOG.debug("Reconcile Termination Point Configuration for node {}", configNodeData.getNodeId());
70         changes.putAll(SouthboundMapper.extractTerminationPointConfigurationChanges(configNodeData));
71         DataChangeEvent changeEvents = new DataChangeEvent() {
72             @Override
73             public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
74                 return changes;
75             }
76
77             @Override
78             public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
79                 return Collections.emptyMap();
80             }
81
82             @Override
83             public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
84                 return Collections.emptyMap();
85             }
86
87             @Override
88             public Set<InstanceIdentifier<?>> getRemovedPaths() {
89                 return Collections.emptySet();
90             }
91         };
92
93         connectionInstance.transact(new TerminationPointCreateCommand(),
94                         new BridgeOperationalState(reconciliationManager.getDb(), changeEvents),
95                         changeEvents, instanceIdentifierCodec);
96
97         List<String> configTerminationPoints = new ArrayList<>();
98         if (configNodeData.getTerminationPoint() != null) {
99             configNodeData.getTerminationPoint().forEach(entry -> {
100                 configTerminationPoints.add(entry.getTpId().getValue());
101             });
102         }
103
104         Set<InstanceIdentifier<?>> removeTerminationPoints = new HashSet<>();
105         final Map<InstanceIdentifier<?>, DataObject> original = new HashMap<>();
106         final InstanceIdentifier<Node> bridgeNodeIid =
107                 SouthboundMapper.createInstanceIdentifier(configNodeData.getNodeId());
108         original.put(bridgeNodeIid, configNodeData);
109         LOG.trace("Config Topology Termination Points during Reconciliation {} for bridge {}",
110             configTerminationPoints, bridgeNodeIid);
111         LOG.trace("Oper Topology Termination Points during Reconciliation {} for bridge {}",
112             operTerminationPoints, bridgeNodeIid);
113         for (Map.Entry<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation> entry :
114                 operTerminationPoints.entrySet()) {
115             OvsdbTerminationPointAugmentation terminationPoint = entry.getValue();
116             if (configTerminationPoints.contains(terminationPoint.getName())) {
117                 LOG.trace("Termination Point {} from Oper Topology also present in config topology During Reconcile",
118                     terminationPoint.getName());
119             } else {
120                 LOG.trace("Termination Point {} from Oper Topology NOT present in config topology During Reconcile,"
121                         + "checking if this created by ODL and perform delete reconciliation",
122                     terminationPoint.getName());
123                 List<PortExternalIds> externalIds = terminationPoint.getPortExternalIds();
124                 if (externalIds != null) {
125                     for (PortExternalIds portExternalIds : externalIds) {
126                         if (portExternalIds.getExternalIdKey().equals(SouthboundConstants.CREATED_BY)
127                             && portExternalIds.getExternalIdValue().equals(SouthboundConstants.ODL)) {
128                             LOG.trace("Termination Point {} created by ODL. Marking for deletion during reconcile",
129                                 entry.getKey());
130                             removeTerminationPoints.add(entry.getKey());
131                             original.put(entry.getKey(), entry.getValue());
132                             break;
133                         }
134                     }
135                 }
136             }
137         }
138
139         DataChangeEvent deleteChangeEvents = new DataChangeEvent() {
140             @Override
141             public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
142                 return Collections.emptyMap();
143             }
144
145             @Override
146             public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
147                 return original;
148             }
149
150             @Override
151             public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
152                 return original;
153             }
154
155             @Override
156             public Set<InstanceIdentifier<?>> getRemovedPaths() {
157                 return removeTerminationPoints;
158             }
159         };
160
161         connectionInstance.transact(new TerminationPointDeleteCommand(),
162                 new BridgeOperationalState(reconciliationManager.getDb(), deleteChangeEvents),
163                 deleteChangeEvents, instanceIdentifierCodec);
164
165         return true;
166     }
167
168     @Override
169     public void doRetry(boolean wasPreviousAttemptSuccessful) {
170     }
171
172     @Override
173     public void checkReadinessAndProcess() {
174     }
175
176     @Override
177     public long retryDelayInMills() {
178         return 0;
179     }
180 }