f32ed0c9a751875b476f67d334a0e88a51c8fd35
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / PhysicalPortUpdateCommand.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
9 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
10
11 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
12
13 import com.google.common.collect.Lists;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Map.Entry;
21 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
23 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
24 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
25 import org.opendaylight.ovsdb.lib.notation.UUID;
26 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
27 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
28 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalPort;
29 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindingsKey;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
43     private static final Logger LOG = LoggerFactory.getLogger(PhysicalPortUpdateCommand.class);
44     private static final VlanBindingsUnMetDependencyGetter DEPENDENCY_GETTER = new VlanBindingsUnMetDependencyGetter();
45
46     public PhysicalPortUpdateCommand(HwvtepOperationalState state,
47             Collection<DataTreeModification<Node>> changes) {
48         super(state, changes);
49     }
50
51     @Override
52     public void execute(TransactionBuilder transaction) {
53         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> createds =
54                 extractCreated(getChanges(),HwvtepPhysicalPortAugmentation.class);
55         if (!createds.isEmpty()) {
56             for (Entry<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> created:
57                 createds.entrySet()) {
58                 updatePhysicalPort(transaction,  created.getKey(), created.getValue());
59             }
60         }
61         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> updateds =
62                 extractUpdatedPorts(getChanges(), HwvtepPhysicalPortAugmentation.class);
63         if (!updateds.isEmpty()) {
64             for (Entry<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> updated:
65                 updateds.entrySet()) {
66                 updatePhysicalPort(transaction,  updated.getKey(), updated.getValue());
67             }
68         }
69     }
70
71     public void updatePhysicalPort(final TransactionBuilder transaction,
72                                    final InstanceIdentifier<Node> psNodeiid,
73                                    final List<HwvtepPhysicalPortAugmentation> listPort) {
74         //Get physical switch which the port belong to: in operation DS or new created
75         for (HwvtepPhysicalPortAugmentation port : listPort) {
76             LOG.debug("Creating a physical port named: {}", port.getHwvtepNodeName().getValue());
77             HwvtepDeviceInfo.DeviceData deviceOperdata = getDeviceInfo().getDeviceOperData(TerminationPoint.class,
78                     getTpIid(psNodeiid, port.getHwvtepNodeName().getValue()));
79             if (deviceOperdata == null) {
80                 //create a physical port always happens from device
81                 LOG.error("Physical port {} not present in oper datastore", port.getHwvtepNodeName().getValue());
82             } else {
83                 PhysicalPort physicalPort = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
84                         PhysicalPort.class);
85                 physicalPort.setName(port.getHwvtepNodeName().getValue());
86                 setVlanBindings(psNodeiid, physicalPort, port, transaction);
87                 setDescription(physicalPort, port);
88                 String existingPhysicalPortName = port.getHwvtepNodeName().getValue();
89                 PhysicalPort extraPhyscialPort =
90                         TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), PhysicalPort.class);
91                 extraPhyscialPort.setName("");
92                 LOG.trace("execute: updating physical port: {}", physicalPort);
93                 transaction.add(op.update(physicalPort)
94                         .where(extraPhyscialPort.getNameColumn().getSchema().opEqual(existingPhysicalPortName))
95                         .build());
96                 transaction.add(op.comment("Physical Port: Updating " + existingPhysicalPortName));
97                 updateControllerTxHistory(TransactionType.UPDATE, physicalPort);
98             }
99         }
100     }
101
102     private void setDescription(PhysicalPort physicalPort, HwvtepPhysicalPortAugmentation inputPhysicalPort) {
103         if (inputPhysicalPort.getHwvtepNodeDescription() != null) {
104             physicalPort.setDescription(inputPhysicalPort.getHwvtepNodeDescription());
105         }
106     }
107
108     private void setVlanBindings(final InstanceIdentifier<Node> psNodeiid,
109                                  final PhysicalPort physicalPort,
110                                  final HwvtepPhysicalPortAugmentation inputPhysicalPort,
111                                  final TransactionBuilder transaction) {
112         if (inputPhysicalPort.getVlanBindings() != null) {
113             //get UUID by LogicalSwitchRef
114             Map<Long, UUID> bindingMap = new HashMap<>();
115             for (VlanBindings vlanBinding: inputPhysicalPort.getVlanBindings()) {
116                 InstanceIdentifier<VlanBindings> vlanIid = getVlanBindingIid(psNodeiid, physicalPort, vlanBinding);
117                 @SuppressWarnings("unchecked")
118                 InstanceIdentifier<LogicalSwitches> lswitchIid =
119                         (InstanceIdentifier<LogicalSwitches>) vlanBinding.getLogicalSwitchRef().getValue();
120
121                 Map inTransitDependencies = DEPENDENCY_GETTER.getInTransitDependencies(
122                         getOperationalState(), vlanBinding);
123                 Map configDependencies = DEPENDENCY_GETTER.getUnMetConfigDependencies(
124                         getOperationalState(), vlanBinding);
125
126                 if (!HwvtepSouthboundUtil.isEmptyMap(configDependencies)) {
127                     createConfigWaitJob(psNodeiid, inputPhysicalPort,
128                             vlanBinding, configDependencies, vlanIid);
129                     continue;
130                 }
131                 if (!HwvtepSouthboundUtil.isEmptyMap(inTransitDependencies)) {
132                     createOperWaitingJob(psNodeiid, inputPhysicalPort,
133                             vlanBinding, inTransitDependencies, vlanIid);
134                     continue;
135                 }
136
137                 bindingMap.put(vlanBinding.getVlanIdKey().getValue().longValue(),
138                         TransactUtils.getLogicalSwitchUUID(transaction, getOperationalState(), lswitchIid));
139             }
140             physicalPort.setVlanBindings(bindingMap);
141         }
142     }
143
144     private void createOperWaitingJob(final InstanceIdentifier<Node> psNodeiid,
145                                       final HwvtepPhysicalPortAugmentation inputPhysicalPort,
146                                       final VlanBindings vlanBinding,
147                                       final Map inTransitDependencies,
148                                       final InstanceIdentifier<VlanBindings> vlanIid) {
149
150         DependentJob<VlanBindings> opWaitingJob = new DependentJob.OpWaitingJob<VlanBindings>(
151                 vlanIid, vlanBinding, inTransitDependencies) {
152             @Override
153             public void onDependencyResolved(final HwvtepOperationalState operationalState,
154                                              final TransactionBuilder transactionBuilder) {
155                 hwvtepOperationalState = operationalState;
156                 deviceTransaction = transactionBuilder;
157                 updatePhysicalPort(transactionBuilder, psNodeiid, Lists.newArrayList(inputPhysicalPort));
158             }
159         };
160         getDeviceInfo().addJobToQueue(opWaitingJob);
161     }
162
163     private void createConfigWaitJob(final InstanceIdentifier<Node> psNodeiid,
164                                      final HwvtepPhysicalPortAugmentation inputPhysicalPort,
165                                      final VlanBindings vlanBinding,
166                                      final Map configDependencies,
167                                      final InstanceIdentifier<VlanBindings> vlanIid) {
168
169         DependentJob<VlanBindings> configWaitingJob = new DependentJob.ConfigWaitingJob<VlanBindings>(
170                 vlanIid, vlanBinding, configDependencies) {
171             @Override
172             public void onDependencyResolved(final HwvtepOperationalState operationalState,
173                                              final TransactionBuilder transactionBuilder) {
174                 hwvtepOperationalState = operationalState;
175                 deviceTransaction = transactionBuilder;
176                 updatePhysicalPort(transactionBuilder, psNodeiid, Lists.newArrayList(inputPhysicalPort));
177             }
178         };
179         getDeviceInfo().addJobToQueue(configWaitingJob);
180     }
181
182     private InstanceIdentifier<TerminationPoint> getTpIid(final InstanceIdentifier<Node> psNodeiid,
183                                                           final String portName) {
184         return psNodeiid.child(
185                 TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
186     }
187
188     private InstanceIdentifier<VlanBindings> getVlanBindingIid(
189             final InstanceIdentifier<Node> psNodeiid,
190             final PhysicalPort physicalPort,
191             final VlanBindings vlanBinding) {
192
193         return psNodeiid.child(
194                 TerminationPoint.class, new TerminationPointKey(new TpId(physicalPort.getName())))
195                 .augmentation(HwvtepPhysicalPortAugmentation.class)
196                 .child(VlanBindings.class, new VlanBindingsKey(vlanBinding.getVlanIdKey()));
197     }
198
199     static class VlanBindingsUnMetDependencyGetter extends UnMetDependencyGetter<VlanBindings> {
200
201         @Override
202         public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(VlanBindings data) {
203             if (data == null) {
204                 return Collections.emptyList();
205             }
206             return Collections.singletonList(data.getLogicalSwitchRef().getValue());
207         }
208
209         @Override
210         public List<InstanceIdentifier<?>> getTerminationPointDependencies(VlanBindings data) {
211             return Collections.emptyList();
212         }
213     }
214
215     private Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> extractCreated(
216             Collection<DataTreeModification<Node>> changes, Class<HwvtepPhysicalPortAugmentation> class1) {
217         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> result = new HashMap<>();
218         if (changes != null && !changes.isEmpty()) {
219             for (DataTreeModification<Node> change : changes) {
220                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
221                 final DataObjectModification<Node> mod = change.getRootNode();
222                 Node created = TransactUtils.getCreated(mod);
223                 if (created != null) {
224                     List<HwvtepPhysicalPortAugmentation> portListUpdated = new ArrayList<>();
225                     if (created.getTerminationPoint() != null) {
226                         for (TerminationPoint tp : created.getTerminationPoint()) {
227                             HwvtepPhysicalPortAugmentation hppAugmentation =
228                                     tp.augmentation(HwvtepPhysicalPortAugmentation.class);
229                             if (hppAugmentation != null) {
230                                 portListUpdated.add(hppAugmentation);
231                             }
232                         }
233                     }
234                     result.put(key, portListUpdated);
235                 }
236             }
237         }
238         return result;
239     }
240
241     private Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> extractUpdatedPorts(
242             Collection<DataTreeModification<Node>> changes, Class<HwvtepPhysicalPortAugmentation> class1) {
243         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> result = new HashMap<>();
244         if (changes != null && !changes.isEmpty()) {
245             for (DataTreeModification<Node> change : changes) {
246                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
247                 final DataObjectModification<Node> mod = change.getRootNode();
248                 Node updated = TransactUtils.getUpdated(mod);
249                 Node before = mod.getDataBefore();
250                 if (updated != null && before != null) {
251                     List<HwvtepPhysicalPortAugmentation> portListUpdated = new ArrayList<>();
252                     List<HwvtepPhysicalPortAugmentation> portListBefore = new ArrayList<>();
253                     if (updated.getTerminationPoint() != null) {
254                         for (TerminationPoint tp : updated.getTerminationPoint()) {
255                             HwvtepPhysicalPortAugmentation hppAugmentation =
256                                     tp.augmentation(HwvtepPhysicalPortAugmentation.class);
257                             if (hppAugmentation != null) {
258                                 portListUpdated.add(hppAugmentation);
259                             }
260                         }
261                     }
262                     if (before.getTerminationPoint() != null) {
263                         for (TerminationPoint tp : before.getTerminationPoint()) {
264                             HwvtepPhysicalPortAugmentation hppAugmentation =
265                                     tp.augmentation(HwvtepPhysicalPortAugmentation.class);
266                             if (hppAugmentation != null) {
267                                 portListBefore.add(hppAugmentation);
268                             }
269                         }
270                     }
271                     portListUpdated.removeAll(portListBefore);
272                     result.put(key, portListUpdated);
273                 }
274             }
275         }
276         return result;
277     }
278 }