diff options
author | Marek Gradzki <mgradzki@cisco.com> | 2016-04-11 08:56:06 +0200 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2016-04-12 11:04:11 +0200 |
commit | f93415dd8b3719b380b4295ab364420b9bf3d927 (patch) | |
tree | 057de7e397985b74cef738936983c7db6e741cd7 /v3po/vpp-cfg-init/src/main | |
parent | d99066504f76a181c90832b939956f43b409c075 (diff) |
HONEYCOMB-34: Config tree initialization using ModifiableDataTree dependency
Change-Id: I9fa6119a92cc1979ed6f3364bb74e856a7a712c5
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Diffstat (limited to 'v3po/vpp-cfg-init/src/main')
7 files changed, 338 insertions, 61 deletions
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 <C> Config data object + * @param <O> Operational data object + */ +@Beta +public abstract class AbstractDataTreeConverter<O extends DataObject, C extends DataObject> + 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<O> idOper; + private final InstanceIdentifier<C> idConfig; + + public AbstractDataTreeConverter(@Nonnull final ReaderRegistry readerRegistry, + @Nonnull final ModifiableDataTree configDataTree, + @Nonnull final BindingNormalizedNodeSerializer serializer, + @Nonnull final InstanceIdentifier<O> idOper, + @Nonnull final InstanceIdentifier<C> 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<? extends DataObject> 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<YangInstanceIdentifier, NormalizedNode<?, ?>> 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<DataTreeInitializer> initializers; - public InitializerRegistryImpl(@Nonnull final ReaderRegistry readerRegistry) { - this.readerRegistry = checkNotNull(readerRegistry, "readerRegistry should not be null"); + public InitializerRegistryImpl(@Nonnull List<DataTreeInitializer> 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<BridgeDomains> bdsID = - InstanceIdentifier.create(VppState.class).child(BridgeDomains.class); - final ReadContext ctx = new ReadContextImpl(); - final Optional<? extends DataObject> 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<VppState, Vpp> { + 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<BridgeDomain> 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<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain> + 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.<DataTreeInitializer>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; + } + } + } } } |