All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.bgpcep.pcep.tunnel.provider.TunnelProviderDeployer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.bgpcep.pcep.tunnel.provider;

import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.lock.qual.GuardedBy;
import org.opendaylight.mdsal.binding.api.DataBroker;
import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
import org.opendaylight.mdsal.binding.api.DataTreeModification;
import org.opendaylight.mdsal.binding.api.RpcProviderService;
import org.opendaylight.mdsal.binding.api.RpcService;
import org.opendaylight.mdsal.singleton.api.ClusterSingletonServiceProvider;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.config.rev181109.PcepTunnelTopologyConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.TopologyTypes1;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
import org.opendaylight.yangtools.binding.DataObjectIdentifier;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(service = { })
public final class TunnelProviderDeployer implements DataTreeChangeListener, AutoCloseable {
    private static final Logger LOG = LoggerFactory.getLogger(TunnelProviderDeployer.class);
    private static final long TIMEOUT_NS = TimeUnit.SECONDS.toNanos(5);

    private final TunnelProviderDependencies dependencies;
    @GuardedBy("this")
    private final Map pcepTunnelServices = new HashMap<>();
    private final Registration reg;

    @Activate
    public TunnelProviderDeployer(@Reference final DataBroker dataBroker,
            @Reference final RpcProviderService rpcProviderRegistry,
            @Reference final RpcService rpcService,
            @Reference final ClusterSingletonServiceProvider cssp,
            // FIXME: do not reference BundleContext in an alternative constructor
            final BundleContext bundleContext) {
        dependencies = new TunnelProviderDependencies(dataBroker, cssp, rpcProviderRegistry, rpcService,
                bundleContext);
        reg = dataBroker.registerTreeChangeListener(DataTreeIdentifier.of(CONFIGURATION,
                InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).build()), this);
        LOG.info("Tunnel Provider Deployer created");
    }

    @Deactivate
    @Override
    public synchronized void close() {
        reg.close();
        pcepTunnelServices.values().iterator().forEachRemaining(PCEPTunnelClusterSingletonService::close);
        pcepTunnelServices.clear();
        LOG.info("Tunnel Provider Deployer closed");
    }

    @SuppressWarnings("checkstyle:IllegalCatch")
    private static void closeTopology(final PCEPTunnelClusterSingletonService topology, final TopologyId topologyId) {
        if (topology != null) {
            try {
                topology.closeServiceInstance().get(TIMEOUT_NS, TimeUnit.NANOSECONDS);
            } catch (final Exception e) {
                LOG.error("Topology {} instance failed to close service instance", topologyId, e);
            }
            topology.close();
        }
    }

    @Override
    public synchronized void onDataTreeChanged(final List> changes) {
        changes.stream().map(DataTreeModification::getRootNode).forEach(topo -> {
            switch (topo.modificationType()) {
                case SUBTREE_MODIFIED:
                    updateTunnelTopologyProvider(topo.dataAfter());
                    break;
                case WRITE:
                    createTunnelTopologyProvider(topo.dataAfter());
                    break;
                case DELETE:
                    removeTunnelTopologyProvider(topo.dataBefore());
                    break;
                default:
            }
        });
    }

    private static boolean filterPcepTopologies(final TopologyTypes topologyTypes) {
        if (topologyTypes == null) {
            return false;
        }
        final TopologyTypes1 aug = topologyTypes.augmentation(TopologyTypes1.class);
        return aug != null && aug.getTopologyTunnelPcep() != null;
    }

    private synchronized void createTunnelTopologyProvider(final Topology topology) {
        if (!filterPcepTopologies(topology.getTopologyTypes())) {
            return;
        }
        final var topologyId = topology.getTopologyId();
        if (pcepTunnelServices.containsKey(topology.getTopologyId())) {
            LOG.warn("Tunnel Topology {} already exist. New instance won't be created", topologyId);
            return;
        }
        LOG.debug("Create Tunnel Topology {}", topologyId);

        final var config = topology.augmentation(PcepTunnelTopologyConfig.class);
        final var pcepTopoID = StringUtils.substringBetween(config.getPcepTopologyReference().getValue(), "=\"", "\"");
        final var pcepTopoRef = DataObjectIdentifier.builder(NetworkTopology.class)
                .child(Topology.class, new TopologyKey(new TopologyId(pcepTopoID)))
                .build();

        final var tunnelTopoCss = new PCEPTunnelClusterSingletonService(dependencies, pcepTopoRef, topologyId);
        pcepTunnelServices.put(topology.getTopologyId(), tunnelTopoCss);
    }

    private synchronized void updateTunnelTopologyProvider(final Topology topology) {
        if (!filterPcepTopologies(topology.getTopologyTypes())) {
            return;
        }
        final TopologyId topologyId = topology.getTopologyId();
        final PCEPTunnelClusterSingletonService previous = pcepTunnelServices.remove(topology.getTopologyId());
        closeTopology(previous, topologyId);
        createTunnelTopologyProvider(topology);
    }

    private synchronized void removeTunnelTopologyProvider(final Topology topo) {
        if (!filterPcepTopologies(topo.getTopologyTypes())) {
            return;
        }
        final TopologyId topologyId = topo.getTopologyId();
        final PCEPTunnelClusterSingletonService topology = pcepTunnelServices.remove(topologyId);
        closeTopology(topology, topologyId);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy