Add new revision for pcep types model
[bgpcep.git] / pcep / tunnel / tunnel-provider / src / main / java / org / opendaylight / bgpcep / pcep / tunnel / provider / PCEPTunnelClusterSingletonService.java
1 /*
2  * Copyright (c) 2017 AT&T Intellectual Property. 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.tunnel.provider;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.FluentFuture;
14 import java.util.Collections;
15 import java.util.Dictionary;
16 import java.util.Hashtable;
17 import java.util.concurrent.TimeUnit;
18 import javax.annotation.Nonnull;
19 import javax.annotation.concurrent.GuardedBy;
20 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
21 import org.opendaylight.bgpcep.topology.DefaultTopologyReference;
22 import org.opendaylight.mdsal.common.api.CommitInfo;
23 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
24 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
25 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev181109.TopologyTunnelPcepProgrammingService;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
31 import org.opendaylight.yangtools.concepts.ObjectRegistration;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.osgi.framework.Constants;
34 import org.osgi.framework.InvalidSyntaxException;
35 import org.osgi.framework.ServiceRegistration;
36 import org.osgi.util.tracker.ServiceTracker;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 public final class PCEPTunnelClusterSingletonService implements ClusterSingletonService, AutoCloseable {
41
42     private static final Logger LOG = LoggerFactory.getLogger(PCEPTunnelClusterSingletonService.class);
43     private final PCEPTunnelTopologyProvider ttp;
44     private final TunnelProgramming tp;
45     private final ServiceGroupIdentifier sgi;
46     private final TopologyId tunnelTopologyId;
47     private final TunnelProviderDependencies dependencies;
48     @GuardedBy("this")
49     private ServiceRegistration<?> serviceRegistration;
50     @GuardedBy("this")
51     private ClusterSingletonServiceRegistration pcepTunnelCssReg;
52     @GuardedBy("this")
53     private ObjectRegistration<TunnelProgramming> reg;
54
55     public PCEPTunnelClusterSingletonService(
56             final TunnelProviderDependencies dependencies,
57             final InstanceIdentifier<Topology> pcepTopology,
58             final TopologyId tunnelTopologyId
59     ) {
60         this.dependencies = requireNonNull(dependencies);
61         this.tunnelTopologyId = requireNonNull(tunnelTopologyId);
62         final TopologyId pcepTopologyId = pcepTopology.firstKeyOf(Topology.class).getTopologyId();
63
64         final InstructionScheduler scheduler;
65         ServiceTracker<InstructionScheduler, ?> tracker = null;
66         try {
67             tracker = new ServiceTracker<>(dependencies.getBundleContext(),
68                     dependencies.getBundleContext().createFilter(String.format("(&(%s=%s)%s)", Constants.OBJECTCLASS,
69                             InstructionScheduler.class.getName(), "(" + InstructionScheduler.class.getName()
70                             + "=" + pcepTopologyId.getValue() + ")")), null);
71             tracker.open();
72             scheduler = (InstructionScheduler) tracker.waitForService(
73                     TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
74             Preconditions.checkState(scheduler != null, "InstructionScheduler service not found");
75         } catch (InvalidSyntaxException | InterruptedException e) {
76             throw new IllegalStateException("Error retrieving InstructionScheduler service", e);
77         } finally {
78             if (tracker != null) {
79                 tracker.close();
80             }
81         }
82
83         final InstanceIdentifier<Topology> tunnelTopology = InstanceIdentifier.builder(NetworkTopology.class)
84                 .child(Topology.class, new TopologyKey(tunnelTopologyId)).build();
85         this.ttp = new PCEPTunnelTopologyProvider(dependencies.getDataBroker(), pcepTopology, pcepTopologyId,
86                 tunnelTopology, tunnelTopologyId);
87
88
89         this.sgi = scheduler.getIdentifier();
90         this.tp = new TunnelProgramming(scheduler, dependencies);
91
92
93         final Dictionary<String, String> properties = new Hashtable<>();
94         properties.put(PCEPTunnelTopologyProvider.class.getName(), tunnelTopologyId.getValue());
95         this.serviceRegistration = dependencies.getBundleContext()
96                 .registerService(DefaultTopologyReference.class.getName(), this.ttp, properties);
97
98         LOG.info("PCEP Tunnel Cluster Singleton service {} registered", getIdentifier().getValue());
99         this.pcepTunnelCssReg = dependencies.getCssp().registerClusterSingletonService(this);
100     }
101
102
103     @Override
104     public synchronized void instantiateServiceInstance() {
105         LOG.info("Instantiate PCEP Tunnel Topology Provider Singleton Service {}", getIdentifier().getValue());
106
107         final InstanceIdentifier<Topology> topology = InstanceIdentifier
108                 .builder(NetworkTopology.class).child(Topology.class, new TopologyKey(this.tunnelTopologyId)).build();
109         this.reg = this.dependencies.getRpcProviderRegistry()
110                 .registerRpcImplementation(TopologyTunnelPcepProgrammingService.class,
111                         this.tp, Collections.singleton(topology));
112         this.ttp.init();
113     }
114
115     @Override
116     public synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
117         LOG.info("Close Service Instance PCEP Tunnel Topology Provider Singleton Service {}",
118                 getIdentifier().getValue());
119         this.reg.close();
120         this.tp.close();
121         this.ttp.close();
122         return CommitInfo.emptyFluentFuture();
123     }
124
125     @Nonnull
126     @Override
127     public ServiceGroupIdentifier getIdentifier() {
128         return this.sgi;
129     }
130
131     @Override
132     @SuppressWarnings("checkstyle:IllegalCatch")
133     public synchronized void close() {
134         LOG.info("Close PCEP Tunnel Topology Provider Singleton Service {}", getIdentifier().getValue());
135
136         if (this.pcepTunnelCssReg != null) {
137             try {
138                 this.pcepTunnelCssReg.close();
139             } catch (final Exception e) {
140                 LOG.debug("Failed to close PCEP Tunnel Topology service {}", this.sgi.getValue(), e);
141             }
142             this.pcepTunnelCssReg = null;
143         }
144         if (this.serviceRegistration != null) {
145             this.serviceRegistration.unregister();
146             this.serviceRegistration = null;
147         }
148     }
149 }