From f93415dd8b3719b380b4295ab364420b9bf3d927 Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Mon, 11 Apr 2016 08:56:06 +0200 Subject: HONEYCOMB-34: Config tree initialization using ModifiableDataTree dependency Change-Id: I9fa6119a92cc1979ed6f3364bb74e856a7a712c5 Signed-off-by: Marek Gradzki --- .../fd/honeycomb/v3po/data/ModifiableDataTree.java | 8 ++ .../honeycomb/v3po/data/impl/ConfigDataTree.java | 10 ++ .../io/fd/honeycomb/v3po/data/impl/DataBroker.java | 8 +- .../data/impl/rev160411/ConfigDataTreeModule.java | 15 ++ .../impl/rev160411/OperationalDataTreeModule.java | 8 ++ v3po/impl/src/main/config/default-config.xml | 122 ++++++++-------- .../impl/VppDataBrokerInitializationProvider.java | 159 +-------------------- .../yang/v3po/impl/rev141210/DataBrokerModule.java | 104 ++++++++++++++ .../impl/rev141210/DataBrokerModuleFactory.java | 13 ++ .../ns/yang/v3po/impl/rev141210/V3poModule.java | 2 +- v3po/impl/src/main/yang/v3po-impl.yang | 33 ++++- v3po/vpp-cfg-init/pom.xml | 11 ++ .../vpp/data/init/AbstractDataTreeConverter.java | 127 ++++++++++++++++ .../v3po/vpp/data/init/DataTreeInitializer.java | 47 ++++++ .../v3po/vpp/data/init/InitializerRegistry.java | 15 +- .../vpp/data/init/InitializerRegistryImpl.java | 68 ++------- .../v3po/vpp/data/init/VppInitializer.java | 84 +++++++++++ .../VppConfigurationInitializerModule.java | 37 ++++- v3po/vpp-cfg-init/src/main/yang/vpp-cfg-init.yang | 21 +++ .../vpp/data/init/InitializerRegistryImplTest.java | 73 ++++++++++ 20 files changed, 678 insertions(+), 287 deletions(-) create mode 100644 v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/DataBrokerModule.java create mode 100644 v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/DataBrokerModuleFactory.java create mode 100644 v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/AbstractDataTreeConverter.java create mode 100644 v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/DataTreeInitializer.java create mode 100644 v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/VppInitializer.java create mode 100644 v3po/vpp-cfg-init/src/test/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImplTest.java diff --git a/v3po/data-api/src/main/java/io/fd/honeycomb/v3po/data/ModifiableDataTree.java b/v3po/data-api/src/main/java/io/fd/honeycomb/v3po/data/ModifiableDataTree.java index 8b21ddf24..a3b5c9c34 100644 --- a/v3po/data-api/src/main/java/io/fd/honeycomb/v3po/data/ModifiableDataTree.java +++ b/v3po/data-api/src/main/java/io/fd/honeycomb/v3po/data/ModifiableDataTree.java @@ -35,6 +35,14 @@ public interface ModifiableDataTree { */ void modify(final DataTreeModification modification) throws DataValidationFailedException, TranslationException; + /** + * Initializes data tree using supplied modification. + * + * @param modification data tree modification + * @throws DataValidationFailedException if modification data is not valid + */ + void initialize(final DataTreeModification modification) throws DataValidationFailedException; + /** * Creates read-only snapshot of a ModifiableDataTree. * diff --git a/v3po/data-impl/src/main/java/io/fd/honeycomb/v3po/data/impl/ConfigDataTree.java b/v3po/data-impl/src/main/java/io/fd/honeycomb/v3po/data/impl/ConfigDataTree.java index 59a555fda..b90a57acd 100644 --- a/v3po/data-impl/src/main/java/io/fd/honeycomb/v3po/data/impl/ConfigDataTree.java +++ b/v3po/data-impl/src/main/java/io/fd/honeycomb/v3po/data/impl/ConfigDataTree.java @@ -90,6 +90,8 @@ public final class ConfigDataTree implements ModifiableDataTree { @Override public void modify(final DataTreeModification modification) throws DataValidationFailedException, TranslationException { + LOG.debug("ConfigDataTree.modify"); + dataTree.validate(modification); final DataTreeCandidate candidate = dataTree.prepare(modification); @@ -135,6 +137,14 @@ public final class ConfigDataTree implements ModifiableDataTree { dataTree.commit(candidate); } + @Override + public void initialize(final DataTreeModification modification) throws DataValidationFailedException { + LOG.debug("ConfigDataTree.initialize"); + dataTree.validate(modification); + final DataTreeCandidate candidate = dataTree.prepare(modification); + dataTree.commit(candidate); + } + private Map, DataObject> extractNetconfData( final Optional> parentOptional) { if (parentOptional.isPresent()) { diff --git a/v3po/data-impl/src/main/java/io/fd/honeycomb/v3po/data/impl/DataBroker.java b/v3po/data-impl/src/main/java/io/fd/honeycomb/v3po/data/impl/DataBroker.java index 47b27f707..a0b585143 100644 --- a/v3po/data-impl/src/main/java/io/fd/honeycomb/v3po/data/impl/DataBroker.java +++ b/v3po/data-impl/src/main/java/io/fd/honeycomb/v3po/data/impl/DataBroker.java @@ -35,6 +35,8 @@ import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Data Broker which provides data transaction functionality for YANG capable data provider using {@link NormalizedNode} @@ -42,6 +44,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; */ public class DataBroker implements DOMDataBroker { + private static final Logger LOG = LoggerFactory.getLogger(DataBroker.class); private final ReadableDataTree operationalDataTree; private final ModifiableDataTree configDataTree; @@ -56,16 +59,18 @@ public class DataBroker implements DOMDataBroker { this.operationalDataTree = Preconditions.checkNotNull(operationalDataTree, "operationalDataTree should not be null"); this.configDataTree = Preconditions.checkNotNull(configDataTree, "configDataTree should not be null"); + LOG.trace("DataBroker({}).init() operationalDataTree={}, configDataTree={}", this, operationalDataTree, configDataTree); } @Override public DOMDataReadOnlyTransaction newReadOnlyTransaction() { + LOG.trace("DataBroker({}).newReadOnlyTransaction()", this); return new ReadOnlyTransaction(operationalDataTree, configDataTree.takeSnapshot()); } @Override public DOMDataReadWriteTransaction newReadWriteTransaction() { - // todo use the same snapshot + LOG.trace("DataBroker({}).newReadWriteTransaction()", this); final DataTreeSnapshot configSnapshot = configDataTree.takeSnapshot(); final DOMDataReadOnlyTransaction readOnlyTx = new ReadOnlyTransaction(operationalDataTree, configSnapshot); final DOMDataWriteTransaction writeOnlyTx = new WriteTransaction(configDataTree, configSnapshot); @@ -74,6 +79,7 @@ public class DataBroker implements DOMDataBroker { @Override public DOMDataWriteTransaction newWriteOnlyTransaction() { + LOG.trace("DataBroker({}).newWriteOnlyTransaction()", this); return new WriteTransaction(configDataTree); } diff --git a/v3po/data-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/data/impl/rev160411/ConfigDataTreeModule.java b/v3po/data-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/data/impl/rev160411/ConfigDataTreeModule.java index 115eb065f..19267b1bd 100644 --- a/v3po/data-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/data/impl/rev160411/ConfigDataTreeModule.java +++ b/v3po/data-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/data/impl/rev160411/ConfigDataTreeModule.java @@ -9,9 +9,14 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType; import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ConfigDataTreeModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.data.impl.rev160411.AbstractConfigDataTreeModule { + + private static final Logger LOG = LoggerFactory.getLogger(ConfigDataTreeModule.class); + public ConfigDataTreeModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); @@ -31,6 +36,7 @@ public class ConfigDataTreeModule extends @Override public java.lang.AutoCloseable createInstance() { + LOG.info("ConfigDataTreeModule.createInstance()"); final DataTree dataTree = InMemoryDataTreeFactory.getInstance().create(TreeType.CONFIGURATION); dataTree.setSchemaContext(getSchemaServiceDependency().getGlobalContext()); return new CloseableConfigDataTree( @@ -47,17 +53,26 @@ public class ConfigDataTreeModule extends @Override public void close() throws Exception { + LOG.info("CloseableConfigDataTree.close()"); // NOP } @Override public void modify(final DataTreeModification modification) throws DataValidationFailedException, TranslationException { + LOG.trace("CloseableConfigDataTree.modify modification={}", modification); delegate.modify(modification); } + @Override + public void initialize(final DataTreeModification modification) throws DataValidationFailedException { + LOG.trace("CloseableConfigDataTree.initialize modification={}", modification); + delegate.initialize(modification); + } + @Override public DataTreeSnapshot takeSnapshot() { + LOG.trace("CloseableConfigDataTree.takeSnapshot"); return delegate.takeSnapshot(); } } diff --git a/v3po/data-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/data/impl/rev160411/OperationalDataTreeModule.java b/v3po/data-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/data/impl/rev160411/OperationalDataTreeModule.java index 48053c366..0034b12c5 100644 --- a/v3po/data-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/data/impl/rev160411/OperationalDataTreeModule.java +++ b/v3po/data-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/data/impl/rev160411/OperationalDataTreeModule.java @@ -8,9 +8,14 @@ import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class OperationalDataTreeModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.data.impl.rev160411.AbstractOperationalDataTreeModule { + + private static final Logger LOG = LoggerFactory.getLogger(OperationalDataTreeModule.class); + public OperationalDataTreeModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); @@ -30,6 +35,7 @@ public class OperationalDataTreeModule extends @Override public java.lang.AutoCloseable createInstance() { + LOG.info("OperationalDataTreeModule.createInstance()"); return new CloseableOperationalDataTree( new OperationalDataTree(getSerializerDependency(), getSchemaServiceDependency().getGlobalContext(), getReaderRegistryDependency())); @@ -45,12 +51,14 @@ public class OperationalDataTreeModule extends @Override public void close() throws Exception { + LOG.info("CloseableOperationalDataTree.close()"); // NOP } @Override public CheckedFuture>, ReadFailedException> read( @Nonnull final YangInstanceIdentifier path) { + LOG.trace("CloseableOperationalDataTree.read path={}", path); return delegate.read(path); } } diff --git a/v3po/impl/src/main/config/default-config.xml b/v3po/impl/src/main/config/default-config.xml index e35c3a421..328d00204 100644 --- a/v3po/impl/src/main/config/default-config.xml +++ b/v3po/impl/src/main/config/default-config.xml @@ -28,54 +28,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - prefix:delegating-reader-registry read-registry @@ -119,6 +71,39 @@ + + prefix:honeycomb-dom-data-broker + honeycomb-dom-data-broker + + prefix:honeycomb-modifiable-data-tree + config-data-tree + + + prefix:honeycomb-readable-data-tree + operational-data-tree + + + + + prefix:binding-forwarded-data-broker + honeycomb-binding-data-broker + + + + dom:dom-async-data-broker + honeycomb-dom-data-broker + + + dom:schema-service + yang-schema-service + + + binding:binding-dom-mapping-service + runtime-mapping-singleton + + + + prefix:v3po v3po-default @@ -142,10 +127,10 @@ prefix:honeycomb-writer-registry write-registry - + prefix:binding-dom-mapping-service runtime-mapping-singleton - + prefix:honeycomb-modifiable-data-tree config-data-tree @@ -163,28 +148,35 @@ prefix:honeycomb-reader-registry read-registry + + prefix:honeycomb-modifiable-data-tree + config-data-tree + + + binding:binding-dom-mapping-service + runtime-mapping-singleton + - - - - - - - - - - - - - - - + + dom:dom-async-data-broker + + honeycomb-dom-data-broker + /modules/module[type='honeycomb-dom-data-broker'][name='honeycomb-dom-data-broker'] + + + + binding:binding-async-data-broker + + honeycomb-binding-data-broker + /modules/module[type='binding-forwarded-data-broker'][name='honeycomb-binding-data-broker'] + + prefix:honeycomb-reader-registry diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppDataBrokerInitializationProvider.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppDataBrokerInitializationProvider.java index 84301b711..bbb004b73 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppDataBrokerInitializationProvider.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppDataBrokerInitializationProvider.java @@ -20,22 +20,13 @@ 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; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; import io.fd.honeycomb.v3po.data.ModifiableDataTree; import io.fd.honeycomb.v3po.data.ReadableDataTree; import io.fd.honeycomb.v3po.data.impl.DataBroker; -import io.fd.honeycomb.v3po.translate.Context; -import io.fd.honeycomb.v3po.translate.TranslationException; -import io.fd.honeycomb.v3po.translate.read.ReadContext; import io.fd.honeycomb.v3po.translate.read.ReaderRegistry; import io.fd.honeycomb.v3po.translate.write.WriterRegistry; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.List; -import java.util.Map; import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; @@ -43,19 +34,11 @@ 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.dom.api.DOMDataBroker; -import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; -import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; import org.opendaylight.controller.sal.core.api.Broker; import org.opendaylight.controller.sal.core.api.Provider; import org.opendaylight.controller.sal.core.api.model.SchemaService; -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.VppBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppState; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomains; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomain; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; @@ -66,13 +49,9 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer; import org.opendaylight.yangtools.concepts.ObjectRegistration; -import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -136,7 +115,7 @@ public final class VppDataBrokerInitializationProvider implements Provider, Auto final DOMMountPointService.DOMMountPointBuilder mountPointBuilder = mountPointService.createMountPoint(path); mountPointBuilder.addInitialSchemaContext(globalContext); - broker = initVppDataBroker(operationalDataTree, serializer, configDataTree); + broker = new DataBroker(operationalDataTree, configDataTree); mountPointBuilder.addService(DOMDataBroker.class, broker); mountPointRegistration = mountPointBuilder.register(); @@ -145,9 +124,6 @@ public final class VppDataBrokerInitializationProvider implements Provider, Auto mountPoint.getSchemaContext()); createMountPointPlaceholder(); - - // TODO initial sync has to go out of here -// initialVppConfigSynchronization(broker); } @Override @@ -168,98 +144,6 @@ public final class VppDataBrokerInitializationProvider implements Provider, Auto } } - private DOMDataBroker initVppDataBroker(final ReadableDataTree operationalDataTree, - final BindingNormalizedNodeSerializer serializer, - final ModifiableDataTree configDataTree) { - // init operational data tree before data broker is initialized - - try { - initConfig(serializer, configDataTree); - } catch (Exception e) { - LOG.warn("Failed to initialize config", e); - } - - return new DataBroker(operationalDataTree, configDataTree); - } - - // FIXME move to initializer after wiring is finished - private void initConfig(final BindingNormalizedNodeSerializer serializer, final ModifiableDataTree configDataTree) - throws TranslationException, DataValidationFailedException { - LOG.info("Config initialization"); - - final Optional data = readerRegistry.read(InstanceIdentifier.create(VppState.class), new ReadContextImpl()); - LOG.info("Config initialization data={}", data); - - if (data.isPresent()) { - // conversion - VppState vppOperationalData = (VppState) data.get(); - final Vpp vppConfigData = convert(vppOperationalData); - - final Map.Entry> normalizedData = - serializer.toNormalizedNode(InstanceIdentifier.create(Vpp.class), vppConfigData); - - final DataTreeModification modification = configDataTree.takeSnapshot().newModification(); - final YangInstanceIdentifier biPath = normalizedData.getKey(); - final NormalizedNode biData = normalizedData.getValue(); - LOG.info("Config initialization biPath={}, biData={}", biPath, biData); - modification.write(biPath, biData); - modification.ready(); - - LOG.info("Config writing modification ..."); - configDataTree.modify(modification); // TODO do not write to VPP - LOG.info("Config writing modification written successfully."); - } else { - LOG.info("Data is not present"); - } - } - - private Vpp convert(final VppState vppState) { - final BridgeDomains bridgeDomains = vppState.getBridgeDomains(); - final List bridgeDomainList = bridgeDomains.getBridgeDomain(); - - VppBuilder vppBuilder = new VppBuilder(); - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomainsBuilder bdsBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomainsBuilder(); - final List - listOfBDs = new ArrayList<>(); - - // TODO use reflexion - for (BridgeDomain bd : bridgeDomainList) { - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainBuilder bdBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainBuilder(); - bdBuilder.setLearn(bd.isLearn()); - bdBuilder.setUnknownUnicastFlood(bd.isUnknownUnicastFlood()); - bdBuilder.setArpTermination(bd.isArpTermination()); - bdBuilder.setFlood(bd.isFlood()); - bdBuilder.setForward(bd.isForward()); - bdBuilder.setKey(new BridgeDomainKey(bd.getKey().getName())); - // TODO bdBuilder.setL2Fib(bd.getL2Fib()); - bdBuilder.setName(bd.getName()); - listOfBDs.add(bdBuilder.build()); - } - - bdsBuilder.setBridgeDomain(listOfBDs); - vppBuilder.setBridgeDomains(bdsBuilder.build()); - return vppBuilder.build(); - } - - - // TODO move to utility module - private static final class ReadContextImpl implements ReadContext { - public final Context ctx = new Context(); - - @Nonnull - @Override - public Context getContext() { - return ctx; - } - - @Override - public void close() { - // Make sure to clear the storage in case some customizer stored it to prevent memory leaks - ctx.close(); - } - } - - /** * Writes placeholder data into MD-SAL's global datastore to indicate the presence of VPP mountpoint. */ @@ -279,47 +163,6 @@ public final class VppDataBrokerInitializationProvider implements Provider, Auto } } - // TODO operational and config models are not 1-1 - // decide what part of operational data should be written to config during initialization - private void initialVppConfigSynchronization(final DOMDataBroker broker) { - // read from operational - final DOMDataReadOnlyTransaction readTx = broker.newReadOnlyTransaction(); - - final YangInstanceIdentifier - id = YangInstanceIdentifier.builder().node(VppState.QNAME).node(BridgeDomains.QNAME).build(); - - LOG.trace("initialVppStateSynchronization id: {}", id); - - final ListenableFuture writeFuture = Futures.transform( - readTx.read(LogicalDatastoreType.OPERATIONAL, id), - new AsyncFunction>, Void>() { - @Override - public ListenableFuture apply(final Optional> readResult) - throws Exception { - if (readResult.isPresent()) { - final DOMDataWriteTransaction writeTx = broker.newWriteOnlyTransaction(); - final NormalizedNode node = readResult.get(); - LOG.trace("Read result: {}", node); - - // FIXME - // this will fail because we are reading OPERATIONAL data and writing to CONFIGURATION - // we need to provide extensible way to register initializer that would - // translate between models - - // writeTx.put(LogicalDatastoreType.CONFIGURATION, id, node); - return writeTx.submit(); - } else { - return Futures - .immediateFailedFuture( - new IllegalStateException("Failed to read data from VPP.")); - } - } - }); - - Futures.addCallback(writeFuture, - new LoggingFuturesCallBack("Initializing VPP config DataTree failed", LOG)); - } - public Optional getBroker() { return Optional.fromNullable(broker); } diff --git a/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/DataBrokerModule.java b/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/DataBrokerModule.java new file mode 100644 index 000000000..76f014456 --- /dev/null +++ b/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/DataBrokerModule.java @@ -0,0 +1,104 @@ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.impl.rev141210; + +import io.fd.honeycomb.v3po.data.impl.DataBroker; +import java.util.Map; +import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension; +import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DataBrokerModule extends + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.impl.rev141210.AbstractDataBrokerModule { + + private static final Logger LOG = LoggerFactory.getLogger(DataBrokerModule.class); + + public DataBrokerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public DataBrokerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.impl.rev141210.DataBrokerModule oldModule, + java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + LOG.info("DataBrokerModule.createInstance()"); + return new CloseableDataBroker( + new DataBroker(getOperationalDataTreeDependency(), getConfigDataTreeDependency())); + } + + private static final class CloseableDataBroker implements AutoCloseable, DOMDataBroker { + + private final DataBroker delegate; + + CloseableDataBroker(final DataBroker delegate) { + this.delegate = delegate; + } + + @Override + public void close() throws Exception { + LOG.info("CloseableDataBroker.close()"); + // NOP + } + + @Override + public DOMDataReadOnlyTransaction newReadOnlyTransaction() { + LOG.trace("CloseableDataBroker.newReadOnlyTransaction()"); + return delegate.newReadOnlyTransaction(); + } + + @Override + public DOMDataReadWriteTransaction newReadWriteTransaction() { + LOG.trace("CloseableDataBroker.newReadWriteTransaction()"); + return delegate.newReadWriteTransaction(); + } + + @Override + public DOMDataWriteTransaction newWriteOnlyTransaction() { + LOG.trace("CloseableDataBroker.newWriteOnlyTransaction()"); + return delegate.newWriteOnlyTransaction(); + } + + @Override + public ListenerRegistration registerDataChangeListener(final LogicalDatastoreType store, + final YangInstanceIdentifier path, + final DOMDataChangeListener listener, + final DataChangeScope triggeringScope) { + LOG.trace("CloseableDataBroker.createTransactionChain store={}, path={}, listener={}, triggeringScope={}", + store, path, listener, triggeringScope); + return delegate.registerDataChangeListener(store, path, listener, triggeringScope); + } + + @Override + public DOMTransactionChain createTransactionChain(final TransactionChainListener listener) { + LOG.trace("CloseableDataBroker.createTransactionChain listener={}", listener); + return delegate.createTransactionChain(listener); + } + + @Nonnull + @Override + public Map, DOMDataBrokerExtension> getSupportedExtensions() { + LOG.trace("CloseableDataBroker.getSupportedExtensions()"); + return delegate.getSupportedExtensions(); + } + } +} diff --git a/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/DataBrokerModuleFactory.java b/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/DataBrokerModuleFactory.java new file mode 100644 index 000000000..cc30beacf --- /dev/null +++ b/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/DataBrokerModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: v3po-impl yang module local name: honeycomb-dom-data-broker +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Mon Apr 11 07:53:38 CEST 2016 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.impl.rev141210; +public class DataBrokerModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.impl.rev141210.AbstractDataBrokerModuleFactory { + +} diff --git a/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/V3poModule.java b/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/V3poModule.java index bae4a29d3..959780496 100644 --- a/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/V3poModule.java +++ b/v3po/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/v3po/impl/rev141210/V3poModule.java @@ -58,7 +58,7 @@ public class V3poModule extends domBroker.registerProvider(new InitializationProvider()); final V3poProvider provider = new V3poProvider(domBroker, getVppJapiDependency(), getReaderRegistryDependency(), - getWriterRegistryDependency(), getBindingNormalizedNodeSerializerDependency(), + getWriterRegistryDependency(), getSerializerDependency(), getConfigDataTreeDependency(), getOperationalDataTreeDependency()); getBrokerDependency().registerProvider(provider); return provider; diff --git a/v3po/impl/src/main/yang/v3po-impl.yang b/v3po/impl/src/main/yang/v3po-impl.yang index b9868c450..c0240cde3 100644 --- a/v3po/impl/src/main/yang/v3po-impl.yang +++ b/v3po/impl/src/main/yang/v3po-impl.yang @@ -72,7 +72,7 @@ module v3po-impl { } } - container binding-normalized-node-serializer { + container serializer { uses config:service-ref { refine type { mandatory true; @@ -123,4 +123,35 @@ module v3po-impl { } } + + identity honeycomb-dom-data-broker { + base config:module-type; + config:provided-service dom:dom-async-data-broker; + config:java-name-prefix DataBroker; + } + + augment "/config:modules/config:module/config:configuration" { + case honeycomb-dom-data-broker { + when "/config:modules/config:module/config:type = 'honeycomb-dom-data-broker'"; + + container config-data-tree { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity dapi:honeycomb-modifiable-data-tree; + } + } + } + + container operational-data-tree { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity dapi:honeycomb-readable-data-tree; + } + } + } + + } + } } diff --git a/v3po/vpp-cfg-init/pom.xml b/v3po/vpp-cfg-init/pom.xml index 002a1c8d7..a73fa8126 100644 --- a/v3po/vpp-cfg-init/pom.xml +++ b/v3po/vpp-cfg-init/pom.xml @@ -44,6 +44,17 @@ data-api ${project.version} + + + junit + junit + test + + + org.mockito + mockito-all + test + diff --git a/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/AbstractDataTreeConverter.java b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/AbstractDataTreeConverter.java new file mode 100644 index 000000000..3048dc18b --- /dev/null +++ b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/AbstractDataTreeConverter.java @@ -0,0 +1,127 @@ +/* + * 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.vpp.data.init; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.Beta; +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.data.ModifiableDataTree; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.read.ReaderRegistry; +import java.util.Map; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.binding.data.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; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base class for initializers which perform conversion between operational and config YANG model. + * + * @param Config data object + * @param Operational data object + */ +@Beta +public abstract class AbstractDataTreeConverter + implements DataTreeInitializer { + private static final Logger LOG = LoggerFactory.getLogger(AbstractDataTreeConverter.class); + + private final ReaderRegistry readerRegistry; + private final ModifiableDataTree configDataTree; + private final BindingNormalizedNodeSerializer serializer; + private final InstanceIdentifier idOper; + private final InstanceIdentifier idConfig; + + public AbstractDataTreeConverter(@Nonnull final ReaderRegistry readerRegistry, + @Nonnull final ModifiableDataTree configDataTree, + @Nonnull final BindingNormalizedNodeSerializer serializer, + @Nonnull final InstanceIdentifier idOper, + @Nonnull final InstanceIdentifier idConfig) { + this.readerRegistry = checkNotNull(readerRegistry, "readerRegistry should not be null"); + this.configDataTree = checkNotNull(configDataTree, "configDataTree should not be null"); + this.serializer = checkNotNull(serializer, "serializer should not be null"); + this.idOper = checkNotNull(idOper, "idOper should not be null"); + this.idConfig = checkNotNull(idConfig, "idConfig should not be null"); + } + + @Override + public final void initialize() throws InitializeException { + LOG.debug("AbstractDataTreeConverter.initialize()"); + + final Optional data; + try (ReadContext ctx = new ReadContextImpl()) { + data = readerRegistry.read(idOper, ctx); + } catch (ReadFailedException e) { + LOG.warn("Failed to read operational state", e); + return; + } + LOG.debug("Config initialization data={}", data); + + if (data.isPresent()) { + // conversion + final O operationalData = idOper.getTargetType().cast(data.get()); + final C configData = convert(operationalData); + + final Map.Entry> normalizedData = + serializer.toNormalizedNode(idConfig, configData); + + final DataTreeModification modification = configDataTree.takeSnapshot().newModification(); + final YangInstanceIdentifier biPath = normalizedData.getKey(); + final NormalizedNode biData = normalizedData.getValue(); + LOG.debug("Config initialization biPath={}, biData={}", biPath, biData); + modification.write(biPath, biData); + modification.ready(); + + LOG.debug("Config writing modification ..."); + try { + configDataTree.initialize(modification); + LOG.debug("Config writing modification written successfully."); + } catch (DataValidationFailedException e) { + throw new InitializeException("Failed to read operational state", e); + } + } else { + LOG.warn("Data is not present"); + } + } + + protected abstract C convert(final O operationalData); + + // TODO move to utility module + private static final class ReadContextImpl implements ReadContext { + public final Context ctx = new Context(); + + @Nonnull + @Override + public Context getContext() { + return ctx; + } + + @Override + public void close() { + // Make sure to clear the storage in case some customizer stored it to prevent memory leaks + ctx.close(); + } + } +} diff --git a/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/DataTreeInitializer.java b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/DataTreeInitializer.java new file mode 100644 index 000000000..3cb6f14e4 --- /dev/null +++ b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/DataTreeInitializer.java @@ -0,0 +1,47 @@ +/* + * 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.vpp.data.init; + +import com.google.common.annotations.Beta; + +/** + * Service for config data tree initialization. + * Implementation reads operational data and initializes config data tree. + * Initialization does not cause any change in VPP state, unlike ordinary writes to config. + */ +@Beta +public interface DataTreeInitializer extends AutoCloseable { + + /** + * Initializes config data tree for supported root node. + * @throws InitializeException if initialization failed + */ + void initialize() throws InitializeException; + + /** + * Removes all data managed by the initializer. + */ + @Override + void close() throws Exception; + + class InitializeException extends Exception { + + public InitializeException(final String message, final Throwable cause) { + super(message, cause); + } + } +} diff --git a/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistry.java b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistry.java index bdb633831..8760f0f09 100644 --- a/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistry.java +++ b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistry.java @@ -16,9 +16,18 @@ package io.fd.honeycomb.v3po.vpp.data.init; -public interface InitializerRegistry extends AutoCloseable { +import com.google.common.annotations.Beta; - void initialize(); +/** + * Data tree initializer suitable as a holder for all other root initializers, providing initializeAll feature. + */ +@Beta +public interface InitializerRegistry extends DataTreeInitializer { - void clean(); + /** + * Performs initialize on all registered root initializers. + * @throws if initialization failed + */ + @Override + void initialize() throws InitializeException; } diff --git a/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImpl.java b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImpl.java index eaf86a633..e5220f7e8 100644 --- a/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImpl.java +++ b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImpl.java @@ -16,75 +16,37 @@ package io.fd.honeycomb.v3po.vpp.data.init; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import com.google.common.base.Optional; -import io.fd.honeycomb.v3po.translate.Context; -import io.fd.honeycomb.v3po.translate.read.ReadContext; -import io.fd.honeycomb.v3po.translate.read.ReadFailedException; -import io.fd.honeycomb.v3po.translate.read.ReaderRegistry; +import java.util.List; import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppState; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomains; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class InitializerRegistryImpl implements InitializerRegistry, AutoCloseable { +public class InitializerRegistryImpl implements InitializerRegistry { private static final Logger LOG = LoggerFactory.getLogger(InitializerRegistryImpl.class); - private final ReaderRegistry readerRegistry; + private final List initializers; - public InitializerRegistryImpl(@Nonnull final ReaderRegistry readerRegistry) { - this.readerRegistry = checkNotNull(readerRegistry, "readerRegistry should not be null"); + public InitializerRegistryImpl(@Nonnull List initializers) { + this.initializers = checkNotNull(initializers, "initializers should not be null"); + checkArgument(!initializers.contains(null), "initializers should not contain null elements"); } - @Override public void close() throws Exception { - LOG.info("Initializer.close()"); - // TODO remove data - } - - public void initialize() { - try { - initializeBridgeDomains(); - } catch (Exception e) { - LOG.error("Initialization failed", e); + LOG.debug("InitializerRegistryImpl.close()"); + for (DataTreeInitializer initializer : initializers) { + initializer.close(); } } @Override - public void clean() { - - } - - // TODO make configurable - private void initializeBridgeDomains() throws ReadFailedException { - - final InstanceIdentifier bdsID = - InstanceIdentifier.create(VppState.class).child(BridgeDomains.class); - final ReadContext ctx = new ReadContextImpl(); - final Optional data = readerRegistry.read(bdsID, ctx); - - LOG.info("BridgeDomains data: {}", data); - - } - - // TODO move to utility module - private static final class ReadContextImpl implements ReadContext { - public final Context ctx = new Context(); - - @Nonnull - @Override - public Context getContext() { - return ctx; - } - - @Override - public void close() { - // Make sure to clear the storage in case some customizer stored it to prevent memory leaks - ctx.close(); + public void initialize() throws InitializeException { + // TODO check if readers are there + LOG.debug("InitializerRegistryImpl.initialize()"); + for (DataTreeInitializer initializer : initializers) { + initializer.initialize(); } } } diff --git a/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/VppInitializer.java b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/VppInitializer.java new file mode 100644 index 000000000..c0316c0b8 --- /dev/null +++ b/v3po/vpp-cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/VppInitializer.java @@ -0,0 +1,84 @@ +/* + * 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.vpp.data.init; + +import io.fd.honeycomb.v3po.data.ModifiableDataTree; +import io.fd.honeycomb.v3po.translate.read.ReaderRegistry; +import java.util.ArrayList; +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.VppBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppState; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomains; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomain; +import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VppInitializer extends AbstractDataTreeConverter { + private static final Logger LOG = LoggerFactory.getLogger(VppInitializer.class); + + public VppInitializer(@Nonnull final ReaderRegistry readerRegistry, + @Nonnull final ModifiableDataTree configDataTree, + @Nonnull final BindingNormalizedNodeSerializer serializer) { + super(readerRegistry, configDataTree, serializer, InstanceIdentifier.create(VppState.class), InstanceIdentifier.create(Vpp.class) ); + } + + @Override + public void close() throws Exception { + // NOP + LOG.debug("VppStateInitializer.close()"); + // FIXME implement delete + } + + @Override + protected Vpp convert(final VppState operationalData) { + LOG.debug("VppStateInitializer.convert()"); + final BridgeDomains bridgeDomains = operationalData.getBridgeDomains(); + final List bridgeDomainList = bridgeDomains.getBridgeDomain(); + + VppBuilder vppBuilder = new VppBuilder(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomainsBuilder + bdsBuilder = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomainsBuilder(); + final List + listOfBDs = new ArrayList<>(); + + // TODO use reflexion + for (BridgeDomain bd : bridgeDomainList) { + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainBuilder + bdBuilder = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainBuilder(); + bdBuilder.setLearn(bd.isLearn()); + bdBuilder.setUnknownUnicastFlood(bd.isUnknownUnicastFlood()); + bdBuilder.setArpTermination(bd.isArpTermination()); + bdBuilder.setFlood(bd.isFlood()); + bdBuilder.setForward(bd.isForward()); + bdBuilder.setKey(new BridgeDomainKey(bd.getKey().getName())); + // TODO bdBuilder.setL2Fib(bd.getL2Fib()); + bdBuilder.setName(bd.getName()); + listOfBDs.add(bdBuilder.build()); + } + + bdsBuilder.setBridgeDomain(listOfBDs); + vppBuilder.setBridgeDomains(bdsBuilder.build()); + return vppBuilder.build(); + } +} diff --git a/v3po/vpp-cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/VppConfigurationInitializerModule.java b/v3po/vpp-cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/VppConfigurationInitializerModule.java index ecfbaa6d4..8b6f589c4 100644 --- a/v3po/vpp-cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/VppConfigurationInitializerModule.java +++ b/v3po/vpp-cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/VppConfigurationInitializerModule.java @@ -1,15 +1,30 @@ package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407; +import io.fd.honeycomb.v3po.data.ModifiableDataTree; import io.fd.honeycomb.v3po.translate.read.ReaderRegistry; +import io.fd.honeycomb.v3po.vpp.data.init.DataTreeInitializer; import io.fd.honeycomb.v3po.vpp.data.init.InitializerRegistry; import io.fd.honeycomb.v3po.vpp.data.init.InitializerRegistryImpl; +import io.fd.honeycomb.v3po.vpp.data.init.VppInitializer; +import java.util.Collections; +import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public class VppConfigurationInitializerModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.AbstractVppConfigurationInitializerModule { - public VppConfigurationInitializerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { +public class VppConfigurationInitializerModule extends + org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.AbstractVppConfigurationInitializerModule { + + private static final Logger LOG = LoggerFactory.getLogger(VppConfigurationInitializerModule.class); + + public VppConfigurationInitializerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); } - public VppConfigurationInitializerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.VppConfigurationInitializerModule oldModule, java.lang.AutoCloseable oldInstance) { + public VppConfigurationInitializerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.VppConfigurationInitializerModule oldModule, + java.lang.AutoCloseable oldInstance) { super(identifier, dependencyResolver, oldModule, oldInstance); } @@ -20,11 +35,23 @@ public class VppConfigurationInitializerModule extends org.opendaylight.yang.gen @Override public java.lang.AutoCloseable createInstance() { + LOG.info("VppConfigurationInitializerModule.createInstance()"); final ReaderRegistry readerRegistry = getReaderRegistryDependency(); + final ModifiableDataTree configDataTree = getConfigDataTreeDependency(); + final BindingNormalizedNodeSerializer serializer = getSerializerDependency(); + + // TODO make configurable + final VppInitializer vppInitializer = + new VppInitializer(readerRegistry, configDataTree, serializer); - InitializerRegistry initializer = new InitializerRegistryImpl(readerRegistry); + final InitializerRegistry initializer = + new InitializerRegistryImpl(Collections.singletonList(vppInitializer)); - initializer.initialize(); + try { + initializer.initialize(); + } catch (Exception e) { + LOG.warn("Failed to initialize config", e); + } return initializer; } diff --git a/v3po/vpp-cfg-init/src/main/yang/vpp-cfg-init.yang b/v3po/vpp-cfg-init/src/main/yang/vpp-cfg-init.yang index 2f6822c6d..15a842e0e 100644 --- a/v3po/vpp-cfg-init/src/main/yang/vpp-cfg-init.yang +++ b/v3po/vpp-cfg-init/src/main/yang/vpp-cfg-init.yang @@ -4,7 +4,9 @@ module vpp-cfg-init { prefix "init"; import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;} import translate-api { prefix tapi; revision-date 2016-04-06; } + import data-api { prefix dapi; revision-date 2016-04-11; } description "This module contains initializers for VPP config data tree"; @@ -37,6 +39,25 @@ module vpp-cfg-init { } } } + + // TODO swich to binding broker + container config-data-tree { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity dapi:honeycomb-modifiable-data-tree; + } + } + } + + container serializer { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding:binding-normalized-node-serializer; + } + } + } } } diff --git a/v3po/vpp-cfg-init/src/test/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImplTest.java b/v3po/vpp-cfg-init/src/test/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImplTest.java new file mode 100644 index 000000000..d77ac3fe5 --- /dev/null +++ b/v3po/vpp-cfg-init/src/test/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImplTest.java @@ -0,0 +1,73 @@ +/* + * 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.vpp.data.init; + +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +import java.util.ArrayList; +import java.util.Arrays; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; + +public class InitializerRegistryImplTest { + + @Mock(name="dti1") + private DataTreeInitializer dti1; + @Mock(name="dti2") + private DataTreeInitializer dti2; + @Mock(name="dti3") + private DataTreeInitializer dti3; + + private ArrayList initializers; + + private InitializerRegistryImpl initializerRegistry; + + @Before + public void setUp() throws Exception { + initMocks(this); + initializers = new ArrayList<>(); + initializers.add(dti1); + initializers.add(dti2); + initializers.add(dti3); + initializerRegistry = new InitializerRegistryImpl(initializers); + } + + @Test(expected = IllegalArgumentException.class) + public void testConstructorFailed() throws Exception { + new InitializerRegistryImpl(Arrays.asList(dti1, null)); + } + + @Test + public void testInitialize() throws Exception { + initializerRegistry.initialize(); + + verify(dti1).initialize(); + verify(dti2).initialize(); + verify(dti3).initialize(); + } + + @Test + public void testClose() throws Exception { + initializerRegistry.close(); + + verify(dti1).close(); + verify(dti2).close(); + verify(dti3).close(); + } +} \ No newline at end of file -- cgit 1.2.3-korg