2 * Copyright (c) 2016 Brocade Communication Systems and others. 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.netconf.callhome.mount;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import io.netty.util.Timer;
16 import java.net.InetSocketAddress;
17 import java.util.concurrent.Executor;
18 import java.util.concurrent.ScheduledExecutorService;
19 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
20 import org.opendaylight.controller.config.threadpool.ThreadPool;
21 import org.opendaylight.mdsal.binding.api.DataBroker;
22 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
23 import org.opendaylight.netconf.callhome.protocol.CallHomeChannelActivator;
24 import org.opendaylight.netconf.callhome.protocol.CallHomeNetconfSubsystemListener;
25 import org.opendaylight.netconf.callhome.protocol.CallHomeProtocolSessionContext;
26 import org.opendaylight.netconf.client.NetconfClientFactory;
27 import org.opendaylight.netconf.client.NetconfClientSession;
28 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
29 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
30 import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
31 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
32 import org.opendaylight.netconf.topology.spi.NetconfClientConfigurationBuilderFactory;
33 import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
35 import org.osgi.service.component.annotations.Activate;
36 import org.osgi.service.component.annotations.Component;
37 import org.osgi.service.component.annotations.Reference;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
41 @Component(service = { CallHomeMountFactory.class, CallHomeNetconfSubsystemListener.class }, immediate = true)
42 // Non-final for testing
43 public class CallHomeMountFactory implements NetconfClientFactory, CallHomeNetconfSubsystemListener {
44 private static final Logger LOG = LoggerFactory.getLogger(CallHomeMountFactory.class);
46 private final CallHomeMountSessionManager sessionManager = new CallHomeMountSessionManager();
47 private final String topologyId;
48 private final Timer timer;
49 private final ScheduledExecutorService scheduledExecutor;
50 private final Executor processingExecutor;
51 private final SchemaResourceManager schemaRepositoryProvider;
52 private final DataBroker dataBroker;
53 private final DOMMountPointService mountService;
54 private final NetconfClientConfigurationBuilderFactory builderFactory;
56 protected CallHomeTopology topology;
58 private final DeviceActionFactory deviceActionFactory;
59 private final BaseNetconfSchemas baseSchemas;
61 public CallHomeMountFactory(final String topologyId, final Timer timer,
62 final ScheduledExecutorService scheduledExecutor, final Executor processingExecutor,
63 final SchemaResourceManager schemaRepositoryProvider, final BaseNetconfSchemas baseSchemas,
64 final DataBroker dataBroker, final DOMMountPointService mountService,
65 final NetconfClientConfigurationBuilderFactory builderFactory) {
66 this(topologyId, timer, scheduledExecutor, processingExecutor, schemaRepositoryProvider, baseSchemas,
67 dataBroker, mountService, builderFactory, null);
71 public CallHomeMountFactory(@Reference(target = "(type=global-timer)") final Timer timer,
72 @Reference(target = "(type=global-netconf-ssh-scheduled-executor)")
73 final ScheduledThreadPool scheduledThreadPool,
74 @Reference(target = "(type=global-netconf-processing-executor)") final ThreadPool processingThreadPool,
75 @Reference final SchemaResourceManager schemaRepositoryProvider,
76 @Reference final BaseNetconfSchemas baseSchemas, @Reference final DataBroker dataBroker,
77 @Reference final DOMMountPointService mountService,
78 @Reference(target = "(type=legacy)") final NetconfClientConfigurationBuilderFactory builderFactory,
79 @Reference final DeviceActionFactory deviceActionFactory) {
80 this(NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME, timer, scheduledThreadPool.getExecutor(),
81 processingThreadPool.getExecutor(), schemaRepositoryProvider, baseSchemas, dataBroker, mountService,
82 builderFactory, deviceActionFactory);
85 public CallHomeMountFactory(final String topologyId, final Timer timer,
86 final ScheduledExecutorService scheduledExecutor, final Executor processingExecutor,
87 final SchemaResourceManager schemaRepositoryProvider, final BaseNetconfSchemas baseSchemas,
88 final DataBroker dataBroker, final DOMMountPointService mountService,
89 final NetconfClientConfigurationBuilderFactory builderFactory,
90 final DeviceActionFactory deviceActionFactory) {
91 this.topologyId = topologyId;
92 this.timer = requireNonNull(timer);
93 this.scheduledExecutor = scheduledExecutor;
94 this.processingExecutor = processingExecutor;
95 this.schemaRepositoryProvider = schemaRepositoryProvider;
96 this.deviceActionFactory = deviceActionFactory;
97 this.baseSchemas = requireNonNull(baseSchemas);
98 this.dataBroker = dataBroker;
99 this.mountService = mountService;
100 this.builderFactory = requireNonNull(builderFactory);
105 public ListenableFuture<NetconfClientSession> createClient(final NetconfClientConfiguration clientConfiguration) {
106 return activateChannel(clientConfiguration);
109 private ListenableFuture<NetconfClientSession> activateChannel(final NetconfClientConfiguration conf) {
110 final InetSocketAddress remoteAddr = conf.getAddress();
111 final CallHomeMountSessionContext context = sessionManager().getByAddress(remoteAddr);
112 LOG.info("Activating NETCONF channel for ip {} device context {}", remoteAddr, context);
113 return context == null ? Futures.immediateFailedFuture(new NullPointerException("context is null"))
114 : context.activateNetconfChannel(conf.getSessionListener());
118 public void onNetconfSubsystemOpened(final CallHomeProtocolSessionContext session,
119 final CallHomeChannelActivator activator) {
120 final var deviceContext = sessionManager().createSession(session, activator, device -> {
121 final var nodeId = device.getId();
122 LOG.info("Removing {} from Netconf Topology.", nodeId);
123 topology.disconnectNode(nodeId);
125 if (deviceContext != null) {
126 final Node configNode = deviceContext.getConfigNode();
127 LOG.info("Provisioning fake config {}", configNode);
128 topology.connectNode(configNode);
133 void createTopology() {
134 topology = new CallHomeTopology(topologyId, this, timer, scheduledExecutor, processingExecutor,
135 schemaRepositoryProvider, dataBroker, mountService, builderFactory, baseSchemas, deviceActionFactory);
139 CallHomeMountSessionManager sessionManager() {
140 return sessionManager;
144 public void close() throws Exception {