From: Tony Tkacik Date: Thu, 5 Mar 2015 09:15:26 +0000 (+0000) Subject: Merge "Fixed discard-changes for mdsal netconf, mapping code cleanup." X-Git-Tag: release/lithium~453 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=f78b7f15e24efdb5dd9f91b487bc63dad7517b1c;hp=0a47323940b1fc2ba3d200baafcc85e51bf023d7 Merge "Fixed discard-changes for mdsal netconf, mapping code cleanup." --- diff --git a/opendaylight/netconf/mdsal-netconf-connector/pom.xml b/opendaylight/netconf/mdsal-netconf-connector/pom.xml index 2808672ca2..8b3b196049 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/pom.xml +++ b/opendaylight/netconf/mdsal-netconf-connector/pom.xml @@ -59,7 +59,6 @@ org.opendaylight.yangtools yang-data-operations - 0.7.0-SNAPSHOT diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java index 15396cfbf8..5a980c44d3 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java @@ -37,7 +37,7 @@ public class Commit extends AbstractLastNetconfOperation{ protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { boolean commitStatus = transactionProvider.commitTransaction(); - LOG.trace("Transaction commited succesfuly", commitStatus); + LOG.trace("Transaction commited succesfuly {}", commitStatus); return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); } diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java index 36f6d8e3cf..b47bb18434 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java @@ -40,7 +40,6 @@ public class DiscardChanges extends AbstractLastNetconfOperation{ @Override protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { - operationElement.getOnlyChildElement(OPERATION_NAME); try { transactionProvider.abortTransaction(); diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java index 09be4163df..aebdfd9baf 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java @@ -23,9 +23,12 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorT import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext; import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException; import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.opendaylight.yangtools.yang.data.api.ModifyAction; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; @@ -51,6 +54,9 @@ public class EditConfig extends AbstractLastNetconfOperation { private static final String OPERATION_NAME = "edit-config"; private static final String CONFIG_KEY = "config"; + private static final String TARGET_KEY = "target"; + private static final String DEFAULT_OPERATION_KEY = "default-operation"; + private final CurrentSchemaContext schemaContext; private final TransactionProvider transactionProvider; @@ -63,7 +69,17 @@ public class EditConfig extends AbstractLastNetconfOperation { @Override protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { - final XmlElement configElement = getConfigElement(operationElement); + final Datastore targetDatastore = extractTargetParameter(operationElement); + if (targetDatastore == Datastore.running) { + throw new NetconfDocumentedException("edit-config on running datastore is not supported", + ErrorType.protocol, + ErrorTag.operation_not_supported, + ErrorSeverity.error); + } + + final ModifyAction defaultAction = getDefaultOperation(operationElement); + + final XmlElement configElement = getElement(operationElement, CONFIG_KEY); for (XmlElement element : configElement.getChildElements()) { final String ns = element.getNamespace(); @@ -72,22 +88,19 @@ public class EditConfig extends AbstractLastNetconfOperation { final NormalizedNode storedNode = readStoredNode(LogicalDatastoreType.CONFIGURATION, ident); try { - final Optional> newNode = modifyNode(schemaNode, element, storedNode); + final Optional> newNode = modifyNode(schemaNode, element, storedNode, defaultAction); final DOMDataReadWriteTransaction rwTx = transactionProvider.getOrCreateTransaction(); if (newNode.isPresent()) { rwTx.put(LogicalDatastoreType.CONFIGURATION, ident, newNode.get()); } else { rwTx.delete(LogicalDatastoreType.CONFIGURATION, ident); } + } catch (final DataExistsException e) { + throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.data_exists, ErrorSeverity.error); + } catch (final DataMissingException e) { + throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.data_missing, ErrorSeverity.error); } catch (final DataModificationException e) { - if (e instanceof DataExistsException) { - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.data_exists, ErrorSeverity.error); - } else if (e instanceof DataMissingException) { - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.data_missing, ErrorSeverity.error); - } else { - //should never happen, since in edit-config only the 2 previous cases can happen - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.operation_failed, ErrorSeverity.error); - } + throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.operation_failed, ErrorSeverity.error); } } @@ -102,23 +115,32 @@ public class EditConfig extends AbstractLastNetconfOperation { final NormalizedNode node = readFuture.checkedGet().get(); return node; } else { - LOG.warn("Unable to read node : {} from {} datastore", path, logicalDatastoreType); + LOG.debug("Unable to read node : {} from {} datastore", path, logicalDatastoreType); } } catch (final ReadFailedException e) { //only log this since DataOperations.modify will handle throwing an exception or writing the node. - LOG.warn("Unable to read stored data: {}", path, e); + LOG.debug("Unable to read stored data: {}", path, e); } //we can return null here since DataOperations.modify handles null as input return null; } - private Optional getSchemaNodeFromNamespace(final String namespace, final XmlElement element){ + private Optional getSchemaNodeFromNamespace(final String namespace, final XmlElement element) throws NetconfDocumentedException{ Optional dataSchemaNode = Optional.absent(); try { //returns module with newest revision since findModuleByNamespace returns a set of modules and we only need the newest one final Module module = schemaContext.getCurrentContext().findModuleByNamespaceAndRevision(new URI(namespace), null); - dataSchemaNode = Optional.of(module.getDataChildByName(element.getName())); + DataSchemaNode schemaNode = module.getDataChildByName(element.getName()); + if (schemaNode != null) { + dataSchemaNode = Optional.of(module.getDataChildByName(element.getName())); + } else { + throw new NetconfDocumentedException("Unable to find node with namespace: " + namespace + "in module: " + module.toString(), + ErrorType.application, + ErrorTag.unknown_namespace, + ErrorSeverity.error); + } + } catch (URISyntaxException e) { LOG.debug("Unable to create URI for namespace : {}", namespace); } @@ -126,7 +148,7 @@ public class EditConfig extends AbstractLastNetconfOperation { return dataSchemaNode; } - private Optional> modifyNode(final DataSchemaNode schemaNode, final XmlElement element, final NormalizedNode storedNode) throws DataModificationException{ + private Optional> modifyNode(final DataSchemaNode schemaNode, final XmlElement element, final NormalizedNode storedNode, final ModifyAction defaultAction) throws DataModificationException{ if (schemaNode instanceof ContainerSchemaNode) { final ContainerNode modifiedNode = DomToNormalizedNodeParserFactory @@ -134,7 +156,7 @@ public class EditConfig extends AbstractLastNetconfOperation { .getContainerNodeParser() .parse(Collections.singletonList(element.getDomElement()), (ContainerSchemaNode) schemaNode); - final Optional oNode = DataOperations.modify((ContainerSchemaNode) schemaNode, (ContainerNode) storedNode, modifiedNode); + final Optional oNode = DataOperations.modify((ContainerSchemaNode) schemaNode, (ContainerNode) storedNode, modifiedNode, defaultAction); if (!oNode.isPresent()) { return Optional.absent(); } @@ -148,7 +170,7 @@ public class EditConfig extends AbstractLastNetconfOperation { .getMapNodeParser() .parse(Collections.singletonList(element.getDomElement()), (ListSchemaNode) schemaNode); - final Optional oNode = DataOperations.modify((ListSchemaNode) schemaNode, (MapNode) storedNode, modifiedNode); + final Optional oNode = DataOperations.modify((ListSchemaNode) schemaNode, (MapNode) storedNode, modifiedNode, defaultAction); if (!oNode.isPresent()) { return Optional.absent(); } @@ -163,16 +185,44 @@ public class EditConfig extends AbstractLastNetconfOperation { } - private XmlElement getConfigElement(final XmlElement operationElement) throws NetconfDocumentedException{ - final Optional configChildNode = operationElement.getOnlyChildElementOptionally(CONFIG_KEY); - if (!configChildNode.isPresent()) { - throw new NetconfDocumentedException("Can't get child element with name: " + CONFIG_KEY, - ErrorType.application, - ErrorTag.unknown_element, + private Datastore extractTargetParameter(final XmlElement operationElement) throws NetconfDocumentedException { + final XmlElement targetChildNode; + try { + final XmlElement targetElement = operationElement.getOnlyChildElementWithSameNamespace(TARGET_KEY); + targetChildNode = targetElement.getOnlyChildElementWithSameNamespace(); + } catch (final MissingNameSpaceException | UnexpectedNamespaceException e) { + LOG.trace("Can't get only child element with same namespace", e); + throw NetconfDocumentedException.wrap(e); + } + + return Datastore.valueOf(targetChildNode.getName()); + } + + private ModifyAction getDefaultOperation(final XmlElement operationElement) throws NetconfDocumentedException{ + try { + return ModifyAction.fromXmlValue(getElement(operationElement, DEFAULT_OPERATION_KEY).getTextContent()); + } catch (NetconfDocumentedException e) { + if (e.getErrorType() == ErrorType.protocol + && e.getErrorSeverity() == ErrorSeverity.error + && e.getErrorTag() == ErrorTag.missing_element) { + return ModifyAction.MERGE; + } + else { + throw e; + } + } + } + + private XmlElement getElement(final XmlElement operationElement, String elementName) throws NetconfDocumentedException { + final Optional childNode = operationElement.getOnlyChildElementOptionally(elementName); + if (!childNode.isPresent()) { + throw new NetconfDocumentedException(elementName + " element is missing", + ErrorType.protocol, + ErrorTag.missing_element, ErrorSeverity.error); } - return configChildNode.get(); + return childNode.get(); } @Override diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java index 8f6ff417d6..4253591fee 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java @@ -32,7 +32,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -57,7 +56,6 @@ public abstract class AbstractGet extends AbstractLastNetconfOperation { } protected Node transformNormalizedNode(final Document document, final NormalizedNode data, final YangInstanceIdentifier dataRoot) { -// boolean isDataRoot = true; final DOMResult result = new DOMResult(document.createElement(XmlNetconfConstants.DATA_KEY)); @@ -68,17 +66,7 @@ public abstract class AbstractGet extends AbstractLastNetconfOperation { final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter); -// if (isDataRoot) { writeRootElement(xmlWriter, nnWriter, (ContainerNode) data); -// } else { -// if (data instanceof MapEntryNode) { -// // Restconf allows returning one list item. We need to wrap it -// // in map node in order to serialize it properly -// data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).addChild((MapEntryNode) data).build(); -// } -// nnWriter.write(data); -// nnWriter.flush(); -// } return result.getNode(); } @@ -104,7 +92,6 @@ public abstract class AbstractGet extends AbstractLastNetconfOperation { // TODO this code is located in Restconf already private void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data) { try { - final QName name = SchemaContext.NAME; for (final DataContainerChild child : data.getValue()) { nnWriter.write(child); } diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java index cebd8c8883..b62734baf0 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java @@ -42,14 +42,6 @@ public class Get extends AbstractGet { @Override protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException { - GetConfigExecution getConfigExecution = null; - try { - getConfigExecution = GetConfigExecution.fromXml(operationElement, OPERATION_NAME); - - } catch (final NetconfDocumentedException e) { - LOG.warn("Get request processing failed on session: {}", getNetconfSessionIdForReporting(), e); - throw e; - } final YangInstanceIdentifier dataRoot = ROOT; DOMDataReadWriteTransaction rwTx = getTransaction(Datastore.running); diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java index f2d8abbb61..6eb94f2f1e 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java @@ -61,7 +61,6 @@ public class GetConfig extends AbstractGet { final Optional> normalizedNodeOptional = rwTx.read(LogicalDatastoreType.CONFIGURATION, dataRoot).checkedGet(); if (getConfigExecution.getDatastore().get() == Datastore.running) { transactionProvider.abortRunningTransaction(rwTx); - rwTx = null; } return (Element) transformNormalizedNode(document, normalizedNodeOptional.get(), dataRoot); } catch (ReadFailedException e) { diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java index 8b2c02bcd4..fb0d3448a3 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java @@ -37,6 +37,7 @@ public class DefaultCommit extends AbstractNetconfOperation { private static final String NOTIFY_ATTR = "notify"; + //TODO make commit notification optional private final CommitNotifier notificationProducer; private final NetconfMonitoringService cap; private final NetconfOperationRouter operationRouter;