2 * Copyright (c) 2015 NEC Corporation
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this
7 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.vtn.manager.internal.inventory;
12 import java.util.List;
14 import com.google.common.base.Optional;
15 import com.google.common.util.concurrent.CheckedFuture;
17 import org.slf4j.Logger;
19 import org.opendaylight.vtn.manager.VTNException;
21 import org.opendaylight.vtn.manager.internal.TxContext;
22 import org.opendaylight.vtn.manager.internal.TxQueue;
23 import org.opendaylight.vtn.manager.internal.TxTask;
24 import org.opendaylight.vtn.manager.internal.util.DataStoreListener;
25 import org.opendaylight.vtn.manager.internal.util.DataStoreUtils;
26 import org.opendaylight.vtn.manager.internal.util.inventory.InventoryReader;
27 import org.opendaylight.vtn.manager.internal.util.inventory.InventoryUtils;
28 import org.opendaylight.vtn.manager.internal.util.inventory.SalNode;
29 import org.opendaylight.vtn.manager.internal.util.inventory.SalPort;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
33 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
34 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
35 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
37 import org.opendaylight.yangtools.yang.binding.DataObject;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.inventory.rev150209.vtn.node.info.VtnPort;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.inventory.rev150209.vtn.port.info.PortLink;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.topology.rev150209.IgnoredLinks;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.topology.rev150209.VtnTopology;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.topology.rev150209.ignored.links.IgnoredLink;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.topology.rev150209.vtn.topology.VtnLink;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
52 * Base class for MD-SAL data change listeners that maintain the VTN inventory
55 * @param <T> Type of data object in the MD-SAL datastore to listen.
56 * @param <C> Type of event context.
58 public abstract class InventoryMaintainer<T extends DataObject, C>
59 extends DataStoreListener<T, C> {
61 * The transaction submit queue for the VTN inventory data models.
63 private final TxQueue txQueue;
66 * Construct a new instance.
68 * @param queue A {@link TxQueue} instance used to update the
70 * @param broker A {@link DataBroker} service instance.
71 * @param clz A {@link Class} instance that represents the target type.
72 * @param scope A {@link DataChangeScope} instance used to register
73 * data change listener.
75 protected InventoryMaintainer(TxQueue queue, DataBroker broker,
76 Class<T> clz, DataChangeScope scope) {
79 registerListener(broker, LogicalDatastoreType.OPERATIONAL, scope);
83 * Execute the given transaction task on the transaction queue.
85 * @param task A {@link TxTask} that updates the MD-SAL datastore.
87 protected final void submit(TxTask<?> task) {
92 * Execute the given transaction task for initialization on the
95 * @param task A {@link TxTask} that initializes the MD-SAL datastore.
97 protected final void submitInitial(TxTask<?> task) {
98 txQueue.postFirst(task);
102 * Read the specified VTN port asynchronously.
104 * @param tx A {@link ReadWriteTransaction} instance.
105 * @param sport A {@link SalPort} instance corresponding to the VTN port.
106 * @return A future associated with a MD-SAL datastore read transaction.
108 protected final CheckedFuture<Optional<VtnPort>, ReadFailedException> read(
109 ReadWriteTransaction tx, SalPort sport) {
110 InstanceIdentifier<VtnPort> path = sport.getVtnPortIdentifier();
111 return tx.read(LogicalDatastoreType.OPERATIONAL, path);
115 * Determine whether the given VTN port is present or not.
117 * @param tx A {@link ReadWriteTransaction} instance.
118 * @param sport A {@link SalPort} instance corresponding to the VTN port.
119 * @return {@code true} only if the specified VTN port is present.
120 * @throws VTNException
123 protected final boolean isPresent(ReadWriteTransaction tx, SalPort sport)
124 throws VTNException {
125 InstanceIdentifier<VtnPort> path = sport.getVtnPortIdentifier();
126 LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
127 return DataStoreUtils.read(tx, oper, path).isPresent();
131 * Add the given inter-switch link information into the VTN inventory data.
133 * @param tx A {@link ReadWriteTransaction} instance.
134 * @param lid The identifier of the created link.
135 * @param src A {@link SalPort} instance corresponding to the source
136 * of the created link.
137 * @param dst A {@link SalPort} instance corresponding to the destination
138 * of the created link.
139 * @return {@code true} if the link was added to the vtn-topology list.
140 * {@code false} if the link was added to the ignored-links list.
141 * @throws VTNException
144 protected final boolean addVtnLink(ReadWriteTransaction tx, LinkId lid,
145 SalPort src, SalPort dst)
146 throws VTNException {
147 // Determine whether the VTN port for both termination points are
149 CheckedFuture<Optional<VtnPort>, ReadFailedException> sf =
151 CheckedFuture<Optional<VtnPort>, ReadFailedException> df =
153 boolean srcPresent = DataStoreUtils.read(sf).isPresent();
154 boolean dstPresent = DataStoreUtils.read(df).isPresent();
157 if (srcPresent && dstPresent) {
158 // Create link information.
159 createVtnLink(tx, lid, src, dst);
162 // Put link information into ignored link list.
163 InstanceIdentifier<IgnoredLink> key =
164 InventoryUtils.toIgnoredLinkIdentifier(lid);
166 InventoryUtils.toIgnoredLinkBuilder(lid, src, dst).build();
167 tx.merge(LogicalDatastoreType.OPERATIONAL, key, ilink, true);
175 * Remove all VTN links affected by the the removed VTN node.
177 * @param tx A {@link ReadWriteTransaction} instance.
178 * @param snode A {@link SalNode} instance corresponding to the removed
180 * @throws VTNException
183 protected final void removeVtnLink(ReadWriteTransaction tx, SalNode snode)
184 throws VTNException {
185 removeVtnTopologyLink(tx, snode);
186 removeIgnoredLink(tx, snode);
190 * Remove all VTN links in vtn-topology affected by the removed VTN node.
192 * @param tx A {@link ReadWriteTransaction} instance.
193 * @param snode A {@link SalNode} instance corresponding to the removed
195 * @throws VTNException
198 protected final void removeVtnTopologyLink(ReadWriteTransaction tx,
200 throws VTNException {
201 InstanceIdentifier<VtnTopology> topoPath =
202 InstanceIdentifier.create(VtnTopology.class);
203 LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
204 VtnTopology topology = DataStoreUtils.read(tx, oper, topoPath).
206 if (topology == null) {
210 List<VtnLink> links = topology.getVtnLink();
215 long dpid = snode.getNodeNumber();
216 for (VtnLink vlink: links) {
217 LinkId lid = vlink.getLinkId();
218 SalPort src = SalPort.create(vlink.getSource());
219 SalPort dst = SalPort.create(vlink.getDestination());
220 long srcDpid = src.getNodeNumber();
221 long dstDpid = dst.getNodeNumber();
223 boolean rmLink = false;
224 if (srcDpid == dpid) {
226 if (dstDpid != dpid) {
227 removePortLink(tx, dst, lid);
229 } else if (dstDpid == dpid) {
231 removePortLink(tx, src, lid);
235 InstanceIdentifier<VtnLink> lpath =
236 InventoryUtils.toVtnLinkIdentifier(lid);
237 tx.delete(oper, lpath);
243 * Remove all VTN links in ignored-links affected by the removed VTN node.
245 * @param tx A {@link ReadWriteTransaction} instance.
246 * @param snode A {@link SalNode} instance corresponding to the removed
248 * @throws VTNException
251 protected final void removeIgnoredLink(ReadWriteTransaction tx,
253 throws VTNException {
254 InstanceIdentifier<IgnoredLinks> igPath =
255 InstanceIdentifier.create(IgnoredLinks.class);
256 LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
257 IgnoredLinks igList = DataStoreUtils.read(tx, oper, igPath).orNull();
258 if (igList == null) {
262 List<IgnoredLink> links = igList.getIgnoredLink();
267 long dpid = snode.getNodeNumber();
268 for (IgnoredLink vlink: links) {
269 LinkId lid = vlink.getLinkId();
270 SalPort src = SalPort.create(vlink.getSource());
271 SalPort dst = SalPort.create(vlink.getDestination());
272 long srcDpid = src.getNodeNumber();
273 long dstDpid = dst.getNodeNumber();
275 if (srcDpid == dpid || dstDpid == dpid) {
276 InstanceIdentifier<VtnLink> lpath =
277 InventoryUtils.toVtnLinkIdentifier(lid);
278 tx.delete(LogicalDatastoreType.OPERATIONAL, lpath);
284 * Remove all VTN links affected by the removed VTN port.
286 * @param tx A {@link ReadWriteTransaction} instance.
287 * @param vport A {@link VtnPort} instance corresponding to the removed
290 protected final void removeVtnLink(ReadWriteTransaction tx,
292 List<PortLink> links = vport.getPortLink();
297 for (PortLink plink: links) {
298 LinkId lid = plink.getLinkId();
299 NodeConnectorId peer = plink.getPeer();
300 SalPort p = SalPort.create(peer);
301 removePortLink(tx, p, lid);
303 InstanceIdentifier<VtnLink> lpath =
304 InventoryUtils.toVtnLinkIdentifier(lid);
305 tx.delete(LogicalDatastoreType.OPERATIONAL, lpath);
310 * Remove the specified port link.
312 * @param tx A {@link ReadWriteTransaction} instance.
313 * @param sport A {@link SalPort} instance corresponding to a VTN port.
314 * @param lid A {@link LinkId} that specifies inter-switch link to be
317 protected final void removePortLink(ReadWriteTransaction tx, SalPort sport,
319 InstanceIdentifier<PortLink> path = sport.getPortLinkIdentifier(lid);
320 tx.delete(LogicalDatastoreType.OPERATIONAL, path);
324 * Try to resolve ignored inter-switch links.
326 * @param ctx A runtime context for transaction task.
327 * @param logger A {@link Logger} instance.
328 * @throws VTNException
331 protected final void resolveIgnoredLinks(TxContext ctx, Logger logger)
332 throws VTNException {
333 // Read all ignored inter-switch links.
334 InstanceIdentifier<IgnoredLinks> igPath =
335 InstanceIdentifier.create(IgnoredLinks.class);
336 ReadWriteTransaction tx = ctx.getReadWriteTransaction();
337 LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
338 IgnoredLinks igLinks = DataStoreUtils.read(tx, oper, igPath).orNull();
339 if (igLinks == null) {
343 List<IgnoredLink> igList = igLinks.getIgnoredLink();
344 if (igList == null) {
348 InventoryReader reader = ctx.getInventoryReader();
349 for (IgnoredLink ignored: igList) {
350 SalPort src = SalPort.create(ignored.getSource());
351 SalPort dst = SalPort.create(ignored.getDestination());
352 if (reader.get(src) != null && reader.get(dst) != null) {
353 // Move this link to vtn-topology.
354 LinkId lid = ignored.getLinkId();
355 InstanceIdentifier<IgnoredLink> ipath =
356 InventoryUtils.toIgnoredLinkIdentifier(lid);
357 tx.delete(oper, ipath);
358 createVtnLink(tx, lid, src, dst);
359 logger.info("Inter-switch link has been resolved: {}: {} -> {}",
360 lid.getValue(), src, dst);
366 * Create a VTN link information.
368 * @param tx A {@link ReadWriteTransaction} instance.
369 * @param lid The identifier of the created link.
370 * @param src A {@link SalPort} instance corresponding to the source
371 * of the created link.
372 * @param dst A {@link SalPort} instance corresponding to the destination
373 * of the created link.
375 private void createVtnLink(ReadWriteTransaction tx, LinkId lid,
376 SalPort src, SalPort dst) {
377 // Put the link information into vtn-topology list.
378 InstanceIdentifier<VtnLink> key =
379 InventoryUtils.toVtnLinkIdentifier(lid);
380 VtnLink vlink = InventoryUtils.toVtnLinkBuilder(lid, src, dst).build();
381 LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
382 tx.merge(oper, key, vlink, true);
384 // Create source port link.
385 InstanceIdentifier<PortLink> pkey = src.getPortLinkIdentifier(lid);
386 PortLink plink = InventoryUtils.toPortLinkBuilder(lid, dst).build();
387 tx.merge(oper, pkey, plink, true);
389 // Create destination port link.
390 pkey = dst.getPortLinkIdentifier(lid);
391 plink = InventoryUtils.toPortLinkBuilder(lid, src).build();
392 tx.merge(oper, pkey, plink, true);