summaryrefslogtreecommitdiffstats
path: root/v3po/impl/src/main/java/io/fd
diff options
context:
space:
mode:
authorMarek Gradzki <mgradzki@cisco.com>2016-04-01 12:33:39 +0200
committerMarek Gradzki <mgradzki@cisco.com>2016-04-01 12:53:15 +0200
commit355c2205a7088bc7b3ccabc278c477b838975c65 (patch)
tree18f5f82861513318c2ee14dfd18cc63001b4fdfd /v3po/impl/src/main/java/io/fd
parent4c4f1743dc29e87b0ab4b39087f79f7f01befa49 (diff)
VPP API <-> YANG translation layer integration #2(Writers)
Change-Id: If91364f1900693b040aee163f1c6e092381b0efd Signed-off-by: Maros Marsalek <mmarsale@cisco.com> Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Diffstat (limited to 'v3po/impl/src/main/java/io/fd')
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java4
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java102
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProvider.java17
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataTree.java2
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java2
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java92
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationException.java (renamed from v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppApiInvocationException.java)2
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java49
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/DefaultVppWriter.java43
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppInterfacesReader.java56
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppReader.java30
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppWriter.java27
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizer.java71
13 files changed, 253 insertions, 244 deletions
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java
index 4afd86099..931ecefd6 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java
@@ -22,6 +22,7 @@ import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import io.fd.honeycomb.v3po.impl.data.VppDataBrokerInitializationProvider;
import io.fd.honeycomb.v3po.impl.data.VppReaderRegistry;
+import io.fd.honeycomb.v3po.impl.data.VppWriterRegistry;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
@@ -196,9 +197,10 @@ public class V3poProvider implements BindingAwareProvider, AutoCloseable, Broker
startOperationalUpdateTimer();
final VppReaderRegistry readerRegistry = VppReaderRegistry.getInstance(api);
+ final VppWriterRegistry writerRegistry = VppWriterRegistry.getInstance(api);
// TODO make configurable:
- vppDataBrokerInitializationProvider = new VppDataBrokerInitializationProvider(db, readerRegistry);
+ vppDataBrokerInitializationProvider = new VppDataBrokerInitializationProvider(db, readerRegistry, writerRegistry);
// TODO pull the registration into Module
domBroker.registerProvider(vppDataBrokerInitializationProvider);
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java
index 41a68e7bb..6fdeea348 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java
@@ -16,12 +16,15 @@
package io.fd.honeycomb.v3po.impl.data;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Collections.singletonList;
+
import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
-import io.fd.honeycomb.v3po.impl.trans0.VppApiInvocationException;
-import io.fd.honeycomb.v3po.impl.trans0.VppWriter;
+import io.fd.honeycomb.v3po.impl.trans.w.WriteContext;
+import io.fd.honeycomb.v3po.impl.trans.w.util.TransactionWriteContext;
+import io.fd.honeycomb.v3po.impl.trans.VppApiInvocationException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -31,6 +34,7 @@ import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -55,7 +59,14 @@ public final class VppConfigDataTree implements VppDataTree {
private final BindingNormalizedNodeSerializer serializer;
private final DataTree dataTree;
- private final VppWriter writer;
+ private final VppWriterRegistry writer;
+ public static final ReadableVppDataTree EMPTY_OPERATIONAL = new ReadableVppDataTree() {
+ @Override
+ public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
+ @Nonnull final YangInstanceIdentifier path) {
+ return Futures.immediateCheckedFuture(Optional.<NormalizedNode<?, ?>>absent());
+ }
+ };
/**
* Creates configuration data tree instance.
@@ -66,10 +77,10 @@ public final class VppConfigDataTree implements VppDataTree {
* @param vppWriter service for translation between Java Binding Data and Vpp.
*/
public VppConfigDataTree(@Nonnull final BindingNormalizedNodeSerializer serializer,
- @Nonnull final DataTree dataTree, @Nonnull final VppWriter vppWriter) {
- this.serializer = Preconditions.checkNotNull(serializer, "serializer should not be null");
- this.dataTree = Preconditions.checkNotNull(dataTree, "dataTree should not be null");
- this.writer = Preconditions.checkNotNull(vppWriter, "vppWriter should not be null");
+ @Nonnull final DataTree dataTree, @Nonnull final VppWriterRegistry vppWriter) {
+ this.serializer = checkNotNull(serializer, "serializer should not be null");
+ this.dataTree = checkNotNull(dataTree, "dataTree should not be null");
+ this.writer = checkNotNull(vppWriter, "vppWriter should not be null");
}
@Override
@@ -78,7 +89,8 @@ public final class VppConfigDataTree implements VppDataTree {
}
@Override
- public void commit(final DataTreeModification modification) throws DataValidationFailedException, VppApiInvocationException {
+ public void commit(final DataTreeModification modification)
+ throws DataValidationFailedException, VppApiInvocationException {
dataTree.validate(modification);
final DataTreeCandidate candidate = dataTree.prepare(modification);
@@ -87,16 +99,22 @@ public final class VppConfigDataTree implements VppDataTree {
final YangInstanceIdentifier rootPath = candidate.getRootPath();
final Optional<NormalizedNode<?, ?>> normalizedDataBefore = rootNode.getDataBefore();
final Optional<NormalizedNode<?, ?>> normalizedDataAfter = rootNode.getDataAfter();
- LOG.debug("VppConfigDataProxy.commit() rootPath={}, rootNode={}, dataBefore={}, dataAfter={}",
+ LOG.debug("VppConfigDataTree.commit() rootPath={}, rootNode={}, dataBefore={}, dataAfter={}",
rootPath, rootNode, normalizedDataBefore, normalizedDataAfter);
final Map<InstanceIdentifier<?>, DataObject> nodesBefore = extractNetconfData(normalizedDataBefore);
- LOG.debug("VppConfigDataProxy.commit() extracted nodesBefore={}", nodesBefore.keySet());
+ LOG.debug("VppConfigDataTree.commit() extracted nodesBefore={}", nodesBefore.keySet());
final Map<InstanceIdentifier<?>, DataObject> nodesAfter = extractNetconfData(normalizedDataAfter);
- LOG.debug("VppConfigDataProxy.commit() extracted nodesAfter={}", nodesAfter.keySet());
+ LOG.debug("VppConfigDataTree.commit() extracted nodesAfter={}", nodesAfter.keySet());
- final ChangesProcessor processor = new ChangesProcessor(writer, nodesBefore, nodesAfter);
+
+ final DOMDataReadOnlyTransaction beforeTx = new VppReadOnlyTransaction(EMPTY_OPERATIONAL, takeSnapshot());
+ final ConfigSnapshot modificationSnapshot = new ConfigSnapshot(modification);
+ final DOMDataReadOnlyTransaction afterTx = new VppReadOnlyTransaction(EMPTY_OPERATIONAL, modificationSnapshot);
+ final WriteContext ctx = new TransactionWriteContext(serializer, beforeTx, afterTx);
+
+ final ChangesProcessor processor = new ChangesProcessor(writer, nodesBefore, nodesAfter, ctx);
try {
processor.applyChanges();
} catch (VppApiInvocationException e) {
@@ -118,9 +136,10 @@ public final class VppConfigDataTree implements VppDataTree {
dataTree.commit(candidate);
}
- private Map<InstanceIdentifier<?>, DataObject> extractNetconfData(final Optional<NormalizedNode<?, ?>> parentOptional) {
+ private Map<InstanceIdentifier<?>, DataObject> extractNetconfData(
+ final Optional<NormalizedNode<?, ?>> parentOptional) {
if (parentOptional.isPresent()) {
- final DataContainerNode parent = (DataContainerNode)parentOptional.get();
+ final DataContainerNode parent = (DataContainerNode) parentOptional.get();
return DataTreeUtils.childrenFromNormalized(parent, serializer);
}
return Collections.emptyMap();
@@ -135,7 +154,7 @@ public final class VppConfigDataTree implements VppDataTree {
@Override
public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
- final YangInstanceIdentifier path) {
+ @Nonnull final YangInstanceIdentifier path) {
final Optional<NormalizedNode<?, ?>> node = snapshot.readNode(path);
if (LOG.isTraceEnabled() && node.isPresent()) {
LOG.trace("ConfigSnapshot.read: {}", node.get());
@@ -150,57 +169,80 @@ public final class VppConfigDataTree implements VppDataTree {
}
private static final class ChangesProcessor {
- private final VppWriter writer;
+ private final VppWriterRegistry writer;
private final List<InstanceIdentifier<?>> processedNodes;
private final Map<InstanceIdentifier<?>, DataObject> nodesBefore;
private final Map<InstanceIdentifier<?>, DataObject> nodesAfter;
+ private final WriteContext ctx;
- ChangesProcessor(@Nonnull final VppWriter writer,
+ ChangesProcessor(@Nonnull final VppWriterRegistry writer,
final Map<InstanceIdentifier<?>, DataObject> nodesBefore,
- final Map<InstanceIdentifier<?>, DataObject> nodesAfter) {
- this.writer = Preconditions.checkNotNull(writer, "VppWriter is null!");
- this.nodesBefore = Preconditions.checkNotNull(nodesBefore, "nodesBefore is null!");
- this.nodesAfter = Preconditions.checkNotNull(nodesAfter, "nodesAfter is null!");
+ final Map<InstanceIdentifier<?>, DataObject> nodesAfter,
+ @Nonnull final WriteContext writeContext) {
+ this.ctx = checkNotNull(writeContext, "writeContext is null!");
+ this.writer = checkNotNull(writer, "VppWriter is null!");
+ this.nodesBefore = checkNotNull(nodesBefore, "nodesBefore is null!");
+ this.nodesAfter = checkNotNull(nodesAfter, "nodesAfter is null!");
processedNodes = new ArrayList<>();
}
void applyChanges() throws VppApiInvocationException {
// TODO we should care about the order of modified subtrees
+ // TODO maybe WriterRegistry could provide writeAll method and it will process the updates
+ // in order in which it child writers are registered
final Set<InstanceIdentifier<?>> allNodes = new HashSet<>();
allNodes.addAll(nodesBefore.keySet());
allNodes.addAll(nodesAfter.keySet());
- LOG.debug("VppConfigDataProxy.applyChanges() all extracted nodes: {}", allNodes);
+ LOG.debug("ChangesProcessor.applyChanges() all extracted nodes: {}", allNodes);
for (InstanceIdentifier<?> node : allNodes) {
- LOG.debug("VppConfigDataProxy.applyChanges() processing node={}", node);
+ LOG.debug("ChangesProcessor.applyChanges() processing node={}", node);
final DataObject dataBefore = nodesBefore.get(node);
final DataObject dataAfter = nodesAfter.get(node);
+ LOG.debug("ChangesProcessor.applyChanges() processing dataBefore={}, dataAfter={}", dataBefore,
+ dataAfter);
try {
- writer.process(dataBefore, dataAfter);
+ // TODO is List as input argument really necessary for writer ?
+ final List<DataObject> dataObjectsBefore = dataBefore == null
+ ? Collections.<DataObject>emptyList()
+ : singletonList(dataBefore);
+ final List<DataObject> dataObjectsAfter = dataAfter == null
+ ? Collections.<DataObject>emptyList()
+ : singletonList(dataAfter);
+ LOG.debug("ChangesProcessor.applyChanges() processing dataObjectsBefore={}, dataObjectsAfter={}",
+ dataObjectsBefore, dataObjectsAfter);
+ writer.update(node, dataObjectsBefore, dataObjectsAfter, ctx);
processedNodes.add(node);
- } catch (VppApiInvocationException e) {
+ } catch (RuntimeException e) {
LOG.error("Error while processing data change (before={}, after={})", dataBefore, dataAfter, e);
- throw e;
+ // FIXME ex handling
+ throw new VppApiInvocationException("", 1, -1);
}
}
}
void revertChanges() throws VppApiInvocationException {
- Preconditions.checkNotNull(writer, "VppWriter is null!");
+ checkNotNull(writer, "VppWriter is null!");
// revert changes in reverse order they were applied
final ListIterator<InstanceIdentifier<?>> iterator = processedNodes.listIterator(processedNodes.size());
while (iterator.hasPrevious()) {
final InstanceIdentifier<?> node = iterator.previous();
- LOG.debug("VppConfigDataProxy.revertChanges() processing node={}", node);
+ LOG.debug("ChangesProcessor.revertChanges() processing node={}", node);
final DataObject dataBefore = nodesBefore.get(node);
final DataObject dataAfter = nodesAfter.get(node);
// revert a change by invoking writer with reordered arguments
- writer.process(dataAfter, dataBefore);
+ try {
+ // TODO is List as input argument really necessary for writer ?
+ writer.update(node, singletonList(dataAfter), singletonList(dataBefore), ctx);
+ } catch (RuntimeException e) {
+ // FIXME ex handling
+ throw new VppApiInvocationException("", 1, -1);
+ }
}
}
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProvider.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProvider.java
index 129a1b84b..2a14f48b1 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProvider.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProvider.java
@@ -16,6 +16,8 @@
package io.fd.honeycomb.v3po.impl.data;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.AsyncFunction;
@@ -23,7 +25,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import io.fd.honeycomb.v3po.impl.LoggingFuturesCallBack;
import io.fd.honeycomb.v3po.impl.trans.r.ReaderRegistry;
-import io.fd.honeycomb.v3po.impl.trans0.DefaultVppWriter;
import java.util.Collection;
import java.util.Collections;
import javassist.ClassPool;
@@ -84,12 +85,16 @@ public final class VppDataBrokerInitializationProvider implements Provider, Auto
private final DataBroker bindingBroker;
private final ReaderRegistry readerRegistry;
private final InstanceIdentifier<Node> mountPointPath;
+ private final VppWriterRegistry writerRegistry;
private ObjectRegistration<DOMMountPoint> mountPointRegistration;
private DOMDataBroker broker;
- public VppDataBrokerInitializationProvider(@Nonnull final DataBroker bindingBroker, final ReaderRegistry readerRegistry) {
- this.bindingBroker = Preconditions.checkNotNull(bindingBroker, "bindingBroker should not be null");
- this.readerRegistry = Preconditions.checkNotNull(readerRegistry, "readerRegistry should not be null");
+ public VppDataBrokerInitializationProvider(@Nonnull final DataBroker bindingBroker,
+ final ReaderRegistry readerRegistry,
+ final VppWriterRegistry writerRegistry) {
+ this.bindingBroker = checkNotNull(bindingBroker, "bindingBroker should not be null");
+ this.readerRegistry = checkNotNull(readerRegistry, "readerRegistry should not be null");
+ this.writerRegistry = checkNotNull(writerRegistry, "writerRegistry should not be null");
this.mountPointPath = getMountPointPath();
}
@@ -180,9 +185,7 @@ public final class VppDataBrokerInitializationProvider implements Provider, Auto
InMemoryDataTreeFactory.getInstance().create(TreeType.CONFIGURATION); // TODO make configurable
dataTree.setSchemaContext(globalContext);
- // FIXME use the new writer API
- final VppDataTree configDataProxy = new VppConfigDataTree(serializer, dataTree,
- new DefaultVppWriter()); // TODO make configurable
+ final VppDataTree configDataProxy = new VppConfigDataTree(serializer, dataTree, writerRegistry); // TODO make configurable
return new VppDataBroker(operationalData, configDataProxy);
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataTree.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataTree.java
index 17d3b7149..a3a4fae65 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataTree.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataTree.java
@@ -17,7 +17,7 @@
package io.fd.honeycomb.v3po.impl.data;
import com.google.common.annotations.Beta;
-import io.fd.honeycomb.v3po.impl.trans0.VppApiInvocationException;
+import io.fd.honeycomb.v3po.impl.trans.VppApiInvocationException;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java
index 8cdd10b7e..b7aa2f854 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java
@@ -26,7 +26,7 @@ import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import io.fd.honeycomb.v3po.impl.trans0.VppApiInvocationException;
+import io.fd.honeycomb.v3po.impl.trans.VppApiInvocationException;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java
new file mode 100644
index 000000000..67b45cfd2
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.v3po.impl.data;
+
+import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
+import io.fd.honeycomb.v3po.impl.trans.w.ChildVppWriter;
+import io.fd.honeycomb.v3po.impl.trans.w.VppWriter;
+import io.fd.honeycomb.v3po.impl.trans.w.WriteContext;
+import io.fd.honeycomb.v3po.impl.trans.w.impl.CompositeChildVppWriter;
+import io.fd.honeycomb.v3po.impl.trans.w.impl.CompositeListVppWriter;
+import io.fd.honeycomb.v3po.impl.trans.w.impl.CompositeRootVppWriter;
+import io.fd.honeycomb.v3po.impl.trans.w.util.DelegatingWriterRegistry;
+import io.fd.honeycomb.v3po.impl.trans.w.util.NoopWriterCustomizer;
+import io.fd.honeycomb.v3po.impl.trans.w.util.ReflexiveChildWriterCustomizer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Vpp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.vppjapi.vppApi;
+
+// TODO use some DI framework instead of singleton
+public class VppWriterRegistry implements VppWriter<DataObject> {
+
+ private static VppWriterRegistry instance;
+
+ private final DelegatingWriterRegistry writer;
+
+ private VppWriterRegistry(@Nonnull final vppApi vppApi) {
+ final CompositeRootVppWriter<Vpp> vppWriter = initVppStateWriter(vppApi);
+ writer = new DelegatingWriterRegistry(Collections.<VppWriter<? extends DataObject>>singletonList(vppWriter));
+ }
+
+ private static CompositeRootVppWriter<Vpp> initVppStateWriter(@Nonnull final vppApi vppApi) {
+ final CompositeListVppWriter<BridgeDomain, BridgeDomainKey> bridgeDomainWriter = new CompositeListVppWriter<>(
+ BridgeDomain.class,
+ new io.fd.honeycomb.v3po.impl.vpp.BridgeDomainCustomizer(vppApi));
+
+ final ChildVppWriter<BridgeDomains> bridgeDomainsWriter = new CompositeChildVppWriter<>(
+ BridgeDomains.class,
+ VppRWUtils.singletonChildWriterList(bridgeDomainWriter),
+ new ReflexiveChildWriterCustomizer<BridgeDomains>());
+
+ final List<ChildVppWriter<? extends ChildOf<Vpp>>> childWriters = new ArrayList<>();
+ childWriters.add(bridgeDomainsWriter);
+
+ return new CompositeRootVppWriter<>(
+ Vpp.class,
+ childWriters,
+ new NoopWriterCustomizer<Vpp>());
+ }
+
+ public static synchronized VppWriterRegistry getInstance(@Nonnull final vppApi vppApi) {
+ if (instance == null) {
+ instance = new VppWriterRegistry(vppApi);
+ }
+ return instance;
+ }
+
+ @Nonnull
+ @Override
+ public InstanceIdentifier<DataObject> getManagedDataObjectType() {
+ return writer.getManagedDataObjectType();
+ }
+
+ @Override
+ public void update(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+ @Nonnull final List<? extends DataObject> dataBefore,
+ @Nonnull final List<? extends DataObject> data, @Nonnull final WriteContext ctx) {
+ writer.update(id, dataBefore, data, ctx);
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppApiInvocationException.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationException.java
index 119563bdd..b0076cd9c 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppApiInvocationException.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationException.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.fd.honeycomb.v3po.impl.trans0;
+package io.fd.honeycomb.v3po.impl.trans;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java
index 3a1fd2f57..7c1a63da6 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java
@@ -22,29 +22,30 @@ import io.fd.honeycomb.v3po.impl.trans.util.Context;
import io.fd.honeycomb.v3po.impl.trans.w.WriteContext;
import java.util.Collections;
import java.util.List;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import java.util.Map;
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.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
public class TransactionWriteContext implements WriteContext, AutoCloseable {
- private final ReadOnlyTransaction beforeTx;
- private final ReadOnlyTransaction afterTx;
+ private final DOMDataReadOnlyTransaction beforeTx;
+ private final DOMDataReadOnlyTransaction afterTx;
private final Context ctx;
+ private final BindingNormalizedNodeSerializer serializer;
- public TransactionWriteContext(final ReadOnlyTransaction beforeTx, final ReadOnlyTransaction afterTx,
- final Context ctx) {
- super();
+ public TransactionWriteContext(final BindingNormalizedNodeSerializer serializer,
+ final DOMDataReadOnlyTransaction beforeTx,
+ final DOMDataReadOnlyTransaction afterTx) {
+ this.serializer = serializer;
this.beforeTx = beforeTx;
this.afterTx = afterTx;
- this.ctx = ctx;
- }
-
- public TransactionWriteContext(final ReadOnlyTransaction beforeTx,
- final ReadOnlyTransaction afterTx) {
- this(beforeTx, afterTx, new Context());
+ this.ctx = new Context();
}
@Override
@@ -53,16 +54,26 @@ public class TransactionWriteContext implements WriteContext, AutoCloseable {
}
private List<? extends DataObject> read(final InstanceIdentifier<? extends DataObject> currentId,
- final ReadOnlyTransaction tx) {
+ final DOMDataReadOnlyTransaction tx) {
// FIXME how to read all for list (using wildcarded ID) ?
- final CheckedFuture<? extends Optional<? extends DataObject>, ReadFailedException> read =
- tx.read(LogicalDatastoreType.CONFIGURATION, currentId);
+ final YangInstanceIdentifier path = serializer.toYangInstanceIdentifier(currentId);
+
+ final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read =
+ tx.read(LogicalDatastoreType.CONFIGURATION, path);
+
try {
- final Optional<? extends DataObject> optional = read.checkedGet();
- return optional.isPresent()
- ? Collections.singletonList(optional.get())
- : Collections.<DataObject>emptyList();
+ final Optional<NormalizedNode<?, ?>> optional = read.checkedGet();
+
+ if (!optional.isPresent()) {
+ return Collections.<DataObject>emptyList();
+ }
+
+ final NormalizedNode<?, ?> data = optional.get();
+ final Map.Entry<InstanceIdentifier<?>, DataObject> entry =
+ serializer.fromNormalizedNode(path, data);
+
+ return Collections.singletonList(entry.getValue());
} catch (ReadFailedException e) {
throw new IllegalStateException("Unable to perform read", e);
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/DefaultVppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/DefaultVppWriter.java
deleted file mode 100644
index 573353b55..000000000
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/DefaultVppWriter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.fd.honeycomb.v3po.impl.trans0;
-
-import java.util.Objects;
-import javax.annotation.Nullable;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DefaultVppWriter implements VppWriter {
- private static final Logger LOG = LoggerFactory.getLogger(DefaultVppWriter.class);
-
- @Override
- public void process(@Nullable final DataObject dataBefore, @Nullable final DataObject dataAfter)
- throws VppApiInvocationException {
- LOG.debug("Processing modification: dataBefore={}, dataAfter={}", dataBefore, dataAfter);
-
- if (Objects.equals(dataBefore, dataAfter)) {
- LOG.debug("No modification");
- } else if (dataBefore == null) {
- LOG.debug("modification type: CREATE");
- } else if (dataAfter == null) {
- LOG.debug("modification type: DELETE");
- } else {
- LOG.debug("modification type: UPDATE");
- }
- }
-}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppInterfacesReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppInterfacesReader.java
deleted file mode 100644
index 39b5f0208..000000000
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppInterfacesReader.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.fd.honeycomb.v3po.impl.trans0;
-
-import java.util.Collections;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class VppInterfacesReader implements VppReader<Interfaces> {
- private static final Logger LOG = LoggerFactory.getLogger(VppInterfacesReader.class);
-
- @Override
- public Interfaces read(final InstanceIdentifier<? extends DataObject> id) {
- LOG.info("VppInterfacesReader.read, id={}", id);
-
- InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
- final String interfaceName = "eth0";
- ifaceBuilder.setName(interfaceName);
- ifaceBuilder.setDescription("eth0 description");
- ifaceBuilder.setEnabled(false);
- ifaceBuilder.setKey(new InterfaceKey(interfaceName));
- ifaceBuilder.setType(EthernetCsmacd.class);
- ifaceBuilder.setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Disabled);
-
- InterfacesBuilder ifacesBuilder = new InterfacesBuilder();
- ifacesBuilder.setInterface(Collections.singletonList(ifaceBuilder.build()));
- return ifacesBuilder.build();
- }
-
- @Override
- public Class<Interfaces> getManagedDataObjectType() {
- return null;
- }
-}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppReader.java
deleted file mode 100644
index 5a4215edb..000000000
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppReader.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.fd.honeycomb.v3po.impl.trans0;
-
-import com.google.common.annotations.Beta;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-@Beta
-public interface VppReader<C extends DataObject> {
-
- C read(InstanceIdentifier<? extends DataObject> id);
-
- Class<C> getManagedDataObjectType();
-
-} \ No newline at end of file
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppWriter.java
deleted file mode 100644
index ee6e1f4be..000000000
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans0/VppWriter.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.fd.honeycomb.v3po.impl.trans0;
-
-import com.google.common.annotations.Beta;
-import javax.annotation.Nullable;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-
-@Beta
-public interface VppWriter<C extends DataObject> {
-
- void process(@Nullable C dataBefore, @Nullable C dataAfter) throws VppApiInvocationException;
-} \ No newline at end of file
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizer.java
index f707164eb..c56ebb1a8 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizer.java
@@ -16,6 +16,8 @@
package io.fd.honeycomb.v3po.impl.vpp;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import io.fd.honeycomb.v3po.impl.trans.util.Context;
@@ -38,9 +40,9 @@ public class BridgeDomainCustomizer
private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class);
- static final byte ADD_BD = (byte) 1;
- static final int NO_RET_VAL = -77;
- static final int RELEASE = 1;
+ private static final byte ADD_OR_UPDATE_BD = (byte) 1;
+ private static final int RESPONSE_NOT_READY = -77;
+ private static final int RELEASE = 1;
public BridgeDomainCustomizer(final org.openvpp.vppjapi.vppApi api) {
super(api);
@@ -53,30 +55,37 @@ public class BridgeDomainCustomizer
return ((BridgeDomains) parentData).getBridgeDomain();
}
+ private int waitForResponse(final int ctxId) {
+ int rv;
+ while ((rv = getVppApi().getRetval(ctxId, RELEASE)) == RESPONSE_NOT_READY) {
+ // TODO limit attempts
+ }
+ return rv;
+ }
+
+ private int addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd) {
+ byte flood = booleanToByte(bd.isFlood());
+ byte forward = booleanToByte(bd.isForward());
+ byte learn = booleanToByte(bd.isLearn());
+ byte uuf = booleanToByte(bd.isUnknownUnicastFlood());
+ byte arpTerm = booleanToByte(bd.isArpTermination());
+
+ int ctxId = getVppApi().bridgeDomainAddDel(bdId, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD);
+ return waitForResponse(ctxId);
+ }
+
@Override
public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
@Nonnull final BridgeDomain current,
@Nonnull final Context ctx) {
+ LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, current, ctx);
final String bdName = current.getName();
int bdId = getVppApi().findOrAddBridgeDomainId(bdName);
checkState(bdId > 0, "Unable to find or create bridge domain. Return code: %s", bdId);
- byte flood = booleanToByte(current.isFlood());
- byte forward = booleanToByte(current.isForward());
- byte learn = booleanToByte(current.isLearn());
- byte uuf = booleanToByte(current.isUnknownUnicastFlood());
- byte arpTerm = booleanToByte(current.isArpTermination());
-
- int ctxId = getVppApi().bridgeDomainAddDel(bdId, flood, forward, learn, uuf, arpTerm, ADD_BD);
-
- int rv = NO_RET_VAL;
- while (rv == -77) {
- rv = getVppApi().getRetval(ctxId, RELEASE /* release */);
- // TODO limit attempts
- }
- checkState(rv > 0, "Bridge domain %s(%s) write failed. Return code: %s", bdName, bdId, rv);
+ int rv = addOrUpdateBridgeDomain(bdId, current);
- bdId = getVppApi().bridgeDomainIdFromName(bdName);
+ checkState(rv >= 0, "Bridge domain %s(%s) write failed. Return code: %s", bdName, bdId, rv);
LOG.debug("Bridge domain {} written as {} successfully", bdName, bdId);
}
@@ -88,9 +97,10 @@ public class BridgeDomainCustomizer
public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
@Nonnull final BridgeDomain dataBefore,
@Nonnull final Context ctx) {
+ LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx);
String bdName = id.firstKeyOf(BridgeDomain.class).getName();
- int bdId = getVppApi().findOrAddBridgeDomainId(bdName);
+ int bdId = getVppApi().bridgeDomainIdFromName(bdName);
checkState(bdId > 0, "Unable to delete bridge domain. Does not exist. Return code: %s", bdId);
int ctxId = getVppApi().bridgeDomainAddDel(bdId,
@@ -101,13 +111,9 @@ public class BridgeDomainCustomizer
(byte) 0 /* arpTerm */,
(byte) 0 /* isAdd */);
- int rv = NO_RET_VAL;
- while (rv == NO_RET_VAL) {
- rv = getVppApi().getRetval(ctxId, RELEASE /* release */);
- // TODO limit attempts
- }
+ int rv = waitForResponse(ctxId);
- checkState(rv > 0, "Bridge domain delete failed. Return code: %s", rv);
+ checkState(rv >= 0, "Bridge domain delete failed. Return code: %s", rv);
LOG.debug("Bridge domain {} deleted as {} successfully", bdName, bdId);
}
@@ -115,9 +121,18 @@ public class BridgeDomainCustomizer
public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
@Nonnull final BridgeDomain dataBefore, @Nonnull final BridgeDomain dataAfter,
@Nonnull final Context ctx) {
- // Most basic update implementation: Delete + Write
- deleteCurrentAttributes(id, dataBefore, ctx);
- writeCurrentAttributes(id, dataAfter, ctx);
+ LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter, ctx);
+
+ final String bdName = checkNotNull(dataAfter.getName());
+ checkArgument(bdName.equals(dataBefore.getName()), "BridgeDomain name changed. It should be deleted and then created.");
+
+ int bdId = getVppApi().bridgeDomainIdFromName(bdName);
+ checkState(bdId > 0, "Unable to find bridge domain. Return code: %s", bdId);
+
+ final int rv = addOrUpdateBridgeDomain(bdId, dataAfter);
+
+ checkState(rv >= 0, "Bridge domain %s(%s) update failed. Return code: %s", bdName, bdId, rv);
+ LOG.debug("Bridge domain {}({}) updated successfully", bdName, bdId);
}
}