X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=netconf%2Fnetconf-topology-singleton%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Ftopology%2Fsingleton%2Fimpl%2FMasterSalFacade.java;h=55f661d513640261f813f852cde4c7803eb03854;hb=1dba5b2651d7fc60af0263cc0640d5ebeda8e454;hp=e4911acbf72a974251ddcc8f566c1b3c4c5a8286;hpb=8f8b49c1f6a113e88672f935c9cb497944af39f8;p=netconf.git diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java index e4911acbf7..55f661d513 100644 --- a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java +++ b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java @@ -5,173 +5,173 @@ * 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.netconf.topology.singleton.impl; +import static java.util.Objects.requireNonNull; + import akka.actor.ActorRef; import akka.actor.ActorSystem; import akka.cluster.Cluster; import akka.dispatch.OnComplete; import akka.pattern.Patterns; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; +import akka.util.Timeout; import java.util.List; -import java.util.stream.Collectors; -import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; -import org.opendaylight.controller.md.sal.dom.api.DOMNotification; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; -import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; -import org.opendaylight.controller.sal.core.api.Broker; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.dom.api.DOMDataBroker; +import org.opendaylight.mdsal.dom.api.DOMMountPointService; +import org.opendaylight.mdsal.dom.api.DOMNotification; +import org.opendaylight.netconf.dom.api.NetconfDataTreeService; import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler; +import org.opendaylight.netconf.sal.connect.api.RemoteDeviceId; +import org.opendaylight.netconf.sal.connect.api.RemoteDeviceServices; +import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceSchema; import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities; import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences; -import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceNotificationService; -import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalProvider; -import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; -import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction; -import org.opendaylight.netconf.topology.singleton.impl.tx.NetconfMasterDOMTransaction; -import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils; +import org.opendaylight.netconf.sal.connect.netconf.sal.AbstractNetconfDataTreeService; +import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceDataBroker; +import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceMount; import org.opendaylight.netconf.topology.singleton.messages.CreateInitialMasterActorData; -import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier; +import org.opendaylight.netconf.topology.spi.NetconfDeviceTopologyAdapter; +import org.opendaylight.yangtools.rfc8528.data.api.MountPointContext; import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import scala.concurrent.Future; -class MasterSalFacade implements AutoCloseable, RemoteDeviceHandler { - +class MasterSalFacade implements RemoteDeviceHandler, AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(MasterSalFacade.class); private final RemoteDeviceId id; - - private SchemaContext remoteSchemaContext = null; - private NetconfSessionPreferences netconfSessionPreferences = null; - private DOMRpcService deviceRpc = null; - private final NetconfDeviceSalProvider salProvider; - + private final Timeout actorResponseWaitTime; private final ActorRef masterActorRef; private final ActorSystem actorSystem; + private final NetconfDeviceTopologyAdapter datastoreAdapter; + private final NetconfDeviceMount mount; + private final boolean lockDatastore; + + private NetconfDeviceSchema currentSchema = null; + private NetconfSessionPreferences netconfSessionPreferences = null; + private RemoteDeviceServices deviceServices = null; private DOMDataBroker deviceDataBroker = null; + private NetconfDataTreeService netconfService = null; MasterSalFacade(final RemoteDeviceId id, - final Broker domBroker, - final BindingAwareBroker bindingBroker, - final ActorSystem actorSystem, - final ActorRef masterActorRef) { + final ActorSystem actorSystem, + final ActorRef masterActorRef, + final Timeout actorResponseWaitTime, + final DOMMountPointService mountService, + final DataBroker dataBroker, + final boolean lockDatastore) { this.id = id; - this.salProvider = new NetconfDeviceSalProvider(id); + mount = new NetconfDeviceMount(id, mountService, NetconfDeviceMount.defaultTopologyMountPath(id)); this.actorSystem = actorSystem; this.masterActorRef = masterActorRef; + this.actorResponseWaitTime = actorResponseWaitTime; + this.lockDatastore = lockDatastore; - registerToSal(domBroker, bindingBroker); - } - - private void registerToSal(final Broker domRegistryDependency, final BindingAwareBroker bindingBroker) { - // TODO: remove use of provider, there is possible directly create mount instance and - // TODO: NetconfDeviceTopologyAdapter in constructor = less complexity - - domRegistryDependency.registerProvider(salProvider); - bindingBroker.registerProvider(salProvider); + datastoreAdapter = new NetconfDeviceTopologyAdapter(dataBroker, RemoteDeviceId.DEFAULT_TOPOLOGY_IID, id); } @Override - public void onDeviceConnected(final SchemaContext remoteSchemaContext, - final NetconfSessionPreferences netconfSessionPreferences, - final DOMRpcService deviceRpc) { - this.remoteSchemaContext = remoteSchemaContext; - this.netconfSessionPreferences = netconfSessionPreferences; - this.deviceRpc = deviceRpc; + public void onDeviceConnected(final NetconfDeviceSchema deviceSchema, + final NetconfSessionPreferences sessionPreferences, final RemoteDeviceServices services) { + currentSchema = requireNonNull(deviceSchema); + netconfSessionPreferences = requireNonNull(sessionPreferences); + deviceServices = requireNonNull(services); + if (services.actions() != null) { + LOG.debug("{}: YANG 1.1 actions are supported in clustered netconf topology, DOMActionService exposed for " + + "the device", id); + } + + LOG.info("Device {} connected - registering master mount point", id); registerMasterMountPoint(); - sendInitialDataToActor().onComplete(new OnComplete() { + sendInitialDataToActor().onComplete(new OnComplete<>() { @Override - public void onComplete(final Throwable failure, final Object success) throws Throwable { + public void onComplete(final Throwable failure, final Object success) { if (failure == null) { updateDeviceData(); return; } - throw failure; + + LOG.error("{}: CreateInitialMasterActorData to {} failed", id, masterActorRef, failure); } }, actorSystem.dispatcher()); - } @Override public void onDeviceDisconnected() { - salProvider.getTopologyDatastoreAdapter().updateDeviceData(false, new NetconfDeviceCapabilities()); - unregisterMasterMountPoint(); + LOG.info("Device {} disconnected - unregistering master mount point", id); + datastoreAdapter.updateDeviceData(false, NetconfDeviceCapabilities.empty()); + mount.onDeviceDisconnected(); } @Override public void onDeviceFailed(final Throwable throwable) { - salProvider.getTopologyDatastoreAdapter().setDeviceAsFailed(throwable); - unregisterMasterMountPoint(); + datastoreAdapter.setDeviceAsFailed(throwable); + mount.onDeviceDisconnected(); } @Override public void onNotification(final DOMNotification domNotification) { - salProvider.getMountInstance().publish(domNotification); + mount.publish(domNotification); } @Override public void close() { - unregisterMasterMountPoint(); - closeGracefully(salProvider); + datastoreAdapter.close(); + mount.close(); } private void registerMasterMountPoint() { - Preconditions.checkNotNull(id); - Preconditions.checkNotNull(remoteSchemaContext, - "Device has no remote schema context yet. Probably not fully connected."); - Preconditions.checkNotNull(netconfSessionPreferences, - "Device has no capabilities yet. Probably not fully connected."); - - final NetconfDeviceNotificationService notificationService = new NetconfDeviceNotificationService(); - - LOG.info("{}: Creating master data broker for device", id); - - final NetconfDOMTransaction masterDOMTransactions = - new NetconfMasterDOMTransaction(id, remoteSchemaContext, deviceRpc, netconfSessionPreferences); - deviceDataBroker = - new NetconfDOMDataBroker(actorSystem, id, masterDOMTransactions); - salProvider.getMountInstance() - .onTopologyDeviceConnected(remoteSchemaContext, deviceDataBroker, deviceRpc, notificationService); + requireNonNull(id); + + final var mountContext = requireNonNull(currentSchema, + "Device has no remote schema context yet. Probably not fully connected.") + .mountContext(); + final var preferences = requireNonNull(netconfSessionPreferences, + "Device has no capabilities yet. Probably not fully connected."); + + deviceDataBroker = newDeviceDataBroker(mountContext, preferences); + netconfService = newNetconfDataTreeService(mountContext, preferences); + + // We need to create ProxyDOMDataBroker so accessing mountpoint + // on leader node would be same as on follower node + final ProxyDOMDataBroker proxyDataBroker = new ProxyDOMDataBroker(id, masterActorRef, actorSystem.dispatcher(), + actorResponseWaitTime); + final NetconfDataTreeService proxyNetconfService = new ProxyNetconfDataTreeService(id, masterActorRef, + actorSystem.dispatcher(), actorResponseWaitTime); + mount.onDeviceConnected(mountContext.getEffectiveModelContext(), deviceServices, + proxyDataBroker, proxyNetconfService); } - private Future sendInitialDataToActor() { - final List sourceIdentifiers = - remoteSchemaContext.getAllModuleIdentifiers().stream().map(mi -> - RevisionSourceIdentifier.create(mi.getName(), - (SimpleDateFormatUtil.DEFAULT_DATE_REV == mi.getRevision() ? Optional.absent() : - Optional.of(SimpleDateFormatUtil.getRevisionFormat().format(mi.getRevision()))))) - .collect(Collectors.toList()); - - // send initial data to master actor and create actor for providing it - return Patterns.ask(masterActorRef, new CreateInitialMasterActorData(deviceDataBroker, sourceIdentifiers, - deviceRpc), NetconfTopologyUtils.TIMEOUT); + protected DOMDataBroker newDeviceDataBroker(final MountPointContext mountContext, + final NetconfSessionPreferences preferences) { + return new NetconfDeviceDataBroker(id, mountContext, deviceServices.rpcs(), preferences, lockDatastore); } - private void updateDeviceData() { - Cluster cluster = Cluster.get(actorSystem); - salProvider.getTopologyDatastoreAdapter().updateClusteredDeviceData(true, cluster.selfAddress().toString(), - netconfSessionPreferences.getNetconfDeviceCapabilities()); + protected NetconfDataTreeService newNetconfDataTreeService(final MountPointContext mountContext, + final NetconfSessionPreferences preferences) { + return AbstractNetconfDataTreeService.of(id, mountContext, deviceServices.rpcs(), preferences, lockDatastore); } - private void unregisterMasterMountPoint() { - salProvider.getMountInstance().onTopologyDeviceDisconnected(); - } + private Future sendInitialDataToActor() { + final List sourceIdentifiers = List.copyOf(SchemaContextUtil.getConstituentModuleIdentifiers( + currentSchema.mountContext().getEffectiveModelContext())); - private void closeGracefully(final AutoCloseable resource) { - if (resource != null) { - try { - resource.close(); - } catch (final Exception e) { - LOG.error("{}: Ignoring exception while closing {}", id, resource, e); - } - } + LOG.debug("{}: Sending CreateInitialMasterActorData with sourceIdentifiers {} to {}", id, sourceIdentifiers, + masterActorRef); + + // send initial data to master actor + return Patterns.ask(masterActorRef, new CreateInitialMasterActorData(deviceDataBroker, netconfService, + sourceIdentifiers, deviceServices), actorResponseWaitTime); } + private void updateDeviceData() { + final String masterAddress = Cluster.get(actorSystem).selfAddress().toString(); + LOG.debug("{}: updateDeviceData with master address {}", id, masterAddress); + datastoreAdapter.updateClusteredDeviceData(true, masterAddress, currentSchema.capabilities()); + } }