From: Giovanni Meo Date: Wed, 11 Dec 2013 13:37:15 +0000 (+0000) Subject: Merge "Bug 116 - Revisit SanityTest" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~209 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=30c43b1714eff95a8b7b601888fdb03da7150216;hp=effdf86b58e39060b75e6090596b123ec6e8ef69 Merge "Bug 116 - Revisit SanityTest" --- diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigRegistry.java index 5f23c90bbe..56b96e97bb 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigRegistry.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigRegistry.java @@ -19,7 +19,7 @@ import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConsta * Provides functionality for working with configuration registry - mainly * creating and committing config transactions. */ -public interface ConfigRegistry extends LookupRegistry { +public interface ConfigRegistry extends LookupRegistry, ServiceReferenceReadableRegistry { /** * Only well-known ObjectName in configuration system, under which diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java index 7e8ee64daa..c257e55dc0 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java @@ -16,7 +16,7 @@ import javax.management.ObjectName; /** * Represents functionality provided by configuration transaction. */ -public interface ConfigTransactionController extends LookupRegistry { +public interface ConfigTransactionController extends LookupRegistry, ServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry { /** * Create new configuration bean. @@ -64,6 +64,9 @@ public interface ConfigTransactionController extends LookupRegistry { */ String getTransactionName(); + /** + * @return all known module factory names as reported by {@link org.opendaylight.controller.config.spi.ModuleFactory#getImplementationName()} + */ Set getAvailableModuleNames(); } diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java index 7a3c4bf82d..8975471353 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java @@ -7,10 +7,9 @@ */ package org.opendaylight.controller.config.api; -import java.util.Set; - import javax.management.InstanceNotFoundException; import javax.management.ObjectName; +import java.util.Set; public interface LookupRegistry { @@ -58,4 +57,12 @@ public interface LookupRegistry { ObjectName lookupConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException; + /** + * Check that object name corresponds with existing module. + * + * @throws InstanceNotFoundException + * if search did not find exactly one instance + */ + void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException; + } diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java new file mode 100644 index 0000000000..f84fcd48c9 --- /dev/null +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java @@ -0,0 +1,53 @@ +/* + * 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.config.api; + +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import java.util.Map; +import java.util.Set; + +public interface ServiceReferenceReadableRegistry { + + /** + * Lookup object name by fully qualified service interface name and service reference name. + * @param serviceInterfaceName service interface name + * @param refName service reference name supplied in + * {@link org.opendaylight.controller.config.api.ConfigTransactionController#saveServiceReference(String, String, javax.management.ObjectName)} + * @throws java.lang.IllegalArgumentException if module not found + */ + ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName); + + /** + * Get mapping of services to reference names and module object names. + */ + Map> getServiceMapping(); + + /** + * Get current mapping between reference names and module object names for given service interface name. + * @param serviceInterfaceName service interface name + * @throws IllegalArgumentException if there is a mismatch between serviceInterfaceName and objectName + */ + Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName); + + /** + * Find all available service interface names of a module. + * @param objectName module object name + * @throws InstanceNotFoundException if search did not find exactly one instance + */ + Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException; + + /** + * @param namespace service interface namespace + * @param localName service interface local name + * @return fully qualified name needed by all other service reference mapping methods. + * @throws java.lang.IllegalArgumentException if namespace or localName is not found + */ + String getServiceInterfaceName(String namespace, String localName); + +} diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java new file mode 100644 index 0000000000..f3d6d16d6c --- /dev/null +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.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.config.api; + +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; + +public interface ServiceReferenceWritableRegistry extends ServiceReferenceReadableRegistry { + /** + * Create or update reference name to objectName. Reference name is unique per service interface name. + * @throws IllegalArgumentException if there is a mismatch between serviceInterfaceName and objectName + * @throws InstanceNotFoundException if search did not find exactly one instance + */ + void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException; + + /** + * Remove service reference. + * @return true iif removed + * @throws IllegalArgumentException if service interface name is not advertised by any module + */ + boolean removeServiceReference(String serviceInterfaceName, String refName); + + /** + * Remove all service references. + */ + void removeAllServiceReferences(); + + /** + * Remove all service references attached to given module. + * @return true iif at least one reference was removed + */ + boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException; +} diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/annotations/ServiceInterfaceAnnotation.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/annotations/ServiceInterfaceAnnotation.java index a81d992d81..e66de46520 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/annotations/ServiceInterfaceAnnotation.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/annotations/ServiceInterfaceAnnotation.java @@ -23,8 +23,9 @@ import java.lang.annotation.Target; public @interface ServiceInterfaceAnnotation { /** - * Specifies human readable name of this service. Each service name should - * be globally unique. Should not contain spaces. + * Fully qualified name of a service that must be globally unique. + * When generating service interfaces from yang, this will be QName of + * identity extending service-type. */ String value(); @@ -34,4 +35,19 @@ public @interface ServiceInterfaceAnnotation { * is called. */ Class osgiRegistrationType(); + + /** + * Get namespace of {@link #value()} + */ + String namespace(); + + /** + * Get revision of {@link #value()} + */ + String revision(); + + /** + * Get local name of {@link #value()} + */ + String localName(); } diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java index 8111690c72..cc1d89761c 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java @@ -7,6 +7,11 @@ */ package org.opendaylight.controller.config.api.jmx; +import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants; + +import javax.annotation.concurrent.ThreadSafe; +import javax.management.ObjectName; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -15,12 +20,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import javax.annotation.concurrent.ThreadSafe; -import javax.management.ObjectName; - -import org.opendaylight.controller.config.api.ModuleIdentifier; -import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants; - /** * Provides ObjectName creation. Each created ObjectName consists of domain that * is defined as {@link #ON_DOMAIN} and at least one key-value pair. The only @@ -129,18 +128,31 @@ public class ObjectNameUtil { return objectName.getKeyProperty(TRANSACTION_NAME_KEY); } - public static ObjectName withoutTransactionName(ObjectName on) { - if (getTransactionName(on) == null) { + /** + * Sanitize on: keep only mandatory attributes of module + metadata. + */ + public static ObjectName withoutTransactionName(ObjectName inputON) { + if (getTransactionName(inputON) == null) { throw new IllegalArgumentException( - "Expected ObjectName with transaction:" + on); + "Expected ObjectName with transaction:" + inputON); } - if (ON_DOMAIN.equals(on.getDomain()) == false) { + if (ON_DOMAIN.equals(inputON.getDomain()) == false) { throw new IllegalArgumentException("Expected different domain: " - + on); + + inputON); + } + String moduleName = getFactoryName(inputON); + String instanceName = getInstanceName(inputON); + + + Map allProperties = getAdditionalProperties(inputON); + Map outputProperties = new HashMap<>(createModuleON(moduleName, instanceName)); + + for(Entry entry: allProperties.entrySet()) { + if (entry.getKey().startsWith("X-")) { + outputProperties.put(entry.getKey(), entry.getValue()); + } } - String moduleName = getFactoryName(on); - String instanceName = getInstanceName(on); - return createReadOnlyModuleON(moduleName, instanceName); + return createON(ON_DOMAIN, outputProperties); } private static void assertDoesNotContain( diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/spi/ModuleFactory.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/spi/ModuleFactory.java index 7b8f7c164e..c86b381493 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/spi/ModuleFactory.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/spi/ModuleFactory.java @@ -97,6 +97,8 @@ public interface ModuleFactory { boolean isModuleImplementingServiceInterface( Class serviceInterface); + Set> getImplementedServiceIntefaces(); + /** * Called when ModuleFactory is registered to config manager. * Useful for populating the registry with pre-existing state. Since diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java index 1b695a9bda..18326d91f2 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java @@ -10,6 +10,8 @@ package org.opendaylight.controller.config.manager.impl; import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.api.ModuleIdentifier; import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule; +import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; +import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.CommitStatus; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; @@ -102,6 +104,9 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe @GuardedBy("this") private List lastListOfFactories = Collections.emptyList(); + @GuardedBy("this") // switched in every 2ndPC + private ServiceReferenceReadableRegistry readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry(); + // constructor public ConfigRegistryImpl(ModuleFactoriesResolver resolver, BundleContext bundleContext, MBeanServer configMBeanServer) { @@ -142,21 +147,32 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe private synchronized ConfigTransactionControllerInternal beginConfigInternal(boolean blankTransaction) { versionCounter++; - String transactionName = "ConfigTransaction-" + version + "-" + versionCounter; - TransactionJMXRegistrator transactionRegistrator = baseJMXRegistrator - .createTransactionJMXRegistrator(transactionName); - Map> allCurrentFactories = Collections.unmodifiableMap(resolver.getAllFactories()); + final String transactionName = "ConfigTransaction-" + version + "-" + versionCounter; + + TransactionJMXRegistratorFactory factory = new TransactionJMXRegistratorFactory() { + @Override + public TransactionJMXRegistrator create() { + return baseJMXRegistrator.createTransactionJMXRegistrator(transactionName); + } + }; + + ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier( + transactionName), factory); + Map> allCurrentFactories = Collections.unmodifiableMap( + resolver.getAllFactories()); + ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry( + readableSRRegistry, txLookupRegistry, allCurrentFactories); + ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl( - transactionName, transactionRegistrator, version, - versionCounter, allCurrentFactories, transactionsMBeanServer, configMBeanServer, blankTransaction); + txLookupRegistry, version, + versionCounter, allCurrentFactories, transactionsMBeanServer, + configMBeanServer, blankTransaction, writableRegistry); try { - transactionRegistrator.registerMBean(transactionController, transactionController.getControllerObjectName()); + txLookupRegistry.registerMBean(transactionController, transactionController.getControllerObjectName()); } catch (InstanceAlreadyExistsException e) { throw new IllegalStateException(e); } - transactionController.copyExistingModulesAndProcessFactoryDiff(currentConfig.getEntries(), lastListOfFactories); - transactionsHolder.add(transactionName, transactionController); return transactionController; } @@ -352,6 +368,10 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe // update version version = configTransactionController.getVersion(); + + // switch readable Service Reference Registry + this.readableSRRegistry = ServiceReferenceRegistryImpl.createSRReadableRegistry(configTransactionController.getWritableRegistry(), this); + return new CommitStatus(newInstances, reusedInstances, recreatedInstances); } @@ -493,6 +513,43 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe return baseJMXRegistrator.queryNames(namePattern, null); } + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + ObjectNameUtil.checkDomain(objectName); + ObjectNameUtil.checkType(objectName, ObjectNameUtil.TYPE_MODULE); + String transactionName = ObjectNameUtil.getTransactionName(objectName); + if (transactionName != null) { + throw new IllegalArgumentException("Transaction attribute not supported in registry, wrong ObjectName: " + objectName); + } + // make sure exactly one match is found: + LookupBeansUtil.lookupConfigBean(this, ObjectNameUtil.getFactoryName(objectName), ObjectNameUtil.getInstanceName(objectName)); + } + + // service reference functionality: + @Override + public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + return readableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName); + } + + @Override + public synchronized Map> getServiceMapping() { + return readableSRRegistry.getServiceMapping(); + } + + @Override + public synchronized Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + } + + @Override + public synchronized Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + return readableSRRegistry.lookupServiceInterfaceNames(objectName); + } + + @Override + public synchronized String getServiceInterfaceName(String namespace, String localName) { + return readableSRRegistry.getServiceInterfaceName(namespace, localName); + } } /** diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java index 3e53a7a217..36485b1abf 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl; import org.opendaylight.controller.config.api.DependencyResolver; import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager; @@ -16,10 +17,8 @@ import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicWrita import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean; import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean.ReadOnlyAtomicBooleanImpl; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder; -import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator; import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator; import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration; -import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil; import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.yangtools.concepts.Identifiable; @@ -47,7 +46,7 @@ import static java.lang.String.format; /** * This is a JMX bean representing current transaction. It contains - * {@link #transactionIdentifier}, unique version and parent version for + * transaction identifier, unique version and parent version for * optimistic locking. */ class ConfigTransactionControllerImpl implements @@ -56,10 +55,9 @@ class ConfigTransactionControllerImpl implements Identifiable{ private static final Logger logger = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class); - private final TransactionIdentifier transactionIdentifier; + private final ConfigTransactionLookupRegistry txLookupRegistry; private final ObjectName controllerON; - private final TransactionJMXRegistrator transactionRegistrator; - private final TransactionModuleJMXRegistrator txModuleJMXRegistrator; + private final long parentVersion, currentVersion; private final HierarchicalConfigMBeanFactoriesHolder factoriesHolder; private final DependencyResolverManager dependencyResolverManager; @@ -80,19 +78,18 @@ class ConfigTransactionControllerImpl implements private final boolean blankTransaction; - public ConfigTransactionControllerImpl(String transactionName, - TransactionJMXRegistrator transactionRegistrator, + @GuardedBy("this") + private final ServiceReferenceWritableRegistry writableSRRegistry; + + public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry, long parentVersion, long currentVersion, Map> currentlyRegisteredFactories, MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer, - boolean blankTransaction) { - - this.transactionIdentifier = new TransactionIdentifier(transactionName); - this.controllerON = ObjectNameUtil - .createTransactionControllerON(transactionName); - this.transactionRegistrator = transactionRegistrator; - txModuleJMXRegistrator = transactionRegistrator - .createTransactionModuleJMXRegistrator(); + boolean blankTransaction, ServiceReferenceWritableRegistry writableSRRegistry) { + + this.txLookupRegistry = txLookupRegistry; + String transactionName = txLookupRegistry.getTransactionIdentifier().getName(); + this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName); this.parentVersion = parentVersion; this.currentVersion = currentVersion; this.currentlyRegisteredFactories = currentlyRegisteredFactories; @@ -102,6 +99,7 @@ class ConfigTransactionControllerImpl implements this.transactionsMBeanServer = transactionsMBeanServer; this.configMBeanServer = configMBeanServer; this.blankTransaction = blankTransaction; + this.writableSRRegistry = writableSRRegistry; } @Override @@ -225,14 +223,14 @@ class ConfigTransactionControllerImpl implements + moduleIdentifier + ", got " + dependencyResolver.getIdentifier()); } DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper( - module, moduleIdentifier, transactionIdentifier, + module, moduleIdentifier, getTransactionIdentifier(), readOnlyAtomicBoolean, transactionsMBeanServer, configMBeanServer); ObjectName writableON = ObjectNameUtil.createTransactionModuleON( - transactionIdentifier.getName(), moduleIdentifier); + getTransactionIdentifier().getName(), moduleIdentifier); // put wrapper to jmx - TransactionModuleJMXRegistration transactionModuleJMXRegistration = txModuleJMXRegistrator + TransactionModuleJMXRegistration transactionModuleJMXRegistration = getTxModuleJMXRegistrator() .registerMBean(writableDynamicWrapper, writableON); ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo( moduleIdentifier, module, moduleFactory, @@ -243,18 +241,21 @@ class ConfigTransactionControllerImpl implements } @Override - public synchronized void destroyModule(ObjectName objectName) - throws InstanceNotFoundException { + public synchronized void destroyModule(ObjectName objectName) throws InstanceNotFoundException { + checkTransactionName(objectName); + ObjectNameUtil.checkDomain(objectName); + ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName, + ObjectNameUtil.TYPE_MODULE); + destroyModule(moduleIdentifier); + } + + private void checkTransactionName(ObjectName objectName) { String foundTransactionName = ObjectNameUtil .getTransactionName(objectName); - if (transactionIdentifier.getName().equals(foundTransactionName) == false) { + if (getTransactionIdentifier().getName().equals(foundTransactionName) == false) { throw new IllegalArgumentException("Wrong transaction name " + objectName); } - ObjectNameUtil.checkDomain(objectName); - ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName, - ObjectNameUtil.TYPE_MODULE); - destroyModule(moduleIdentifier); } private synchronized void destroyModule(ModuleIdentifier moduleIdentifier) { @@ -268,6 +269,15 @@ class ConfigTransactionControllerImpl implements logger.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem"); } } + // first remove refNames, it checks for objectname existence + try { + writableSRRegistry.removeServiceReferences( + ObjectNameUtil.createTransactionModuleON(getTransactionName(),moduleIdentifier)); + } catch (InstanceNotFoundException e) { + logger.error("Possible code error: cannot find {} in {}", moduleIdentifier, writableSRRegistry); + throw new IllegalStateException("Possible code error: cannot find " + moduleIdentifier, e); + } + ModuleInternalTransactionalInfo removedTInfo = dependencyResolverManager.destroyModule(moduleIdentifier); // remove from jmx removedTInfo.getTransactionModuleJMXRegistration().close(); @@ -297,7 +307,7 @@ class ConfigTransactionControllerImpl implements private void validate_noLocks() throws ValidationException { transactionStatus.checkNotAborted(); - logger.info("Validating transaction {}", transactionIdentifier); + logger.info("Validating transaction {}", getTransactionIdentifier()); // call validate() List collectedExceptions = new ArrayList<>(); for (Entry entry : dependencyResolverManager @@ -317,7 +327,7 @@ class ConfigTransactionControllerImpl implements throw ValidationException .createFromCollectedValidationExceptions(collectedExceptions); } - logger.info("Validated transaction {}", transactionIdentifier); + logger.info("Validated transaction {}", getTransactionIdentifier()); } /** @@ -359,7 +369,7 @@ class ConfigTransactionControllerImpl implements + "to obtain a lock"); } - logger.info("Committing transaction {}", transactionIdentifier); + logger.info("Committing transaction {}", getTransactionIdentifier()); // call getInstance() for (Entry entry : dependencyResolverManager @@ -368,21 +378,21 @@ class ConfigTransactionControllerImpl implements ModuleIdentifier name = entry.getKey(); try { logger.debug("About to commit {} in transaction {}", - name, transactionIdentifier); + name, getTransactionIdentifier()); module.getInstance(); } catch (Exception e) { logger.error("Commit failed on {} in transaction {}", name, - transactionIdentifier, e); + getTransactionIdentifier(), e); internalAbort(); throw new RuntimeException( format("Error - getInstance() failed for %s in transaction %s", - name, transactionIdentifier), e); + name, getTransactionIdentifier()), e); } } // count dependency order - logger.info("Committed configuration {}", transactionIdentifier); + logger.info("Committed configuration {}", getTransactionIdentifier()); transactionStatus.setCommitted(); // unregister this and all modules from jmx close(); @@ -403,7 +413,8 @@ class ConfigTransactionControllerImpl implements } private void close() { - transactionRegistrator.close(); + //FIXME: should not close object that was retrieved in constructor, a wrapper object should do that perhaps + txLookupRegistry.close(); } @Override @@ -413,7 +424,7 @@ class ConfigTransactionControllerImpl implements @Override public String getTransactionName() { - return transactionIdentifier.getName(); + return getTransactionIdentifier().getName(); } /** @@ -421,7 +432,7 @@ class ConfigTransactionControllerImpl implements */ @Override public Set lookupConfigBeans() { - return lookupConfigBeans("*", "*"); + return txLookupRegistry.lookupConfigBeans(); } /** @@ -429,7 +440,7 @@ class ConfigTransactionControllerImpl implements */ @Override public Set lookupConfigBeans(String moduleName) { - return lookupConfigBeans(moduleName, "*"); + return txLookupRegistry.lookupConfigBeans(moduleName); } /** @@ -438,20 +449,29 @@ class ConfigTransactionControllerImpl implements @Override public ObjectName lookupConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException { - return LookupBeansUtil.lookupConfigBean(this, moduleName, instanceName); + return txLookupRegistry.lookupConfigBean(moduleName, instanceName); } /** * {@inheritDoc} */ @Override - public Set lookupConfigBeans(String moduleName, - String instanceName) { - ObjectName namePattern = ObjectNameUtil.createModulePattern(moduleName, - instanceName, transactionIdentifier.getName()); - return txModuleJMXRegistrator.queryNames(namePattern, null); + public Set lookupConfigBeans(String moduleName, String instanceName) { + return txLookupRegistry.lookupConfigBeans(moduleName, instanceName); } + /** + * {@inheritDoc} + */ + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + txLookupRegistry.checkConfigBeanExists(objectName); + } + // -- + + /** + * {@inheritDoc} + */ @Override public Set getAvailableModuleNames() { return factoriesHolder.getModuleNames(); @@ -473,11 +493,11 @@ class ConfigTransactionControllerImpl implements // @VisibleForTesting TransactionModuleJMXRegistrator getTxModuleJMXRegistrator() { - return txModuleJMXRegistrator; + return txLookupRegistry.getTxModuleJMXRegistrator(); } public TransactionIdentifier getName() { - return transactionIdentifier; + return getTransactionIdentifier(); } @Override @@ -487,7 +507,7 @@ class ConfigTransactionControllerImpl implements @Override public TransactionIdentifier getIdentifier() { - return transactionIdentifier; + return getTransactionIdentifier(); } @Override @@ -498,4 +518,62 @@ class ConfigTransactionControllerImpl implements } return factoryBundleContextEntry.getValue(); } + + // service reference functionality: + + + @Override + public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName); + } + + @Override + public synchronized Map> getServiceMapping() { + return writableSRRegistry.getServiceMapping(); + } + + @Override + public synchronized Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + } + + @Override + public synchronized Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + return writableSRRegistry.lookupServiceInterfaceNames(objectName); + } + + @Override + public synchronized String getServiceInterfaceName(String namespace, String localName) { + return writableSRRegistry.getServiceInterfaceName(namespace, localName); + } + + @Override + public synchronized void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException { + writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, objectName); + } + + @Override + public synchronized boolean removeServiceReference(String serviceInterfaceName, String refName) { + return writableSRRegistry.removeServiceReference(serviceInterfaceName, refName); + } + + @Override + public synchronized void removeAllServiceReferences() { + writableSRRegistry.removeAllServiceReferences(); + } + + @Override + public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException { + return writableSRRegistry.removeServiceReferences(objectName); + } + + @Override + public ServiceReferenceWritableRegistry getWritableRegistry() { + return writableSRRegistry; + } + + public TransactionIdentifier getTransactionIdentifier() { + return txLookupRegistry.getTransactionIdentifier(); + } + } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java index 4dc877c62b..82bae44a01 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java @@ -13,6 +13,7 @@ import java.util.List; import javax.management.ObjectName; import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.spi.ModuleFactory; import org.osgi.framework.BundleContext; @@ -71,4 +72,7 @@ interface ConfigTransactionControllerInternal extends List getCurrentlyRegisteredFactories(); BundleContext getModuleFactoryBundleContext(String factoryName); + + ServiceReferenceWritableRegistry getWritableRegistry(); + } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java new file mode 100644 index 0000000000..5d1f0b3976 --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java @@ -0,0 +1,111 @@ +/* + * 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.config.manager.impl; + +import org.opendaylight.controller.config.api.LookupRegistry; +import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator; +import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator; +import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil; + +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import java.io.Closeable; +import java.util.Set; + +/** + * Responsible for creating TransactionJMXRegistrator, registering transaction and all its beans, + * lookup of beans, closing of TransactionJMXRegistrator. + */ +class ConfigTransactionLookupRegistry implements LookupRegistry, Closeable { + private final TransactionJMXRegistrator transactionJMXRegistrator; + private final TransactionIdentifier transactionIdentifier; + private final TransactionModuleJMXRegistrator txModuleJMXRegistrator; + + ConfigTransactionLookupRegistry(TransactionIdentifier transactionIdentifier, + TransactionJMXRegistratorFactory factory) { + this.transactionIdentifier = transactionIdentifier; + this.transactionJMXRegistrator = factory.create(); + this.txModuleJMXRegistrator = transactionJMXRegistrator.createTransactionModuleJMXRegistrator(); + } + + private void checkTransactionName(ObjectName objectName) { + String foundTransactionName = ObjectNameUtil + .getTransactionName(objectName); + if (transactionIdentifier.getName().equals(foundTransactionName) == false) { + throw new IllegalArgumentException("Wrong transaction name " + + objectName); + } + } + + /** + * {@inheritDoc} + */ + @Override + public Set lookupConfigBeans() { + return lookupConfigBeans("*", "*"); + } + + /** + * {@inheritDoc} + */ + @Override + public Set lookupConfigBeans(String moduleName) { + return lookupConfigBeans(moduleName, "*"); + } + + /** + * {@inheritDoc} + */ + @Override + public ObjectName lookupConfigBean(String moduleName, String instanceName) + throws InstanceNotFoundException { + return LookupBeansUtil.lookupConfigBean(this, moduleName, instanceName); + } + + /** + * {@inheritDoc} + */ + @Override + public Set lookupConfigBeans(String moduleName, + String instanceName) { + ObjectName namePattern = ObjectNameUtil.createModulePattern(moduleName, + instanceName, transactionIdentifier.getName()); + return txModuleJMXRegistrator.queryNames(namePattern, null); + } + + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + ObjectNameUtil.checkDomain(objectName); + ObjectNameUtil.checkType(objectName, ObjectNameUtil.TYPE_MODULE); + checkTransactionName(objectName); + // make sure exactly one match is found: + LookupBeansUtil.lookupConfigBean(this, ObjectNameUtil.getFactoryName(objectName), ObjectNameUtil.getInstanceName(objectName)); + } + + TransactionIdentifier getTransactionIdentifier() { + return transactionIdentifier; + } + + TransactionModuleJMXRegistrator getTxModuleJMXRegistrator() { + return txModuleJMXRegistrator; + } + + public void close() { + transactionJMXRegistrator.close(); + } + + public void registerMBean(ConfigTransactionControllerInternal transactionController, ObjectName controllerObjectName) throws InstanceAlreadyExistsException { + transactionJMXRegistrator.registerMBean(transactionController, controllerObjectName); + } +} + +interface TransactionJMXRegistratorFactory { + TransactionJMXRegistrator create(); +} diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java new file mode 100644 index 0000000000..2fd1ca6c2c --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java @@ -0,0 +1,340 @@ +/* + * 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.config.manager.impl; + +import org.opendaylight.controller.config.api.LookupRegistry; +import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; +import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; +import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper; +import org.opendaylight.controller.config.spi.ModuleFactory; +import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry { + private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class); + + private final Map factories; + private final Map> factoryNamesToQNames; + // validator of incoming ObjectNames - throws InstanceNotFoundException if not found either in registry or transaction + private final LookupRegistry lookupRegistry; + // helper method for getting QName of SI from namespace + local name + private final Map> namespacesToAnnotations; + // all Service Interface qNames for sanity checking + private final Set allQNames; + + // actual reference database + private final Map> refNames; + + /** + * Static constructor for config registry. Since only transaction can write to this registry, it will + * return blank state. + */ + public static ServiceReferenceReadableRegistry createInitialSRLookupRegistry() { + // since this is initial state, just throw exception: + LookupRegistry lookupRegistry = new LookupRegistry() { + @Override + public Set lookupConfigBeans() { + throw new UnsupportedOperationException(); + } + + @Override + public Set lookupConfigBeans(String moduleName) { + throw new UnsupportedOperationException(); + } + + @Override + public Set lookupConfigBeans(String moduleName, String instanceName) { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectName lookupConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + throw new InstanceNotFoundException("Cannot find " + objectName); + } + }; + return new ServiceReferenceRegistryImpl(Collections.emptyMap(), lookupRegistry, + Collections.>emptyMap()); + } + + /** + * Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data. + */ + public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry, + LookupRegistry lookupRegistry, Map> currentlyRegisteredFactories) { + + ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldReadableRegistry; + Map factories = extractFactoriesMap(currentlyRegisteredFactories); + return new ServiceReferenceRegistryImpl(factories, lookupRegistry, Collections.unmodifiableMap(old.refNames)); + } + + /** + * Copy back state to config registry after commit. + */ + public static ServiceReferenceReadableRegistry createSRReadableRegistry(ServiceReferenceWritableRegistry oldWritableRegistry, LookupRegistry lookupRegistry) { + ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldWritableRegistry; + // even if factories do change, nothing in the mapping can change between transactions + return new ServiceReferenceRegistryImpl(old.factories, lookupRegistry, Collections.unmodifiableMap(old.refNames)); + } + + private static Map extractFactoriesMap(Map> currentlyRegisteredFactories) { + Map result = new HashMap<>(); + for (Entry> entry : currentlyRegisteredFactories.entrySet()) { + result.put(entry.getKey(), entry.getValue().getKey()); + } + return result; + } + + private ServiceReferenceRegistryImpl(Map factories, LookupRegistry lookupRegistry, + Map> refNamesToCopy) { + this.factories = factories; + this.lookupRegistry = lookupRegistry; + Map> factoryNamesToQNames = new HashMap<>(); + Set allAnnotations = new HashSet<>(); + Set allQNames = new HashSet<>(); + for (Entry entry : factories.entrySet()) { + if (entry.getKey().equals(entry.getValue().getImplementationName()) == false) { + logger.error("Possible error in code: Mismatch between supplied and actual name of {}", entry); + throw new IllegalArgumentException("Possible error in code: Mismatch between supplied and actual name of " + entry); + } + Set siAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(entry.getValue()); + Set qNames = new HashSet<>(); + for (ServiceInterfaceAnnotation sia: siAnnotations) { + qNames.add(sia.value()); + } + allAnnotations.addAll(siAnnotations); + allQNames.addAll(qNames); + factoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames)); + } + this.factoryNamesToQNames = Collections.unmodifiableMap(factoryNamesToQNames); + this.allQNames = Collections.unmodifiableSet(allQNames); + // fill namespacesToAnnotations + Map> namespacesToAnnotations = + new HashMap<>(); + for (ServiceInterfaceAnnotation sia : allAnnotations) { + Map ofNamespace = namespacesToAnnotations.get(sia.namespace()); + if (ofNamespace == null) { + ofNamespace = new HashMap<>(); + namespacesToAnnotations.put(sia.namespace(), ofNamespace); + } + if (ofNamespace.containsKey(sia.localName())) { + logger.error("Cannot construct namespacesToAnnotations map, conflict between local names in {}, offending local name: {}, map so far {}", + sia.namespace(), sia.localName(), namespacesToAnnotations); + throw new IllegalArgumentException("Conflict between local names in " + sia.namespace() + " : " + sia.localName()); + } + ofNamespace.put(sia.localName(), sia); + } + this.namespacesToAnnotations = Collections.unmodifiableMap(namespacesToAnnotations); + // copy refNames + Map> deepCopy = new HashMap<>(); + for (Entry> outerROEntry: refNamesToCopy.entrySet()) { + Map innerWritableMap = new HashMap<>(); + deepCopy.put(outerROEntry.getKey(), innerWritableMap); + for (Entry innerROEntry: outerROEntry.getValue().entrySet()) { + innerWritableMap.put(innerROEntry.getKey(), innerROEntry.getValue()); + } + } + this.refNames = deepCopy; + logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames); + logger.trace("refNames:{}", refNames); + } + + + @Override + public Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + lookupRegistry.checkConfigBeanExists(objectName); + + String factoryName = ObjectNameUtil.getFactoryName(objectName); + Set serviceInterfaceAnnotations = factoryNamesToQNames.get(factoryName); + if (serviceInterfaceAnnotations == null) { + logger.error("Possible error in code: cannot find factory annotations of '{}' extracted from ON {} in {}", + factoryName, objectName, factoryNamesToQNames); + throw new IllegalArgumentException("Cannot find factory with name " + factoryName); + } + return serviceInterfaceAnnotations; + } + + @Override + public String getServiceInterfaceName(String namespace, String localName) { + Map ofNamespace = namespacesToAnnotations.get(namespace); + if (ofNamespace == null) { + logger.error("Cannot find namespace {} in {}", namespace, namespacesToAnnotations); + throw new IllegalArgumentException("Cannot find namespace " + namespace); + } + ServiceInterfaceAnnotation sia = ofNamespace.get(localName); + if (sia == null) { + logger.error("Cannot find local name {} in namespace {}, found only {}", localName, namespace, ofNamespace); + throw new IllegalArgumentException("Cannot find local name " + localName + " in namespace " + namespace); + } + return sia.value(); + } + + + + // reading: + + @Override + public Map> getServiceMapping() { + Map> result = new HashMap<>(); + for (Entry> outerEntry: refNames.entrySet()) { + String qName = outerEntry.getKey(); + Map innerMap = new HashMap<>(); + result.put(qName, innerMap); + for (Entry innerEntry: outerEntry.getValue().entrySet()) { + ModuleIdentifier moduleIdentifier = innerEntry.getValue(); + ObjectName on; + on = getObjectName(moduleIdentifier); + innerMap.put(innerEntry.getKey(), on); + } + } + return result; + } + + private ObjectName getObjectName(ModuleIdentifier moduleIdentifier) { + ObjectName on; + try { + on = lookupRegistry.lookupConfigBean(moduleIdentifier.getFactoryName(), moduleIdentifier.getInstanceName()); + } catch (InstanceNotFoundException e) { + logger.error("Cannot find instance {}", moduleIdentifier); + throw new IllegalStateException("Cannot find instance " + moduleIdentifier, e); + } + return on; + } + + @Override + public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + Map innerMap = refNames.get(serviceInterfaceName); + if (innerMap == null) { + logger.error("Cannot find qname {} in {}", serviceInterfaceName, refName); + throw new IllegalArgumentException("Cannot find " + serviceInterfaceName); + } + ModuleIdentifier moduleIdentifier = innerMap.get(refName); + if (moduleIdentifier == null) { + logger.error("Cannot find refName {} in {}, using qname {}", refName, innerMap, serviceInterfaceName); + throw new IllegalArgumentException("Cannot find module based on service reference " + refName); + } + return getObjectName(moduleIdentifier); + } + + @Override + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + Map innerMap = refNames.get(serviceInterfaceName); + if (innerMap == null) { + logger.error("Cannot find qname {} in {}", serviceInterfaceName, refNames); + throw new IllegalArgumentException("Cannot find " + serviceInterfaceName); + } + Map result = new HashMap<>(); + for (Entry entry: innerMap.entrySet()) { + ObjectName on = getObjectName(entry.getValue()); + result.put(entry.getKey(), on); + } + return result; + } + + // writing: + + @Override + public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException { + // make sure it is found + lookupRegistry.checkConfigBeanExists(objectName); + String factoryName = ObjectNameUtil.getFactoryName(objectName); + // check that service interface name exist + Set serviceInterfaceQNames = factoryNamesToQNames.get(factoryName); + if (serviceInterfaceQNames == null) { + logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, objectName); + throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName); + } + // supplied serviceInterfaceName must exist in this collection + if (serviceInterfaceQNames.contains(serviceInterfaceName) == false) { + logger.error("Cannot find qname {} with factory name {}, found {}", serviceInterfaceName, factoryName, serviceInterfaceQNames); + throw new IllegalArgumentException("Cannot find service interface " + serviceInterfaceName + " within factory " + factoryName ); + } + String instanceName = ObjectNameUtil.getInstanceName(objectName); + ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName); + Map ofQName = refNames.get(serviceInterfaceName); + // might be null + if (ofQName == null) { + ofQName = new HashMap<>(); + refNames.put(serviceInterfaceName, ofQName); + } + ofQName.put(refName, moduleIdentifier); + } + + @Override + public boolean removeServiceReference(String serviceInterfaceName, String refName) { + // is the qname known? + if (allQNames.contains(serviceInterfaceName) == false) { + logger.error("Cannot find qname {} in {}", serviceInterfaceName, allQNames); + throw new IllegalArgumentException("Cannot find service interface " + serviceInterfaceName); + } + Map ofQName = refNames.get(serviceInterfaceName); + if (ofQName == null) { + return false; + } + return ofQName.remove(refName) != null; + } + + @Override + public void removeAllServiceReferences() { + refNames.clear(); + } + + @Override + public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException { + lookupRegistry.checkConfigBeanExists(objectName); + String factoryName = ObjectNameUtil.getFactoryName(objectName); + // check that service interface name exist + Set serviceInterfaceQNames = factoryNamesToQNames.get(factoryName); + if (serviceInterfaceQNames == null) { + logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, objectName); + throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName); + } + String instanceName = ObjectNameUtil.getInstanceName(objectName); + ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName); + boolean found = false; + for(String qName: serviceInterfaceQNames){ + Map ofQName = refNames.get(qName); + if (ofQName != null) { + for(Iterator> it = ofQName.entrySet ().iterator(); it.hasNext();){ + Entry next = it.next(); + if (next.getValue().equals(moduleIdentifier)) { + found = true; + it.remove(); + } + } + } + } + return found; + } + + @Override + public String toString() { + return "ServiceReferenceRegistryImpl{" + + "refNames=" + refNames + + ", factoryNamesToQNames=" + factoryNamesToQNames + + '}'; + } +} diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionJMXRegistrator.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionJMXRegistrator.java index 523cbc5b01..b371c3f170 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionJMXRegistrator.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionJMXRegistrator.java @@ -65,7 +65,7 @@ public class TransactionJMXRegistrator implements Closeable { } @Override - public void close() { + public void close() { // closes also all child TransactionModuleJMXRegistrator instances childJMXRegistrator.close(); } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java index 76cb64cf93..033f7222fc 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java @@ -7,17 +7,18 @@ */ package org.opendaylight.controller.config.manager.impl.util; +import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; +import org.opendaylight.controller.config.spi.Module; +import org.opendaylight.controller.config.spi.ModuleFactory; + +import javax.management.JMX; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; -import javax.management.JMX; - -import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface; -import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; -import org.opendaylight.controller.config.spi.Module; - public class InterfacesHelper { public static Set> getAllInterfaces(Class clazz) { @@ -32,16 +33,25 @@ public class InterfacesHelper { // get parent class clazz = clazz.getSuperclass(); } + return getAllSuperInterfaces(toBeInspected); + + } + + private static Set> getAllSuperInterfaces(Set> ifcs) { + ifcs = new HashSet<>(ifcs); // create copy to modify // each interface can extend other interfaces - Set> inspected = new HashSet<>(); - while (toBeInspected.size() > 0) { - Iterator> iterator = toBeInspected.iterator(); + Set> result = new HashSet<>(); + while (ifcs.size() > 0) { + Iterator> iterator = ifcs.iterator(); Class ifc = iterator.next(); iterator.remove(); - toBeInspected.addAll(Arrays.asList(ifc.getInterfaces())); - inspected.add(ifc); + if (ifc.isInterface() == false) { + throw new IllegalArgumentException(ifc + " should be an interface"); + } + ifcs.addAll(Arrays.asList(ifc.getInterfaces())); + result.add(ifc); } - return inspected; + return result; } /** @@ -80,6 +90,18 @@ public class InterfacesHelper { return result; } + public static Set> getAllAbstractServiceClasses(Class configBeanClass) { + + Set> foundGeneratedSIClasses = new HashSet<>(); + for (Class clazz : getAllInterfaces(configBeanClass)) { + if (AbstractServiceInterface.class.isAssignableFrom(clazz) && AbstractServiceInterface.class.equals(clazz) == false) { + foundGeneratedSIClasses.add((Class) clazz); + } + } + return getAllAbstractServiceInterfaceClasses(foundGeneratedSIClasses); + } + + /** * Get OSGi registration types under which config bean instance should be * registered. This is specified in @@ -98,4 +120,37 @@ public class InterfacesHelper { return result; } + + public static Set getServiceInterfaceAnnotations(ModuleFactory factory) { + Set> implementedServiceIntefaces = Collections.unmodifiableSet(factory.getImplementedServiceIntefaces()); + return getServiceInterfaceAnnotations(implementedServiceIntefaces); + } + + private static Set getServiceInterfaceAnnotations(Set> implementedServiceIntefaces) { + Set> inspected = getAllAbstractServiceInterfaceClasses(implementedServiceIntefaces); + Set result = new HashSet<>(); + // SIs can form hierarchies, inspect superclass until it does not extend AbstractSI + for (Class clazz : inspected) { + ServiceInterfaceAnnotation annotation = clazz.getAnnotation(ServiceInterfaceAnnotation.class); + if (annotation != null) { + result.add(annotation); + } + } + return result; + } + + static Set> getAllAbstractServiceInterfaceClasses( + Set> directlyImplementedAbstractSIs) { + + Set> allInterfaces = getAllSuperInterfaces((Set) directlyImplementedAbstractSIs); + Set> result = new HashSet<>(); + for(Class ifc: allInterfaces){ + if (AbstractServiceInterface.class.isAssignableFrom(ifc) && + ifc.equals(AbstractServiceInterface.class) == false) { + result.add((Class) ifc); + } + + } + return result; + } } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ClassBasedModuleFactory.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ClassBasedModuleFactory.java index d23b5ca128..672f150914 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ClassBasedModuleFactory.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ClassBasedModuleFactory.java @@ -13,6 +13,7 @@ import org.opendaylight.controller.config.api.DependencyResolverFactory; import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; import org.opendaylight.controller.config.api.ModuleIdentifier; import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface; +import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper; import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; import org.osgi.framework.BundleContext; @@ -107,4 +108,9 @@ public class ClassBasedModuleFactory implements ModuleFactory { public Set getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext bundleContext) { return new HashSet(); } + + @Override + public Set> getImplementedServiceIntefaces() { + return InterfacesHelper.getAllAbstractServiceClasses(configBeanClass); + } } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java index 22a959060c..43c75ef1e7 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java @@ -11,6 +11,7 @@ import com.google.common.collect.Sets; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator; import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator; @@ -61,13 +62,22 @@ public class ConfigTransactionControllerImplTest extends ManagementFactory.getPlatformMBeanServer()); transactionsMBeanServer = MBeanServerFactory.createMBeanServer(); Map> currentlyRegisteredFactories = new HashMap<>(); - TransactionJMXRegistrator jmxRegistrator123 = baseJMXRegistrator - .createTransactionJMXRegistrator(transactionName123); + + ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier(transactionName123), new TransactionJMXRegistratorFactory() { + @Override + public TransactionJMXRegistrator create() { + return baseJMXRegistrator.createTransactionJMXRegistrator(transactionName123); + } + }); + + ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry( + ServiceReferenceRegistryImpl.createInitialSRLookupRegistry(), txLookupRegistry, currentlyRegisteredFactories); + testedTxController = new ConfigTransactionControllerImpl( - transactionName123, jmxRegistrator123, 1, 1, + txLookupRegistry, 1, 1, currentlyRegisteredFactories, transactionsMBeanServer, - ManagementFactory.getPlatformMBeanServer(), false); + ManagementFactory.getPlatformMBeanServer(), false, writableRegistry); TransactionModuleJMXRegistrator transactionModuleJMXRegistrator123 = testedTxController .getTxModuleJMXRegistrator(); transactionModuleJMXRegistrator123.registerMBean( diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/AnnotationsTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/AnnotationsTest.java index cf6ed18c6c..75b0414711 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/AnnotationsTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/AnnotationsTest.java @@ -97,7 +97,8 @@ public class AnnotationsTest { static final String SIMPLE = "simple"; static final String SUBCLASS2 = "subclass2"; - @ServiceInterfaceAnnotation(value = SIMPLE, osgiRegistrationType = Executor.class) + @ServiceInterfaceAnnotation(value = SIMPLE, osgiRegistrationType = Executor.class, + namespace = "ns", revision = "rev", localName = SIMPLE) static interface SimpleSI extends AbstractServiceInterface { } @@ -161,7 +162,9 @@ public class AnnotationsTest { } - @ServiceInterfaceAnnotation(value = SUBCLASS2, osgiRegistrationType = ExecutorService.class) + @ServiceInterfaceAnnotation(value = SUBCLASS2, osgiRegistrationType = ExecutorService.class, + namespace = "ns", revision = "rev", localName = SUBCLASS2) + static interface SubSI2 extends SubSI { } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelperTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelperTest.java index 9a5452aa6c..22ea528030 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelperTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelperTest.java @@ -9,11 +9,15 @@ package org.opendaylight.controller.config.manager.impl.util; import static org.junit.Assert.assertEquals; +import java.util.HashSet; import java.util.Set; import javax.management.MXBean; import org.junit.Test; +import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface; +import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingScheduledThreadPoolServiceInterface; +import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface; import org.opendaylight.controller.config.spi.Module; import org.opendaylight.yangtools.concepts.Identifiable; @@ -60,4 +64,17 @@ public class InterfacesHelperTest { assertEquals(expected, InterfacesHelper.getMXInterfaces(SubClass.class)); } + @Test + public void testGetAllAbstractServiceInterfaceClasses(){ + Class clazz = TestingScheduledThreadPoolServiceInterface.class; + Set> input = new HashSet<>(); + input.add(clazz); + Set> result = InterfacesHelper.getAllAbstractServiceInterfaceClasses(input); + + Set> expected = Sets.newHashSet((Class) TestingScheduledThreadPoolServiceInterface.class, + TestingThreadPoolServiceInterface.class + ); + assertEquals(expected, result); + } + } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPConfigMXBean.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPConfigMXBean.java index 4fd2f5f1b5..9674a110ce 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPConfigMXBean.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPConfigMXBean.java @@ -11,7 +11,8 @@ import javax.management.ObjectName; import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; -@ServiceInterfaceAnnotation(value = TestingParallelAPSPConfigMXBean.NAME, osgiRegistrationType = TestingAPSP.class) +@ServiceInterfaceAnnotation(value = TestingParallelAPSPConfigMXBean.NAME, osgiRegistrationType = TestingAPSP.class, +namespace = "namespace", revision = "rev", localName = TestingParallelAPSPConfigMXBean.NAME) public interface TestingParallelAPSPConfigMXBean { static final String NAME = "apsp"; diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModuleFactory.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModuleFactory.java index 3adf11484e..50a58792e1 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModuleFactory.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModuleFactory.java @@ -18,6 +18,7 @@ import org.osgi.framework.BundleContext; import javax.annotation.concurrent.ThreadSafe; import javax.management.ObjectName; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -69,4 +70,9 @@ public class TestingParallelAPSPModuleFactory implements ModuleFactory { public Set getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext context) { return new HashSet(); } + + @Override + public Set> getImplementedServiceIntefaces() { + return Collections.emptySet(); + } } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModuleFactory.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModuleFactory.java index 2e1047849e..e5306a4fa6 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModuleFactory.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModuleFactory.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool; +import com.google.common.collect.Sets; import org.opendaylight.controller.config.api.DependencyResolver; import org.opendaylight.controller.config.api.DependencyResolverFactory; import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; @@ -18,16 +19,16 @@ import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; import org.osgi.framework.BundleContext; -import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; public class TestingScheduledThreadPoolModuleFactory implements ModuleFactory { public static final String NAME = "scheduled"; - private static List> ifc = Arrays - .asList(TestingScheduledThreadPoolServiceInterface.class, TestingThreadPoolServiceInterface.class); + private static Set> ifc = Collections.unmodifiableSet(Sets.newHashSet( + (Class) TestingScheduledThreadPoolServiceInterface.class, + TestingThreadPoolServiceInterface.class)); @Override public boolean isModuleImplementingServiceInterface( @@ -70,4 +71,11 @@ public class TestingScheduledThreadPoolModuleFactory implements ModuleFactory { public Set getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext bundleContext) { return new HashSet(); } + + @Override + public Set> getImplementedServiceIntefaces() { + return ifc; + } + + } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/ModifiableThreadPoolServiceInterface.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/ModifiableThreadPoolServiceInterface.java index ab1b6bd218..5c30d1e977 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/ModifiableThreadPoolServiceInterface.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/ModifiableThreadPoolServiceInterface.java @@ -10,7 +10,8 @@ package org.opendaylight.controller.config.manager.testingservices.seviceinterfa import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingModifiableThreadPoolIfc; -@ServiceInterfaceAnnotation(value = "modifiable-threadpool", osgiRegistrationType = TestingModifiableThreadPoolIfc.class) +@ServiceInterfaceAnnotation(value = "fqn:modifiable-threadpool", osgiRegistrationType = TestingModifiableThreadPoolIfc.class, + namespace = "foo", revision = "bar", localName = "modifiable-threadpool") public interface ModifiableThreadPoolServiceInterface extends TestingThreadPoolServiceInterface { } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingScheduledThreadPoolServiceInterface.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingScheduledThreadPoolServiceInterface.java index e4e388c610..5ddc1892e3 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingScheduledThreadPoolServiceInterface.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingScheduledThreadPoolServiceInterface.java @@ -10,7 +10,8 @@ package org.opendaylight.controller.config.manager.testingservices.seviceinterfa import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolIfc; -@ServiceInterfaceAnnotation(value = "threadpool-scheduled", osgiRegistrationType = TestingScheduledThreadPoolIfc.class) +@ServiceInterfaceAnnotation(value = "threadpool-scheduled", osgiRegistrationType = TestingScheduledThreadPoolIfc.class, + namespace = "ns", revision = "rev", localName = "threadpool-scheduled") public interface TestingScheduledThreadPoolServiceInterface extends TestingThreadPoolServiceInterface { } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java index fd5ab1780d..91a4cff415 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java @@ -11,7 +11,8 @@ import org.opendaylight.controller.config.api.annotations.AbstractServiceInterfa import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc; -@ServiceInterfaceAnnotation(value = "testing-threadpool", osgiRegistrationType = TestingThreadPoolIfc.class) +@ServiceInterfaceAnnotation(value = "testing-threadpool", osgiRegistrationType = TestingThreadPoolIfc.class, + namespace = "ns", revision = "foo", localName = "bar") public interface TestingThreadPoolServiceInterface extends AbstractServiceInterface { } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPoolModuleFactory.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPoolModuleFactory.java index cf05e44530..b749ea7511 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPoolModuleFactory.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPoolModuleFactory.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.config.manager.testingservices.threadpool; +import com.google.common.collect.Sets; import org.opendaylight.controller.config.api.DependencyResolver; import org.opendaylight.controller.config.api.DependencyResolverFactory; import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; @@ -18,15 +19,16 @@ import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; import org.osgi.framework.BundleContext; -import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; public class TestingFixedThreadPoolModuleFactory implements ModuleFactory { public static final String NAME = "fixed"; - private static List> ifc = Arrays - .asList(ModifiableThreadPoolServiceInterface.class, TestingThreadPoolServiceInterface.class); + + private static Set> ifc = Collections.unmodifiableSet(Sets.newHashSet( + (Class) ModifiableThreadPoolServiceInterface.class, + TestingThreadPoolServiceInterface.class)); @Override public String getImplementationName() { @@ -71,4 +73,9 @@ public class TestingFixedThreadPoolModuleFactory implements ModuleFactory { public Set getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext bundleContext) { return new HashSet(); } + + @Override + public Set> getImplementedServiceIntefaces() { + return ifc; + } } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java index 3a1efaeaaf..4ecc7c3a5c 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.config.util; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Set; import javax.management.AttributeNotFoundException; @@ -28,7 +29,7 @@ import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; public class ConfigRegistryJMXClient implements ConfigRegistryClient { - private final ConfigRegistryMXBean configRegistryProxy; + private final ConfigRegistryMXBean configRegistryMXBeanProxy; private final ObjectName configRegistryON; private final MBeanServer configMBeanServer; @@ -40,7 +41,7 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient { if (!(searchResult.size() == 1)) { throw new IllegalStateException("Config registry not found"); } - configRegistryProxy = JMX.newMXBeanProxy(configMBeanServer, configRegistryON, ConfigRegistryMXBean.class, + configRegistryMXBeanProxy = JMX.newMXBeanProxy(configMBeanServer, configRegistryON, ConfigRegistryMXBean.class, false); } @@ -61,7 +62,7 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient { @Override public ConfigTransactionJMXClient getConfigTransactionClient( ObjectName objectName) { - return new ConfigTransactionJMXClient(configRegistryProxy, objectName, + return new ConfigTransactionJMXClient(configRegistryMXBeanProxy, objectName, configMBeanServer); } @@ -75,18 +76,18 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient { @Override public ObjectName beginConfig() { - return configRegistryProxy.beginConfig(); + return configRegistryMXBeanProxy.beginConfig(); } @Override public CommitStatus commitConfig(ObjectName transactionControllerON) throws ConflictingVersionException, ValidationException { - return configRegistryProxy.commitConfig(transactionControllerON); + return configRegistryMXBeanProxy.commitConfig(transactionControllerON); } @Override public List getOpenConfigs() { - return configRegistryProxy.getOpenConfigs(); + return configRegistryMXBeanProxy.getOpenConfigs(); } @Override @@ -101,45 +102,75 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient { @Override public Set getAvailableModuleNames() { - return configRegistryProxy.getAvailableModuleNames(); + return configRegistryMXBeanProxy.getAvailableModuleNames(); } @Override public boolean isHealthy() { - return configRegistryProxy.isHealthy(); + return configRegistryMXBeanProxy.isHealthy(); } @Override public Set lookupConfigBeans() { - return configRegistryProxy.lookupConfigBeans(); + return configRegistryMXBeanProxy.lookupConfigBeans(); } @Override public Set lookupConfigBeans(String moduleName) { - return configRegistryProxy.lookupConfigBeans(moduleName); + return configRegistryMXBeanProxy.lookupConfigBeans(moduleName); } @Override public Set lookupConfigBeans(String moduleName, String instanceName) { - return configRegistryProxy.lookupConfigBeans(moduleName, instanceName); + return configRegistryMXBeanProxy.lookupConfigBeans(moduleName, instanceName); } @Override public ObjectName lookupConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException { - return configRegistryProxy.lookupConfigBean(moduleName, instanceName); + return configRegistryMXBeanProxy.lookupConfigBean(moduleName, instanceName); } @Override public Set lookupRuntimeBeans() { - return configRegistryProxy.lookupRuntimeBeans(); + return configRegistryMXBeanProxy.lookupRuntimeBeans(); } @Override public Set lookupRuntimeBeans(String ifcName, String instanceName) { - return configRegistryProxy.lookupRuntimeBeans(ifcName, instanceName); + return configRegistryMXBeanProxy.lookupRuntimeBeans(ifcName, instanceName); + } + + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + configRegistryMXBeanProxy.checkConfigBeanExists(objectName); + } + + @Override + public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + return configRegistryMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName); + } + + @Override + public Map> getServiceMapping() { + return configRegistryMXBeanProxy.getServiceMapping(); + } + + @Override + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + return configRegistryMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + } + + @Override + public Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + return configRegistryMXBeanProxy.lookupServiceInterfaceNames(objectName); + } + + @Override + public String getServiceInterfaceName(String namespace, String localName) { + return configRegistryMXBeanProxy.getServiceInterfaceName(namespace, localName); } @Override diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java index 548c0e9ea4..bd6f6fa884 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.config.util; +import java.util.Map; import java.util.Set; import javax.management.Attribute; @@ -26,19 +27,19 @@ import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXB import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; public class ConfigTransactionJMXClient implements ConfigTransactionClient { - private final ConfigRegistryMXBean configTransactionManagerProxy; + private final ConfigRegistryMXBean configRegistryMXBeanProxy; private final ObjectName configTransactionControllerON; - private final ConfigTransactionControllerMXBean configControllerProxy; + private final ConfigTransactionControllerMXBean configTransactionControllerMXBeanProxy; private final MBeanServer configMBeanServer; public ConfigTransactionJMXClient( - ConfigRegistryMXBean configTransactionManagerProxy, + ConfigRegistryMXBean configRegistryMXBeanProxy, ObjectName configTransactionControllerON, MBeanServer configMBeanServer) { this.configMBeanServer = configMBeanServer; - this.configTransactionManagerProxy = configTransactionManagerProxy; + this.configRegistryMXBeanProxy = configRegistryMXBeanProxy; this.configTransactionControllerON = configTransactionControllerON; - this.configControllerProxy = JMX.newMXBeanProxy(configMBeanServer, + this.configTransactionControllerMXBeanProxy = JMX.newMXBeanProxy(configMBeanServer, configTransactionControllerON, ConfigTransactionControllerMXBean.class); } @@ -54,7 +55,7 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { @Override public CommitStatus commit() throws ConflictingVersionException, ValidationException { - return configTransactionManagerProxy + return configRegistryMXBeanProxy .commitConfig(configTransactionControllerON); } @@ -73,13 +74,13 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { @Override public ObjectName createModule(String moduleName, String instanceName) throws InstanceAlreadyExistsException { - return configControllerProxy.createModule(moduleName, instanceName); + return configTransactionControllerMXBeanProxy.createModule(moduleName, instanceName); } @Override public void destroyModule(ObjectName objectName) throws InstanceNotFoundException { - configControllerProxy.destroyModule(objectName); + configTransactionControllerMXBeanProxy.destroyModule(objectName); } @Override @@ -91,12 +92,12 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { @Override public void abortConfig() { - configControllerProxy.abortConfig(); + configTransactionControllerMXBeanProxy.abortConfig(); } @Override public void validateConfig() throws ValidationException { - configControllerProxy.validateConfig(); + configTransactionControllerMXBeanProxy.validateConfig(); } @Override @@ -121,12 +122,12 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { @Override public String getTransactionName() { - return configControllerProxy.getTransactionName(); + return configTransactionControllerMXBeanProxy.getTransactionName(); } @Override public Set getAvailableModuleNames() { - return configControllerProxy.getAvailableModuleNames(); + return configTransactionControllerMXBeanProxy.getAvailableModuleNames(); } @Override @@ -136,27 +137,77 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { @Override public Set lookupConfigBeans() { - return configControllerProxy.lookupConfigBeans(); + return configTransactionControllerMXBeanProxy.lookupConfigBeans(); } @Override public Set lookupConfigBeans(String moduleName) { - return configControllerProxy.lookupConfigBeans(moduleName); + return configTransactionControllerMXBeanProxy.lookupConfigBeans(moduleName); } @Override public ObjectName lookupConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException { - return configControllerProxy.lookupConfigBean(moduleName, instanceName); + return configTransactionControllerMXBeanProxy.lookupConfigBean(moduleName, instanceName); } @Override public Set lookupConfigBeans(String moduleName, String instanceName) { - return configControllerProxy + return configTransactionControllerMXBeanProxy .lookupConfigBeans(moduleName, instanceName); } + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + configTransactionControllerMXBeanProxy.checkConfigBeanExists(objectName); + } + + @Override + public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException { + configTransactionControllerMXBeanProxy.saveServiceReference(serviceInterfaceName,refName,objectName); + } + + @Override + public boolean removeServiceReference(String serviceInterfaceName, String refName) { + return configTransactionControllerMXBeanProxy.removeServiceReference(serviceInterfaceName, refName); + } + + @Override + public void removeAllServiceReferences() { + configTransactionControllerMXBeanProxy.removeAllServiceReferences(); + } + + @Override + public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + return configTransactionControllerMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName); + } + + @Override + public Map> getServiceMapping() { + return configTransactionControllerMXBeanProxy.getServiceMapping(); + } + + @Override + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + return configTransactionControllerMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + } + + @Override + public Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + return configTransactionControllerMXBeanProxy.lookupServiceInterfaceNames(objectName); + } + + @Override + public String getServiceInterfaceName(String namespace, String localName) { + return configTransactionControllerMXBeanProxy.getServiceInterfaceName(namespace, localName); + } + + @Override + public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException { + return configTransactionControllerMXBeanProxy.removeServiceReferences(objectName); + } + @Override public void validateBean(ObjectName configBeanON) throws ValidationException { diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigRegistryJolokiaClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigRegistryJolokiaClient.java index f29f0e03ac..9d55f8d529 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigRegistryJolokiaClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigRegistryJolokiaClient.java @@ -8,8 +8,10 @@ package org.opendaylight.controller.config.util.jolokia; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.management.InstanceNotFoundException; import javax.management.ObjectName; import org.jolokia.client.request.J4pExecRequest; @@ -24,6 +26,7 @@ import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.util.ConfigRegistryClient; +@Deprecated public class ConfigRegistryJolokiaClient extends ListableJolokiaClient implements ConfigRegistryClient { @@ -136,4 +139,35 @@ public class ConfigRegistryJolokiaClient extends ListableJolokiaClient public Object getAttributeCurrentValue(ObjectName on, String attributeName) { throw new UnsupportedOperationException(); } + + // TODO: implement or deprecate + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + throw new UnsupportedOperationException(); + } + + @Override + public Map> getServiceMapping() { + throw new UnsupportedOperationException(); + } + + @Override + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + throw new UnsupportedOperationException(); + } + + @Override + public Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public String getServiceInterfaceName(String namespace, String localName) { + throw new UnsupportedOperationException(); + } } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigTransactionJolokiaClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigTransactionJolokiaClient.java index f4824cd794..834e9c6845 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigTransactionJolokiaClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigTransactionJolokiaClient.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.config.util.jolokia; import java.util.Map; +import java.util.Set; import javax.management.Attribute; import javax.management.AttributeNotFoundException; @@ -25,6 +26,7 @@ import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.util.AttributeEntry; import org.opendaylight.controller.config.util.ConfigTransactionClient; +@Deprecated public class ConfigTransactionJolokiaClient extends ListableJolokiaClient implements ConfigTransactionClient { @@ -162,4 +164,54 @@ public class ConfigTransactionJolokiaClient extends ListableJolokiaClient throw new UnsupportedOperationException(); } + // TODO: implement or deprecate + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeServiceReference(String serviceInterfaceName, String refName) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeAllServiceReferences() { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + throw new UnsupportedOperationException(); + } + + @Override + public Map> getServiceMapping() { + throw new UnsupportedOperationException(); + } + + @Override + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + throw new UnsupportedOperationException(); + } + + @Override + public Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public String getServiceInterfaceName(String namespace, String localName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java index 6277f6a0e6..321d23ffdc 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java @@ -39,6 +39,7 @@ import org.opendaylight.controller.config.api.ValidationException.ExceptionMessa import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.util.AttributeEntry; + abstract class ListableJolokiaClient { protected final J4pClient j4pClient; protected final String url; diff --git a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/LookupTest.java b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/LookupTest.java index 0749204324..52e934583e 100644 --- a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/LookupTest.java +++ b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/LookupTest.java @@ -12,6 +12,7 @@ import static org.junit.Assert.fail; import java.lang.management.ManagementFactory; import java.lang.reflect.Method; +import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -69,9 +70,9 @@ public class LookupTest { ManagementFactory.getPlatformMBeanServer()); jolokiaTransactionClient = new ConfigTransactionJolokiaClient( jolokiaURL, testingTransactionControllerON, null); - lookupProvidersToClients = ImmutableMap - .of(testingRegistry, Sets.newHashSet(jmxRegistryClient, jolokiaRegistryClient), - testingTransactionController, Sets.newHashSet(jmxTransactionClient, jolokiaTransactionClient)); + HashSet registryClients = Sets.newHashSet(jmxRegistryClient, jolokiaRegistryClient); + HashSet configTransactionClients = Sets.newHashSet(jmxTransactionClient, jolokiaTransactionClient); + lookupProvidersToClients = ImmutableMap.of((LookupRegistry) testingRegistry, registryClients, testingTransactionController, configTransactionClients); } @After diff --git a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java index d4ae42d3de..ba6262780c 100644 --- a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java +++ b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.config.util; import java.util.List; +import java.util.Map; import java.util.Set; import javax.management.InstanceNotFoundException; @@ -143,4 +144,33 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean { } } + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + throw new UnsupportedOperationException(); + } + + @Override + public Map> getServiceMapping() { + throw new UnsupportedOperationException(); + } + + @Override + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + throw new UnsupportedOperationException(); + } + + @Override + public Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public String getServiceInterfaceName(String namespace, String localName) { + throw new UnsupportedOperationException(); + } } diff --git a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java index 67e31b05e5..0a845e1512 100644 --- a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java +++ b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.config.util; +import java.util.Map; import java.util.Set; import javax.management.InstanceAlreadyExistsException; @@ -109,4 +110,54 @@ public class TestingConfigTransactionController implements return null; } } + + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeServiceReference(String serviceInterfaceName, String refName) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeAllServiceReferences() { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + throw new UnsupportedOperationException(); + } + + @Override + public Map> getServiceMapping() { + throw new UnsupportedOperationException(); + } + + @Override + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + throw new UnsupportedOperationException(); + } + + @Override + public Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public String getServiceInterfaceName(String namespace, String localName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException { + throw new UnsupportedOperationException(); + } } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Annotation.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Annotation.java index 5ec359ea8d..59368e8e49 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Annotation.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Annotation.java @@ -49,10 +49,13 @@ public class Annotation { Preconditions.checkNotNull(exportedClassName, "Cannot create annotation from null exportedClassName"); - List params = Lists.newArrayList(new Parameter("value", - q(qname.getLocalName()))); - params.add(new Parameter("osgiRegistrationType", exportedClassName - + ".class")); + List params = Lists.newArrayList(new Parameter("value", q(qname.toString()))); + params.add(new Parameter("osgiRegistrationType", exportedClassName + ".class")); + + params.add(new Parameter("namespace", q(qname.getNamespace().toString()))); + params.add(new Parameter("revision", q(qname.getFormattedRevision()))); + params.add(new Parameter("localName", q(qname.getLocalName()))); + return new Annotation( ServiceInterfaceAnnotation.class.getCanonicalName(), params); } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/factory_abs_template.ftl b/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/factory_abs_template.ftl index a331e4e0c1..37fd05bc52 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/factory_abs_template.ftl +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/factory_abs_template.ftl @@ -6,12 +6,14 @@ package ${packageName}; { public static final java.lang.String NAME = "${globallyUniqueName}"; - private static final java.util.Set> serviceIfcs = new java.util.HashSet>(); + private static final java.util.Set> serviceIfcs; <#if providedServices??> static { + java.util.Set> serviceIfcs2 = new java.util.HashSet>(); <#list providedServices as refId> - serviceIfcs.add(${refId}); + serviceIfcs2.add(${refId}); + serviceIfcs = java.util.Collections.unmodifiableSet(serviceIfcs2); } @@ -25,6 +27,12 @@ package ${packageName}; return false; } + @Override + public java.util.Set> getImplementedServiceIntefaces() { + return serviceIfcs; + } + + @Override public ${moduleType} createModule(String instanceName, ${dependencyResolverType} dependencyResolver, ${bundleContextType} bundleContext) { return instantiateModule(instanceName, dependencyResolver, bundleContext); diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java index 1945cac1c2..3ef406694a 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java @@ -438,11 +438,11 @@ public class JMXGeneratorTest extends AbstractGeneratorTest { "public static final java.lang.String NAME=\"threadfactory-naming\""); assertDeclaredField( fieldDeclarations, - "private static final java.util.Set> serviceIfcs=new java.util.HashSet>()"); + "private static final java.util.Set> serviceIfcs"); assertEquals(2, fieldDeclarations.size()); - assertFactoryMethods(visitor.methods, 8); + assertFactoryMethods(visitor.methods, 9); assertEquals("Incorrenct number of generated method descriptions", 0, visitor.methodDescriptions.size()); assertEquals("Incorrenct number of generated method javadoc", 0, diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf index fa33215ea6..edee185c17 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf @@ -16,9 +16,9 @@ dom-broker dom:dom-data-store - - ref_hash-map-data-store - + + hash-map-data-store + @@ -26,11 +26,11 @@ binding-broker-impl binding:binding-notification-service - ref_binding-notification-broker + binding-notification-broker binding:binding-data-broker - ref_binding-data-broker + binding-data-broker @@ -46,43 +46,43 @@ binding-data-broker dom:dom-broker-osgi-registry - ref_dom-broker + dom-broker binding:binding-dom-mapping-service - ref_runtime-mapping-singleton + runtime-mapping-singleton //SERVICES START dom:schema-service - ref_yang-schema-service + yang-schema-service /modules/module[type='schema-service-singleton'][name='yang-schema-service'] binding:binding-notification-service - ref_binding-notification-broker + binding-notification-broker /modules/module[type='binding-notification-broker'][name='binding-notification-broker'] dom:dom-data-store - ref_hash-map-data-store + hash-map-data-store /modules/module[type='hash-map-data-store'][name='hash-map-data-store'] - ref_cluster-data-store + cluster-data-store /modules/module[type='dom-clustered-store-impl'][name='cluster-data-store'] binding:binding-broker-osgi-registry - ref_binding-broker-impl + binding-osgi-broker /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] @@ -96,21 +96,21 @@ binding-impl:binding-dom-mapping-service - ref_runtime-mapping-singleton + runtime-mapping-singleton /modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton'] dom:dom-broker-osgi-registry - ref_dom-broker + dom-broker /modules/module[type='dom-broker-impl'][name='dom-broker'] binding:binding-data-broker - ref_binding-data-broker + binding-data-broker /modules/module[type='binding-data-broker'][name='binding-data-broker'] diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend index fed56fe297..930aa663bb 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend @@ -34,11 +34,12 @@ import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil import static com.google.common.base.Preconditions.* import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition +import org.slf4j.LoggerFactory +import com.google.common.collect.FluentIterable class ControllerContext implements SchemaServiceListener { - + val static LOG = LoggerFactory.getLogger(ControllerContext) val static ControllerContext INSTANCE = new ControllerContext - val static NULL_VALUE = "null" var SchemaContext schemas; @@ -292,6 +293,7 @@ class ControllerContext implements SchemaServiceListener { checkArgument(node instanceof LeafSchemaNode); val urlDecoded = URLDecoder.decode(uriValue); val typedef = (node as LeafSchemaNode).type; + var decoded = TypeDefinitionAwareCodec.from(typedef)?.deserialize(urlDecoded) if(decoded == null) { var baseType = typedef @@ -329,8 +331,10 @@ class ControllerContext implements SchemaServiceListener { private def QName toQName(String name) { val module = name.toModuleName; val node = name.toNodeName; - val namespace = moduleNameToUri.get(module); - return new QName(namespace, null, node); + val namespace = FluentIterable.from(schemas.modules.sort[o1,o2 | o1.revision.compareTo(o2.revision)]) // + .transform[QName.create(namespace,revision,it.name)].findFirst[module == localName] + ; + return QName.create(namespace,node); } def getRpcDefinition(String name) { @@ -340,7 +344,7 @@ class ControllerContext implements SchemaServiceListener { override onGlobalContextUpdated(SchemaContext context) { this.schemas = context; for (operation : context.operations) { - val qname = new QName(operation.QName.namespace, null, operation.QName.localName); + val qname = operation.QName; qnameToRpc.put(qname, operation); } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributesConstants.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributesConstants.java new file mode 100644 index 0000000000..4f9e1fe087 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributesConstants.java @@ -0,0 +1,17 @@ +/** + * @author Maros Marsalek + * + * 12 2013 + * + * Copyright (c) 2012 by Cisco Systems, Inc. + * All rights reserved. + */ +package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes; + +public class AttributesConstants { + + /** + * Property placed into object names for dependencies to preserve reference name + */ + public static final String REF_NAME_ON_PROPERTY_KEY = "X-refName"; +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectNameAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectNameAttributeMappingStrategy.java index f4d88c7c8e..8426341636 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectNameAttributeMappingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectNameAttributeMappingStrategy.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributesConstants; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.opendaylight.controller.netconf.confignetconfconnector.util.Util; @@ -42,7 +43,11 @@ public class ObjectNameAttributeMappingStrategy extends Util.checkType(value, ObjectName.class); ObjectName on = (ObjectName) value; - String refName = tracker.addServiceEntry(namespace, serviceName, on); + + String expectedRefName = on.getKeyProperty(AttributesConstants.REF_NAME_ON_PROPERTY_KEY); + + String refName = expectedRefName == null ? tracker.getRefName(namespace, serviceName, on, Optional. absent()) + : tracker.getRefName(namespace, serviceName, on, Optional.of(expectedRefName)); return Optional.of(new MappedDependency(namespace, serviceName, refName)); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectNameAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectNameAttributeResolvingStrategy.java index c6f306b360..d8f0e2357e 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectNameAttributeResolvingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectNameAttributeResolvingStrategy.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri import com.google.common.base.Optional; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributesConstants; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services.ServiceInstance; @@ -46,6 +47,8 @@ public class ObjectNameAttributeResolvingStrategy extends AbstractAttributeResol ServiceInstance byRefName = serviceTracker.getByServiceAndRefName(namespace, serviceName, refName); ObjectName on = ObjectNameUtil.createReadOnlyModuleON(byRefName.getModuleName(), byRefName.getInstanceName()); + on = ObjectNameUtil.createON(on.toString() + "," + AttributesConstants.REF_NAME_ON_PROPERTY_KEY + "=" + refName); + logger.debug("Attribute {} : {} parsed to type {}", attrName, value, getOpenType()); return Optional.of(on); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java index f33a32271f..3a5fa1170f 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java @@ -14,6 +14,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -53,7 +54,7 @@ public class Config { } public static Map>> getMappedInstances(Set instancesToMap, - Services serviceTracker, Map> configs) { + Map> configs) { Multimap moduleToInstances = mapInstancesToModules(instancesToMap); Map>> retVal = Maps.newLinkedHashMap(); @@ -75,13 +76,6 @@ public class Config { innerRetVal.put(moduleName, instances); - // All found instances add to service tracker in advance - // This way all instances will be serialized as all available - // services when get-config is triggered - // (even if they are not used as services by other instances) - // = more user friendly - addServices(serviceTracker, instances, mbeEntry.getValue().getProvidedServices()); - } retVal.put(namespace, innerRetVal); @@ -89,15 +83,6 @@ public class Config { return retVal; } - private static void addServices(Services serviceTracker, Collection instances, - Multimap providedServices) { - for (ObjectName instanceOn : instances) { - for (Entry serviceName : providedServices.entries()) { - serviceTracker.addServiceEntry(serviceName.getKey(), serviceName.getValue(), instanceOn); - } - } - } - private static Multimap mapInstancesToModules(Set instancesToMap) { Multimap retVal = HashMultimap.create(); @@ -114,11 +99,10 @@ public class Config { // } public Element toXml(Set instancesToMap, Optional maybeNamespace, Document document, - Element dataElement) { - Services serviceTracker = new Services(); + Element dataElement, Services serviceTracker) { Map>> moduleToInstances = getMappedInstances(instancesToMap, - serviceTracker, moduleConfigs); + moduleConfigs); Element root = dataElement; if (maybeNamespace.isPresent()) { @@ -167,13 +151,13 @@ public class Config { // TODO refactor, replace string representing namespace with namespace class // TODO refactor, replace Map->Multimap with e.g. ConfigElementResolved // class - public Map> fromXml(XmlElement xml, Set instancesForFillingServiceRefMapping, - EditStrategyType defaultEditStrategyType) { + public ConfigElementResolved fromXml(XmlElement xml, + EditStrategyType defaultEditStrategyType, ServiceReferenceReadableRegistry taClient) { Map> retVal = Maps.newHashMap(); List recognisedChildren = Lists.newArrayList(); - Services serviceTracker = fromXmlServices(xml, recognisedChildren, instancesForFillingServiceRefMapping); + Services serviceTracker = fromXmlServices(xml, recognisedChildren, taClient); List moduleElements = fromXmlModules(xml, recognisedChildren); xml.checkUnrecognisedElements(recognisedChildren); @@ -182,7 +166,26 @@ public class Config { resolveModule(retVal, serviceTracker, moduleElement, defaultEditStrategyType); } - return retVal; + return new ConfigElementResolved(retVal, serviceTracker); + } + + public static class ConfigElementResolved { + + private final Map> resolvedModules; + private final Services services; + + public ConfigElementResolved(Map> retVal, Services serviceTracker) { + this.resolvedModules = retVal; + this.services = serviceTracker; + } + + public Map> getResolvedModules() { + return resolvedModules; + } + + public Services getServices() { + return services; + } } private List fromXmlModules(XmlElement xml, List recognisedChildren) { @@ -224,7 +227,8 @@ public class Config { innerMap.put(factoryName, moduleElementResolved); } - private Services fromXmlServices(XmlElement xml, List recognisedChildren, Set instancesForFillingServiceRefMapping) { + private Services fromXmlServices(XmlElement xml, List recognisedChildren, + ServiceReferenceReadableRegistry taClient) { Optional servicesElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.SERVICES_KEY, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); @@ -235,22 +239,7 @@ public class Config { } else { mappedServices = new HashMap<>(); } - Services services = Services.resolveServices(mappedServices); - // merge with what candidate db contains by default - ref_ - - for(ObjectName existingON: instancesForFillingServiceRefMapping) { - logger.trace("Filling services from {}", existingON); - // get all its services - String factoryName = ObjectNameUtil.getFactoryName(existingON); - ModuleConfig moduleConfig = moduleNamesToConfigs.get(factoryName); - - checkState(moduleConfig != null, "Cannot find ModuleConfig with name " + factoryName + " in " + moduleNamesToConfigs); - // Set services = ; - for (Entry serviceName : moduleConfig.getProvidedServices().entries()) { - - services.addServiceEntry(serviceName.getKey(), serviceName.getValue(), existingON); - } - } + Services services = Services.resolveServices(mappedServices, taClient); return services; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java index 33858746cb..aae1636165 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java @@ -12,6 +12,7 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; @@ -128,7 +129,7 @@ public final class InstanceConfig { } public InstanceConfigElementResolved fromXml(XmlElement moduleElement, Services services, String moduleNamespace, - EditStrategyType defaultStrategy) { + EditStrategyType defaultStrategy, Multimap providedServices) { Map retVal = Maps.newHashMap(); Map strats = new ObjectXmlReader().prepareReading(yangToAttrConfig); @@ -153,7 +154,7 @@ public final class InstanceConfig { XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); InstanceConfigElementResolved instanceConfigElementResolved = perInstanceEditStrategy.equals("") ? new InstanceConfigElementResolved( - retVal, defaultStrategy) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy); + retVal, defaultStrategy, providedServices) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy, providedServices); resolveConfiguration(instanceConfigElementResolved, services); return instanceConfigElementResolved; diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java index e4bd9212e9..55cb60bed5 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config; import com.google.common.base.Preconditions; +import com.google.common.collect.Multimap; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigStrategy; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser; @@ -24,16 +25,19 @@ public class InstanceConfigElementResolved { private final EditStrategyType editStrategy; private final Map configuration; + private final Multimap providedServices; - public InstanceConfigElementResolved(String currentStrategy, Map configuration, EditStrategyType defaultStrategy) { + public InstanceConfigElementResolved(String currentStrategy, Map configuration, EditStrategyType defaultStrategy, Multimap providedServices) { EditStrategyType valueOf = checkStrategy(currentStrategy, defaultStrategy); this.editStrategy = valueOf; this.configuration = configuration; + this.providedServices = providedServices; } - public InstanceConfigElementResolved(Map configuration, EditStrategyType defaultStrategy) { + public InstanceConfigElementResolved(Map configuration, EditStrategyType defaultStrategy, Multimap providedServices) { editStrategy = defaultStrategy; this.configuration = configuration; + this.providedServices = providedServices; } @@ -54,7 +58,7 @@ public class InstanceConfigElementResolved { public EditConfigStrategy getEditStrategy() { - return editStrategy.getFittingStrategy(); + return editStrategy.getFittingStrategy(providedServices); } public Map getConfiguration() { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java index 2e2a26400f..2ac6fe0a9b 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java @@ -87,7 +87,7 @@ public class ModuleConfig { public ModuleElementResolved fromXml(XmlElement moduleElement, Services depTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) { - InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy); + InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices); return new ModuleElementResolved(instanceName, ice); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java index f522668733..a4f5e4999c 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java @@ -9,10 +9,14 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import com.google.common.collect.HashMultimap; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.google.common.collect.Sets; +import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; +import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectNameAttributeReadingStrategy; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; @@ -22,9 +26,9 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import javax.annotation.Nullable; import javax.management.ObjectName; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -33,6 +37,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public final class Services { + private static final Logger logger = LoggerFactory.getLogger(Services.class); private static final String PROVIDER_KEY = "provider"; @@ -42,58 +47,33 @@ public final class Services { private long suffix = 1; - private final Map instanceToRef = Maps.newHashMap(); private final Map>> namespaceToServiceNameToRefNameToInstance = Maps .newHashMap(); + private ServiceReferenceReadableRegistry configServiceRefRegistry; - public String addServiceEntry(String namespace, String serviceName, ObjectName on) { - - String moduleName = on.getKeyProperty("moduleFactoryName"); - String instanceName = on.getKeyProperty("instanceName"); - - String refName = addServiceEntry(namespace, serviceName, moduleName, instanceName); - logger.trace("Added service entry to tracker. Service name {}, ref name {}, module name {}, instance name {}", - serviceName, refName, moduleName, instanceName); - return refName; + public Services(ServiceReferenceReadableRegistry configServiceRefRegistry) { + this.configServiceRefRegistry = configServiceRefRegistry; } @VisibleForTesting - public String addServiceEntry(String namespace, String serviceName, String moduleName, String instanceName) { - ServiceInstance serviceInstance = new ServiceInstance(moduleName, instanceName); - serviceInstance.setServiceName(serviceName); + public String getNewDefaultRefName(String namespace, String serviceName, String moduleName, String instanceName) { + String refName; + refName = "ref_" + instanceName; - String refName = instanceToRef.get(serviceInstance); + Map> serviceNameToRefNameToInstance = getMappedServices().get(namespace); - Map> serviceNameToRefNameToInstance = namespaceToServiceNameToRefNameToInstance.get(namespace); - if (serviceNameToRefNameToInstance == null) { - serviceNameToRefNameToInstance = Maps.newHashMap(); - namespaceToServiceNameToRefNameToInstance.put(namespace, serviceNameToRefNameToInstance); - } + Map refNameToInstance; + if(serviceNameToRefNameToInstance == null || serviceNameToRefNameToInstance.containsKey(serviceName) == false) { + refNameToInstance = Collections.emptyMap(); + } else + refNameToInstance = serviceNameToRefNameToInstance.get(serviceName); - Map refNameToInstance = serviceNameToRefNameToInstance.get(serviceName); - if (refNameToInstance == null) { - refNameToInstance = Maps.newHashMap(); - serviceNameToRefNameToInstance.put(serviceName, refNameToInstance); + final Set refNamesAsSet = toSet(refNameToInstance.keySet()); + if (refNamesAsSet.contains(refName)) { + refName = findAvailableRefName(refName, refNamesAsSet); } - if (refName != null) { - if (serviceNameToRefNameToInstance.get(serviceName).containsKey(moduleName) == false) { - refNameToInstance.put(refName, serviceInstance); - } - return refName; - } else { - refName = "ref_" + instanceName; - - final Set refNamesAsSet = toSet(instanceToRef.values()); - if (refNamesAsSet.contains(refName)) { - refName = findAvailableRefName(refName, refNamesAsSet); - } - - instanceToRef.put(serviceInstance, refName); - refNameToInstance.put(refName, serviceInstance); - - return refName; - } + return refName; } private Set toSet(Collection values) { @@ -109,15 +89,15 @@ public final class Services { } public ServiceInstance getByServiceAndRefName(String namespace, String serviceName, String refName) { - Map> serviceNameToRefNameToInstance = namespaceToServiceNameToRefNameToInstance.get(namespace); - Preconditions.checkArgument(serviceNameToRefNameToInstance != null, "No serviceInstances mapped to " + namespace + " , " - + serviceNameToRefNameToInstance.keySet()); + Map> serviceNameToRefNameToInstance = getMappedServices().get(namespace); + + Preconditions.checkArgument(serviceNameToRefNameToInstance != null, "No serviceInstances mapped to " + namespace); - Map refNameToInstance = serviceNameToRefNameToInstance.get(serviceName); + Map refNameToInstance = serviceNameToRefNameToInstance.get(serviceName); Preconditions.checkArgument(refNameToInstance != null, "No serviceInstances mapped to " + serviceName + " , " + serviceNameToRefNameToInstance.keySet()); - ServiceInstance serviceInstance = refNameToInstance.get(refName); + ServiceInstance serviceInstance = ServiceInstance.fromString(refNameToInstance.get(refName)); Preconditions.checkArgument(serviceInstance != null, "No serviceInstance mapped to " + refName + " under service name " + serviceName + " , " + refNameToInstance.keySet()); return serviceInstance; @@ -136,26 +116,61 @@ public final class Services { for (String serviceName : serviceNameToRefNameToInstance.keySet()) { - Map innerInnerRetVal = Maps.transformValues( - serviceNameToRefNameToInstance.get(serviceName), new Function() { - @Nullable - @Override - public String apply(@Nullable ServiceInstance serviceInstance) { - return serviceInstance.toString(); - } - }); + Map innerInnerRetVal = Maps.newHashMap(); + for (Entry refNameToSi : serviceNameToRefNameToInstance.get(serviceName).entrySet()) { + innerInnerRetVal.put(refNameToSi.getKey(), refNameToSi.getValue().toString()); + } innerRetVal.put(serviceName, innerInnerRetVal); } retVal.put(namespace, innerRetVal); } + Map> serviceMapping = configServiceRefRegistry.getServiceMapping(); + for (String serviceQName : serviceMapping.keySet()) + for (String refName : serviceMapping.get(serviceQName).keySet()) { + + ObjectName on = serviceMapping.get(serviceQName).get(refName); + ServiceInstance si = ServiceInstance.fromObjectName(on); + + // FIXME use QName's new String constructor, after its implemented + Pattern p = Pattern.compile("\\(([^\\(\\?]+)\\?[^\\?\\)]*\\)([^\\)]+)"); + Matcher matcher = p.matcher(serviceQName); + Preconditions.checkArgument(matcher.matches()); + String namespace = matcher.group(1); + String localName = matcher.group(2); + + Map> serviceToRefs = retVal.get(namespace); + if(serviceToRefs==null) { + serviceToRefs = Maps.newHashMap(); + retVal.put(namespace, serviceToRefs); + } + + Map refsToSis = serviceToRefs.get(localName); + if(refsToSis==null) { + refsToSis = Maps.newHashMap(); + serviceToRefs.put(localName, refsToSis); + } + + Preconditions.checkState(refsToSis.containsKey(refName) == false, + "Duplicate reference name %s for service %s:%s, now for instance %s", refName, namespace, + localName, on); + refsToSis.put(refName, si.toString()); + } + return retVal; } + /** + * + */ + public Map>> getNamespaceToServiceNameToRefNameToInstance() { + return namespaceToServiceNameToRefNameToInstance; + } + // TODO hide resolveServices, call it explicitly in fromXml - public static Services resolveServices(Map>> mappedServices) { - Services tracker = new Services(); + public static Services resolveServices(Map>> mappedServices, ServiceReferenceReadableRegistry taClient) { + Services tracker = new Services(taClient); for (Entry>> namespaceEntry : mappedServices.entrySet()) { String namespace = namespaceEntry.getKey(); @@ -179,18 +194,18 @@ public final class Services { } String refName = refEntry.getKey(); - Preconditions.checkState(false == refNameToInstance.containsKey(refName), - "Duplicate reference name to service " + refName + " under service " + serviceName); + ServiceInstance serviceInstance = ServiceInstance.fromString(refEntry.getValue()); refNameToInstance.put(refName, serviceInstance); - tracker.instanceToRef.put(serviceInstance, refEntry.getKey()); } } } return tracker; } + // TODO support edit strategies on services + public static Map>> fromXml(XmlElement xml) { Map>> retVal = Maps.newHashMap(); @@ -275,6 +290,51 @@ public final class Services { return root; } + public String getRefName(String namespace, String serviceName, ObjectName on, Optional expectedRefName) { + Optional refNameOptional = getRefNameOptional(namespace, serviceName, on, expectedRefName); + Preconditions.checkState(refNameOptional.isPresent(), "No reference names mapped to %s, %s, %s", namespace, + serviceName, on); + return refNameOptional.get(); + } + + public Optional getRefNameOptional(String namespace, String serviceName, ObjectName on, + Optional expectedRefName) { + Map> services = getMappedServices().get(namespace); + + if(services == null) return Optional.absent(); + Map refs = services.get(serviceName); + + if(refs == null) return Optional.absent(); + Multimap reverted = revertMap(refs); + + ServiceInstance serviceInstance = ServiceInstance.fromObjectName(on); + Collection references = reverted.get(serviceInstance); + + if (expectedRefName.isPresent() && references.contains(expectedRefName.get())) { + logger.debug("Returning expected ref name {} for {}", expectedRefName.get(), on); + return expectedRefName; + } else if (references.size() > 0) { + String next = references.iterator().next(); + logger.debug("Returning random ref name {} for {}", next, on); + return Optional.of(next); + } else + return Optional.absent(); + } + + private Multimap revertMap(Map refs) { + Multimap multimap = HashMultimap.create(); + + for (Entry e : refs.entrySet()) { + multimap.put(ServiceInstance.fromString(e.getValue()), e.getKey()); + } + + return multimap; + } + + public boolean hasRefName(String key, String value, ObjectName on) { + return getRefNameOptional(key, value, on, Optional.absent()).isPresent(); + } + public static final class ServiceInstance { public ServiceInstance(String moduleName, String instanceName) { this.moduleName = moduleName; @@ -372,6 +432,13 @@ public final class Services { return true; } + public ObjectName getObjectName(String transactionName) { + return ObjectNameUtil.createTransactionModuleON(transactionName, moduleName, instanceName); + } + + public static ServiceInstance fromObjectName(ObjectName on) { + return new ServiceInstance(ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on)); + } } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java index 64f295a4d8..89c782c51c 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java @@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runti import com.google.common.collect.HashMultimap; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig; @@ -60,8 +61,8 @@ public class Runtime { return retVal; } - public Element toXml(Set instancesToMap, Set configBeans, Document document) { - Services serviceTracker = new Services(); + public Element toXml(Set instancesToMap, Set configBeans, Document document, ServiceReferenceReadableRegistry serviceRegistry) { + Services serviceTracker = new Services(serviceRegistry); Element root = document.createElement(XmlNetconfConstants.DATA_KEY); @@ -72,7 +73,7 @@ public class Runtime { Map> moduleToRuntimeInstance = mapInstancesToModules(instancesToMap); Map>> moduleToConfigInstance = Config.getMappedInstances( - configBeans, serviceTracker, moduleConfigs); + configBeans, moduleConfigs); for (String localNamespace : moduleConfigs.keySet()) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java index d8ea7d7af7..65df965afd 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java @@ -8,38 +8,38 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; -import java.util.Map; - -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; - import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import java.util.Map; + public abstract class AbstractEditConfigStrategy implements EditConfigStrategy { private static final Logger logger = LoggerFactory.getLogger(AbstractEditConfigStrategy.class); @Override public void executeConfiguration(String module, String instance, Map configuration, - ConfigTransactionClient ta) { + ConfigTransactionClient ta, Services services) { try { ObjectName on = ta.lookupConfigBean(module, instance); logger.debug("ServiceInstance for {} {} located successfully under {}", module, instance, on); - executeStrategy(configuration, ta, on); + executeStrategy(configuration, ta, on, services); } catch (InstanceNotFoundException e) { - handleMissingInstance(configuration, ta, module, instance); + handleMissingInstance(configuration, ta, module, instance, services); } } abstract void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance); + String module, String instance, Services services); abstract void executeStrategy(Map configuration, ConfigTransactionClient ta, - ObjectName objectName); + ObjectName objectName, Services services); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java index ffe107f8ce..12beaf8f8e 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java @@ -8,28 +8,40 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; -import java.util.Map; - -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; - +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import java.util.Map; + public class DeleteEditConfigStrategy extends AbstractEditConfigStrategy { private static final Logger logger = LoggerFactory.getLogger(DeleteEditConfigStrategy.class); + private final Multimap providedServices; + + public DeleteEditConfigStrategy() { + this.providedServices = HashMultimap.create(); + } + + public DeleteEditConfigStrategy(Multimap providedServices) { + this.providedServices = providedServices; + } + @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance) { + String module, String instance, Services services) { throw new IllegalStateException("Unable to delete " + module + ":" + instance + " , ServiceInstance not found"); } @Override - void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on) { + void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, Services services) { try { ta.destroyModule(on); logger.debug("ServiceInstance {} deleted successfully", on); 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 1fca16433a..1bb1d9bfba 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 @@ -26,6 +26,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved; +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.transactions.TransactionProvider; @@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; +import javax.management.InstanceNotFoundException; import javax.management.ObjectName; import java.util.HashMap; import java.util.Map; @@ -61,6 +63,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { @VisibleForTesting Element getResponseInternal(final Document document, final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException { + if (editConfigExecution.shouldTest()) { executeTests(configRegistryClient, editConfigExecution); } @@ -91,7 +94,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { private void executeTests(ConfigRegistryClient configRegistryClient, EditConfigExecution editConfigExecution) throws NetconfDocumentedException { try { - test(configRegistryClient, editConfigExecution.getResolvedXmlElements(), editConfigExecution.getDefaultStrategy()); + test(configRegistryClient, editConfigExecution, editConfigExecution.getDefaultStrategy()); } catch (IllegalStateException | JmxAttributeValidationException | ValidationException e) { logger.warn("Test phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e); final Map errorInfo = new HashMap<>(); @@ -103,7 +106,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { } private void test(ConfigRegistryClient configRegistryClient, - Map> resolvedModules, EditStrategyType editStrategyType) { + EditConfigExecution execution, EditStrategyType editStrategyType) { ObjectName taON = transactionProvider.getTestTransaction(); try { @@ -111,7 +114,9 @@ public class EditConfig extends AbstractConfigNetconfOperation { if (editStrategyType == EditStrategyType.replace) { transactionProvider.wipeTestTransaction(taON); } - setOnTransaction(configRegistryClient, resolvedModules, taON); + + setOnTransaction(configRegistryClient, execution.getResolvedXmlElements(), execution.getServices(), taON); + // TODO add service reference persistance testing here transactionProvider.validateTestTransaction(taON); } finally { transactionProvider.abortTestTransaction(taON); @@ -126,11 +131,45 @@ public class EditConfig extends AbstractConfigNetconfOperation { if (editConfigExecution.getDefaultStrategy() == EditStrategyType.replace) { transactionProvider.wipeTransaction(); } - setOnTransaction(configRegistryClient, editConfigExecution.getResolvedXmlElements(), taON); + + setOnTransaction(configRegistryClient, editConfigExecution.getResolvedXmlElements(), + editConfigExecution.getServices(), taON); + setServicesOnTransaction(configRegistryClient, editConfigExecution.getServices(), taON); + } + + private void setServicesOnTransaction(ConfigRegistryClient configRegistryClient, Services services, + ObjectName taON) { + ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON); + + Map>> namespaceToServiceNameToRefNameToInstance = services + .getNamespaceToServiceNameToRefNameToInstance(); + + for (String serviceNamespace : namespaceToServiceNameToRefNameToInstance.keySet()) { + for (String serviceName : namespaceToServiceNameToRefNameToInstance.get(serviceNamespace).keySet()) { + + String qnameOfService = getQname(ta, serviceNamespace, serviceName); + Map refNameToInstance = namespaceToServiceNameToRefNameToInstance + .get(serviceNamespace).get(serviceName); + + for (String refName : refNameToInstance.keySet()) { + ObjectName on = refNameToInstance.get(refName).getObjectName(ta.getTransactionName()); + // TODO check for duplicates + try { + ta.saveServiceReference(qnameOfService, refName, on); + } catch (InstanceNotFoundException e) { + throw new IllegalStateException("Unable to save ref name " + refName + " for instance " + on, e); + } + } + } + } + } + + private String getQname(ConfigTransactionClient ta, String namespace, String serviceName) { + return ta.getServiceInterfaceName(namespace, serviceName); } private void setOnTransaction(ConfigRegistryClient configRegistryClient, - Map> resolvedXmlElements, ObjectName taON) { + Map> resolvedXmlElements, Services services, ObjectName taON) { ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON); for (Multimap modulesToResolved : resolvedXmlElements.values()) { @@ -142,7 +181,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { InstanceConfigElementResolved ice = moduleElementResolved.getInstanceConfigElementResolved(); EditConfigStrategy strategy = ice.getEditStrategy(); - strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta); + strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta, services); } } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java index 6b7b622d56..23166e8cca 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java @@ -10,12 +10,13 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ed import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import java.util.Map; public interface EditConfigStrategy { void executeConfiguration(String module, String instance, Map configuration, - ConfigTransactionClient ta); + ConfigTransactionClient ta, Services services); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java index 3d4e5b6d0c..81327133b8 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java @@ -12,10 +12,13 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Multimap; +import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; import org.opendaylight.controller.config.util.ConfigRegistryClient; +import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -25,9 +28,7 @@ import org.slf4j.LoggerFactory; import javax.management.ObjectName; import java.util.Arrays; -import java.util.Collections; import java.util.Map; -import java.util.Set; public class EditConfigXmlParser { @@ -47,6 +48,8 @@ public class EditConfigXmlParser { TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient) throws NetconfDocumentedException { + //TODO remove transactionProvider and CfgRegistry from parameters, accept only service ref store + EditStrategyType editStrategyType = EditStrategyType.getDefaultStrategy(); xml.checkName(EditConfigXmlParser.EDIT_CONFIG); @@ -92,21 +95,14 @@ public class EditConfigXmlParser { logger.trace("Setting merge strategy to {}", mergeStrategyString); editStrategyType = EditStrategyType.valueOf(mergeStrategyString); } - Set instancesForFillingServiceRefMapping = Collections.emptySet(); - if (editStrategyType == EditStrategyType.merge) { - instancesForFillingServiceRefMapping = Datastore.getInstanceQueryStrategy(targetDatastore, transactionProvider) - .queryInstances(configRegistryClient); - logger.trace("Pre-filling services from following instances: {}", instancesForFillingServiceRefMapping); - } XmlElement configElement = xml.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.CONFIG_KEY); - return new EditConfigXmlParser.EditConfigExecution(xml, cfgMapping, configElement, testOption, - instancesForFillingServiceRefMapping, editStrategyType); - } + ObjectName taON = transactionProvider.getOrCreateTransaction(); + ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON); - private void removeMountpointsFromConfig(XmlElement configElement, XmlElement mountpointsElement) { - configElement.getDomElement().removeChild(mountpointsElement.getDomElement()); + return new EditConfigXmlParser.EditConfigExecution(cfgMapping, configElement, testOption, + ta, editStrategyType); } @VisibleForTesting @@ -135,15 +131,16 @@ public class EditConfigXmlParser { @VisibleForTesting static class EditConfigExecution { - private final XmlElement editConfigXml; + private final Map> resolvedXmlElements; private final TestOption testOption; private final EditStrategyType defaultEditStrategyType; + private final Services services; - EditConfigExecution(XmlElement xml, Config configResolver, XmlElement configElement, TestOption testOption, Set instancesForFillingServiceRefMapping, - EditStrategyType defaultStrategy) { - this.editConfigXml = xml; - this.resolvedXmlElements = configResolver.fromXml(configElement, instancesForFillingServiceRefMapping, defaultStrategy); + EditConfigExecution(Config configResolver, XmlElement configElement, TestOption testOption, ServiceReferenceReadableRegistry ta, EditStrategyType defaultStrategy) { + Config.ConfigElementResolved configElementResolved = configResolver.fromXml(configElement, defaultStrategy, ta); + this.resolvedXmlElements = configElementResolved.getResolvedModules(); + this.services = configElementResolved.getServices(); this.testOption = testOption; this.defaultEditStrategyType = defaultStrategy; } @@ -163,5 +160,9 @@ public class EditConfigXmlParser { EditStrategyType getDefaultStrategy() { return defaultEditStrategyType; } + + Services getServices() { + return services; + } } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java index cb03342a1e..676467553b 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java @@ -8,6 +8,8 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; +import com.google.common.collect.Multimap; + import java.util.EnumSet; import java.util.Set; @@ -40,14 +42,14 @@ public enum EditStrategyType { } } - public EditConfigStrategy getFittingStrategy() { + public EditConfigStrategy getFittingStrategy(Multimap providedServices) { switch (this) { case merge: - return new MergeEditConfigStrategy(); + return new MergeEditConfigStrategy(providedServices); case replace: - return new ReplaceEditConfigStrategy(); + return new ReplaceEditConfigStrategy(providedServices); case delete: - return new DeleteEditConfigStrategy(); + return new DeleteEditConfigStrategy(providedServices); case remove: return new RemoveEditConfigStrategy(); case none: diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java index 2a4a784a8a..06befb0565 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java @@ -8,37 +8,67 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; -import java.util.Map; -import java.util.Map.Entry; - -import javax.management.Attribute; -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; - +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.management.Attribute; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import java.util.Map; +import java.util.Map.Entry; + public class MergeEditConfigStrategy extends AbstractEditConfigStrategy { private static final Logger logger = LoggerFactory.getLogger(MergeEditConfigStrategy.class); + private final Multimap providedServices; + + public MergeEditConfigStrategy() { + this.providedServices = HashMultimap.create(); + } + + public MergeEditConfigStrategy(Multimap providedServices) { + this.providedServices = providedServices; + } @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance) { - ObjectName on; + String module, String instance, Services services) { + ObjectName on = null; try { on = ta.createModule(module, instance); logger.info("New instance for {} {} created under name {}", module, instance, on); - executeStrategy(configuration, ta, on); + addRefNames(services, providedServices, module, instance, ta, on); + executeStrategy(configuration, ta, on, services); } catch (InstanceAlreadyExistsException e1) { throw new IllegalStateException("Unable to create instance for " + module + " : " + instance); + } catch (InstanceNotFoundException e) { + throw new IllegalStateException("Unable to save default ref name for instance " + on, e); + } + } + + private void addRefNames(Services services, Multimap providedServices, String module, + String instance, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException { + for (Entry namespaceToService : providedServices.entries()) { + + if(services.hasRefName(namespaceToService.getKey(), + namespaceToService.getValue(), on)) + continue; + + String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(), + module, instance); + ta.saveServiceReference( + ta.getServiceInterfaceName(namespaceToService.getKey(), namespaceToService.getValue()), refName, on); } } @Override - void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on) { + void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, Services services) { for (Entry configAttributeEntry : configuration.entrySet()) { try { AttributeConfigElement ace = configAttributeEntry.getValue(); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/NoneEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/NoneEditConfigStrategy.java index db11ce381e..8347c6b88e 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/NoneEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/NoneEditConfigStrategy.java @@ -12,6 +12,7 @@ import java.util.Map; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,7 +22,7 @@ public class NoneEditConfigStrategy implements EditConfigStrategy { @Override public void executeConfiguration(String module, String instance, Map configuration, - ConfigTransactionClient ta) { + ConfigTransactionClient ta, Services services) { logger.debug("Skipping configuration element for {}:{}", module, instance); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/RemoveEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/RemoveEditConfigStrategy.java index 76ca09433a..64f082da40 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/RemoveEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/RemoveEditConfigStrategy.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ed import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,7 +22,7 @@ public class RemoveEditConfigStrategy extends DeleteEditConfigStrategy { @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance) { + String module, String instance, Services services) { logger.warn("Unable to delete {}:{}, ServiceInstance not found", module, instance); } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java index 0091d6cc84..43d852e76a 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java @@ -8,37 +8,68 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; -import java.util.Map; -import java.util.Map.Entry; - -import javax.management.Attribute; -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; - +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.management.Attribute; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import java.util.Map; +import java.util.Map.Entry; + public class ReplaceEditConfigStrategy extends AbstractEditConfigStrategy { private static final Logger logger = LoggerFactory.getLogger(ReplaceEditConfigStrategy.class); + private final Multimap providedServices; + + public ReplaceEditConfigStrategy() { + this.providedServices = HashMultimap.create(); + } + + public ReplaceEditConfigStrategy(Multimap providedServices) { + this.providedServices = providedServices; + } + @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance) { + String module, String instance, Services services) { + ObjectName on = null; try { - ObjectName on = ta.createModule(module, instance); + on = ta.createModule(module, instance); logger.debug("New instance for {} {} created under name {}", module, instance, on); - executeStrategy(configuration, ta, on); + addRefNames(services, providedServices, module, instance, ta, on); + executeStrategy(configuration, ta, on, services); } catch (InstanceAlreadyExistsException e) { logger.warn("Error creating instance {}:{}, replace failed", module, instance, e); throw new IllegalStateException("Unable to create new instance for " + module + " : " + instance, e); + } catch (InstanceNotFoundException e) { + throw new IllegalStateException("Unable to save default ref name for instance " + on, e); } } + private void addRefNames(Services services, Multimap providedServices, String module, + String instance, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException { + for (Entry namespaceToService : providedServices.entries()) { + + if(services.hasRefName(namespaceToService.getKey(), + namespaceToService.getValue(), on)) + continue; + + String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(), + module, instance); + ta.saveServiceReference( + ta.getServiceInterfaceName(namespaceToService.getKey(), namespaceToService.getValue()), refName, on); + } + } @Override - void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on) { + void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, Services services) { for (Entry configAttributeEntry : configuration.entrySet()) { try { AttributeConfigElement ace = configAttributeEntry.getValue(); 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 7ee13aeb58..efe4f7dde9 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 @@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ge import com.google.common.collect.Maps; import org.opendaylight.controller.config.util.ConfigRegistryClient; +import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; @@ -25,6 +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.getconfig.GetConfig; +import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.slf4j.Logger; @@ -42,11 +44,13 @@ public class Get extends AbstractConfigNetconfOperation { private final YangStoreSnapshot yangStoreSnapshot; private static final Logger logger = LoggerFactory.getLogger(Get.class); + private final TransactionProvider transactionProvider; public Get(YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient, - String netconfSessionIdForReporting) { + String netconfSessionIdForReporting, TransactionProvider transactionProvider) { super(configRegistryClient, netconfSessionIdForReporting); this.yangStoreSnapshot = yangStoreSnapshot; + this.transactionProvider = transactionProvider; } private Map> createModuleRuntimes(ConfigRegistryClient configRegistryClient, @@ -144,7 +148,9 @@ public class Get extends AbstractConfigNetconfOperation { final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs); - final Element element = runtime.toXml(runtimeBeans, configBeans, document); + ObjectName txOn = transactionProvider.getOrCreateTransaction(); + ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(txOn); + final Element element = runtime.toXml(runtimeBeans, configBeans, document, ta); logger.info("{} operation successful", XmlNetconfConstants.GET); 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 f2dfc7079c..d75cfd5d6f 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 @@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ge import com.google.common.base.Optional; import com.google.common.collect.Maps; import org.opendaylight.controller.config.util.ConfigRegistryClient; +import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -20,6 +21,7 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorT import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; @@ -83,7 +85,13 @@ public class GetConfig extends AbstractConfigNetconfOperation { final Config configMapping = new Config(transform(configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap())); - dataElement = configMapping.toXml(instances, this.maybeNamespace, document, dataElement); + + + ObjectName on = transactionProvider.getOrCreateTransaction(); + ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(on); + + Services serviceTracker = new Services(ta); + dataElement = configMapping.toXml(instances, this.maybeNamespace, document, dataElement, serviceTracker); logger.info("{} operation successful", GET_CONFIG); 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 ec1915d6fc..77c58501cd 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 @@ -56,7 +56,7 @@ final class NetconfOperationProvider { ops.add(new EditConfig(yangStoreSnapshot, transactionProvider, configRegistryClient, netconfSessionIdForReporting)); ops.add(new Commit(transactionProvider, configRegistryClient, netconfSessionIdForReporting)); - ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting)); + ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting, transactionProvider)); ops.add(new DiscardChanges(transactionProvider, configRegistryClient, netconfSessionIdForReporting)); ops.add(new Validate(transactionProvider, configRegistryClient, netconfSessionIdForReporting)); ops.add(new RuntimeRpc(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting)); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java index b8113a0903..0fa005e04a 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java @@ -137,13 +137,14 @@ public class TransactionProvider implements AutoCloseable { } /** - * Wiping means removing all module instances keeping the transaction open. + * Wiping means removing all module instances keeping the transaction open + service references. */ synchronized void wipeInternal(ObjectName taON, boolean isTest, String moduleName) { ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON); Set lookupConfigBeans = moduleName == null ? transactionClient.lookupConfigBeans() : transactionClient.lookupConfigBeans(moduleName); + int i = lookupConfigBeans.size(); for (ObjectName instance : lookupConfigBeans) { try { transactionClient.destroyModule(instance); @@ -156,7 +157,10 @@ public class TransactionProvider implements AutoCloseable { throw new IllegalStateException("Unable to clean configuration in transactiom " + taON, e); } } - logger.debug("Transaction {} wiped clean", taON); + logger.debug("Transaction {} wiped clean of {} config beans", taON, i); + + transactionClient.removeAllServiceReferences(); + logger.debug("Transaction {} wiped clean of all service references", taON); } public void wipeTransaction() { 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 f8916ecac2..ccb793149c 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 @@ -12,12 +12,15 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import org.apache.commons.lang3.StringUtils; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.matchers.JUnitMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; @@ -55,15 +58,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; import javax.management.ObjectName; import javax.xml.parsers.ParserConfigurationException; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -82,7 +88,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; public class NetconfMappingTest extends AbstractConfigTest { private static final Logger logger = LoggerFactory.getLogger(NetconfMappingTest.class); - private static final String INSTANCE_NAME = "test1"; + private static final String INSTANCE_NAME = "instance-from-code"; private static final String NETCONF_SESSION_ID = "foo"; private NetconfTestImplModuleFactory factory; private DepTestImplModuleFactory factory2; @@ -105,24 +111,99 @@ public class NetconfMappingTest extends AbstractConfigTest { transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID); } - private ObjectName createModule(final String instanceName) throws InstanceAlreadyExistsException { + private ObjectName createModule(final String instanceName) throws InstanceAlreadyExistsException, InstanceNotFoundException, URISyntaxException { final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction(); final ObjectName on = transaction.createModule(this.factory.getImplementationName(), instanceName); final NetconfTestImplModuleMXBean mxBean = transaction.newMXBeanProxy(on, NetconfTestImplModuleMXBean.class); - setModule(mxBean, transaction); + setModule(mxBean, transaction, instanceName + "_dep"); + int i = 1; + for (Class sInterface : factory.getImplementedServiceIntefaces()) { + ServiceInterfaceAnnotation annotation = sInterface.getAnnotation(ServiceInterfaceAnnotation.class); + transaction.saveServiceReference( + transaction.getServiceInterfaceName(annotation.namespace(), annotation.localName()), "ref_from_code_to_" + instanceName + "_" + i++, + on); + + } transaction.commit(); return on; } + @Test + public void testServicePersistance() throws Exception { + createModule(INSTANCE_NAME); + + edit("netconfMessages/editConfig.xml"); + Element config = getConfigCandidate(); + assertCorrectServiceNames(config, 6, "ref_test2", "user_to_instance_from_code", "ref_dep_user", + "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1", + "ref_from_code_to_instance-from-code_1"); + + edit("netconfMessages/editConfig_addServiceName.xml"); + config = getConfigCandidate(); + assertCorrectServiceNames(config, 7, "ref_test2", "user_to_instance_from_code", "ref_dep_user", + "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1", + "ref_from_code_to_instance-from-code_1", "ref_dep_user_another"); + + commit(); + config = getConfigRunning(); + assertCorrectRefNamesForDependencies(config); + assertCorrectServiceNames(config, 7, "ref_test2", "user_to_instance_from_code", "ref_dep_user", + "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1", + "ref_from_code_to_instance-from-code_1", "ref_dep_user_another"); + + edit("netconfMessages/editConfig_replace_default.xml"); + config = getConfigCandidate(); + assertCorrectServiceNames(config, 2, "ref_dep", "ref_dep2"); + + edit("netconfMessages/editConfig_remove.xml"); + config = getConfigCandidate(); + assertCorrectServiceNames(config, 0); + + commit(); + config = getConfigCandidate(); + assertCorrectServiceNames(config, 0); + + } + + private void assertCorrectRefNamesForDependencies(Element config) { + NodeList modulesList = config.getElementsByTagName("modules"); + assertEquals(1, modulesList.getLength()); + + Element modules = (Element) modulesList.item(0); + + String trimmedModules = XmlUtil.toString(modules).replaceAll("\\s", ""); + int defaultRefNameCount = StringUtils.countMatches(trimmedModules, "ref_dep2"); + int userRefNameCount = StringUtils.countMatches(trimmedModules, "ref_dep_user_two"); + + assertEquals(0, defaultRefNameCount); + assertEquals(2, userRefNameCount); + } + + private void assertCorrectServiceNames(Element configCandidate, int servicesSize, String... refNames) { + NodeList elements = configCandidate.getElementsByTagName("provider"); + assertEquals(servicesSize, elements.getLength()); + + NodeList servicesList = configCandidate.getElementsByTagName("services"); + assertEquals(1, servicesList.getLength()); + + Element services = (Element) servicesList.item(0); + String trimmedServices = XmlUtil.toString(services).replaceAll("\\s", ""); + + for (String s : refNames) { + assertThat(trimmedServices, JUnitMatchers.containsString(s)); + } + } + @Test public void testConfigNetconf() throws Exception { createModule(INSTANCE_NAME); edit("netconfMessages/editConfig.xml"); - checkBinaryLeafEdited(getConfigCandidate()); + Element configCandidate = getConfigCandidate(); + checkBinaryLeafEdited(configCandidate); // default-operation:none, should not affect binary leaf @@ -205,6 +286,7 @@ public class NetconfMappingTest extends AbstractConfigTest { return executeOp(getConfigOp, "netconfMessages/getConfig.xml"); } + @Ignore("second edit message corrupted") @Test(expected = NetconfDocumentedException.class) public void testConfigNetconfReplaceDefaultEx() throws Exception { @@ -394,7 +476,7 @@ public class NetconfMappingTest extends AbstractConfigTest { for (XmlElement moduleElement : modulesElement.getChildElements("module")) { String name = moduleElement.getOnlyChildElement("name").getTextContent(); - if(name.equals("test1")) { + if(name.equals(INSTANCE_NAME)) { XmlElement enumAttr = moduleElement.getOnlyChildElement(enumName); assertEquals(enumContent, enumAttr.getTextContent()); @@ -424,7 +506,8 @@ public class NetconfMappingTest extends AbstractConfigTest { } } - assertEquals("configAttributeType", configAttributeType.getTextContent()); + // TODO verify if should be default value + assertEquals("default-string", configAttributeType.getTextContent()); } private Map> getMbes() throws Exception { @@ -480,7 +563,7 @@ public class NetconfMappingTest extends AbstractConfigTest { } private Element get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException { - Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID); + Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID, transactionProvider); return executeOp(getOp, "netconfMessages/get.xml"); } @@ -516,8 +599,8 @@ public class NetconfMappingTest extends AbstractConfigTest { return Lists.newArrayList(yangDependencies); } - private void setModule(final NetconfTestImplModuleMXBean mxBean, final ConfigTransactionJMXClient transaction) - throws InstanceAlreadyExistsException { + private void setModule(final NetconfTestImplModuleMXBean mxBean, final ConfigTransactionJMXClient transaction, String depName) + throws InstanceAlreadyExistsException, InstanceNotFoundException { mxBean.setSimpleInt((long) 44); mxBean.setBinaryLeaf(new byte[] { 8, 7, 9 }); final DtoD dtob = getDtoD(); @@ -547,7 +630,15 @@ public class NetconfMappingTest extends AbstractConfigTest { mxBean.setComplexList(Lists. newArrayList()); mxBean.setSimpleList(Lists. newArrayList()); - final ObjectName testingDepOn = transaction.createModule(this.factory2.getImplementationName(), "dep"); + final ObjectName testingDepOn = transaction.createModule(this.factory2.getImplementationName(), depName); + int i = 1; + for (Class sInterface : factory2.getImplementedServiceIntefaces()) { + ServiceInterfaceAnnotation annotation = sInterface.getAnnotation(ServiceInterfaceAnnotation.class); + transaction.saveServiceReference( + transaction.getServiceInterfaceName(annotation.namespace(), annotation.localName()), "ref_from_code_to_" + depName + "_" + i++, + testingDepOn); + + } mxBean.setTestingDep(testingDepOn); } diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/ServiceTrackerTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/ServiceTrackerTest.java index 425ecf6d02..d5ba976ccf 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/ServiceTrackerTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/ServiceTrackerTest.java @@ -13,7 +13,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services.ServiceInstance; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; public class ServiceTrackerTest { @@ -28,44 +27,4 @@ public class ServiceTrackerTest { assertEquals(serviceInstance, serviceInstance2); } - @Test - public void testOneInstanceMultipleServices() { - Services services = new Services(); - services.addServiceEntry("nm", "s1", "module", "instance"); - assertEquals(1, services.getMappedServices().size()); - - services.addServiceEntry("nm2", "s2", "module", "instance"); - assertEquals(2, services.getMappedServices().size()); - } - - @Test - public void testMultipleInstancesOneName() throws Exception { - Services services = new Services(); - services.addServiceEntry("nm", "s1", "module", "instance"); - assertEquals(1, services.getMappedServices().size()); - - services.addServiceEntry("nm", "s1", "module2", "instance"); - assertEquals(1, services.getMappedServices().size()); - assertEquals(2, services.getMappedServices().get("nm").get("s1").size()); - assertTrue(services.getMappedServices().get("nm").get("s1").containsKey("ref_instance")); - assertTrue(services.getMappedServices().get("nm").get("s1").containsKey("ref_instance_1")); - } - - @Test - public void testMultipleInstancesOneName2() throws Exception { - Services services = new Services(); - services.addServiceEntry("nm", "s1", "module", "instance_1"); - - services.addServiceEntry("nm2", "s2", "module2", "instance"); - services.addServiceEntry("nm2", "s2", "module3", "instance"); - services.addServiceEntry("nm", "s1", "module3", "instance"); - - assertEquals(2, services.getMappedServices().get("nm").get("s1").size()); - assertEquals(2, services.getMappedServices().get("nm2").get("s2").size()); - assertTrue(services.getMappedServices().get("nm").get("s1").containsKey("ref_instance_2")); - assertTrue(services.getMappedServices().get("nm").get("s1").containsKey("ref_instance_1")); - assertTrue(services.getMappedServices().get("nm2").get("s2").containsKey("ref_instance")); - assertTrue(services.getMappedServices().get("nm2").get("s2").containsKey("ref_instance_2")); - } - } 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 1b8e24702a..6e7a225f38 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 @@ -16,24 +16,23 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; -import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved; +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.transactions.TransactionProvider; -import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import javax.management.ObjectName; import java.util.Collections; import java.util.Map; -import java.util.Set; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyMap; @@ -82,18 +81,11 @@ public class EditConfigTest { EditConfig edit = new EditConfig(yangStoreSnapshot, provider, configRegistry, ValidateTest.NETCONF_SESSION_ID_FOR_REPORTING); EditConfigStrategy editStrat = mock(EditConfigStrategy.class); - doNothing().when(editStrat).executeConfiguration(anyString(), anyString(), anyMap(), - any(ConfigTransactionClient.class)); - Map> resolvedXmlElements = getMapping(editStrat); - Config cfg = mock(Config.class); - XmlElement xmlElement = mock(XmlElement.class); - Set instancesForFillingServiceRefMapping = Collections.emptySet(); - EditStrategyType defaultStrategy = EditStrategyType.getDefaultStrategy(); - doReturn(resolvedXmlElements).when(cfg).fromXml(xmlElement, instancesForFillingServiceRefMapping, defaultStrategy); + doNothing().when(editStrat).executeConfiguration(anyString(), anyString(), anyMap(), + any(ConfigTransactionClient.class), any(Services.class)); - EditConfigExecution editConfigExecution = new EditConfigExecution(null, cfg, xmlElement, - EditConfigXmlParser.TestOption.testThenSet, instancesForFillingServiceRefMapping, defaultStrategy); + EditConfigExecution editConfigExecution = mockExecution(editStrat); edit.getResponseInternal(XmlUtil.newDocument(), editConfigExecution); @@ -105,7 +97,31 @@ public class EditConfigTest { // For every instance execute strat verify(editStrat, times(2/* Test */+ 2/* Set */)).executeConfiguration(anyString(), anyString(), anyMap(), - any(ConfigTransactionClient.class)); + any(ConfigTransactionClient.class), any(Services.class)); + } + + private EditConfigExecution mockExecution(EditConfigStrategy editStrat) { + EditConfigExecution mock = mock(EditConfigExecution.class); + doReturn(getMapping(editStrat)).when(mock).getResolvedXmlElements(); + doReturn(EditStrategyType.merge).when(mock).getDefaultStrategy(); + doReturn(true).when(mock).shouldSet(); + doReturn(true).when(mock).shouldTest(); + doReturn(mockServices()).when(mock).getServices(); + return mock; + } + + private static ServiceReferenceReadableRegistry mockServiceRegistry() { + ServiceReferenceReadableRegistry mock = mock(ServiceReferenceReadableRegistry.class); + doReturn( + Collections.emptyMap()) + .when(mock).getServiceMapping(); + doReturn("mockedServiceReg").when(mock).toString(); + + return mock; + } + + static Services mockServices() { + return new Services(mockServiceRegistry()); } private Map> getMapping(EditConfigStrategy editStrat) { diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategyTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategyTest.java index 704da6dc0d..78a2043e20 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategyTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategyTest.java @@ -48,7 +48,7 @@ public class ReplaceEditConfigStrategyTest { doReturn(Sets.newHashSet(mockON(), mockON())).when(ta).lookupConfigBeans(); - strat.executeConfiguration("m1", "i1", map, ta); + strat.executeConfiguration("m1", "i1", map, ta, EditConfigTest.mockServices()); verify(ta).lookupConfigBean(anyString(), anyString()); verify(ta).setAttribute(any(ObjectName.class), anyString(), any(Attribute.class)); diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml index 94b73f4b10..35cf2c6a14 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml @@ -11,7 +11,7 @@ - dep + instance-from-code_dep test-impl:impl-dep @@ -29,7 +29,7 @@ test-impl:impl-netconf - test1 + instance-from-code 2.58 @@ -91,16 +91,16 @@ prefix:testing - ref_dep + ref_dep_user prefix:testing - ref_dep + ref_dep_user prefix:testing - ref_dep_2 + ref_dep_user_two @@ -113,7 +113,7 @@ prefix:testing - ref_dep_2 + ref_dep_user_two @@ -122,19 +122,19 @@ prefix:testing - ref_dep - /modules/module[type='impl-dep'][name='dep'] + ref_dep_user + /modules/module[type='impl-dep'][name='instance-from-code_dep'] - ref_dep_2 + ref_dep_user_two /config/modules/module[name='impl-dep']/instance[name='dep2'] - ref_test1 + user_to_instance_from_code - /modules/module[type='impl-netconf'][name='test1'] + /modules/module[type='impl-netconf'][name='instance-from-code'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_addServiceName.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_addServiceName.xml new file mode 100644 index 0000000000..30be98e6b5 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_addServiceName.xml @@ -0,0 +1,34 @@ + + + + + + + set + + merge + + + + + instance-from-code_dep + + test-impl:impl-dep + + + + + + + + prefix:testing + + ref_dep_user_another + /modules/module[type='impl-dep'][name='instance-from-code_dep'] + + + + + + + diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_threadfactory.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_threadfactory.xml index ad7c84f3c9..25976707d4 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_threadfactory.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_threadfactory.xml @@ -1,4 +1,4 @@ - + @@ -22,6 +22,16 @@ + + + prefix:threadfactory + + user_to_instance_from_code + + /modules/module[type='threadfactory-naming'][name='threadfactory-naming-instance'] + + + diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml index b48730d3f7..a7f1c86391 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml @@ -8,7 +8,7 @@ - dep + instance-from-code_dep test-impl:impl-dep @@ -21,6 +21,7 @@ + test-impl:impl-netconf @@ -66,42 +67,16 @@ 456 44 - - prefix:testing - ref_dep - test-impl:impl-netconf test2 - - prefix:testing - ref_dep - + - - prefix:testing - - ref_dep - /modules/module[type='impl-dep'][name='dep'] - - - - ref_dep_2 - /modules/module[type='impl-dep'][name='dep2'] - - - - ref_test1 - - /modules/module[type='impl-netconf'][name='test1'] - - - diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_remove.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_remove.xml index 9d06d98f1c..e07f18cb51 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_remove.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_remove.xml @@ -6,6 +6,15 @@ none + + instance-from-code_dep + + test-impl:impl-dep + + + + dep @@ -27,7 +36,7 @@ test-impl:impl-netconf - test1 + instance-from-code - /modules/module[type='impl-netconf' and name='test1'] + /modules/module[type='impl-netconf' and name='instance-from-code'] testarg1 diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInner.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInner.xml index 3d5117e3bd..da9afd7bf1 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInner.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInner.xml @@ -1,7 +1,7 @@ - /modules/module[name='test1'][type='impl-netconf']/inner-running-data-additional[key='1'] + /modules/module[name='instance-from-code'][type='impl-netconf']/inner-running-data-additional[key='1'] diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner_complex_output.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner_complex_output.xml index 4ba0349f9b..a5b83e6db6 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner_complex_output.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner_complex_output.xml @@ -2,7 +2,7 @@ - /modules/module[type='impl-netconf'][name='test1']/inner-running-data[key='0']/inner-inner-running-data[key='1'] + /modules/module[type='impl-netconf'][name='instance-from-code']/inner-running-data[key='0']/inner-inner-running-data[key='1']