org.opendaylight.controller.netconf.cli.NetconfDeviceConnectionManager.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.controller.netconf.cli.NetconfDeviceConnectionManager.java

Source

/*
 * Copyright (c) 2014 Cisco Systems, Inc. and others.  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.controller.netconf.cli;

import com.google.common.base.Preconditions;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.opendaylight.controller.netconf.cli.commands.CommandDispatcher;
import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
import org.opendaylight.controller.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
import org.opendaylight.controller.sal.connect.netconf.NetconfStateSchemas.NetconfStateSchemasResolverImpl;
import org.opendaylight.controller.sal.connect.netconf.listener.NetconfDeviceCommunicator;
import org.opendaylight.controller.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider;
import org.opendaylight.yangtools.yang.model.util.repo.FilesystemSchemaCachingProvider;
import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProviders;
import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;

/**
 * Manages connect/disconnect to 1 remote device
 */
public class NetconfDeviceConnectionManager implements Closeable {

    private final CommandDispatcher commandDispatcher;
    private final SchemaContextRegistry schemaContextRegistry;
    private final ConsoleIO console;

    private final ExecutorService executor;
    private final NioEventLoopGroup nettyThreadGroup;
    private final NetconfClientDispatcherImpl netconfClientDispatcher;

    private static final String CACHE = "cache/schema";

    // Connection
    private NetconfDeviceConnectionHandler handler;
    private NetconfDevice device;
    private NetconfDeviceCommunicator listener;

    public NetconfDeviceConnectionManager(final CommandDispatcher commandDispatcher,
            final CommandArgHandlerRegistry argumentHandlerRegistry,
            final SchemaContextRegistry schemaContextRegistry, final ConsoleIO consoleIO) {
        this.commandDispatcher = commandDispatcher;
        this.schemaContextRegistry = schemaContextRegistry;
        this.console = consoleIO;

        executor = Executors.newSingleThreadExecutor();
        nettyThreadGroup = new NioEventLoopGroup();
        netconfClientDispatcher = new NetconfClientDispatcherImpl(nettyThreadGroup, nettyThreadGroup,
                new HashedWheelTimer());
    }

    // TODO we receive configBuilder in order to add SessionListener, Session
    // Listener should not be part of config
    public synchronized void connect(final String name, final InetSocketAddress address,
            final NetconfClientConfigurationBuilder configBuilder) {
        // TODO change IllegalState exceptions to custom ConnectionException
        Preconditions.checkState(listener == null, "Already connected");

        final RemoteDeviceId deviceId = new RemoteDeviceId(name, address);

        handler = new NetconfDeviceConnectionHandler(commandDispatcher, schemaContextRegistry, console, name);

        final SharedSchemaRepository repository = new SharedSchemaRepository("repo");
        final SchemaContextFactory schemaContextFactory = repository
                .createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
        final FilesystemSchemaSourceCache<YangTextSchemaSource> cache = new FilesystemSchemaSourceCache<>(
                repository, YangTextSchemaSource.class, new File(CACHE));
        repository.registerSchemaSourceListener(cache);
        repository.registerSchemaSourceListener(TextToASTTransformer.create(repository, repository));

        device = new NetconfDevice(
                new SchemaResourcesDTO(repository, schemaContextFactory, new NetconfStateSchemasResolverImpl()),
                deviceId, handler, executor, new NetconfMessageTransformer());
        listener = new NetconfDeviceCommunicator(deviceId, device);
        configBuilder.withSessionListener(listener);
        listener.initializeRemoteConnection(netconfClientDispatcher, configBuilder.build());
    }

    /**
     * Blocks thread until connection is fully established
     */
    public synchronized Set<String> connectBlocking(final String name, final InetSocketAddress address,
            final NetconfClientConfigurationBuilder configBuilder) {
        this.connect(name, address, configBuilder);
        synchronized (handler) {
            while (handler.isUp() == false) {
                try {
                    // TODO implement Timeout for unsuccessful connection
                    handler.wait();
                } catch (final InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new IllegalArgumentException(e);
                }
            }
        }

        return commandDispatcher.getRemoteCommandIds();
    }

    public synchronized void disconnect() {
        Preconditions.checkState(listener != null, "Not connected yet");
        Preconditions.checkState(handler.isUp(), "Not connected yet");
        listener.close();
        listener = null;
        device = null;
        handler.close();
        handler = null;
    }

    private static AbstractCachingSchemaSourceProvider<String, InputStream> getGlobalNetconfSchemaProvider() {
        // FIXME move to args
        final String storageFile = "cache/schema";
        final File directory = new File(storageFile);
        final SchemaSourceProvider<String> defaultProvider = SchemaSourceProviders.noopProvider();
        return FilesystemSchemaCachingProvider.createFromStringSourceProvider(defaultProvider, directory);
    }

    @Override
    public void close() throws IOException {
        executor.shutdownNow();
        nettyThreadGroup.shutdownGracefully();
    }
}