summaryrefslogtreecommitdiffstats
path: root/infra/cfg-init
diff options
context:
space:
mode:
Diffstat (limited to 'infra/cfg-init')
-rw-r--r--infra/cfg-init/pom.xml55
-rw-r--r--infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/AbstractDataTreeConverter.java114
-rw-r--r--infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/DataTreeInitializer.java51
-rw-r--r--infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistry.java33
-rw-r--r--infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImpl.java52
-rw-r--r--infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/RestoringInitializer.java112
-rw-r--r--infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/ConfigurationInitializerRegistryModule.java54
-rw-r--r--infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/ConfigurationInitializerRegistryModuleFactory.java13
-rw-r--r--infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/PersistedFileInitializerModule.java38
-rw-r--r--infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/PersistedFileInitializerModuleFactory.java13
-rw-r--r--infra/cfg-init/src/main/yang/vpp-cfg-init.yang117
-rw-r--r--infra/cfg-init/src/test/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImplTest.java66
12 files changed, 718 insertions, 0 deletions
diff --git a/infra/cfg-init/pom.xml b/infra/cfg-init/pom.xml
new file mode 100644
index 000000000..ddacb632a
--- /dev/null
+++ b/infra/cfg-init/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>io.fd.honeycomb.common</groupId>
+ <artifactId>impl-parent</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../../common/impl-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>cfg-init</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>translate-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>data-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/AbstractDataTreeConverter.java b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/AbstractDataTreeConverter.java
new file mode 100644
index 000000000..f0058264e
--- /dev/null
+++ b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/AbstractDataTreeConverter.java
@@ -0,0 +1,114 @@
+/*
+ * 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 com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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 InstanceIdentifier<O> idOper;
+ private final InstanceIdentifier<C> idConfig;
+ private final DataBroker bindingDataBroker;
+
+ public AbstractDataTreeConverter(final DataBroker bindingDataBroker,
+ final InstanceIdentifier<O> operRootId,
+ final InstanceIdentifier<C> cfgRootId) {
+ this.bindingDataBroker = checkNotNull(bindingDataBroker, "bindingDataBroker should not be null");
+ this.idOper = checkNotNull(operRootId, "operRootId should not be null");
+ this.idConfig = checkNotNull(cfgRootId, "cfgRootId should not be null");
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.debug("AbstractDataTreeConverter.close()");
+ // Not removing initialized data, since this works in cooperation with persistence, it could remove
+ // data restored by persistence or remove user configured data when shutting down HC
+ }
+
+ @Override
+ public final void initialize() throws InitializeException {
+ LOG.debug("AbstractDataTreeConverter.initialize() from(oper): {}, to(cfg): {}", idOper, idConfig);
+ final Optional<O> data = readData();
+
+ if (data.isPresent()) {
+ LOG.debug("Config initialization, operational data={}", data);
+
+ final O operationalData = data.get();
+ final C configData = convert(operationalData);
+
+ try {
+ LOG.debug("Initializing config with data={}", configData);
+ writeData(configData);
+ LOG.info("Config initialization successful from(oper): {}, to(cfg): {}", idOper, idConfig);
+ } catch (TransactionCommitFailedException e) {
+ throw new InitializeException("Failed to perform config initialization", e);
+ }
+ } else {
+ LOG.info("Data is not present under: {}, no initial changes to config at: {}", idOper, idConfig);
+ }
+ }
+
+ private Optional<O> readData() {
+ try (ReadOnlyTransaction readTx = bindingDataBroker.newReadOnlyTransaction()) {
+ final CheckedFuture<Optional<O>, org.opendaylight.controller.md.sal.common.api.data.ReadFailedException>
+ readFuture = readTx.read(LogicalDatastoreType.OPERATIONAL, idOper);
+ return readFuture.checkedGet();
+ } catch (org.opendaylight.controller.md.sal.common.api.data.ReadFailedException e) {
+ LOG.warn("Failed to read operational state", e);
+ }
+ return Optional.absent();
+ }
+
+ private void writeData(final C configData) throws TransactionCommitFailedException {
+ final WriteTransaction writeTx = bindingDataBroker.newWriteOnlyTransaction();
+ // Merge(instead of put) has to be used due to dynamic start, this might be executed multiple times
+ // and might overwrite config restored from persisted file with the same incomplete config.
+ // Making the entire configuration trigger VPP twice (on second persis ... and VPP does not like that
+ writeTx.merge(LogicalDatastoreType.CONFIGURATION, idConfig, configData);
+ writeTx.submit().checkedGet();
+ }
+
+ // TODO make this class concrete and use function dependency instead of abstract method
+ /**
+ * Converts operational data to config data for given root node
+ * @param operationalData data object representing operational data
+ * @return data object representing config data
+ */
+ protected abstract C convert(final O operationalData);
+}
diff --git a/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/DataTreeInitializer.java b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/DataTreeInitializer.java
new file mode 100644
index 000000000..d760401f9
--- /dev/null
+++ b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/DataTreeInitializer.java
@@ -0,0 +1,51 @@
+/*
+ * 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);
+ }
+
+ public InitializeException(final String msg) {
+ super(msg);
+ }
+ }
+}
diff --git a/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistry.java b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistry.java
new file mode 100644
index 000000000..8760f0f09
--- /dev/null
+++ b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistry.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+/**
+ * Data tree initializer suitable as a holder for all other root initializers, providing initializeAll feature.
+ */
+@Beta
+public interface InitializerRegistry extends DataTreeInitializer {
+
+ /**
+ * Performs initialize on all registered root initializers.
+ * @throws if initialization failed
+ */
+ @Override
+ void initialize() throws InitializeException;
+}
diff --git a/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImpl.java b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImpl.java
new file mode 100644
index 000000000..e5220f7e8
--- /dev/null
+++ b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImpl.java
@@ -0,0 +1,52 @@
+/*
+ * 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.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InitializerRegistryImpl implements InitializerRegistry {
+ private static final Logger LOG = LoggerFactory.getLogger(InitializerRegistryImpl.class);
+ private final List<DataTreeInitializer> initializers;
+
+ 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.debug("InitializerRegistryImpl.close()");
+ for (DataTreeInitializer initializer : initializers) {
+ initializer.close();
+ }
+ }
+
+ @Override
+ public void initialize() throws InitializeException {
+ // TODO check if readers are there
+ LOG.debug("InitializerRegistryImpl.initialize()");
+ for (DataTreeInitializer initializer : initializers) {
+ initializer.initialize();
+ }
+ }
+}
diff --git a/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/RestoringInitializer.java b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/RestoringInitializer.java
new file mode 100644
index 000000000..abc3f54c0
--- /dev/null
+++ b/infra/cfg-init/src/main/java/io/fd/honeycomb/v3po/vpp/data/init/RestoringInitializer.java
@@ -0,0 +1,112 @@
+/*
+ * 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.checkArgument;
+
+import io.fd.honeycomb.v3po.translate.util.JsonUtils;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.DOMDataWriteTransaction;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.RestorationType;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RestoringInitializer implements DataTreeInitializer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RestoringInitializer.class);
+
+ private final SchemaService schemaService;
+ private final Path path;
+ private final DOMDataBroker dataTree;
+ private final RestorationType restorationType;
+ private final LogicalDatastoreType datastoreType;
+
+ public RestoringInitializer(@Nonnull final SchemaService schemaService,
+ @Nonnull final Path path,
+ @Nonnull final DOMDataBroker dataTree,
+ @Nonnull final RestorationType restorationType,
+ @Nonnull final LogicalDatastoreType datastoreType) {
+ this.schemaService = schemaService;
+ this.datastoreType = datastoreType;
+ this.path = checkStorage(path);
+ this.dataTree = dataTree;
+ this.restorationType = restorationType;
+ }
+
+ private Path checkStorage(final Path path) {
+ if (Files.exists(path)) {
+ checkArgument(!Files.isDirectory(path), "File %s is a directory", path);
+ checkArgument(Files.isReadable(path), "File %s is not readable", path);
+ }
+
+ return path;
+ }
+
+ @Override
+ public void initialize() throws InitializeException {
+ LOG.debug("Starting restoration of {} from {} using {}", dataTree, path, restorationType);
+ if(!Files.exists(path)) {
+ LOG.debug("Persist file {} does not exist. Skipping restoration", path);
+ return;
+ }
+
+ try {
+ final ContainerNode containerNode = JsonUtils
+ .readJsonRoot(schemaService.getGlobalContext(), Files.newInputStream(path, StandardOpenOption.READ));
+
+ final DOMDataWriteTransaction domDataWriteTransaction = dataTree.newWriteOnlyTransaction();
+ for (DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild : containerNode
+ .getValue()) {
+ final YangInstanceIdentifier iid = YangInstanceIdentifier.create(dataContainerChild.getIdentifier());
+ LOG.trace("Restoring {} from {}", iid, path);
+
+ switch (restorationType) {
+ case Merge:
+ domDataWriteTransaction.merge(datastoreType, iid, dataContainerChild);
+ break;
+ case Put:
+ domDataWriteTransaction.put(datastoreType, iid, dataContainerChild);
+ break;
+ default:
+ throw new InitializeException(
+ "Unable to initialize data using " + restorationType + " restoration strategy. Unsupported");
+ }
+ }
+
+ // Block here to prevent subsequent initializers processing before context is fully restored
+ domDataWriteTransaction.submit().checkedGet();
+ LOG.debug("Data from {} restored successfully", path);
+
+ } catch (IOException | TransactionCommitFailedException e) {
+ throw new InitializeException("Unable to restore data from " + path, e);
+ }
+ }
+
+ @Override
+ public void close() {}
+}
diff --git a/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/ConfigurationInitializerRegistryModule.java b/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/ConfigurationInitializerRegistryModule.java
new file mode 100644
index 000000000..3fff82e32
--- /dev/null
+++ b/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/ConfigurationInitializerRegistryModule.java
@@ -0,0 +1,54 @@
+package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407;
+
+import io.fd.honeycomb.v3po.vpp.data.init.InitializerRegistry;
+import io.fd.honeycomb.v3po.vpp.data.init.InitializerRegistryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+* Initializer registry, delegating initialization to a list of initializers
+*/
+public class ConfigurationInitializerRegistryModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.AbstractConfigurationInitializerRegistryModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigurationInitializerRegistryModule.class);
+
+ public ConfigurationInitializerRegistryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public ConfigurationInitializerRegistryModule(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.ConfigurationInitializerRegistryModule 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("VppConfigurationInitializerModule.createInstance(): initialization started");
+
+ final InitializerRegistry initializer = new InitializerRegistryImpl(getInitializersDependency());
+
+ try {
+ // Initialize contexts first so that other initializers can find any relevant mapping before initializing
+ // configuration to what is already in VPP
+ getPersistedContextInitializerDependency().initialize();
+ LOG.info("Persisted context restored successfully");
+ // Initialize all registered initializers
+ initializer.initialize();
+ LOG.info("VPP configuration initialized successfully from VPP");
+ // Initialize stored configuration on top
+ getPersistedConfigInitializerDependency().initialize();
+ LOG.info("Persisted configuration restored successfully");
+ } catch (Exception e) {
+ LOG.warn("Failed to initialize config", e);
+ }
+
+ LOG.info("Honeycomb initialized");
+
+ return initializer;
+ }
+
+}
diff --git a/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/ConfigurationInitializerRegistryModuleFactory.java b/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/ConfigurationInitializerRegistryModuleFactory.java
new file mode 100644
index 000000000..f07be953e
--- /dev/null
+++ b/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/ConfigurationInitializerRegistryModuleFactory.java
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: vpp-cfg-init yang module local name: cfg-initializer-registry
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed May 18 14:43:49 CEST 2016
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407;
+public class ConfigurationInitializerRegistryModuleFactory extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.AbstractConfigurationInitializerRegistryModuleFactory {
+
+}
diff --git a/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/PersistedFileInitializerModule.java b/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/PersistedFileInitializerModule.java
new file mode 100644
index 000000000..188d1641c
--- /dev/null
+++ b/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/PersistedFileInitializerModule.java
@@ -0,0 +1,38 @@
+package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407;
+
+import io.fd.honeycomb.v3po.vpp.data.init.RestoringInitializer;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Paths;
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.data.api.rev160411.DatatreeType;
+
+/**
+* Initializer restoring data from a persisted file
+*/
+public class PersistedFileInitializerModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.AbstractPersistedFileInitializerModule {
+ public PersistedFileInitializerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public PersistedFileInitializerModule(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.PersistedFileInitializerModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ try {
+ Paths.get(getPersistFilePath());
+ } catch (InvalidPathException e) {
+ throw new JmxAttributeValidationException("Invalid persist path", e, persistFilePathJmxAttribute);
+ }
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ return new RestoringInitializer(getSchemaServiceDependency(), Paths.get(getPersistFilePath()),
+ getDomDataBrokerDependency(), getRestorationType(),
+ getDatastoreType() == DatatreeType.Config ? LogicalDatastoreType.CONFIGURATION : LogicalDatastoreType.OPERATIONAL);
+ }
+
+}
diff --git a/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/PersistedFileInitializerModuleFactory.java b/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/PersistedFileInitializerModuleFactory.java
new file mode 100644
index 000000000..1d7a3c9c6
--- /dev/null
+++ b/infra/cfg-init/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/vpp/data/init/rev160407/PersistedFileInitializerModuleFactory.java
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: vpp-cfg-init yang module local name: persisted-file-initializer
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed May 18 13:48:52 CEST 2016
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407;
+public class PersistedFileInitializerModuleFactory extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.vpp.data.init.rev160407.AbstractPersistedFileInitializerModuleFactory {
+
+}
diff --git a/infra/cfg-init/src/main/yang/vpp-cfg-init.yang b/infra/cfg-init/src/main/yang/vpp-cfg-init.yang
new file mode 100644
index 000000000..52750d926
--- /dev/null
+++ b/infra/cfg-init/src/main/yang/vpp-cfg-init.yang
@@ -0,0 +1,117 @@
+module vpp-cfg-init {
+ yang-version 1;
+ namespace "urn:honeycomb:params:xml:ns:yang:vpp:data:init";
+ prefix "init";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-dom {prefix dom;}
+ 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";
+
+ revision "2016-04-07" {
+ description
+ "Initial revision";
+ }
+
+ identity cfg-initializer {
+ base "config:service-type";
+ config:java-class io.fd.honeycomb.v3po.vpp.data.init.DataTreeInitializer;
+ }
+
+ identity cfg-initializer-registry {
+ base config:module-type;
+ config:provided-service cfg-initializer;
+ config:java-name-prefix ConfigurationInitializerRegistry;
+ description "Initializer registry, delegating initialization to a list of initializers";
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case cfg-initializer-registry {
+ when "/config:modules/config:module/config:type = 'cfg-initializer-registry'";
+
+ list initializers {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity cfg-initializer;
+ }
+ }
+ }
+
+ container persisted-context-initializer {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity cfg-initializer;
+ }
+ }
+ }
+
+ container persisted-config-initializer {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity cfg-initializer;
+ }
+ }
+ }
+ }
+ }
+
+ identity persisted-file-initializer {
+ base config:module-type;
+ config:provided-service cfg-initializer;
+ description "Initializer restoring data from a persisted file";
+ }
+
+ typedef restoration-type {
+ type enumeration {
+ enum merge;
+ enum put;
+ }
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case persisted-file-initializer {
+ when "/config:modules/config:module/config:type = 'persisted-file-initializer'";
+
+ container dom-data-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity dom:dom-async-data-broker;
+ }
+ }
+ }
+
+ container schema-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity dom:schema-service;
+ }
+ }
+ }
+
+ leaf persist-file-path {
+ type string;
+ mandatory true;
+ }
+
+ leaf restoration-type {
+ type restoration-type;
+ default merge;
+ }
+
+
+ leaf datastore-type {
+ type dapi:datatree-type;
+ mandatory true;
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/infra/cfg-init/src/test/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImplTest.java b/infra/cfg-init/src/test/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImplTest.java
new file mode 100644
index 000000000..d562fb60c
--- /dev/null
+++ b/infra/cfg-init/src/test/java/io/fd/honeycomb/v3po/vpp/data/init/InitializerRegistryImplTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.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 InitializerRegistryImpl initializerRegistry;
+
+ @Before
+ public void setUp() throws Exception {
+ initMocks(this);
+ initializerRegistry = new InitializerRegistryImpl(Arrays.asList(dti1, dti2, dti3));
+ }
+
+ @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