2 * Copyright (c) 2021 Orange. 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
8 package org.opendaylight.bgpcep.pcep.server.provider;
10 import static java.util.Objects.requireNonNull;
12 import java.util.Collection;
13 import java.util.List;
14 import java.util.stream.Collectors;
15 import org.opendaylight.mdsal.binding.api.DataBroker;
16 import org.opendaylight.mdsal.binding.api.DataObjectModification;
17 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
18 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
19 import org.opendaylight.mdsal.binding.api.DataTreeModification;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PcepNodeConfig;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLsp;
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
27 import org.opendaylight.yangtools.concepts.ListenerRegistration;
28 import org.opendaylight.yangtools.yang.binding.DataObject;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
35 * This Class Implements the DataStoreService interface providing the methods required to manage the path
36 * representation elements in the Data Store.
38 * @author Olivier Dugeon
41 public final class PathManagerListener implements DataTreeChangeListener<Node>, AutoCloseable {
42 private static final Logger LOG = LoggerFactory.getLogger(PathManagerListener.class);
43 private ListenerRegistration<PathManagerListener> listenerRegistration;
45 private final PathManagerProvider pathManager;
47 public PathManagerListener(final DataBroker dataBroker, KeyedInstanceIdentifier<Topology, TopologyKey> topology,
48 final PathManagerProvider pathManager) {
49 requireNonNull(dataBroker);
50 requireNonNull(topology);
51 this.pathManager = requireNonNull(pathManager);
52 final InstanceIdentifier<Node> nodeTopology = topology.child(Node.class);
53 this.listenerRegistration = dataBroker.registerDataTreeChangeListener(
54 DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION, nodeTopology), this);
55 LOG.info("Registered listener for Managed TE Path on Topology {}",
56 topology.getKey().getTopologyId().getValue());
60 * Close this Listener.
64 if (this.listenerRegistration != null) {
65 LOG.debug("Unregistered listener {} for Managed TE Path", this);
66 this.listenerRegistration.close();
67 this.listenerRegistration = null;
72 * Handle Configured LSP modifications.
74 * @param nodeId Node Identifier to which the modified children belongs to.
75 * @param lspMod List of Configured LSP modifications.
77 private void handleLspChange(NodeId nodeId, List<? extends DataObjectModification<? extends DataObject>> lspMod) {
78 for (DataObjectModification<? extends DataObject> lsp : lspMod) {
80 switch (lsp.getModificationType()) {
82 cfgLsp = (ConfiguredLsp) lsp.getDataBefore();
83 LOG.debug("Delete Managed TE Path: {}", cfgLsp.getName());
84 pathManager.deleteManagedTePath(nodeId, cfgLsp.key());
86 case SUBTREE_MODIFIED:
88 cfgLsp = (ConfiguredLsp) lsp.getDataAfter();
89 LOG.debug("Update Managed TE Path {}", cfgLsp);
90 pathManager.createManagedTePath(nodeId, cfgLsp);
100 * Parse Sub Tree modification. Given list has been filtered to get only Path Computation Client1 modifications.
101 * This function first create, update or delete Managed TE Node that corresponds to the given NodeId. Then, it
102 * filter the children to retain only the Configured LSP modifications.
104 * @param nodeId Node Identifier to which the modified children belongs to.
105 * @param pccMod List of PCEP Node Configuration modifications.
107 private void handlePccChange(NodeId nodeId, List<? extends DataObjectModification<? extends DataObject>> pccMod) {
108 for (DataObjectModification<? extends DataObject> node : pccMod) {
109 /* First, process PCC modification */
110 switch (node.getModificationType()) {
112 LOG.debug("Delete Managed TE Node: {}", nodeId);
113 pathManager.deleteManagedTeNode(nodeId);
115 case SUBTREE_MODIFIED:
117 /* First look if the Managed TE Node belongs to this PCC was not already created */
118 final PcepNodeConfig pccNode = (PcepNodeConfig) node.getDataAfter();
119 if (!pathManager.checkManagedTeNode(nodeId)) {
120 LOG.info("Create new Managed Node {}", nodeId);
121 pathManager.createManagedTeNode(nodeId, pccNode);
123 /* Then, look to Configured LSP modification */
124 final List<DataObjectModification<? extends DataObject>> lspMod = node.getModifiedChildren()
125 .stream().filter(mod -> mod.getDataType().equals(ConfiguredLsp.class))
126 .collect(Collectors.toList());
127 if (!lspMod.isEmpty()) {
128 handleLspChange(nodeId, lspMod);
139 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
140 for (DataTreeModification<Node> change : changes) {
141 DataObjectModification<Node> root = change.getRootNode();
143 final String nodeAddr = root.getModificationType() == DataObjectModification.ModificationType.DELETE
144 ? root.getDataBefore().getNodeId().getValue()
145 : root.getDataAfter().getNodeId().getValue();
147 if (nodeAddr.startsWith("pcc://")) {
148 nodeId = new NodeId(nodeAddr);
150 nodeId = new NodeId("pcc://" + nodeAddr);
153 /* Look only to PcepNodeConfig.class modification */
154 final List<DataObjectModification<? extends DataObject>> pccMod = root.getModifiedChildren().stream()
155 .filter(mod -> mod.getDataType().equals(PcepNodeConfig.class)).collect(Collectors.toList());
156 if (!pccMod.isEmpty()) {
157 handlePccChange(nodeId, pccMod);