X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Frestconf%2Fimpl%2FBrokerFacade.java;h=95fb9a4826d2b6c5115c31d6dfff066b9a0b4af5;hp=be24fd26dd416f7d69838121cb7bf4f7ae2fdb0e;hb=531621aac4cff9d39cbd8668a53bdeba8a0e6d81;hpb=eb887b1c2c8cd2768f8b4c2ed2b5054f97798466 diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java index be24fd26dd..95fb9a4826 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java @@ -13,12 +13,19 @@ import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastor import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.ListenableFuture; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import javax.ws.rs.core.Response.Status; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction; @@ -34,6 +41,7 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -94,15 +102,17 @@ public class BrokerFacade { public CheckedFuture commitConfigurationDataPut( final YangInstanceIdentifier path, final NormalizedNode payload) { checkPreconditions(); - return putDataViaTransaction(domDataBroker.newWriteOnlyTransaction(), CONFIGURATION, path, payload); + DataNormalizationOperation rootOp = ControllerContext.getInstance().getRootOperation(); + return putDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, rootOp); } public CheckedFuture commitConfigurationDataPut( final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode payload) { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - return putDataViaTransaction(domDataBrokerService.get().newWriteOnlyTransaction(), CONFIGURATION, path, - payload); + DataNormalizationOperation rootOp = new DataNormalizer(mountPoint.getSchemaContext()).getRootOperation(); + return putDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path, + payload, rootOp); } throw new RestconfDocumentedException("DOM data broker service isn't available for mount point."); } @@ -111,15 +121,17 @@ public class BrokerFacade { public CheckedFuture commitConfigurationDataPost( final YangInstanceIdentifier path, final NormalizedNode payload) { checkPreconditions(); - return postDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload); + DataNormalizationOperation rootOp = ControllerContext.getInstance().getRootOperation(); + return postDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, rootOp); } public CheckedFuture commitConfigurationDataPost( final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode payload) { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { + DataNormalizationOperation rootOp = new DataNormalizer(mountPoint.getSchemaContext()).getRootOperation(); return postDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path, - payload); + payload, rootOp); } throw new RestconfDocumentedException("DOM data broker service isn't available for mount point."); } @@ -186,7 +198,7 @@ public class BrokerFacade { private CheckedFuture postDataViaTransaction( final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload) { + final YangInstanceIdentifier path, final NormalizedNode payload, DataNormalizationOperation root) { ListenableFuture>> futureDatastoreData = rWTransaction.read(datastore, path); try { final Optional> optionalDatastoreData = futureDatastoreData.get(); @@ -199,15 +211,18 @@ public class BrokerFacade { } catch (InterruptedException | ExecutionException e) { LOG.trace("It wasn't possible to get data loaded from datastore at path " + path); } + + ensureParentsByMerge(datastore, path, rWTransaction, root); rWTransaction.merge(datastore, path, payload); LOG.trace("Post " + datastore.name() + " via Restconf: {}", path); return rWTransaction.submit(); } private CheckedFuture putDataViaTransaction( - final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload) { + final DOMDataReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, DataNormalizationOperation root) { LOG.trace("Put " + datastore.name() + " via Restconf: {}", path); + ensureParentsByMerge(datastore, path, writeTransaction, root); writeTransaction.put(datastore, path, payload); return writeTransaction.submit(); } @@ -215,7 +230,7 @@ public class BrokerFacade { private CheckedFuture deleteDataViaTransaction( final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType datastore, YangInstanceIdentifier path) { - LOG.info("Delete " + datastore.name() + " via Restconf: {}", path); + LOG.trace("Delete " + datastore.name() + " via Restconf: {}", path); writeTransaction.delete(datastore, path); return writeTransaction.submit(); } @@ -223,4 +238,38 @@ public class BrokerFacade { public void setDomDataBroker(DOMDataBroker domDataBroker) { this.domDataBroker = domDataBroker; } + + private final void ensureParentsByMerge(final LogicalDatastoreType store, + final YangInstanceIdentifier normalizedPath, final DOMDataReadWriteTransaction rwTx, + final DataNormalizationOperation root) { + List currentArguments = new ArrayList<>(); + Iterator iterator = normalizedPath.getPathArguments().iterator(); + DataNormalizationOperation currentOp = root; + while (iterator.hasNext()) { + PathArgument currentArg = iterator.next(); + try { + currentOp = currentOp.getChild(currentArg); + } catch (DataNormalizationException e) { + throw new IllegalArgumentException( + String.format("Invalid child encountered in path %s", normalizedPath), e); + } + currentArguments.add(currentArg); + YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments); + + final Boolean exists; + + try { + + CheckedFuture future = rwTx.exists(store, currentPath); + exists = future.checkedGet(); + } catch (ReadFailedException e) { + LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e); + throw new IllegalStateException("Failed to read pre-existing data", e); + } + + if (!exists && iterator.hasNext()) { + rwTx.merge(store, currentPath, currentOp.createDefault(currentArg)); + } + } + } }