From f73a6cd4c81794193d42893fab61b97416f751f2 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Tue, 10 Feb 2015 09:15:15 +0100 Subject: [PATCH] BUG-2600 Dynamic schemas in netconf server Netconf server does not preserve snapshots of schema contexts for each netconf session anymore Every netconf session is using current SchemaContext + Use notification manager to notify about capability changes Change-Id: Ie47125e1eb6851b54b09d5e4afe38fee323850de Signed-off-by: Maros Marsalek --- opendaylight/md-sal/sal-binding-it/pom.xml | 5 + .../test/sal/binding/it/TestHelper.java | 3 + .../netconf/config-netconf-connector/pom.xml | 6 +- .../operations/editconfig/EditConfig.java | 8 +- .../operations/get/Get.java | 6 +- .../operations/getconfig/GetConfig.java | 6 +- .../operations/runtimerpc/RuntimeRpc.java | 6 +- .../osgi/Activator.java | 6 +- .../osgi/NetconfOperationProvider.java | 4 +- .../NetconfOperationServiceFactoryImpl.java | 6 +- .../osgi/NetconfOperationServiceImpl.java | 49 +--- .../osgi/YangStoreContext.java | 38 +++ .../osgi/YangStoreException.java | 18 -- .../osgi/YangStoreService.java | 220 +++++++++++++++++- .../osgi/YangStoreServiceImpl.java | 72 ------ .../osgi/YangStoreSnapshot.java | 121 ++++++++-- .../osgi/YangStoreSnapshotImpl.java | 115 --------- .../NetconfMappingTest.java | 26 ++- .../operations/editconfig/EditConfigTest.java | 4 +- .../osgi/NetconfOperationServiceImplTest.java | 122 ---------- .../impl/osgi/NetconfOperationRouterImpl.java | 4 + .../netconf/it/AbstractNetconfConfigTest.java | 47 ++-- 22 files changed, 445 insertions(+), 447 deletions(-) create mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreContext.java delete mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreException.java delete mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreServiceImpl.java delete mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshotImpl.java delete mode 100644 opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImplTest.java diff --git a/opendaylight/md-sal/sal-binding-it/pom.xml b/opendaylight/md-sal/sal-binding-it/pom.xml index 491e5dcb61..7c6710fdbb 100644 --- a/opendaylight/md-sal/sal-binding-it/pom.xml +++ b/opendaylight/md-sal/sal-binding-it/pom.xml @@ -69,6 +69,10 @@ org.opendaylight.controller netconf-monitoring + + org.opendaylight.controller + netconf-notifications-api + org.opendaylight.controller sal-binding-broker-impl @@ -77,6 +81,7 @@ org.opendaylight.yangtools.thirdparty antlr4-runtime-osgi-nohead + diff --git a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java index a64e3600f5..96f52bd8dc 100644 --- a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java +++ b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java @@ -83,6 +83,9 @@ public class TestHelper { mavenBundle("org.eclipse.birt.runtime.3_7_1", "org.apache.xml.resolver", "1.2.0"), mavenBundle(CONTROLLER, "config-netconf-connector").versionAsInProject(), // + mavenBundle(CONTROLLER, "netconf-notifications-api").versionAsInProject(), // + mavenBundle(CONTROLLER, "ietf-netconf").versionAsInProject(), // + mavenBundle(CONTROLLER, "ietf-netconf-notifications").versionAsInProject(), // mavenBundle(CONTROLLER, "netconf-impl").versionAsInProject(), // mavenBundle(CONTROLLER, "config-persister-file-xml-adapter").versionAsInProject().noStart(), diff --git a/opendaylight/netconf/config-netconf-connector/pom.xml b/opendaylight/netconf/config-netconf-connector/pom.xml index 2b3015243f..3a949697e9 100644 --- a/opendaylight/netconf/config-netconf-connector/pom.xml +++ b/opendaylight/netconf/config-netconf-connector/pom.xml @@ -29,6 +29,10 @@ ${project.groupId} netconf-mapping-api + + ${project.groupId} + netconf-notifications-api + ${project.groupId} netconf-util @@ -106,8 +110,6 @@ org.opendaylight.controller.netconf.confignetconfconnector.util, org.opendaylight.controller.netconf.confignetconfconnector.osgi, org.opendaylight.controller.netconf.confignetconfconnector.exception, - * - diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java index f526d92895..ca6a8c46b9 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java @@ -37,7 +37,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser.EditConfigExecution; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -52,12 +52,12 @@ public class EditConfig extends AbstractConfigNetconfOperation { private static final Logger LOG = LoggerFactory.getLogger(EditConfig.class); - private final YangStoreSnapshot yangStoreSnapshot; + private final YangStoreContext yangStoreSnapshot; private final TransactionProvider transactionProvider; private EditConfigXmlParser editConfigXmlParser; - public EditConfig(YangStoreSnapshot yangStoreSnapshot, TransactionProvider transactionProvider, + public EditConfig(YangStoreContext yangStoreSnapshot, TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) { super(configRegistryClient, netconfSessionIdForReporting); this.yangStoreSnapshot = yangStoreSnapshot; @@ -204,7 +204,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { } } - public static Config getConfigMapping(ConfigRegistryClient configRegistryClient, YangStoreSnapshot yangStoreSnapshot) { + public static Config getConfigMapping(ConfigRegistryClient configRegistryClient, YangStoreContext yangStoreSnapshot) { Map> factories = transformMbeToModuleConfigs(configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap()); Map> identitiesMap = transformIdentities(yangStoreSnapshot.getModules()); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java index b504cbf6fd..27d53cdc32 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java @@ -26,7 +26,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtim import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext; import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException; import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException; @@ -38,10 +38,10 @@ import org.w3c.dom.Element; public class Get extends AbstractConfigNetconfOperation { - private final YangStoreSnapshot yangStoreSnapshot; + private final YangStoreContext yangStoreSnapshot; private static final Logger LOG = LoggerFactory.getLogger(Get.class); - public Get(YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient, + public Get(YangStoreContext yangStoreSnapshot, ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) { super(configRegistryClient, netconfSessionIdForReporting); this.yangStoreSnapshot = yangStoreSnapshot; diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java index 2ff4dd677f..350ace5eb1 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java @@ -20,7 +20,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException; @@ -36,14 +36,14 @@ public class GetConfig extends AbstractConfigNetconfOperation { public static final String GET_CONFIG = "get-config"; - private final YangStoreSnapshot yangStoreSnapshot; + private final YangStoreContext yangStoreSnapshot; private final Optional maybeNamespace; private final TransactionProvider transactionProvider; private static final Logger LOG = LoggerFactory.getLogger(GetConfig.class); - public GetConfig(YangStoreSnapshot yangStoreSnapshot, Optional maybeNamespace, + public GetConfig(YangStoreContext yangStoreSnapshot, Optional maybeNamespace, TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) { super(configRegistryClient, netconfSessionIdForReporting); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java index 937a2ad588..ebbc0e5695 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java @@ -30,7 +30,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.In import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.ModuleRpcs; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.Rpcs; import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -45,9 +45,9 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { private static final Logger LOG = LoggerFactory.getLogger(RuntimeRpc.class); public static final String CONTEXT_INSTANCE = "context-instance"; - private final YangStoreSnapshot yangStoreSnapshot; + private final YangStoreContext yangStoreSnapshot; - public RuntimeRpc(final YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient, + public RuntimeRpc(final YangStoreContext yangStoreSnapshot, ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) { super(configRegistryClient, netconfSessionIdForReporting); this.yangStoreSnapshot = yangStoreSnapshot; diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java index faaa17d528..1579d1927f 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java @@ -43,7 +43,7 @@ public class Activator implements BundleActivator { SchemaContextProvider schemaContextProvider = reference.getBundle().getBundleContext().getService(reference); - YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(schemaContextProvider); + YangStoreService yangStoreService = new YangStoreService(schemaContextProvider, context); configRegistryLookup = new ConfigRegistryLookupThread(yangStoreService); configRegistryLookup.start(); return configRegistryLookup; @@ -79,9 +79,9 @@ public class Activator implements BundleActivator { } private class ConfigRegistryLookupThread extends Thread { - private final YangStoreServiceImpl yangStoreService; + private final YangStoreService yangStoreService; - private ConfigRegistryLookupThread(YangStoreServiceImpl yangStoreService) { + private ConfigRegistryLookupThread(YangStoreService yangStoreService) { super("config-registry-lookup"); this.yangStoreService = yangStoreService; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationProvider.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationProvider.java index 04d5d4bb6f..612bd85998 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationProvider.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationProvider.java @@ -27,7 +27,7 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; final class NetconfOperationProvider { private final Set operations; - NetconfOperationProvider(YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient, + NetconfOperationProvider(YangStoreContext yangStoreSnapshot, ConfigRegistryClient configRegistryClient, TransactionProvider transactionProvider, String netconfSessionIdForReporting) { operations = setUpOperations(yangStoreSnapshot, configRegistryClient, transactionProvider, @@ -38,7 +38,7 @@ final class NetconfOperationProvider { return operations; } - private static Set setUpOperations(YangStoreSnapshot yangStoreSnapshot, + private static Set setUpOperations(YangStoreContext yangStoreSnapshot, ConfigRegistryClient configRegistryClient, TransactionProvider transactionProvider, String netconfSessionIdForReporting) { Set ops = Sets.newHashSet(); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java index b5ae66d605..82c04a50e0 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java @@ -66,10 +66,6 @@ public class NetconfOperationServiceFactoryImpl implements NetconfOperationServi @Override public NetconfOperationServiceImpl createService(String netconfSessionIdForReporting) { - try { - return new NetconfOperationServiceImpl(yangStoreService, jmxClient, netconfSessionIdForReporting); - } catch (YangStoreException e) { - throw new IllegalStateException(e); - } + return new NetconfOperationServiceImpl(yangStoreService, jmxClient, netconfSessionIdForReporting); } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java index 902be44fd9..ef0a72c0f0 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java @@ -8,18 +8,12 @@ package org.opendaylight.controller.netconf.confignetconfconnector.osgi; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.Map; import java.util.Set; -import org.opendaylight.controller.config.api.LookupRegistry; import org.opendaylight.controller.config.util.ConfigRegistryJMXClient; -import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.confignetconfconnector.util.Util; import org.opendaylight.controller.netconf.mapping.api.Capability; @@ -28,61 +22,32 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.yangtools.yang.model.api.Module; /** - * Manages life cycle of {@link YangStoreSnapshot}. + * Manages life cycle of {@link YangStoreContext}. */ public class NetconfOperationServiceImpl implements NetconfOperationService { - private final YangStoreSnapshot yangStoreSnapshot; private final NetconfOperationProvider operationProvider; - private final Set capabilities; private final TransactionProvider transactionProvider; + private final YangStoreService yangStoreService; public NetconfOperationServiceImpl(final YangStoreService yangStoreService, final ConfigRegistryJMXClient jmxClient, - final String netconfSessionIdForReporting) throws YangStoreException { + final String netconfSessionIdForReporting) { - yangStoreSnapshot = yangStoreService.getYangStoreSnapshot(); - checkConsistencyBetweenYangStoreAndConfig(jmxClient, yangStoreSnapshot); + this.yangStoreService = yangStoreService; transactionProvider = new TransactionProvider(jmxClient, netconfSessionIdForReporting); - operationProvider = new NetconfOperationProvider(yangStoreSnapshot, jmxClient, transactionProvider, + operationProvider = new NetconfOperationProvider(yangStoreService, jmxClient, transactionProvider, netconfSessionIdForReporting); - capabilities = setupCapabilities(yangStoreSnapshot); - } - - - @VisibleForTesting - static void checkConsistencyBetweenYangStoreAndConfig(final LookupRegistry jmxClient, final YangStoreSnapshot yangStoreSnapshot) { - Set missingModulesFromConfig = Sets.newHashSet(); - - Set modulesSeenByConfig = jmxClient.getAvailableModuleFactoryQNames(); - Map> moduleMXBeanEntryMap = yangStoreSnapshot.getModuleMXBeanEntryMap(); - - for (Map moduleNameToMBE : moduleMXBeanEntryMap.values()) { - for (ModuleMXBeanEntry moduleMXBeanEntry : moduleNameToMBE.values()) { - String moduleSeenByYangStore = moduleMXBeanEntry.getYangModuleQName().toString(); - if(!modulesSeenByConfig.contains(moduleSeenByYangStore)){ - missingModulesFromConfig.add(moduleSeenByYangStore); - } - } - } - - Preconditions - .checkState( - missingModulesFromConfig.isEmpty(), - "There are inconsistencies between configuration subsystem and yangstore in terms of discovered yang modules, yang modules missing from config subsystem but present in yangstore: %s, %sAll modules present in config: %s", - missingModulesFromConfig, System.lineSeparator(), modulesSeenByConfig); - } @Override public void close() { - yangStoreSnapshot.close(); transactionProvider.close(); } @Override public Set getCapabilities() { - return capabilities; + return setupCapabilities(yangStoreService); } @Override @@ -90,7 +55,7 @@ public class NetconfOperationServiceImpl implements NetconfOperationService { return operationProvider.getOperations(); } - private static Set setupCapabilities(final YangStoreSnapshot yangStoreSnapshot) { + private static Set setupCapabilities(final YangStoreContext yangStoreSnapshot) { Set capabilities = new HashSet<>(); // [RFC6241] 8.3. Candidate Configuration Capability capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0")); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreContext.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreContext.java new file mode 100644 index 0000000000..6a38a9ad3d --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreContext.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * 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.controller.netconf.confignetconfconnector.osgi; + +import java.util.Map; +import java.util.Set; +import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; + +public interface YangStoreContext { + + /** + * @deprecated Use {@link #getQNamesToIdentitiesToModuleMXBeanEntries()} instead. This method return only one + * module representation even if multiple revisions are available. + */ + @Deprecated + Map> getModuleMXBeanEntryMap(); + + + Map> getQNamesToIdentitiesToModuleMXBeanEntries(); + + /** + * Get all modules discovered when this snapshot was created. + * @return all modules discovered. If one module exists with two different revisions, return both. + */ + Set getModules(); + + String getModuleSource(ModuleIdentifier moduleIdentifier); + +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreException.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreException.java deleted file mode 100644 index 18558b39ca..0000000000 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreException.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * 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.controller.netconf.confignetconfconnector.osgi; - -public class YangStoreException extends Exception { - - private static final long serialVersionUID = 2841238836278528836L; - - public YangStoreException(String message, Throwable cause) { - super(message, cause); - } - -} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java index 969d7cfdb3..de151a8969 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java @@ -5,18 +5,224 @@ * 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.controller.netconf.confignetconfconnector.osgi; -/** - * Yang store OSGi service - */ -public interface YangStoreService { +import com.google.common.base.Function; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import java.lang.ref.SoftReference; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicReference; +import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; +import org.opendaylight.controller.netconf.notifications.BaseNetconfNotificationListener; +import org.opendaylight.controller.netconf.notifications.BaseNotificationPublisherRegistration; +import org.opendaylight.controller.netconf.notifications.NetconfNotificationCollector; +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.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.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; +import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class YangStoreService implements YangStoreContext { + + private static final Logger LOG = LoggerFactory.getLogger(YangStoreService.class); /** - * Module entry objects mapped to module names and namespaces. + * This is a rather interesting locking model. We need to guard against both the + * cache expiring from GC and being invalidated by schema context change. The + * context can change while we are doing processing, so we do not want to block + * it, so no synchronization can happen on the methods. + * + * So what we are doing is the following: * - * @return actual view of what is available in OSGi service registry. + * We synchronize with GC as usual, using a SoftReference. + * + * The atomic reference is used to synchronize with {@link #refresh()}, e.g. when + * refresh happens, it will push a SoftReference(null), e.g. simulate the GC. Now + * that may happen while the getter is already busy acting on the old schema context, + * so it needs to understand that a refresh has happened and retry. To do that, it + * attempts a CAS operation -- if it fails, in knows that the SoftReference has + * been replaced and thus it needs to retry. + * + * Note that {@link #getYangStoreSnapshot()} will still use synchronize() internally + * to stop multiple threads doing the same work. */ - YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException; + private final AtomicReference> ref = + new AtomicReference<>(new SoftReference(null)); + + private final SchemaContextProvider schemaContextProvider; + private final BaseNetconfNotificationListener notificationPublisher; + + private final ExecutorService notificationExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() { + @Override + public Thread newThread(final Runnable r) { + return new Thread(r, "config-netconf-connector-capability-notifications"); + } + }); + + public YangStoreService(final SchemaContextProvider schemaContextProvider, final BundleContext context) { + this(schemaContextProvider, new NotificationCollectorTracker(context)); + } + + public YangStoreService(final SchemaContextProvider schemaContextProvider, final BaseNetconfNotificationListener notificationHandler) { + this.schemaContextProvider = schemaContextProvider; + this.notificationPublisher = notificationHandler; + } + + private synchronized YangStoreContext getYangStoreSnapshot() { + SoftReference r = ref.get(); + YangStoreSnapshot ret = r.get(); + + while (ret == null) { + // We need to be compute a new value + ret = new YangStoreSnapshot(schemaContextProvider.getSchemaContext()); + + if (!ref.compareAndSet(r, new SoftReference<>(ret))) { + LOG.debug("Concurrent refresh detected, recomputing snapshot"); + r = ref.get(); + ret = null; + } + } + + return ret; + } + + @Override + public Map> getModuleMXBeanEntryMap() { + return getYangStoreSnapshot().getModuleMXBeanEntryMap(); + } + + @Override + public Map> getQNamesToIdentitiesToModuleMXBeanEntries() { + return getYangStoreSnapshot().getQNamesToIdentitiesToModuleMXBeanEntries(); + } + + @Override + public Set getModules() { + return getYangStoreSnapshot().getModules(); + } + + @Override + public String getModuleSource(final ModuleIdentifier moduleIdentifier) { + return getYangStoreSnapshot().getModuleSource(moduleIdentifier); + } + + public void refresh() { + final YangStoreSnapshot previous = ref.get().get(); + ref.set(new SoftReference(null)); + notificationExecutor.submit(new CapabilityChangeNotifier(previous)); + } + + private final class CapabilityChangeNotifier implements Runnable { + private final YangStoreSnapshot previous; + + public CapabilityChangeNotifier(final YangStoreSnapshot previous) { + this.previous = previous; + } + + @Override + public void run() { + final YangStoreContext current = getYangStoreSnapshot(); + + if(current.equals(previous) == false) { + notificationPublisher.onCapabilityChanged(computeDiff(previous, current)); + } + } + } + + private static final Function MODULE_TO_URI = new Function() { + @Override + public Uri apply(final Module input) { + final QName qName = QName.cachedReference(QName.create(input.getQNameModule(), input.getName())); + return new Uri(qName.toString()); + } + }; + + static NetconfCapabilityChange computeDiff(final YangStoreContext previous, final YangStoreContext current) { + final Sets.SetView removed = Sets.difference(previous.getModules(), current.getModules()); + final Sets.SetView added = Sets.difference(current.getModules(), previous.getModules()); + + final NetconfCapabilityChangeBuilder netconfCapabilityChangeBuilder = new NetconfCapabilityChangeBuilder(); + netconfCapabilityChangeBuilder.setChangedBy(new ChangedByBuilder().setServerOrUser(new ServerBuilder().setServer(true).build()).build()); + netconfCapabilityChangeBuilder.setDeletedCapability(Lists.newArrayList(Collections2.transform(removed, MODULE_TO_URI))); + netconfCapabilityChangeBuilder.setAddedCapability(Lists.newArrayList(Collections2.transform(added, MODULE_TO_URI))); + // TODO modified should be computed ... but why ? + netconfCapabilityChangeBuilder.setModifiedCapability(Collections.emptyList()); + return netconfCapabilityChangeBuilder.build(); + } + + + /** + * Looks for NetconfNotificationCollector service and publishes base netconf notifications if possible + */ + private static class NotificationCollectorTracker implements ServiceTrackerCustomizer, BaseNetconfNotificationListener, AutoCloseable { + + private final BundleContext context; + private final ServiceTracker listenerTracker; + private BaseNotificationPublisherRegistration publisherReg; + + public NotificationCollectorTracker(final BundleContext context) { + this.context = context; + listenerTracker = new ServiceTracker<>(context, NetconfNotificationCollector.class, this); + listenerTracker.open(); + } + + @Override + public synchronized NetconfNotificationCollector addingService(final ServiceReference reference) { + closePublisherRegistration(); + publisherReg = context.getService(reference).registerBaseNotificationPublisher(); + return null; + } + + @Override + public synchronized void modifiedService(final ServiceReference reference, final NetconfNotificationCollector service) { + closePublisherRegistration(); + publisherReg = context.getService(reference).registerBaseNotificationPublisher(); + } + + @Override + public synchronized void removedService(final ServiceReference reference, final NetconfNotificationCollector service) { + closePublisherRegistration(); + publisherReg = null; + } + + private void closePublisherRegistration() { + if(publisherReg != null) { + publisherReg.close(); + } + } + + @Override + public synchronized void close() { + closePublisherRegistration(); + listenerTracker.close(); + } + + @Override + public void onCapabilityChanged(final NetconfCapabilityChange capabilityChange) { + if(publisherReg == null) { + LOG.warn("Omitting notification due to missing notification service: {}", capabilityChange); + return; + } + publisherReg.onCapabilityChanged(capabilityChange); + } + } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreServiceImpl.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreServiceImpl.java deleted file mode 100644 index 958af54e3f..0000000000 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreServiceImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * 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.controller.netconf.confignetconfconnector.osgi; - -import java.lang.ref.SoftReference; -import java.util.concurrent.atomic.AtomicReference; -import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class YangStoreServiceImpl implements YangStoreService { - private static final Logger LOG = LoggerFactory.getLogger(YangStoreServiceImpl.class); - - /** - * This is a rather interesting locking model. We need to guard against both the - * cache expiring from GC and being invalidated by schema context change. The - * context can change while we are doing processing, so we do not want to block - * it, so no synchronization can happen on the methods. - * - * So what we are doing is the following: - * - * We synchronize with GC as usual, using a SoftReference. - * - * The atomic reference is used to synchronize with {@link #refresh()}, e.g. when - * refresh happens, it will push a SoftReference(null), e.g. simulate the GC. Now - * that may happen while the getter is already busy acting on the old schema context, - * so it needs to understand that a refresh has happened and retry. To do that, it - * attempts a CAS operation -- if it fails, in knows that the SoftReference has - * been replaced and thus it needs to retry. - * - * Note that {@link #getYangStoreSnapshot()} will still use synchronize() internally - * to stop multiple threads doing the same work. - */ - private final AtomicReference> ref = new AtomicReference<>(new SoftReference(null)); - private final SchemaContextProvider service; - - public YangStoreServiceImpl(final SchemaContextProvider service) { - this.service = service; - } - - @Override - public synchronized YangStoreSnapshotImpl getYangStoreSnapshot() throws YangStoreException { - SoftReference r = ref.get(); - YangStoreSnapshotImpl ret = r.get(); - - while (ret == null) { - // We need to be compute a new value - ret = new YangStoreSnapshotImpl(service.getSchemaContext()); - - if (!ref.compareAndSet(r, new SoftReference<>(ret))) { - LOG.debug("Concurrent refresh detected, recomputing snapshot"); - r = ref.get(); - ret = null; - } - } - - return ret; - } - - /** - * Called when schema context changes, invalidates cache. - */ - public void refresh() { - ref.set(new SoftReference(null)); - } -} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshot.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshot.java index 8ec4fddbd4..0d3370548a 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshot.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshot.java @@ -5,36 +5,123 @@ * 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.controller.netconf.confignetconfconnector.osgi; +import com.google.common.collect.Maps; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; +import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslator; +import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry; +import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper; +import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class YangStoreSnapshot implements YangStoreContext { + private static final Logger LOG = LoggerFactory.getLogger(YangStoreSnapshot.class); + + + private final Map> moduleMXBeanEntryMap; + + + private final Map> qNamesToIdentitiesToModuleMXBeanEntries; + + private final SchemaContext schemaContext; + + public YangStoreSnapshot(final SchemaContext resolveSchemaContext) { + LOG.trace("Resolved modules:{}", resolveSchemaContext.getModules()); + this.schemaContext = resolveSchemaContext; + // JMX generator + + Map namespaceToPackageMapping = Maps.newHashMap(); + PackageTranslator packageTranslator = new PackageTranslator(namespaceToPackageMapping); + Map qNamesToSIEs = new HashMap<>(); + Map knownSEITracker = new HashMap<>(); + // create SIE structure qNamesToSIEs + for (Module module : resolveSchemaContext.getModules()) { + String packageName = packageTranslator.getPackageName(module); + Map namesToSIEntries = ServiceInterfaceEntry + .create(module, packageName, knownSEITracker); + for (Entry sieEntry : namesToSIEntries.entrySet()) { + // merge value into qNamesToSIEs + if (qNamesToSIEs.containsKey(sieEntry.getKey()) == false) { + qNamesToSIEs.put(sieEntry.getKey(), sieEntry.getValue()); + } else { + throw new IllegalStateException("Cannot add two SIE with same qname " + + sieEntry.getValue()); + } + } + } + + Map> moduleMXBeanEntryMap = Maps.newHashMap(); + + Map> qNamesToIdentitiesToModuleMXBeanEntries = new HashMap<>(); + -public interface YangStoreSnapshot extends AutoCloseable { + for (Module module : schemaContext.getModules()) { + String packageName = packageTranslator.getPackageName(module); + TypeProviderWrapper typeProviderWrapper = new TypeProviderWrapper( + new TypeProviderImpl(resolveSchemaContext)); - /** - * @deprecated Use {@link #getQNamesToIdentitiesToModuleMXBeanEntries()} instead. This method return only one - * module representation even if multiple revisions are available. - */ - @Deprecated - Map> getModuleMXBeanEntryMap(); + QName qName = QName.create(module.getNamespace(), module.getRevision(), module.getName()); + Map namesToMBEs = + Collections.unmodifiableMap(ModuleMXBeanEntry.create(module, qNamesToSIEs, resolveSchemaContext, + typeProviderWrapper, packageName)); + moduleMXBeanEntryMap.put(module.getNamespace().toString(), namesToMBEs); + + qNamesToIdentitiesToModuleMXBeanEntries.put(qName, namesToMBEs); + } + this.moduleMXBeanEntryMap = Collections.unmodifiableMap(moduleMXBeanEntryMap); + this.qNamesToIdentitiesToModuleMXBeanEntries = Collections.unmodifiableMap(qNamesToIdentitiesToModuleMXBeanEntries); + + } + + @Override + public Map> getModuleMXBeanEntryMap() { + return moduleMXBeanEntryMap; + } + + @Override + public Map> getQNamesToIdentitiesToModuleMXBeanEntries() { + return qNamesToIdentitiesToModuleMXBeanEntries; + } + + @Override + public Set getModules() { + return schemaContext.getModules(); + } + + @Override + public String getModuleSource(final org.opendaylight.yangtools.yang.model.api.ModuleIdentifier moduleIdentifier) { + return schemaContext.getModuleSource(moduleIdentifier).get(); + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; - Map> getQNamesToIdentitiesToModuleMXBeanEntries(); + final YangStoreSnapshot that = (YangStoreSnapshot) o; - /** - * Get all modules discovered when this snapshot was created. - * @return all modules discovered. If one module exists with two different revisions, return both. - */ - Set getModules(); + if (schemaContext != null ? !schemaContext.equals(that.schemaContext) : that.schemaContext != null) + return false; - String getModuleSource(ModuleIdentifier moduleIdentifier); + return true; + } @Override - void close(); + public int hashCode() { + return schemaContext != null ? schemaContext.hashCode() : 0; + } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshotImpl.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshotImpl.java deleted file mode 100644 index 075ae63343..0000000000 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshotImpl.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * 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.controller.netconf.confignetconfconnector.osgi; - -import com.google.common.collect.Maps; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; -import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslator; -import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry; -import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper; -import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class YangStoreSnapshotImpl implements YangStoreSnapshot { - private static final Logger LOG = LoggerFactory.getLogger(YangStoreSnapshotImpl.class); - - - private final Map> moduleMXBeanEntryMap; - - - private final Map> qNamesToIdentitiesToModuleMXBeanEntries; - - private final SchemaContext schemaContext; - - - public YangStoreSnapshotImpl(final SchemaContext resolveSchemaContext) { - LOG.trace("Resolved modules:{}", resolveSchemaContext.getModules()); - this.schemaContext = resolveSchemaContext; - // JMX generator - - Map namespaceToPackageMapping = Maps.newHashMap(); - PackageTranslator packageTranslator = new PackageTranslator(namespaceToPackageMapping); - Map qNamesToSIEs = new HashMap<>(); - Map knownSEITracker = new HashMap<>(); - // create SIE structure qNamesToSIEs - for (Module module : resolveSchemaContext.getModules()) { - String packageName = packageTranslator.getPackageName(module); - Map namesToSIEntries = ServiceInterfaceEntry - .create(module, packageName, knownSEITracker); - for (Entry sieEntry : namesToSIEntries.entrySet()) { - // merge value into qNamesToSIEs - if (qNamesToSIEs.containsKey(sieEntry.getKey()) == false) { - qNamesToSIEs.put(sieEntry.getKey(), sieEntry.getValue()); - } else { - throw new IllegalStateException("Cannot add two SIE with same qname " - + sieEntry.getValue()); - } - } - } - - Map> moduleMXBeanEntryMap = Maps.newHashMap(); - - Map> qNamesToIdentitiesToModuleMXBeanEntries = new HashMap<>(); - - - for (Module module : schemaContext.getModules()) { - String packageName = packageTranslator.getPackageName(module); - TypeProviderWrapper typeProviderWrapper = new TypeProviderWrapper( - new TypeProviderImpl(resolveSchemaContext)); - - QName qName = QName.create(module.getNamespace(), module.getRevision(), module.getName()); - - Map namesToMBEs = - Collections.unmodifiableMap(ModuleMXBeanEntry.create(module, qNamesToSIEs, resolveSchemaContext, - typeProviderWrapper, packageName)); - moduleMXBeanEntryMap.put(module.getNamespace().toString(), namesToMBEs); - - qNamesToIdentitiesToModuleMXBeanEntries.put(qName, namesToMBEs); - } - this.moduleMXBeanEntryMap = Collections.unmodifiableMap(moduleMXBeanEntryMap); - this.qNamesToIdentitiesToModuleMXBeanEntries = Collections.unmodifiableMap(qNamesToIdentitiesToModuleMXBeanEntries); - - } - - @Override - public Map> getModuleMXBeanEntryMap() { - return moduleMXBeanEntryMap; - } - - @Override - public Map> getQNamesToIdentitiesToModuleMXBeanEntries() { - return qNamesToIdentitiesToModuleMXBeanEntries; - } - - @Override - public Set getModules() { - return schemaContext.getModules(); - } - - @Override - public String getModuleSource(final org.opendaylight.yangtools.yang.model.api.ModuleIdentifier moduleIdentifier) { - return schemaContext.getModuleSource(moduleIdentifier).get(); - } - - @Override - public void close() { - - } -} diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java index 6f9a62af1a..f1fc27725b 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java @@ -13,6 +13,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -89,8 +91,8 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.edi import org.opendaylight.controller.netconf.confignetconfconnector.operations.get.Get; import org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig.GetConfig; import org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc.RuntimeRpc; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; @@ -109,6 +111,9 @@ import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; +import org.osgi.framework.Filter; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -132,7 +137,7 @@ public class NetconfMappingTest extends AbstractConfigTest { private TestImplModuleFactory factory4; @Mock - YangStoreSnapshot yangStoreSnapshot; + YangStoreContext yangStoreSnapshot; @Mock NetconfOperationRouter netconfOperationRouter; @Mock @@ -143,6 +148,13 @@ public class NetconfMappingTest extends AbstractConfigTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + + + final Filter filter = mock(Filter.class); + doReturn(filter).when(mockedContext).createFilter(anyString()); + doNothing().when(mockedContext).addServiceListener(any(ServiceListener.class), anyString()); + doReturn(new ServiceReference[]{}).when(mockedContext).getServiceReferences(anyString(), anyString()); + doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap(); doReturn(getModules()).when(this.yangStoreSnapshot).getModules(); doNothing().when(netconfOperationServiceSnapshot).close(); @@ -151,6 +163,8 @@ public class NetconfMappingTest extends AbstractConfigTest { this.factory2 = new DepTestImplModuleFactory(); this.factory3 = new IdentityTestModuleFactory(); factory4 = new TestImplModuleFactory(); + + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, this.factory, this.factory2, this.factory3, factory4)); @@ -629,13 +643,13 @@ public class NetconfMappingTest extends AbstractConfigTest { YangParserImpl yangParser = new YangParserImpl(); final SchemaContext schemaContext = yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(yangDependencies).values())); - YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(new SchemaContextProvider() { + YangStoreService yangStoreService = new YangStoreService(new SchemaContextProvider() { @Override public SchemaContext getSchemaContext() { return schemaContext ; } - }); - mBeanEntries.putAll(yangStoreService.getYangStoreSnapshot().getModuleMXBeanEntryMap()); + }, mockedContext); + mBeanEntries.putAll(yangStoreService.getModuleMXBeanEntryMap()); return mBeanEntries; } diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java index 817bedf4e2..ad57f897e0 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java @@ -41,14 +41,14 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.opendaylight.controller.netconf.confignetconfconnector.operations.ValidateTest; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser.EditConfigExecution; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.util.xml.XmlUtil; public class EditConfigTest { @Mock - private YangStoreSnapshot yangStoreSnapshot; + private YangStoreContext yangStoreSnapshot; @Mock private TransactionProvider provider; @Mock diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImplTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImplTest.java deleted file mode 100644 index 413aa5cc67..0000000000 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImplTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * 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.controller.netconf.confignetconfconnector.osgi; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import java.net.URI; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Map; -import java.util.Set; -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Test; -import org.opendaylight.controller.config.api.LookupRegistry; -import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; -import org.opendaylight.yangtools.yang.common.QName; - -public class NetconfOperationServiceImplTest { - - private static final Date date1970_01_01; - - static { - try { - date1970_01_01 = new SimpleDateFormat("yyyy-MM-dd").parse("1970-01-01"); - } catch (ParseException e) { - throw new IllegalStateException(e); - } - } - - @Test - public void testCheckConsistencyBetweenYangStoreAndConfig_ok() throws Exception { - NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig( - mockJmxClient("qname1", "qname2"), - mockYangStoreSnapshot("qname2", "qname1")); - } - - @Test - public void testCheckConsistencyBetweenYangStoreAndConfig_ok2() throws Exception { - NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig( - mockJmxClient("qname1", "qname2", "qname4", "qname5"), - mockYangStoreSnapshot("qname2", "qname1")); - } - - @Test - public void testCheckConsistencyBetweenYangStoreAndConfig_ok3() throws Exception { - NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig( - mockJmxClient(), - mockYangStoreSnapshot()); - } - - @Test - public void testCheckConsistencyBetweenYangStoreAndConfig_yangStoreMore() throws Exception { - try { - NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(mockJmxClient("qname1"), - mockYangStoreSnapshot("qname2", "qname1")); - fail("An exception of type " + IllegalStateException.class + " was expected"); - } catch (IllegalStateException e) { - String message = e.getMessage(); - Assert.assertThat( - message, - CoreMatchers - .containsString("missing from config subsystem but present in yangstore: [(namespace?revision=1970-01-01)qname2]")); - Assert.assertThat( - message, - CoreMatchers - .containsString("All modules present in config: [(namespace?revision=1970-01-01)qname1]")); - } - } - - private YangStoreSnapshot mockYangStoreSnapshot(final String... qnames) { - YangStoreSnapshot mock = mock(YangStoreSnapshot.class); - - Map> map = Maps.newHashMap(); - - Map innerMap = Maps.newHashMap(); - - int i = 1; - for (String qname : qnames) { - innerMap.put(Integer.toString(i++), mockMBeanEntry(qname)); - } - - map.put("1", innerMap); - - doReturn(map).when(mock).getModuleMXBeanEntryMap(); - - return mock; - } - - private ModuleMXBeanEntry mockMBeanEntry(final String qname) { - ModuleMXBeanEntry mock = mock(ModuleMXBeanEntry.class); - QName q = getQName(qname); - doReturn(q).when(mock).getYangModuleQName(); - return mock; - } - - private QName getQName(final String qname) { - return QName.create(URI.create("namespace"), date1970_01_01, qname); - } - - private LookupRegistry mockJmxClient(final String... visibleQNames) { - LookupRegistry mock = mock(LookupRegistry.class); - Set qnames = Sets.newHashSet(); - for (String visibleQName : visibleQNames) { - QName q = getQName(visibleQName); - qnames.add(q.toString()); - } - doReturn(qnames).when(mock).getAvailableModuleFactoryQNames(); - return mock; - } -} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java index aeab13f7e2..2178d4eedf 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java @@ -31,6 +31,7 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot; +import org.opendaylight.controller.netconf.mapping.api.SessionAwareNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -147,6 +148,9 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { if (netconfOperation instanceof DefaultNetconfOperation) { ((DefaultNetconfOperation) netconfOperation).setNetconfSession(session); } + if(netconfOperation instanceof SessionAwareNetconfOperation) { + ((SessionAwareNetconfOperation) netconfOperation).setSession(session); + } if (!handlingPriority.equals(HandlingPriority.CANNOT_HANDLE)) { Preconditions.checkState(!sortedPriority.containsKey(handlingPriority), diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java index fd362f83e7..bf1385398b 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java @@ -52,10 +52,7 @@ import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionList import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; @@ -67,8 +64,10 @@ import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.controller.netconf.notifications.BaseNetconfNotificationListener; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.opendaylight.protocol.framework.NeverReconnectStrategy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; @@ -176,7 +175,7 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { return clientDispatcher; } - private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException { + private HardcodedYangStoreService getYangStore() throws IOException { final Collection yangDependencies = getBasicYangs(); return new HardcodedYangStoreService(yangDependencies); } @@ -246,22 +245,35 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { return b.build(); } - public static final class HardcodedYangStoreService implements YangStoreService { - - private final List byteArrayInputStreams; + public static final class HardcodedYangStoreService extends YangStoreService { + public HardcodedYangStoreService(final Collection inputStreams) throws IOException { + super(new SchemaContextProvider() { + @Override + public SchemaContext getSchemaContext() { + return getSchema(inputStreams); + } + }, new BaseNetconfNotificationListener() { + @Override + public void onCapabilityChanged(final NetconfCapabilityChange capabilityChange) { + // NOOP + } + }); + } - public HardcodedYangStoreService(final Collection inputStreams) throws YangStoreException, IOException { - byteArrayInputStreams = new ArrayList<>(); + private static SchemaContext getSchema(final Collection inputStreams) { + final ArrayList byteArrayInputStreams = new ArrayList<>(); for (final InputStream inputStream : inputStreams) { assertNotNull(inputStream); - final byte[] content = IOUtils.toByteArray(inputStream); + final byte[] content; + try { + content = IOUtils.toByteArray(inputStream); + } catch (IOException e) { + throw new IllegalStateException("Cannot read " + inputStream, e); + } final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content); byteArrayInputStreams.add(byteArrayInputStream); } - } - @Override - public YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException { for (final InputStream inputStream : byteArrayInputStreams) { try { inputStream.reset(); @@ -271,14 +283,7 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { } final YangParserImpl yangParser = new YangParserImpl(); - final SchemaContext schemaContext = yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values())); - final YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(new SchemaContextProvider() { - @Override - public SchemaContext getSchemaContext() { - return schemaContext ; - } - }); - return yangStoreService.getYangStoreSnapshot(); + return yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values())); } } } -- 2.36.6