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.List;
13 import java.util.stream.Collectors;
14 import org.opendaylight.mdsal.binding.api.DataBroker;
15 import org.opendaylight.mdsal.binding.api.DataObjectModification;
16 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
17 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
18 import org.opendaylight.mdsal.binding.api.DataTreeModification;
19 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PcepNodeConfig;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLsp;
22 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
26 import org.opendaylight.yangtools.concepts.Registration;
27 import org.opendaylight.yangtools.yang.binding.DataObject;
28 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * This Class Implements the DataStoreService interface providing the methods required to manage the path
34 * representation elements in the Data Store.
36 * @author Olivier Dugeon
39 public final class PathManagerListener implements DataTreeChangeListener<Node>, AutoCloseable {
40 private static final Logger LOG = LoggerFactory.getLogger(PathManagerListener.class);
42 private Registration listenerRegistration;
44 private final PathManagerProvider pathManager;
46 public PathManagerListener(final DataBroker dataBroker,
47 final KeyedInstanceIdentifier<Topology, TopologyKey> topology, final PathManagerProvider pathManager) {
48 this.pathManager = requireNonNull(pathManager);
49 listenerRegistration = dataBroker.registerLegacyTreeChangeListener(
50 DataTreeIdentifier.of(LogicalDatastoreType.CONFIGURATION, topology.child(Node.class)), this);
51 LOG.info("Registered listener for Managed TE Path on Topology {}",
52 topology.getKey().getTopologyId().getValue());
56 * Close this Listener.
60 if (listenerRegistration != null) {
61 LOG.debug("Unregistered listener {} for Managed TE Path", this);
62 listenerRegistration.close();
63 listenerRegistration = null;
68 * Handle Configured LSP modifications.
70 * @param nodeId Node Identifier to which the modified children belongs to.
71 * @param lspMod List of Configured LSP modifications.
73 private void handleLspChange(final NodeId nodeId,
74 final List<? extends DataObjectModification<? extends DataObject>> lspMod) {
75 for (DataObjectModification<? extends DataObject> lsp : lspMod) {
77 switch (lsp.modificationType()) {
79 cfgLsp = (ConfiguredLsp) lsp.dataBefore();
80 LOG.debug("Delete Managed TE Path: {}", cfgLsp.getName());
81 pathManager.deleteManagedTePath(nodeId, cfgLsp.key());
83 case SUBTREE_MODIFIED:
85 cfgLsp = (ConfiguredLsp) lsp.dataAfter();
86 LOG.debug("Update Managed TE Path {}", cfgLsp);
87 pathManager.createManagedTePath(nodeId, cfgLsp);
97 * Parse Sub Tree modification. Given list has been filtered to get only Path Computation Client1 modifications.
98 * This function first create, update or delete Managed TE Node that corresponds to the given NodeId. Then, it
99 * filter the children to retain only the Configured LSP modifications.
101 * @param nodeId Node Identifier to which the modified children belongs to.
102 * @param pccMod List of PCEP Node Configuration modifications.
104 private void handlePccChange(final NodeId nodeId,
105 final List<? extends DataObjectModification<? extends DataObject>> pccMod) {
106 for (var node : pccMod) {
107 /* First, process PCC modification */
108 switch (node.modificationType()) {
110 LOG.debug("Delete Managed TE Node: {}", nodeId);
111 pathManager.deleteManagedTeNode(nodeId);
113 case SUBTREE_MODIFIED:
115 /* First look if the Managed TE Node belongs to this PCC was not already created */
116 final var pccNode = (PcepNodeConfig) node.dataAfter();
117 if (!pathManager.checkManagedTeNode(nodeId)) {
118 LOG.info("Create new Managed Node {}", nodeId);
119 pathManager.createManagedTeNode(nodeId, pccNode);
121 /* Then, look to Configured LSP modification */
122 final var lspMod = node.modifiedChildren()
123 .stream().filter(mod -> mod.dataType().equals(ConfiguredLsp.class))
124 .collect(Collectors.toList());
125 if (!lspMod.isEmpty()) {
126 handleLspChange(nodeId, lspMod);
137 public void onDataTreeChanged(final List<DataTreeModification<Node>> changes) {
138 for (var change : changes) {
139 final var root = change.getRootNode();
141 final String nodeAddr = root.modificationType() == DataObjectModification.ModificationType.DELETE
142 ? root.dataBefore().getNodeId().getValue()
143 : root.dataAfter().getNodeId().getValue();
145 if (nodeAddr.startsWith("pcc://")) {
146 nodeId = new NodeId(nodeAddr);
148 nodeId = new NodeId("pcc://" + nodeAddr);
151 /* Look only to PcepNodeConfig.class modification */
152 final var pccMod = root.modifiedChildren().stream()
153 .filter(mod -> mod.dataType().equals(PcepNodeConfig.class))
154 .collect(Collectors.toList());
155 if (!pccMod.isEmpty()) {
156 handlePccChange(nodeId, pccMod);