X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fimpl%2Fosgi%2FNetconfMonitoringServiceImpl.java;h=2b0d35bc9d96320070080a0914234fc6f2852d27;hp=8e5c1a7da3e1b947f1de1429f11bddcc81fb6cb6;hb=b2e81149739c87f0ecc2ce7f06448d7a5d3162b8;hpb=45757bbd6c220f0f805715c84025c75a9388770a diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java index 8e5c1a7da3..2b0d35bc9d 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java @@ -13,21 +13,31 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import io.netty.util.internal.ConcurrentSet; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; -import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.config.util.capability.BasicCapability; +import org.opendaylight.controller.config.util.capability.Capability; import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.controller.netconf.notifications.BaseNotificationPublisherRegistration; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfStateBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Capabilities; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.CapabilitiesBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SchemasBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions; @@ -36,10 +46,14 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.mon import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.SchemaBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.SchemaKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChangeBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.changed.by.parms.ChangedByBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.changed.by.parms.changed.by.server.or.user.ServerBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class NetconfMonitoringServiceImpl implements NetconfMonitoringService { +public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, AutoCloseable { private static final Schema.Location NETCONF_LOCATION = new Schema.Location(Schema.Location.Enumeration.NETCONF); private static final List NETCONF_LOCATIONS = ImmutableList.of(NETCONF_LOCATION); @@ -50,18 +64,19 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService { return input.toManagementSession(); } }; - - private final Set sessions = new ConcurrentSet<>(); - private final NetconfOperationServiceFactory netconfOperationProvider; - private final Map capabilities = new ConcurrentHashMap<>(); - private static final Function CAPABILITY_TO_URI = new Function() { + private static final Function CAPABILITY_TO_URI = new Function() { @Override - public String apply(final Capability input) { - return input.getCapabilityUri(); + public Uri apply(final Capability input) { + return new Uri(input.getCapabilityUri()); } }; - // FIXME check threadsafety + private final Set sessions = new ConcurrentSet<>(); + private final NetconfOperationServiceFactory netconfOperationProvider; + private final Map capabilities = new ConcurrentHashMap<>(); + + private final Set listeners = Sets.newHashSet(); + private volatile BaseNotificationPublisherRegistration notificationPublisher; public NetconfMonitoringServiceImpl(final NetconfOperationServiceFactory netconfOperationProvider) { this.netconfOperationProvider = netconfOperationProvider; @@ -69,26 +84,28 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService { } @Override - public void onSessionUp(final NetconfManagementSession session) { + public synchronized void onSessionUp(final NetconfManagementSession session) { LOG.debug("Session {} up", session); Preconditions.checkState(!sessions.contains(session), "Session %s was already added", session); sessions.add(session); + notifyListeners(); } @Override - public void onSessionDown(final NetconfManagementSession session) { + public synchronized void onSessionDown(final NetconfManagementSession session) { LOG.debug("Session {} down", session); Preconditions.checkState(sessions.contains(session), "Session %s not present", session); sessions.remove(session); + notifyListeners(); } @Override - public Sessions getSessions() { + public synchronized Sessions getSessions() { return new SessionsBuilder().setSession(ImmutableList.copyOf(Collections2.transform(sessions, SESSION_FUNCTION))).build(); } @Override - public Schemas getSchemas() { + public synchronized Schemas getSchemas() { try { return transformSchemas(netconfOperationProvider.getCapabilities()); } catch (final RuntimeException e) { @@ -99,7 +116,7 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService { } @Override - public String getSchemaForCapability(final String moduleName, final Optional revision) { + public synchronized String getSchemaForCapability(final String moduleName, final Optional revision) { // FIXME not effective at all @@ -146,8 +163,28 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService { } @Override - public Set getCapabilities() { - return capabilities.keySet(); + public synchronized Capabilities getCapabilities() { + return new CapabilitiesBuilder().setCapability(Lists.newArrayList(capabilities.keySet())).build(); + } + + @Override + public synchronized AutoCloseable registerListener(final MonitoringListener listener) { + listeners.add(listener); + listener.onStateChanged(getCurrentNetconfState()); + return new AutoCloseable() { + @Override + public void close() throws Exception { + listeners.remove(listener); + } + }; + } + + private NetconfState getCurrentNetconfState() { + return new NetconfStateBuilder() + .setCapabilities(getCapabilities()) + .setSchemas(getSchemas()) + .setSessions(getSessions()) + .build(); } private static Schemas transformSchemas(final Set caps) { @@ -194,16 +231,63 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService { return b.build(); } + public static Set setupCapabilities(final Set caps) { + Set capabilities = new HashSet<>(caps); + capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0")); + // TODO rollback on error not supported EditConfigXmlParser:100 + // [RFC6241] 8.5. Rollback-on-Error Capability + // capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:rollback-on-error:1.0")); + return capabilities; + } + @Override - public void onCapabilitiesAdded(final Set addedCaps) { - // FIXME what check for duplicates - this.capabilities.putAll(Maps.uniqueIndex(addedCaps, CAPABILITY_TO_URI)); + public synchronized void close() throws Exception { + listeners.clear(); + sessions.clear(); + capabilities.clear(); } @Override - public void onCapabilitiesRemoved(final Set addedCaps) { + public void onCapabilitiesChanged(Set added, Set removed) { + onCapabilitiesAdded(added); + onCapabilitiesRemoved(removed); + notifyListeners(); + + // publish notification to notification collector about changed capabilities + if (notificationPublisher != null) { + notificationPublisher.onCapabilityChanged(computeDiff(added, removed)); + } + } + + static NetconfCapabilityChange computeDiff(final Set removed, final Set added) { + final NetconfCapabilityChangeBuilder netconfCapabilityChangeBuilder = new NetconfCapabilityChangeBuilder(); + netconfCapabilityChangeBuilder.setChangedBy(new ChangedByBuilder().setServerOrUser(new ServerBuilder().setServer(true).build()).build()); + netconfCapabilityChangeBuilder.setDeletedCapability(Lists.newArrayList(Collections2.transform(removed, CAPABILITY_TO_URI))); + netconfCapabilityChangeBuilder.setAddedCapability(Lists.newArrayList(Collections2.transform(added, CAPABILITY_TO_URI))); + // TODO modified should be computed ... but why ? + netconfCapabilityChangeBuilder.setModifiedCapability(Collections.emptyList()); + return netconfCapabilityChangeBuilder.build(); + } + + + private synchronized void onCapabilitiesAdded(final Set addedCaps) { + // FIXME howto check for duplicates + this.capabilities.putAll(Maps.uniqueIndex(setupCapabilities(addedCaps), CAPABILITY_TO_URI)); + } + + private void notifyListeners() { + for (final MonitoringListener listener : listeners) { + listener.onStateChanged(getCurrentNetconfState()); + } + } + + private synchronized void onCapabilitiesRemoved(final Set addedCaps) { for (final Capability addedCap : addedCaps) { - capabilities.remove(addedCap.getCapabilityUri()); + capabilities.remove(CAPABILITY_TO_URI.apply(addedCap)); } } + + public void setNotificationPublisher(final BaseNotificationPublisherRegistration notificationPublisher) { + this.notificationPublisher = notificationPublisher; + } }