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=b02137b748c71584841df04817a9f8bb552147e2;hp=505c74714a71c269ad9721497cdbffaedd4fb706;hb=7ab97f33c1d0c7da891337d8ec0b117555914115;hpb=a57a5b4002790af8574db2b1d940106298bf18c3 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 505c74714a..b02137b748 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 @@ -8,17 +8,32 @@ package org.opendaylight.controller.netconf.impl.osgi; import com.google.common.base.Function; +import com.google.common.base.Optional; 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.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.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; -import org.opendaylight.controller.netconf.mapping.api.Capability; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; 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; @@ -30,106 +45,208 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.mon import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.List; -import java.util.Set; +public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, AutoCloseable { -public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, SessionMonitoringService { - - private static final Logger logger = LoggerFactory.getLogger(NetconfMonitoringServiceImpl.class); + private static final Schema.Location NETCONF_LOCATION = new Schema.Location(Schema.Location.Enumeration.NETCONF); + private static final List NETCONF_LOCATIONS = ImmutableList.of(NETCONF_LOCATION); + private static final Logger LOG = LoggerFactory.getLogger(NetconfMonitoringServiceImpl.class); + private static final Function SESSION_FUNCTION = new Function() { + @Override + public Session apply(@Nonnull final NetconfManagementSession input) { + return input.toManagementSession(); + } + }; + private static final Function CAPABILITY_TO_URI = new Function() { + @Override + public Uri apply(final Capability input) { + return new Uri(input.getCapabilityUri()); + } + }; private final Set sessions = new ConcurrentSet<>(); - private final NetconfOperationServiceFactoryListener factoriesListener; + private final NetconfOperationServiceFactory netconfOperationProvider; + private final Map capabilities = new ConcurrentHashMap<>(); - public NetconfMonitoringServiceImpl(NetconfOperationServiceFactoryListener factoriesListener) { - this.factoriesListener = factoriesListener; + private final Set listeners = Sets.newHashSet(); + + public NetconfMonitoringServiceImpl(final NetconfOperationServiceFactory netconfOperationProvider) { + this.netconfOperationProvider = netconfOperationProvider; + netconfOperationProvider.registerCapabilityListener(this); } @Override - public void onSessionUp(NetconfManagementSession session) { - logger.debug("Session {} up", session); - Preconditions.checkState(sessions.contains(session) == false, "Session %s was already added", 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(NetconfManagementSession session) { - logger.debug("Session {} down", session); - Preconditions.checkState(sessions.contains(session) == true, "Session %s not present", 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() { - return new SessionsBuilder().setSession(transformSessions(sessions)).build(); + public synchronized Sessions getSessions() { + return new SessionsBuilder().setSession(ImmutableList.copyOf(Collections2.transform(sessions, SESSION_FUNCTION))).build(); } @Override - public Schemas getSchemas() { - // FIXME, session ID - // capabilities should be split from operations (it will allow to move getSchema operation to monitoring module) - return transformSchemas(factoriesListener.getSnapshot(0)); + public synchronized Schemas getSchemas() { + try { + return transformSchemas(netconfOperationProvider.getCapabilities()); + } catch (final RuntimeException e) { + throw e; + } catch (final Exception e) { + throw new IllegalStateException("Exception while closing", e); + } } - private Schemas transformSchemas(NetconfOperationServiceSnapshot snapshot) { - Set caps = Sets.newHashSet(); + @Override + public synchronized String getSchemaForCapability(final String moduleName, final Optional revision) { + + // FIXME not effective at all - List schemas = Lists.newArrayList(); + Map> mappedModulesToRevisionToSchema = Maps.newHashMap(); - for (NetconfOperationService netconfOperationService : snapshot.getServices()) { - // TODO check for duplicates ? move capability merging to snapshot - // Split capabilities from operations first and delete this duplicate code - caps.addAll(netconfOperationService.getCapabilities()); - } + final Collection caps = capabilities.values(); for (Capability cap : caps) { - SchemaBuilder builder = new SchemaBuilder(); - - if(cap.getCapabilitySchema().isPresent() == false) + if (!cap.getModuleName().isPresent() + || !cap.getRevision().isPresent() + || !cap.getCapabilitySchema().isPresent()){ continue; + } + + final String currentModuleName = cap.getModuleName().get(); + Map revisionMap = mappedModulesToRevisionToSchema.get(currentModuleName); + if (revisionMap == null) { + revisionMap = Maps.newHashMap(); + mappedModulesToRevisionToSchema.put(currentModuleName, revisionMap); + } + + String currentRevision = cap.getRevision().get(); + revisionMap.put(currentRevision, cap.getCapabilitySchema().get()); + } + + Map revisionMapRequest = mappedModulesToRevisionToSchema.get(moduleName); + Preconditions.checkState(revisionMapRequest != null, "Capability for module %s not present, " + "" + + "available modules : %s", moduleName, Collections2.transform(caps, CAPABILITY_TO_URI)); + + if (revision.isPresent()) { + String schema = revisionMapRequest.get(revision.get()); + + Preconditions.checkState(schema != null, + "Capability for module %s:%s not present, available revisions for module: %s", moduleName, + revision.get(), revisionMapRequest.keySet()); + + return schema; + } else { + Preconditions.checkState(revisionMapRequest.size() == 1, + "Expected 1 capability for module %s, available revisions : %s", moduleName, + revisionMapRequest.keySet()); + return revisionMapRequest.values().iterator().next(); + } + } + + @Override + public synchronized Capabilities getCapabilities() { + return new CapabilitiesBuilder().setCapability(Lists.newArrayList(capabilities.keySet())).build(); + } - Preconditions.checkState(cap.getModuleNamespace().isPresent()); - builder.setNamespace(new Uri(cap.getModuleNamespace().get())); + @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); + } + }; + } - Preconditions.checkState(cap.getRevision().isPresent()); - String version = cap.getRevision().get(); - builder.setVersion(version); + private NetconfState getCurrentNetconfState() { + return new NetconfStateBuilder() + .setCapabilities(getCapabilities()) + .setSchemas(getSchemas()) + .setSessions(getSessions()) + .build(); + } - Preconditions.checkState(cap.getModuleName().isPresent()); - String identifier = cap.getModuleName().get(); - builder.setIdentifier(identifier); + private static Schemas transformSchemas(final Set caps) { + final List schemas = new ArrayList<>(caps.size()); + for (final Capability cap : caps) { + if (cap.getCapabilitySchema().isPresent()) { + final SchemaBuilder builder = new SchemaBuilder(); + Preconditions.checkState(cap.getModuleNamespace().isPresent()); + builder.setNamespace(new Uri(cap.getModuleNamespace().get())); - builder.setFormat(Yang.class); + Preconditions.checkState(cap.getRevision().isPresent()); + final String version = cap.getRevision().get(); + builder.setVersion(version); - builder.setLocation(transformLocations(cap.getLocation().or(Collections. emptyList()))); + Preconditions.checkState(cap.getModuleName().isPresent()); + final String identifier = cap.getModuleName().get(); + builder.setIdentifier(identifier); - builder.setKey(new SchemaKey(Yang.class, identifier, version)); + builder.setFormat(Yang.class); - schemas.add(builder.build()); + builder.setLocation(transformLocations(cap.getLocation())); + + builder.setKey(new SchemaKey(Yang.class, identifier, version)); + + schemas.add(builder.build()); + } } return new SchemasBuilder().setSchema(schemas).build(); } - private List transformLocations(List locations) { - List monitoringLocations = Lists.newArrayList(); - monitoringLocations.add(new Schema.Location(Schema.Location.Enumeration.NETCONF)); + private static List transformLocations(final Collection locations) { + if (locations.isEmpty()) { + return NETCONF_LOCATIONS; + } + + final Builder b = ImmutableList.builder(); + b.add(NETCONF_LOCATION); - for (String location : locations) { - monitoringLocations.add(new Schema.Location(new Uri(location))); + for (final String location : locations) { + b.add(new Schema.Location(new Uri(location))); } - return monitoringLocations; + return b.build(); } - private List transformSessions(Set sessions) { - return Lists.newArrayList(Collections2.transform(sessions, new Function() { - @Nullable - @Override - public Session apply(@Nullable NetconfManagementSession input) { - return input.toManagementSession(); - } - })); + @Override + public synchronized void onCapabilitiesAdded(final Set addedCaps) { + // FIXME howto check for duplicates + this.capabilities.putAll(Maps.uniqueIndex(addedCaps, CAPABILITY_TO_URI)); + notifyListeners(); + } + + private void notifyListeners() { + for (final MonitoringListener listener : listeners) { + listener.onStateChanged(getCurrentNetconfState()); + } + } + + @Override + public synchronized void onCapabilitiesRemoved(final Set addedCaps) { + for (final Capability addedCap : addedCaps) { + capabilities.remove(addedCap.getCapabilityUri()); + } + notifyListeners(); + } + + @Override + public synchronized void close() throws Exception { + listeners.clear(); + sessions.clear(); + capabilities.clear(); } }