Created reference names under services/ subtree are now persisted and available for further edit-config operations.
Change-Id: I366eaab457e9264d266e16eb4e1a1ad8d97d33bc
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
--- /dev/null
+/**
+ * @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";
+}
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;
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.<String> absent())
+ : tracker.getRefName(namespace, serviceName, on, Optional.of(expectedRefName));
return Optional.of(new MappedDependency(namespace, serviceName, refName));
}
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;
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);
}
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;
}
public static Map<String, Map<String, Collection<ObjectName>>> getMappedInstances(Set<ObjectName> instancesToMap,
- Services serviceTracker, Map<String, Map<String, ModuleConfig>> configs) {
+ Map<String, Map<String, ModuleConfig>> configs) {
Multimap<String, ObjectName> moduleToInstances = mapInstancesToModules(instancesToMap);
Map<String, Map<String, Collection<ObjectName>>> retVal = Maps.newLinkedHashMap();
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);
return retVal;
}
- private static void addServices(Services serviceTracker, Collection<ObjectName> instances,
- Multimap<String, String> providedServices) {
- for (ObjectName instanceOn : instances) {
- for (Entry<String, String> serviceName : providedServices.entries()) {
- serviceTracker.addServiceEntry(serviceName.getKey(), serviceName.getValue(), instanceOn);
- }
- }
- }
-
private static Multimap<String, ObjectName> mapInstancesToModules(Set<ObjectName> instancesToMap) {
Multimap<String, ObjectName> retVal = HashMultimap.create();
// }
public Element toXml(Set<ObjectName> instancesToMap, Optional<String> maybeNamespace, Document document,
- Element dataElement) {
- Services serviceTracker = new Services();
+ Element dataElement, Services serviceTracker) {
Map<String, Map<String, Collection<ObjectName>>> moduleToInstances = getMappedInstances(instancesToMap,
- serviceTracker, moduleConfigs);
+ moduleConfigs);
Element root = dataElement;
if (maybeNamespace.isPresent()) {
// TODO refactor, replace string representing namespace with namespace class
// TODO refactor, replace Map->Multimap with e.g. ConfigElementResolved
// class
- public Map<String, Multimap<String, ModuleElementResolved>> fromXml(XmlElement xml, Set<ObjectName> instancesForFillingServiceRefMapping,
- EditStrategyType defaultEditStrategyType) {
+ public ConfigElementResolved fromXml(XmlElement xml,
+ EditStrategyType defaultEditStrategyType, ServiceReferenceReadableRegistry taClient) {
Map<String, Multimap<String, ModuleElementResolved>> retVal = Maps.newHashMap();
List<XmlElement> recognisedChildren = Lists.newArrayList();
- Services serviceTracker = fromXmlServices(xml, recognisedChildren, instancesForFillingServiceRefMapping);
+ Services serviceTracker = fromXmlServices(xml, recognisedChildren, taClient);
List<XmlElement> moduleElements = fromXmlModules(xml, recognisedChildren);
xml.checkUnrecognisedElements(recognisedChildren);
resolveModule(retVal, serviceTracker, moduleElement, defaultEditStrategyType);
}
- return retVal;
+ return new ConfigElementResolved(retVal, serviceTracker);
+ }
+
+ public static class ConfigElementResolved {
+
+ private final Map<String, Multimap<String, ModuleElementResolved>> resolvedModules;
+ private final Services services;
+
+ public ConfigElementResolved(Map<String, Multimap<String, ModuleElementResolved>> retVal, Services serviceTracker) {
+ this.resolvedModules = retVal;
+ this.services = serviceTracker;
+ }
+
+ public Map<String, Multimap<String, ModuleElementResolved>> getResolvedModules() {
+ return resolvedModules;
+ }
+
+ public Services getServices() {
+ return services;
+ }
}
private List<XmlElement> fromXmlModules(XmlElement xml, List<XmlElement> recognisedChildren) {
innerMap.put(factoryName, moduleElementResolved);
}
- private Services fromXmlServices(XmlElement xml, List<XmlElement> recognisedChildren, Set<ObjectName> instancesForFillingServiceRefMapping) {
+ private Services fromXmlServices(XmlElement xml, List<XmlElement> recognisedChildren,
+ ServiceReferenceReadableRegistry taClient) {
Optional<XmlElement> servicesElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.SERVICES_KEY,
XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_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<String> services = ;
- for (Entry<String, String> serviceName : moduleConfig.getProvidedServices().entries()) {
-
- services.addServiceEntry(serviceName.getKey(), serviceName.getValue(), existingON);
- }
- }
+ Services services = Services.resolveServices(mappedServices, taClient);
return services;
}
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;
}
public InstanceConfigElementResolved fromXml(XmlElement moduleElement, Services services, String moduleNamespace,
- EditStrategyType defaultStrategy) {
+ EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig);
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;
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;
private final EditStrategyType editStrategy;
private final Map<String, AttributeConfigElement> configuration;
+ private final Multimap<String, String> providedServices;
- public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy) {
+ public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
EditStrategyType valueOf = checkStrategy(currentStrategy, defaultStrategy);
this.editStrategy = valueOf;
this.configuration = configuration;
+ this.providedServices = providedServices;
}
- public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy) {
+ public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
editStrategy = defaultStrategy;
this.configuration = configuration;
+ this.providedServices = providedServices;
}
public EditConfigStrategy getEditStrategy() {
- return editStrategy.getFittingStrategy();
+ return editStrategy.getFittingStrategy(providedServices);
}
public Map<String, AttributeConfigElement> getConfiguration() {
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);
}
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;
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;
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";
private long suffix = 1;
- private final Map<ServiceInstance, String> instanceToRef = Maps.newHashMap();
private final Map<String /*Namespace*/, Map<String/* ServiceName */, Map<String/* refName */, ServiceInstance>>> 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<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
- Map<String, Map<String, ServiceInstance>> serviceNameToRefNameToInstance = namespaceToServiceNameToRefNameToInstance.get(namespace);
- if (serviceNameToRefNameToInstance == null) {
- serviceNameToRefNameToInstance = Maps.newHashMap();
- namespaceToServiceNameToRefNameToInstance.put(namespace, serviceNameToRefNameToInstance);
- }
+ Map<String, String> refNameToInstance;
+ if(serviceNameToRefNameToInstance == null || serviceNameToRefNameToInstance.containsKey(serviceName) == false) {
+ refNameToInstance = Collections.emptyMap();
+ } else
+ refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
- Map<String, ServiceInstance> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
- if (refNameToInstance == null) {
- refNameToInstance = Maps.newHashMap();
- serviceNameToRefNameToInstance.put(serviceName, refNameToInstance);
+ final Set<String> 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<String> 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<String> toSet(Collection<String> values) {
}
public ServiceInstance getByServiceAndRefName(String namespace, String serviceName, String refName) {
- Map<String, Map<String, ServiceInstance>> serviceNameToRefNameToInstance = namespaceToServiceNameToRefNameToInstance.get(namespace);
- Preconditions.checkArgument(serviceNameToRefNameToInstance != null, "No serviceInstances mapped to " + namespace + " , "
- + serviceNameToRefNameToInstance.keySet());
+ Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
+
+ Preconditions.checkArgument(serviceNameToRefNameToInstance != null, "No serviceInstances mapped to " + namespace);
- Map<String, ServiceInstance> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
+ Map<String, String> 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;
for (String serviceName : serviceNameToRefNameToInstance.keySet()) {
- Map<String, String> innerInnerRetVal = Maps.transformValues(
- serviceNameToRefNameToInstance.get(serviceName), new Function<ServiceInstance, String>() {
- @Nullable
- @Override
- public String apply(@Nullable ServiceInstance serviceInstance) {
- return serviceInstance.toString();
- }
- });
+ Map<String, String> innerInnerRetVal = Maps.newHashMap();
+ for (Entry<String, ServiceInstance> refNameToSi : serviceNameToRefNameToInstance.get(serviceName).entrySet()) {
+ innerInnerRetVal.put(refNameToSi.getKey(), refNameToSi.getValue().toString());
+ }
innerRetVal.put(serviceName, innerInnerRetVal);
}
retVal.put(namespace, innerRetVal);
}
+ Map<String, Map<String, ObjectName>> 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<String, Map<String, String>> serviceToRefs = retVal.get(namespace);
+ if(serviceToRefs==null) {
+ serviceToRefs = Maps.newHashMap();
+ retVal.put(namespace, serviceToRefs);
+ }
+
+ Map<String, String> 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<String, Map<String, Map<String, ServiceInstance>>> getNamespaceToServiceNameToRefNameToInstance() {
+ return namespaceToServiceNameToRefNameToInstance;
+ }
+
// TODO hide resolveServices, call it explicitly in fromXml
- public static Services resolveServices(Map<String, Map<String, Map<String, String>>> mappedServices) {
- Services tracker = new Services();
+ public static Services resolveServices(Map<String, Map<String, Map<String, String>>> mappedServices, ServiceReferenceReadableRegistry taClient) {
+ Services tracker = new Services(taClient);
for (Entry<String, Map<String, Map<String, String>>> namespaceEntry : mappedServices.entrySet()) {
String namespace = namespaceEntry.getKey();
}
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<String, Map<String, Map<String, String>>> fromXml(XmlElement xml) {
Map<String, Map<String, Map<String, String>>> retVal = Maps.newHashMap();
return root;
}
+ public String getRefName(String namespace, String serviceName, ObjectName on, Optional<String> expectedRefName) {
+ Optional<String> 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<String> getRefNameOptional(String namespace, String serviceName, ObjectName on,
+ Optional<String> expectedRefName) {
+ Map<String, Map<String, String>> services = getMappedServices().get(namespace);
+
+ if(services == null) return Optional.absent();
+ Map<String, String> refs = services.get(serviceName);
+
+ if(refs == null) return Optional.absent();
+ Multimap<ServiceInstance, String> reverted = revertMap(refs);
+
+ ServiceInstance serviceInstance = ServiceInstance.fromObjectName(on);
+ Collection<String> 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<ServiceInstance, String> revertMap(Map<String, String> refs) {
+ Multimap<ServiceInstance, String> multimap = HashMultimap.create();
+
+ for (Entry<String, String> 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.<String>absent()).isPresent();
+ }
+
public static final class ServiceInstance {
public ServiceInstance(String moduleName, String instanceName) {
this.moduleName = moduleName;
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));
+ }
}
}
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;
return retVal;
}
- public Element toXml(Set<ObjectName> instancesToMap, Set<ObjectName> configBeans, Document document) {
- Services serviceTracker = new Services();
+ public Element toXml(Set<ObjectName> instancesToMap, Set<ObjectName> configBeans, Document document, ServiceReferenceReadableRegistry serviceRegistry) {
+ Services serviceTracker = new Services(serviceRegistry);
Element root = document.createElement(XmlNetconfConstants.DATA_KEY);
Map<String, Multimap<String, ObjectName>> moduleToRuntimeInstance = mapInstancesToModules(instancesToMap);
Map<String, Map<String, Collection<ObjectName>>> moduleToConfigInstance = Config.getMappedInstances(
- configBeans, serviceTracker, moduleConfigs);
+ configBeans, moduleConfigs);
for (String localNamespace : moduleConfigs.keySet()) {
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<String, AttributeConfigElement> 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<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- String module, String instance);
+ String module, String instance, Services services);
abstract void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- ObjectName objectName);
+ ObjectName objectName, Services services);
}
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<String, String> providedServices;
+
+ public DeleteEditConfigStrategy() {
+ this.providedServices = HashMultimap.create();
+ }
+
+ public DeleteEditConfigStrategy(Multimap<String, String> providedServices) {
+ this.providedServices = providedServices;
+ }
+
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> 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<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on) {
+ void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, Services services) {
try {
ta.destroyModule(on);
logger.debug("ServiceInstance {} deleted successfully", on);
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;
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;
@VisibleForTesting
Element getResponseInternal(final Document document,
final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
+
if (editConfigExecution.shouldTest()) {
executeTests(configRegistryClient, editConfigExecution);
}
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<String, String> errorInfo = new HashMap<>();
}
private void test(ConfigRegistryClient configRegistryClient,
- Map<String, Multimap<String, ModuleElementResolved>> resolvedModules, EditStrategyType editStrategyType) {
+ EditConfigExecution execution, EditStrategyType editStrategyType) {
ObjectName taON = transactionProvider.getTestTransaction();
try {
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);
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<String, Map<String, Map<String, Services.ServiceInstance>>> namespaceToServiceNameToRefNameToInstance = services
+ .getNamespaceToServiceNameToRefNameToInstance();
+
+ for (String serviceNamespace : namespaceToServiceNameToRefNameToInstance.keySet()) {
+ for (String serviceName : namespaceToServiceNameToRefNameToInstance.get(serviceNamespace).keySet()) {
+
+ String qnameOfService = getQname(ta, serviceNamespace, serviceName);
+ Map<String, Services.ServiceInstance> 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<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements, ObjectName taON) {
+ Map<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements, Services services, ObjectName taON) {
ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON);
for (Multimap<String, ModuleElementResolved> modulesToResolved : resolvedXmlElements.values()) {
InstanceConfigElementResolved ice = moduleElementResolved.getInstanceConfigElementResolved();
EditConfigStrategy strategy = ice.getEditStrategy();
- strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta);
+ strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta, services);
}
}
}
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<String, AttributeConfigElement> configuration,
- ConfigTransactionClient ta);
+ ConfigTransactionClient ta, Services services);
}
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;
import javax.management.ObjectName;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Map;
-import java.util.Set;
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);
logger.trace("Setting merge strategy to {}", mergeStrategyString);
editStrategyType = EditStrategyType.valueOf(mergeStrategyString);
}
- Set<ObjectName> 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
@VisibleForTesting
static class EditConfigExecution {
- private final XmlElement editConfigXml;
+
private final Map<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements;
private final TestOption testOption;
private final EditStrategyType defaultEditStrategyType;
+ private final Services services;
- EditConfigExecution(XmlElement xml, Config configResolver, XmlElement configElement, TestOption testOption, Set<ObjectName> 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;
}
EditStrategyType getDefaultStrategy() {
return defaultEditStrategyType;
}
+
+ Services getServices() {
+ return services;
+ }
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
+import com.google.common.collect.Multimap;
+
import java.util.EnumSet;
import java.util.Set;
}
}
- public EditConfigStrategy getFittingStrategy() {
+ public EditConfigStrategy getFittingStrategy(Multimap<String, String> 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:
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<String, String> providedServices;
+
+ public MergeEditConfigStrategy() {
+ this.providedServices = HashMultimap.create();
+ }
+
+ public MergeEditConfigStrategy(Multimap<String, String> providedServices) {
+ this.providedServices = providedServices;
+ }
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> 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<String, String> providedServices, String module,
+ String instance, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
+ for (Entry<String, String> 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<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on) {
+ void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, Services services) {
for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
try {
AttributeConfigElement ace = configAttributeEntry.getValue();
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;
@Override
public void executeConfiguration(String module, String instance, Map<String, AttributeConfigElement> configuration,
- ConfigTransactionClient ta) {
+ ConfigTransactionClient ta, Services services) {
logger.debug("Skipping configuration element for {}:{}", module, instance);
}
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;
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- String module, String instance) {
+ String module, String instance, Services services) {
logger.warn("Unable to delete {}:{}, ServiceInstance not found", module, instance);
}
}
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<String, String> providedServices;
+
+ public ReplaceEditConfigStrategy() {
+ this.providedServices = HashMultimap.create();
+ }
+
+ public ReplaceEditConfigStrategy(Multimap<String, String> providedServices) {
+ this.providedServices = providedServices;
+ }
+
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> 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<String, String> providedServices, String module,
+ String instance, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
+ for (Entry<String, String> 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<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on) {
+ void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, Services services) {
for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
try {
AttributeConfigElement ace = configAttributeEntry.getValue();
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;
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;
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<String, Map<String, ModuleRuntime>> createModuleRuntimes(ConfigRegistryClient configRegistryClient,
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);
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;
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;
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);
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));
}
/**
- * 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<ObjectName> lookupConfigBeans = moduleName == null ? transactionClient.lookupConfigBeans()
: transactionClient.lookupConfigBeans(moduleName);
+ int i = lookupConfigBeans.size();
for (ObjectName instance : lookupConfigBeans) {
try {
transactionClient.destroyModule(instance);
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() {
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;
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;
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;
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<? extends AbstractServiceInterface> 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
return executeOp(getConfigOp, "netconfMessages/getConfig.xml");
}
+ @Ignore("second edit message corrupted")
@Test(expected = NetconfDocumentedException.class)
public void testConfigNetconfReplaceDefaultEx() throws Exception {
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());
}
}
- assertEquals("configAttributeType", configAttributeType.getTextContent());
+ // TODO verify if should be default value
+ assertEquals("default-string", configAttributeType.getTextContent());
}
private Map<String, Map<String, ModuleMXBeanEntry>> getMbes() throws Exception {
}
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");
}
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();
mxBean.setComplexList(Lists.<ComplexList> newArrayList());
mxBean.setSimpleList(Lists.<Integer> newArrayList());
- final ObjectName testingDepOn = transaction.createModule(this.factory2.getImplementationName(), "dep");
+ final ObjectName testingDepOn = transaction.createModule(this.factory2.getImplementationName(), depName);
+ int i = 1;
+ for (Class<? extends AbstractServiceInterface> 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);
}
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 {
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"));
- }
-
}
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;
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<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements = getMapping(editStrat);
- Config cfg = mock(Config.class);
- XmlElement xmlElement = mock(XmlElement.class);
- Set<ObjectName> 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);
// 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<String, Multimap<String, ModuleElementResolved>> getMapping(EditConfigStrategy editStrat) {
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));
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<module>
- <name>dep</name>
+ <name>instance-from-code_dep</name>
<type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
test-impl:impl-dep
</type>
test-impl:impl-netconf
</type>
- <name>test1</name>
+ <name>instance-from-code</name>
<sleep-factor>
2.58
</peers>
<testing-dep>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
+ <name>ref_dep_user</name>
</testing-dep>
<testing-deps>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
+ <name>ref_dep_user</name>
</testing-deps>
<testing-deps>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep_2</name>
+ <name>ref_dep_user_two</name>
</testing-deps>
</module>
<testing-dep>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep_2</name>
+ <name>ref_dep_user_two</name>
</testing-dep>
</module>
</modules>
<service>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
<instance>
- <name>ref_dep</name>
- <provider>/modules/module[type='impl-dep'][name='dep']
+ <name>ref_dep_user</name>
+ <provider>/modules/module[type='impl-dep'][name='instance-from-code_dep']
</provider>
</instance>
<instance>
- <name>ref_dep_2</name>
+ <name>ref_dep_user_two</name>
<provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
</provider>
</instance>
<instance>
- <name>ref_test1</name>
+ <name>user_to_instance_from_code</name>
<provider>
- /modules/module[type='impl-netconf'][name='test1']
+ /modules/module[type='impl-netconf'][name='instance-from-code']
</provider>
</instance>
</service>
--- /dev/null
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <test-option>
+ set
+ </test-option>
+ <default-operation>merge</default-operation>
+ <config>
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+ <module>
+ <name>instance-from-code_dep</name>
+ <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ test-impl:impl-dep
+ </type>
+ </module>
+
+ </modules>
+
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <instance>
+ <name>ref_dep_user_another</name>
+ <provider>/modules/module[type='impl-dep'][name='instance-from-code_dep']
+ </provider>
+ </instance>
+ </service>
+ </services>
+ </config>
+ </edit-config>
+</rpc>
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8" ?>
<rpc message-id="6"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
</name-prefix>
</module>
</modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">prefix:threadfactory</type>
+ <instance>
+ <name>user_to_instance_from_code</name>
+ <provider>
+ /modules/module[type='threadfactory-naming'][name='threadfactory-naming-instance']</provider>
+ </instance>
+ </service>
+ </services>
</config>
</edit-config>
</rpc>
<config>
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<module>
- <name>dep</name>
+ <name>instance-from-code_dep</name>
<type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
test-impl:impl-dep
</type>
</type>
</module>
+
<module>
<type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
test-impl:impl-netconf
<simple-int3>456</simple-int3>
<core-size>44</core-size>
</peers>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
</module>
<module>
<type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
test-impl:impl-netconf
</type>
<name>test2</name>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
</module>
</modules>
+
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <service>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <instance>
- <name>ref_dep</name>
- <provider>/modules/module[type='impl-dep'][name='dep']
- </provider>
- </instance>
- <instance>
- <name>ref_dep_2</name>
- <provider>/modules/module[type='impl-dep'][name='dep2']
- </provider>
- </instance>
- <instance>
- <name>ref_test1</name>
- <provider>
- /modules/module[type='impl-netconf'][name='test1']
- </provider>
- </instance>
- </service>
</services>
</config>
</edit-config>
<default-operation>none</default-operation>
<config>
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+ nc:operation="remove">
+ <name>instance-from-code_dep</name>
+ <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ test-impl:impl-dep
+ </type>
+ </module>
+
+
<module xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
nc:operation="remove">
<name>dep</name>
<type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
test-impl:impl-netconf
</type>
- <name>test1</name>
+ <name>instance-from-code</name>
</module>
<module xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<no-arg xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- <context-instance>/modules/module[type='impl-netconf' and name='test1']</context-instance>
+ <context-instance>/modules/module[type='impl-netconf' and name='instance-from-code']</context-instance>
<arg1>
testarg1
</arg1>
<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<noArgInner xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
<context-instance>
- /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']
</context-instance>
</noArgInner>
</rpc>
<leaf-list-output
xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
<context-instance>
- /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']
</context-instance>
</leaf-list-output>
</rpc>