2 * Copyright © 2015, 2017 China Telecom Beijing Research Institute and others. All rights reserved.
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
9 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
11 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
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;
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.schema.hardwarevtep.PhysicalPort;
28 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindingsKey;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
41 public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
42 private static final Logger LOG = LoggerFactory.getLogger(PhysicalPortUpdateCommand.class);
43 private static final VlanBindingsUnMetDependencyGetter DEPENDENCY_GETTER = new VlanBindingsUnMetDependencyGetter();
45 public PhysicalPortUpdateCommand(final HwvtepOperationalState state,
46 final Collection<DataTreeModification<Node>> changes) {
47 super(state, changes);
51 public void execute(final TransactionBuilder transaction) {
52 Map<InstanceIdentifier<Node>, List<TerminationPoint>> createds =
53 extractCreated(getChanges(),TerminationPoint.class);
54 if (!createds.isEmpty()) {
55 for (Entry<InstanceIdentifier<Node>, List<TerminationPoint>> created:
56 createds.entrySet()) {
57 updatePhysicalPort(transaction, created.getKey(), created.getValue());
60 Map<InstanceIdentifier<Node>, List<TerminationPoint>> updateds =
61 extractUpdatedPorts(getChanges(), TerminationPoint.class);
62 if (!updateds.isEmpty()) {
63 for (Entry<InstanceIdentifier<Node>, List<TerminationPoint>> updated:
64 updateds.entrySet()) {
65 updatePhysicalPort(transaction, updated.getKey(), updated.getValue());
70 public void updatePhysicalPort(final TransactionBuilder transaction,
71 final InstanceIdentifier<Node> psNodeiid,
72 final List<TerminationPoint> listPort) {
73 //Get physical switch which the port belong to: in operation DS or new created
74 for (TerminationPoint tp : listPort) {
75 HwvtepPhysicalPortAugmentation port = tp.augmentation(HwvtepPhysicalPortAugmentation.class);
76 LOG.debug("Creating a physical port named: {}", port.getHwvtepNodeName().getValue());
77 InstanceIdentifier<TerminationPoint> key = getTpIid(psNodeiid, port.getHwvtepNodeName().getValue());
79 getOperationalState().getDeviceInfo().updateConfigData(TerminationPoint.class, key, tp);
80 HwvtepDeviceInfo.DeviceData deviceOperdata = getDeviceInfo().getDeviceOperData(TerminationPoint.class, key);
81 if (deviceOperdata == null || deviceOperdata.getData() == null) {
82 LOG.error("Updated the device oper cache for port from actual device {}", key);
83 deviceOperdata = super.fetchDeviceData(TerminationPoint.class, key);
85 if (deviceOperdata == null || deviceOperdata.getData() == null) {
86 //create a physical port always happens from device
87 LOG.error("Physical port {} not present in oper datastore", port.getHwvtepNodeName().getValue());
89 PhysicalPort physicalPort = transaction.getTypedRowWrapper(PhysicalPort.class);
90 physicalPort.setName(port.getHwvtepNodeName().getValue());
91 setVlanBindings(psNodeiid, physicalPort, tp, transaction);
92 setDescription(physicalPort, port);
93 String existingPhysicalPortName = port.getHwvtepNodeName().getValue();
94 PhysicalPort extraPhyscialPort = transaction.getTypedRowWrapper(PhysicalPort.class);
95 extraPhyscialPort.setName("");
96 LOG.trace("execute: updating physical port: {}", physicalPort);
97 transaction.add(op.update(physicalPort)
98 .where(extraPhyscialPort.getNameColumn().getSchema().opEqual(existingPhysicalPortName))
100 transaction.add(op.comment("Physical Port: Updating " + existingPhysicalPortName));
101 updateControllerTxHistory(TransactionType.UPDATE, physicalPort);
106 private static void setDescription(final PhysicalPort physicalPort,
107 final HwvtepPhysicalPortAugmentation inputPhysicalPort) {
108 if (inputPhysicalPort.getHwvtepNodeDescription() != null) {
109 physicalPort.setDescription(inputPhysicalPort.getHwvtepNodeDescription());
113 private void setVlanBindings(final InstanceIdentifier<Node> psNodeiid,
114 final PhysicalPort physicalPort,
115 final TerminationPoint tp,
116 final TransactionBuilder transaction) {
117 HwvtepPhysicalPortAugmentation inputPhysicalPort = tp.augmentation(HwvtepPhysicalPortAugmentation.class);
118 if (inputPhysicalPort.getVlanBindings() != null) {
119 //get UUID by LogicalSwitchRef
120 Map<Long, UUID> bindingMap = new HashMap<>();
121 for (VlanBindings vlanBinding: inputPhysicalPort.getVlanBindings()) {
122 InstanceIdentifier<VlanBindings> vlanIid = getVlanBindingIid(psNodeiid, physicalPort, vlanBinding);
123 @SuppressWarnings("unchecked")
124 InstanceIdentifier<LogicalSwitches> lswitchIid =
125 (InstanceIdentifier<LogicalSwitches>) vlanBinding.getLogicalSwitchRef().getValue();
127 Map inTransitDependencies = DEPENDENCY_GETTER.getInTransitDependencies(
128 getOperationalState(), vlanBinding);
129 Map configDependencies = DEPENDENCY_GETTER.getUnMetConfigDependencies(
130 getOperationalState(), vlanBinding);
132 if (!HwvtepSouthboundUtil.isEmptyMap(configDependencies)) {
133 createConfigWaitJob(psNodeiid, tp,
134 vlanBinding, configDependencies, vlanIid);
137 if (!HwvtepSouthboundUtil.isEmptyMap(inTransitDependencies)) {
138 createOperWaitingJob(psNodeiid, tp,
139 vlanBinding, inTransitDependencies, vlanIid);
143 UUID lsUUid = TransactUtils.getLogicalSwitchUUID(transaction, getOperationalState(), lswitchIid);
144 if (lsUUid == null) {
145 LOG.error("Could not get the logical switch uuid for {}", vlanBinding);
148 bindingMap.put(vlanBinding.getVlanIdKey().getValue().longValue(), lsUUid);
150 physicalPort.setVlanBindings(bindingMap);
154 private void createOperWaitingJob(final InstanceIdentifier<Node> psNodeiid,
155 final TerminationPoint inputPhysicalPort,
156 final VlanBindings vlanBinding,
157 final Map inTransitDependencies,
158 final InstanceIdentifier<VlanBindings> vlanIid) {
160 DependentJob<VlanBindings> opWaitingJob = new DependentJob.OpWaitingJob<VlanBindings>(
161 vlanIid, vlanBinding, inTransitDependencies) {
163 public void onDependencyResolved(final HwvtepOperationalState operationalState,
164 final TransactionBuilder transactionBuilder) {
165 hwvtepOperationalState = operationalState;
166 deviceTransaction = transactionBuilder;
167 updatePhysicalPort(transactionBuilder, psNodeiid, Lists.newArrayList(inputPhysicalPort));
170 getDeviceInfo().addJobToQueue(opWaitingJob);
173 private void createConfigWaitJob(final InstanceIdentifier<Node> psNodeiid,
174 final TerminationPoint inputPhysicalPort,
175 final VlanBindings vlanBinding,
176 final Map configDependencies,
177 final InstanceIdentifier<VlanBindings> vlanIid) {
179 DependentJob<VlanBindings> configWaitingJob = new DependentJob.ConfigWaitingJob<VlanBindings>(
180 vlanIid, vlanBinding, configDependencies) {
182 public void onDependencyResolved(final HwvtepOperationalState operationalState,
183 final TransactionBuilder transactionBuilder) {
184 hwvtepOperationalState = operationalState;
185 deviceTransaction = transactionBuilder;
186 updatePhysicalPort(transactionBuilder, psNodeiid, Lists.newArrayList(inputPhysicalPort));
189 getDeviceInfo().addJobToQueue(configWaitingJob);
192 private static InstanceIdentifier<TerminationPoint> getTpIid(final InstanceIdentifier<Node> psNodeiid,
193 final String portName) {
194 return psNodeiid.child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
197 private static InstanceIdentifier<VlanBindings> getVlanBindingIid(final InstanceIdentifier<Node> psNodeiid,
198 final PhysicalPort physicalPort,
199 final VlanBindings vlanBinding) {
200 return getTpIid(psNodeiid, physicalPort.getName())
201 .augmentation(HwvtepPhysicalPortAugmentation.class)
202 .child(VlanBindings.class, new VlanBindingsKey(vlanBinding.getVlanIdKey()));
205 static class VlanBindingsUnMetDependencyGetter extends UnMetDependencyGetter<VlanBindings> {
208 public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(final VlanBindings data) {
210 return Collections.emptyList();
212 return Collections.singletonList(data.getLogicalSwitchRef().getValue());
216 public List<InstanceIdentifier<?>> getTerminationPointDependencies(final VlanBindings data) {
217 return Collections.emptyList();
221 private static Map<InstanceIdentifier<Node>, List<TerminationPoint>> extractCreated(
222 final Collection<DataTreeModification<Node>> changes, final Class<TerminationPoint> class1) {
223 Map<InstanceIdentifier<Node>, List<TerminationPoint>> result = new HashMap<>();
224 if (changes != null && !changes.isEmpty()) {
225 for (DataTreeModification<Node> change : changes) {
226 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
227 final DataObjectModification<Node> mod = change.getRootNode();
228 Node created = TransactUtils.getCreated(mod);
229 if (created != null) {
230 List<TerminationPoint> portListUpdated = new ArrayList<>();
231 if (created.getTerminationPoint() != null) {
232 for (TerminationPoint tp : created.getTerminationPoint()) {
233 HwvtepPhysicalPortAugmentation hppAugmentation =
234 tp.augmentation(HwvtepPhysicalPortAugmentation.class);
235 if (hppAugmentation != null) {
236 portListUpdated.add(tp);
240 result.put(key, portListUpdated);
247 private static Map<InstanceIdentifier<Node>, List<TerminationPoint>> extractUpdatedPorts(
248 final Collection<DataTreeModification<Node>> changes, final Class<TerminationPoint> class1) {
249 Map<InstanceIdentifier<Node>, List<TerminationPoint>> result = new HashMap<>();
250 if (changes != null && !changes.isEmpty()) {
251 for (DataTreeModification<Node> change : changes) {
252 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
253 final DataObjectModification<Node> mod = change.getRootNode();
254 Node updated = TransactUtils.getUpdated(mod);
255 Node before = mod.getDataBefore();
256 if (updated != null && before != null) {
257 List<TerminationPoint> portListUpdated = new ArrayList<>();
258 List<TerminationPoint> portListBefore = new ArrayList<>();
259 if (updated.getTerminationPoint() != null) {
260 for (TerminationPoint tp : updated.getTerminationPoint()) {
261 HwvtepPhysicalPortAugmentation hppAugmentation =
262 tp.augmentation(HwvtepPhysicalPortAugmentation.class);
263 if (hppAugmentation != null) {
264 portListUpdated.add(tp);
268 if (before.getTerminationPoint() != null) {
269 for (TerminationPoint tp : before.getTerminationPoint()) {
270 HwvtepPhysicalPortAugmentation hppAugmentation =
271 tp.augmentation(HwvtepPhysicalPortAugmentation.class);
272 if (hppAugmentation != null) {
273 portListBefore.add(tp);
277 portListUpdated.removeAll(portListBefore);
278 result.put(key, portListUpdated);
285 protected String getKeyStr(InstanceIdentifier iid) {
287 return ((TerminationPoint)iid.firstKeyOf(TerminationPoint.class)).getTpId().getValue();
288 } catch (ClassCastException exp) {
289 LOG.error("Error in getting the TerminationPoint id ", exp);
291 return super.getKeyStr(iid);