BGPCEP-704: Rework Deployer
[bgpcep.git] / pcep / topology / topology-provider / src / main / java / org / opendaylight / bgpcep / pcep / topology / provider / config / PCEPTopologyDeployerImpl.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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 package org.opendaylight.bgpcep.pcep.topology.provider.config;
9
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyProviderUtil.closeTopology;
12 import static org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyProviderUtil.filterPcepTopologies;
13 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
14
15 import java.net.InetSocketAddress;
16 import java.util.Collection;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.stream.Collectors;
21 import javax.annotation.concurrent.GuardedBy;
22 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
23 import org.opendaylight.bgpcep.programming.spi.InstructionSchedulerFactory;
24 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
27 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
28 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
29 import org.opendaylight.protocol.concepts.KeyMapping;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.config.rev171025.pcep.config.SessionConfig;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pce.config.rev171025.PcepTopologyTypeConfig;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
35 import org.opendaylight.yangtools.concepts.ListenerRegistration;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.osgi.service.blueprint.container.BlueprintContainer;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class PCEPTopologyDeployerImpl implements ClusteredDataTreeChangeListener<Topology>, AutoCloseable {
42
43     private static final Logger LOG = LoggerFactory.getLogger(PCEPTopologyDeployerImpl.class);
44
45     private final BlueprintContainer container;
46     private final InstanceIdentifier<NetworkTopology> networTopology;
47     private final DataBroker dataBroker;
48     private final InstructionSchedulerFactory instructionSchedulerFactory;
49     @GuardedBy("this")
50     private final Map<TopologyId, PCEPTopologyProviderBean> pcepTopologyServices = new HashMap<>();
51     private ListenerRegistration<PCEPTopologyDeployerImpl> listenerRegistration;
52
53     public PCEPTopologyDeployerImpl(final BlueprintContainer container,
54             final DataBroker dataBroker, final InstructionSchedulerFactory instructionSchedulerFactory) {
55         this.container = requireNonNull(container);
56         this.dataBroker = requireNonNull(dataBroker);
57         this.instructionSchedulerFactory = requireNonNull(instructionSchedulerFactory);
58         this.networTopology = InstanceIdentifier.builder(NetworkTopology.class).build();
59     }
60
61     public synchronized void init() {
62         this.listenerRegistration = this.dataBroker.registerDataTreeChangeListener(
63                 new DataTreeIdentifier<>(CONFIGURATION, this.networTopology.child(Topology.class)), this);
64     }
65
66     @Override
67     public synchronized void onDataTreeChanged(final Collection<DataTreeModification<Topology>> changes) {
68         final List<DataObjectModification<Topology>> topoChanges = changes.stream()
69                 .map(DataTreeModification::getRootNode)
70                 .collect(Collectors.toList());
71         topoChanges.stream()
72                 .iterator().forEachRemaining(topo -> {
73             switch (topo.getModificationType()) {
74                 case SUBTREE_MODIFIED:
75                     updateTopologyProvider(topo.getDataAfter());
76                     break;
77                 case WRITE:
78                     createTopologyProvider(topo.getDataAfter());
79                     break;
80                 case DELETE:
81                     removeTopologyProvider(topo.getDataBefore());
82                     break;
83             }
84         });
85     }
86
87     private synchronized void updateTopologyProvider(final Topology topology) {
88         if (!filterPcepTopologies(topology.getTopologyTypes())) {
89             return;
90         }
91         final TopologyId topologyId = topology.getTopologyId();
92         final PCEPTopologyProviderBean previous = this.pcepTopologyServices.remove(topology.getTopologyId());
93         closeTopology(previous, topologyId);
94         createTopologyProvider(topology);
95     }
96
97     private synchronized void createTopologyProvider(final Topology topology) {
98         if (!filterPcepTopologies(topology.getTopologyTypes())) {
99             return;
100         }
101         final TopologyId topologyId = topology.getTopologyId();
102         if (this.pcepTopologyServices.containsKey(topology.getTopologyId())) {
103             LOG.warn("Topology Provider {} already exist. New instance won't be created", topologyId);
104             return;
105         }
106
107         final PcepTopologyTypeConfig pcepTopo = topology.getAugmentation(PcepTopologyTypeConfig.class);
108
109         final SessionConfig config = pcepTopo.getSessionConfig();
110
111         final InstructionScheduler instructionScheduler = this.instructionSchedulerFactory
112                 .createInstructionScheduler(topologyId.getValue());
113
114         final InetSocketAddress inetAddress = PCEPTopologyProviderUtil
115                 .getInetSocketAddress(config.getListenAddress(), config.getListenPort());
116
117         final KeyMapping keys = PCEPTopologyProviderUtil.contructKeys(topology);
118         final PCEPTopologyConfigDependencies dependencies = new PCEPTopologyConfigDependencies(
119                 inetAddress, keys, instructionScheduler, topology.getTopologyId(),
120                 config.getRpcTimeout());
121
122         final PCEPTopologyProviderBean pcepTopologyProviderBean = (PCEPTopologyProviderBean) this.container
123                 .getComponentInstance(PCEPTopologyProviderBean.class.getSimpleName());
124         this.pcepTopologyServices.put(topologyId, pcepTopologyProviderBean);
125         pcepTopologyProviderBean.start(dependencies);
126     }
127
128     private synchronized void removeTopologyProvider(final Topology topo) {
129         if (!filterPcepTopologies(topo.getTopologyTypes())) {
130             return;
131         }
132         final TopologyId topologyId = topo.getTopologyId();
133         final PCEPTopologyProviderBean topology = this.pcepTopologyServices.remove(topologyId);
134         closeTopology(topology, topologyId);
135     }
136
137     @Override
138     public synchronized void close() {
139         if (this.listenerRegistration != null) {
140             this.listenerRegistration.close();
141             this.listenerRegistration = null;
142         }
143         this.pcepTopologyServices.entrySet().iterator()
144                 .forEachRemaining(entry -> closeTopology(entry.getValue(), entry.getKey()));
145         this.pcepTopologyServices.clear();
146     }
147 }