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=6360b71ebcaad951b03f2badda098d969eab3511;hb=af45b16ab668b74b6853b46c46fb20f5784f0c67;hp=2e683734da5820e520d304c16a96ca9df3ffc19a;hpb=4bfe02adb718d58f9cdcb3ef4e9d2476cb98f6ad;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 2e683734da..6360b71ebc 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,166 +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 akka.util.Timeout; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import java.util.List; -import java.util.stream.Collectors; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; -import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; -import org.opendaylight.controller.md.sal.dom.api.DOMNotification; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; +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.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.AbstractNetconfDataTreeService; import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceDataBroker; -import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceNotificationService; -import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalProvider; +import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceMount; import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; 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 final Timeout actorResponseWaitTime; - private final NetconfDeviceSalProvider salProvider; private final ActorRef masterActorRef; private final ActorSystem actorSystem; + private final NetconfDeviceTopologyAdapter datastoreAdapter; + private final NetconfDeviceMount mount; + private final boolean lockDatastore; - private SchemaContext remoteSchemaContext = null; + private NetconfDeviceSchema currentSchema = null; private NetconfSessionPreferences netconfSessionPreferences = null; - private DOMRpcService deviceRpc = null; + private RemoteDeviceServices deviceServices = null; private DOMDataBroker deviceDataBroker = null; + private NetconfDataTreeService netconfService = null; MasterSalFacade(final RemoteDeviceId id, final ActorSystem actorSystem, final ActorRef masterActorRef, final Timeout actorResponseWaitTime, final DOMMountPointService mountService, - final DataBroker dataBroker) { + final DataBroker dataBroker, + final boolean lockDatastore) { this.id = id; - this.salProvider = new NetconfDeviceSalProvider(id, mountService, dataBroker); + mount = new NetconfDeviceMount(mountService, id); this.actorSystem = actorSystem; this.masterActorRef = masterActorRef; this.actorResponseWaitTime = actorResponseWaitTime; + this.lockDatastore = lockDatastore; + + 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."); + requireNonNull(id); - final NetconfDeviceNotificationService notificationService = new NetconfDeviceNotificationService(); + 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."); - LOG.info("{}: Creating master data broker for device", id); + deviceDataBroker = newDeviceDataBroker(mountContext, preferences); + netconfService = newNetconfDataTreeService(mountContext, preferences); - deviceDataBroker = new NetconfDeviceDataBroker(id, remoteSchemaContext, deviceRpc, netconfSessionPreferences); // We need to create ProxyDOMDataBroker so accessing mountpoint // on leader node would be same as on follower node - final ProxyDOMDataBroker proxyDataBroker = - new ProxyDOMDataBroker(actorSystem, id, masterActorRef, actorResponseWaitTime); - salProvider.getMountInstance() - .onTopologyDeviceConnected(remoteSchemaContext, proxyDataBroker, deviceRpc, notificationService); + 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(mi.getQNameModule().getFormattedRevision())))) - .collect(Collectors.toList()); - - // send initial data to master actor and create actor for providing it - return Patterns.ask(masterActorRef, new CreateInitialMasterActorData(deviceDataBroker, sourceIdentifiers, - deviceRpc), actorResponseWaitTime); + protected DOMDataBroker newDeviceDataBroker(final MountPointContext mountContext, + final NetconfSessionPreferences preferences) { + return new NetconfDeviceDataBroker(id, mountContext, deviceServices.rpcs(), preferences, lockDatastore); } - private void updateDeviceData() { - final 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())); - @SuppressWarnings("checkstyle:IllegalCatch") - 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()); + } }