diff options
author | Maros Marsalek <mmarsale@cisco.com> | 2016-08-11 13:04:56 +0200 |
---|---|---|
committer | Maros Marsalek <mmarsale@cisco.com> | 2016-08-19 12:49:56 +0200 |
commit | 83efb0ff929801a5a2ab89f6b66c07ed940a309d (patch) | |
tree | 8d8ce5dec617fe8227c3089600a256f72842e6fb /infra/minimal-distribution/src/main/java/io/fd | |
parent | 0f5925e907ab8f37eefc29a1843f4beb6ba9f4a8 (diff) |
HONEYCOMB-19 Minimal distro ans wiring for hc infra
Change-Id: I8f0e577ac91106e6025f7f2f27811f850e1c5253
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Diffstat (limited to 'infra/minimal-distribution/src/main/java/io/fd')
46 files changed, 2548 insertions, 0 deletions
diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/Main.java b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/Main.java new file mode 100644 index 000000000..d715c592d --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/Main.java @@ -0,0 +1,116 @@ +/* + * 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.infra.distro; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.name.Names; +import groovy.util.logging.Slf4j; +import io.fd.honeycomb.data.init.DataTreeInitializer; +import io.fd.honeycomb.data.init.InitializerRegistry; +import io.fd.honeycomb.infra.distro.cfgattrs.CfgAttrsModule; +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration; +import io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule; +import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule; +import io.fd.honeycomb.infra.distro.initializer.InitializerPipelineModule; +import io.fd.honeycomb.infra.distro.netconf.HoneycombNotification2NetconfProvider; +import io.fd.honeycomb.infra.distro.netconf.NetconfModule; +import io.fd.honeycomb.infra.distro.netconf.NetconfReadersModule; +import io.fd.honeycomb.infra.distro.netconf.NetconfSshServerProvider; +import io.fd.honeycomb.infra.distro.netconf.NetconfTcpServerProvider; +import io.fd.honeycomb.infra.distro.restconf.RestconfModule; +import io.fd.honeycomb.infra.distro.schema.SchemaModule; +import io.fd.honeycomb.infra.distro.schema.YangBindingProviderModule; +import io.fd.honeycomb.infra.distro.data.NotificationModule; +import java.util.List; +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.netconf.sal.rest.api.RestConnector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Slf4j +public final class Main { + + private static final Logger LOG = LoggerFactory.getLogger(Main.class); + + public static final List<Module> BASE_MODULES = ImmutableList.of( + // Infra + new YangBindingProviderModule(), + new SchemaModule(), + new NotificationModule(), + new ConfigAndOperationalPipelineModule(), + new ContextPipelineModule(), + new InitializerPipelineModule(), + new NetconfModule(), + new NetconfReadersModule(), + new RestconfModule(), + // Json config attributes + new CfgAttrsModule()); + + public static void main(String[] args) { + // TODO add "clean" argument + init(BASE_MODULES); + } + + public static void init(final List<? extends Module> modules) { + LOG.info("Starting honeycomb"); + + Injector injector = Guice.createInjector(modules); + LOG.info("Honeycomb configuration: " + injector.getInstance(HoneycombConfiguration.class)); + + // Log all bindings + injector.getAllBindings().entrySet().stream() + .forEach(e -> LOG.trace("Component available under: {} is {}", e.getKey(), e.getValue())); + + final HoneycombConfiguration cfgAttributes = injector.getInstance(HoneycombConfiguration.class); + + // Now get instances for all dependency roots + + LOG.info("Starting RESTCONF"); + injector.getInstance(RestConnector.class); + + LOG.info("Starting NETCONF"); + injector.getInstance( + Key.get(NetconfOperationServiceFactory.class, Names.named(NetconfModule.NETCONF_MAPPER_HONEYCOMB))); + injector.getInstance( + Key.get(NetconfOperationServiceFactory.class, Names.named(NetconfModule.NETCONF_MAPPER_NOTIFICATION))); + injector.getInstance( + Key.get(NetconfOperationServiceFactory.class, Names.named(NetconfModule.NETCONF_MAPPER_MONITORING))); + + if (cfgAttributes.isNetconfTcpServerEnabled()) { + injector.getInstance(NetconfTcpServerProvider.NetconfTcpServer.class); + } + + injector.getInstance(NetconfSshServerProvider.NetconfSshServer.class); + injector.getInstance(HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf.class); + + LOG.info("Honeycomb started successfully!"); + + try { + LOG.info("Initializing configuration"); + injector.getInstance(Key.get(InitializerRegistry.class, Names.named("honeycomb-initializer"))).initialize(); + LOG.info("Configuration initialized successfully"); + } catch (DataTreeInitializer.InitializeException e) { + LOG.error("Unable to initialize configuration", e); + } + + LOG.info("Honeycomb started successfully!"); + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/ProviderTrait.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/ProviderTrait.groovy new file mode 100644 index 000000000..d1bce3176 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/ProviderTrait.groovy @@ -0,0 +1,36 @@ +/* + * 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.infra.distro + +import com.google.inject.Provider +import groovy.util.logging.Slf4j + +// TODO this should be a trait, but groovy compilation/stub generation sometimes fails (only) in Intellij if using trait + +@Slf4j +abstract class ProviderTrait<T> implements Provider<T> { + + @Override + T get() { + log.info "Providing: {}", this + T create = create() as T + log.debug "Provided: {}", create + create + } + + abstract def create() +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.groovy new file mode 100644 index 000000000..6c9b0a50a --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.groovy @@ -0,0 +1,31 @@ +/* + * 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.infra.distro.cfgattrs + +import com.google.inject.AbstractModule +import groovy.util.logging.Slf4j +import net.jmob.guice.conf.core.ConfigurationModule + +@Slf4j +class CfgAttrsModule extends AbstractModule { + + protected void configure() { + install(ConfigurationModule.create()) + // Inject non-dependency configuration + requestInjection(HoneycombConfiguration) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.groovy new file mode 100644 index 000000000..78a1a04fd --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.groovy @@ -0,0 +1,74 @@ +/* + * 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.infra.distro.cfgattrs + +import groovy.transform.ToString +import net.jmob.guice.conf.core.BindConfig +import net.jmob.guice.conf.core.InjectConfig +import net.jmob.guice.conf.core.Syntax + +@ToString(includeNames = true) +@BindConfig(value = "honeycomb", syntax = Syntax.JSON) +class HoneycombConfiguration { + + // TODO break into smaller pieces, config, context, rest, netconf etc. + + @InjectConfig("persisted-context-path") + String peristContextPath + @InjectConfig("persisted-context-restoration-type") + String persistedContextRestorationType + + @InjectConfig("persisted-config-path") + String peristConfigPath + @InjectConfig("persisted-config-restoration-type") + String persistedConfigRestorationType + + @InjectConfig("notification-service-queue-depth") + int notificationServiceQueueDepth + + // RESTCONF + @InjectConfig("restconf-websocket-port") + int restconfWebsocketPort + @InjectConfig("restconf-port") + int restconfPort + @InjectConfig("restconf-root-path") + String restconfRootPath + + // NETCONF + @InjectConfig("netconf-netty-threads") + Optional<Integer> netconfNettyThreads + // NETCONF TCP optional + @InjectConfig("netconf-tcp-binding-address") + Optional<String> netconfTcpBindingAddress + @InjectConfig("netconf-tcp-binding-port") + Optional<Integer> netconfTcpBindingPort + // NETCONF SSH + @InjectConfig("netconf-ssh-binding-address") + String netconfSshBindingAddress + @InjectConfig("netconf-ssh-binding-port") + Integer netconfSshBindingPort + + @InjectConfig("netconf-notification-stream-name") + String netconfNotificationStreamName + + boolean isNetconfTcpServerEnabled() { netconfTcpBindingAddress.isPresent() && netconfTcpBindingPort.isPresent() } + + @InjectConfig("username") + String username + @InjectConfig("password") + String password +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.groovy new file mode 100644 index 000000000..e73f14932 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.groovy @@ -0,0 +1,39 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker + +@Slf4j +@ToString +class BindingDataBrokerProvider extends ProviderTrait<DataBroker> { + + @Inject + DOMDataBroker domDataBroker + @Inject + BindingToNormalizedNodeCodec mappingService + + @Override + def create() { new BindingDOMDataBrokerAdapter(domDataBroker, mappingService) } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.groovy new file mode 100644 index 000000000..01ec8c16a --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.groovy @@ -0,0 +1,71 @@ +/* + * 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.infra.distro.data + +import com.google.inject.PrivateModule +import com.google.inject.Singleton +import com.google.inject.name.Names +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.ModifiableDataManager +import io.fd.honeycomb.data.ReadableDataManager +import io.fd.honeycomb.data.init.DataTreeInitializer +import io.fd.honeycomb.infra.distro.data.config.WriterRegistryProvider +import io.fd.honeycomb.infra.distro.data.oper.ReadableDTDelegProvider +import io.fd.honeycomb.infra.distro.data.oper.ReaderRegistryProvider +import io.fd.honeycomb.infra.distro.initializer.PersistedFileInitializerProvider +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree + +@Slf4j +class ConfigAndOperationalPipelineModule extends PrivateModule { + + protected void configure() { + // Expose registries + bind(ModifiableWriterRegistryBuilder).toProvider(WriterRegistryProvider).in(Singleton) + expose(ModifiableWriterRegistryBuilder) + bind(ModifiableReaderRegistryBuilder).toProvider(ReaderRegistryProvider).in(Singleton) + expose(ModifiableReaderRegistryBuilder) + + def dataTreeProvider = new DataTreeProvider.ConfigDataTreeProvider() + bind(DataTree).annotatedWith(Names.named("honeycomb-config")).toProvider(dataTreeProvider).in(Singleton) + expose(DataTree).annotatedWith(Names.named("honeycomb-config")) + + bind(ModifiableDataManager).toProvider(ModifiableDTDelegProvider).in(Singleton) + bind(ReadableDataManager) + .annotatedWith(Names.named("honeycomb-operational")) + .toProvider(ReadableDTDelegProvider).in(Singleton) + // Expose reader for initializer + expose(ReadableDataManager).annotatedWith(Names.named("honeycomb-operational")) + + def domBrokerProvider = new HoneycombDOMDataBrokerProvider() + bind(DOMDataBroker).annotatedWith(Names.named("honeycomb-config")).toProvider(domBrokerProvider).in(Singleton) + // Bind also without annotation for easy private injection + bind(DOMDataBroker).toProvider(domBrokerProvider).in(Singleton) + expose(DOMDataBroker).annotatedWith(Names.named("honeycomb-config")) + bind(DataBroker).annotatedWith(Names.named("honeycomb-config")).toProvider(BindingDataBrokerProvider).in(Singleton) + expose(DataBroker).annotatedWith(Names.named("honeycomb-config")) + + bind(DataTreeInitializer) + .annotatedWith(Names.named("honeycomb-config")) + .toProvider(PersistedFileInitializerProvider.PersistedConfigInitializerProvider) + .in(Singleton) + expose(DataTreeInitializer).annotatedWith(Names.named("honeycomb-config")) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.groovy new file mode 100644 index 000000000..f8a1859e2 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.groovy @@ -0,0 +1,34 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter + +@Slf4j +@ToString +class DOMNotificationServiceProvider extends ProviderTrait<DOMNotificationRouter> { + + @Inject + HoneycombConfiguration cfg + + def create() { DOMNotificationRouter.create(cfg.notificationServiceQueueDepth) } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.groovy new file mode 100644 index 000000000..6d075ccc8 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.groovy @@ -0,0 +1,40 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory +import org.opendaylight.controller.sal.core.api.model.SchemaService + +@Slf4j +@ToString +class DataStoreProvider extends ProviderTrait<InMemoryDOMDataStore> { + + @Inject + SchemaService schemaService + + String name + LogicalDatastoreType type + + @Override + def create() { InMemoryDOMDataStoreFactory.create(name, type, schemaService, false, null) } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.groovy new file mode 100644 index 000000000..6915a3cec --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.groovy @@ -0,0 +1,59 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.impl.PersistingDataTreeAdapter +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.sal.core.api.model.SchemaService +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree +import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType +import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory + +import java.nio.file.Paths + +@Slf4j +@ToString +abstract class DataTreeProvider extends ProviderTrait<DataTree> { + + @Inject + SchemaService schemaService + @Inject + HoneycombConfiguration config + + def create() { + def delegate = InMemoryDataTreeFactory.getInstance().create(getType()) + delegate.setSchemaContext(schemaService.getGlobalContext()) + new PersistingDataTreeAdapter(delegate, schemaService, Paths.get(getPath())) + } + + abstract String getPath() + abstract TreeType getType() + + static class ConfigDataTreeProvider extends DataTreeProvider { + String getPath() { config.peristConfigPath } + TreeType getType() { TreeType.CONFIGURATION } + } + + static class ContextDataTreeProvider extends DataTreeProvider { + String getPath() { config.peristContextPath } + TreeType getType() { TreeType.OPERATIONAL } + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.groovy new file mode 100644 index 000000000..2b275f7ff --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.groovy @@ -0,0 +1,44 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.impl.NorthboundFacadeHoneycombDOMBroker +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker +import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService +import org.opendaylight.controller.sal.core.api.Broker +import org.opendaylight.controller.sal.core.api.model.SchemaService + +@Slf4j +@ToString +class HoneycombDOMBrokerProvider extends ProviderTrait<Broker> { + + @Inject + @Named("honeycomb-config") + DOMDataBroker domDataBroker + @Inject + SchemaService schemaService + @Inject + @Named("honeycomb") + DOMNotificationService domNotificationService + + def create() { new NorthboundFacadeHoneycombDOMBroker(domDataBroker, schemaService, domNotificationService) } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.groovy new file mode 100644 index 000000000..e91054b3b --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.groovy @@ -0,0 +1,43 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.ModifiableDataManager +import io.fd.honeycomb.data.ReadableDataManager +import io.fd.honeycomb.data.impl.DataBroker +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker + +@Slf4j +@ToString +class HoneycombDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> { + + @Inject + ModifiableDataManager modDataManager + + @Inject + @Named("honeycomb-operational") + ReadableDataManager readDataManager + + def create() { + readDataManager ? DataBroker.create(modDataManager, readDataManager) : DataBroker.create(modDataManager) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.groovy new file mode 100644 index 000000000..f150691a8 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.groovy @@ -0,0 +1,72 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.fd.honeycomb.notification.ManagedNotificationProducer +import io.fd.honeycomb.notification.NotificationCollector +import io.fd.honeycomb.notification.impl.HoneycombNotificationCollector +import io.fd.honeycomb.notification.impl.NotificationProducerRegistry +import io.fd.honeycomb.notification.impl.NotificationProducerTracker +import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationPublishServiceAdapter +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec +import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter + +/** + * Mirror of org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.notification.impl.rev160601.HoneycombNotificationManagerModule + */ +@Slf4j +@ToString +class HoneycombNotificationManagerProvider extends ProviderTrait<NotificationCollector> { + + @Inject + @Named("honeycomb") + DOMNotificationRouter notificationRouter + @Inject(optional = true) + Set<ManagedNotificationProducer> notificationProducers = [] + @Inject + BindingToNormalizedNodeCodec codec + + @Override + def create() { + // Create the registry to keep track of what'OPERATIONAL registered + def notificationProducerRegistry = new NotificationProducerRegistry(notificationProducers as List); + + // Create BA version of notification service (implementation is free from ODL) + def bindingDOMNotificationPublishServiceAdapter = + new BindingDOMNotificationPublishServiceAdapter(codec, notificationRouter); + + // Create Collector on top of BA notification service and registry + def honeycombNotificationCollector = + new HoneycombNotificationCollector(bindingDOMNotificationPublishServiceAdapter, notificationProducerRegistry); + + // Create tracker, responsible for starting and stopping registered notification producers whenever necessary + def notificationProducerTracker = + new NotificationProducerTracker(notificationProducerRegistry, honeycombNotificationCollector, + notificationRouter); + + // TODO wire with restconf + // DOMNotificationService is already provided by DOMBroker injected into RESTCONF, however RESTCONF + // only supports data-change notification, nothing else. So currently its impossible. + + honeycombNotificationCollector + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.groovy new file mode 100644 index 000000000..6462baa71 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.groovy @@ -0,0 +1,65 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker +import org.opendaylight.controller.md.sal.dom.broker.impl.SerializedDOMDataBroker +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore +import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService +import org.opendaylight.yangtools.util.concurrent.SpecialExecutors +/** + * Mirror of org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModule + */ +@Slf4j +@ToString +class InmemoryDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> { + + public static final String CONFIG = "config" + public static final String OPERATIONAL = "operational" + + @Inject + @Named(InmemoryDOMDataBrokerProvider.CONFIG) + InMemoryDOMDataStore cfgDataStore + + @Inject + @Named(InmemoryDOMDataBrokerProvider.OPERATIONAL) + InMemoryDOMDataStore operDataStore + + @Override + def create() { + // This Databroker is dedicated for netconf metadata, not expected to be under heavy load + def listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(1, 100, "commits") + def commitExecutor = SpecialExecutors.newBoundedSingleThreadExecutor(100, "WriteTxCommit") + // TODO try to provide more lightweight implementation of DataBroker, maybe a single executor would be enough + + def map = [:] + map.put(LogicalDatastoreType.CONFIGURATION, cfgDataStore) + map.put(LogicalDatastoreType.OPERATIONAL, operDataStore) + + new SerializedDOMDataBroker(map, + new DeadlockDetectingListeningExecutorService(commitExecutor, + TransactionCommitDeadlockException.DEADLOCK_EXCEPTION_SUPPLIER, + listenableFutureExecutor)) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.groovy new file mode 100644 index 000000000..f7ec4cc12 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.groovy @@ -0,0 +1,48 @@ +/* + * 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.infra.distro.data + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.ModifiableDataManager +import io.fd.honeycomb.data.impl.ModifiableDataTreeDelegator +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree + +@Slf4j +@ToString +class ModifiableDTDelegProvider extends ProviderTrait<ModifiableDataManager> { + + @Inject + BindingToNormalizedNodeCodec serializer + @Inject + @Named("honeycomb-config") + DataTree dataTree + @Inject + ModifiableWriterRegistryBuilder registry + @Inject + @Named("honeycomb-context") + DataBroker contextBroker + + @Override + def create() { new ModifiableDataTreeDelegator(serializer, dataTree, registry.build(), contextBroker) } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/NotificationModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/NotificationModule.groovy new file mode 100644 index 000000000..4836a0fbe --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/NotificationModule.groovy @@ -0,0 +1,45 @@ +/* + * 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.infra.distro.data + +import com.google.inject.AbstractModule +import com.google.inject.Singleton +import com.google.inject.name.Names +import groovy.util.logging.Slf4j +import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService +import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter +import org.opendaylight.controller.sal.core.api.Broker + +@Slf4j +class NotificationModule extends AbstractModule { + + protected void configure() { + def provider = new DOMNotificationServiceProvider() + bind(DOMNotificationService) + .annotatedWith(Names.named("honeycomb")) + .toProvider(provider) + .in(Singleton) + bind(DOMNotificationRouter) + .annotatedWith(Names.named("honeycomb")) + .toProvider(provider) + .in(Singleton) + bind(Broker) + .annotatedWith(Names.named("honeycomb")) + .toProvider(HoneycombDOMBrokerProvider) + .in(Singleton) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.groovy new file mode 100644 index 000000000..3c94812ef --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.groovy @@ -0,0 +1,39 @@ +/* + * 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.infra.distro.data.config + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.fd.honeycomb.translate.util.write.registry.FlatWriterRegistryBuilder +import io.fd.honeycomb.translate.write.WriterFactory +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder + +@Slf4j +@ToString +class WriterRegistryProvider extends ProviderTrait<ModifiableWriterRegistryBuilder> { + + @Inject(optional = true) + Set<WriterFactory> writerFactories = [] + + def create() { + def builder = new FlatWriterRegistryBuilder() + writerFactories.forEach { it.init(builder) } + builder + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.groovy new file mode 100644 index 000000000..01124131f --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.groovy @@ -0,0 +1,58 @@ +/* + * 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.infra.distro.data.context + +import com.google.inject.PrivateModule +import com.google.inject.Singleton +import com.google.inject.name.Names +import io.fd.honeycomb.data.ModifiableDataManager +import io.fd.honeycomb.data.init.DataTreeInitializer +import io.fd.honeycomb.infra.distro.data.BindingDataBrokerProvider +import io.fd.honeycomb.infra.distro.data.DataTreeProvider +import io.fd.honeycomb.infra.distro.initializer.PersistedFileInitializerProvider +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree + +class ContextPipelineModule extends PrivateModule { + + protected void configure() { + // Bind also without annotation for easy private injection + def dataTreeProvider = new DataTreeProvider.ContextDataTreeProvider() + bind(DataTree).toProvider(dataTreeProvider).in(Singleton) + bind(DataTree).annotatedWith(Names.named("honeycomb-context")).toProvider(dataTreeProvider).in(Singleton) + expose(DataTree).annotatedWith(Names.named("honeycomb-context")) + + bind(ModifiableDataManager).toProvider(ModifiableDTMgrProvider).in(Singleton) + + def domBrokerProvider = new HoneycombContextDOMDataBrokerProvider() + bind(DOMDataBroker).annotatedWith(Names.named("honeycomb-context")).toProvider(domBrokerProvider).in(Singleton) + // Bind also without annotation for easy private injection + bind(DOMDataBroker).toProvider(domBrokerProvider).in(Singleton) + expose(DOMDataBroker).annotatedWith(Names.named("honeycomb-context")) + + bind(DataBroker).annotatedWith(Names.named("honeycomb-context")).toProvider(BindingDataBrokerProvider).in(Singleton) + expose(DataBroker).annotatedWith(Names.named("honeycomb-context")) + + bind(DataTreeInitializer) + .annotatedWith(Names.named("honeycomb-context")) + .toProvider(PersistedFileInitializerProvider.PersistedContextInitializerProvider) + .in(Singleton) + expose(DataTreeInitializer).annotatedWith(Names.named("honeycomb-context")) + } + +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.groovy new file mode 100644 index 000000000..eecd87e42 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.groovy @@ -0,0 +1,36 @@ +/* + * 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.infra.distro.data.context + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.ModifiableDataManager +import io.fd.honeycomb.data.impl.DataBroker +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker + +@Slf4j +@ToString +class HoneycombContextDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> { + + @Inject + ModifiableDataManager modDataManager + + def create() { DataBroker.create(modDataManager) } + +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.groovy new file mode 100644 index 000000000..01d854b28 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.groovy @@ -0,0 +1,36 @@ +/* + * 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.infra.distro.data.context + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.ModifiableDataManager +import io.fd.honeycomb.data.impl.ModifiableDataTreeManager +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree + +@Slf4j +@ToString +class ModifiableDTMgrProvider extends ProviderTrait<ModifiableDataManager> { + + @Inject + DataTree dataTree + + @Override + def create() { new ModifiableDataTreeManager(dataTree) } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.groovy new file mode 100644 index 000000000..384278793 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.groovy @@ -0,0 +1,48 @@ +/* + * 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.infra.distro.data.oper + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.ReadableDataManager +import io.fd.honeycomb.data.impl.ReadableDataTreeDelegator +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec +import org.opendaylight.controller.sal.core.api.model.SchemaService + +@Slf4j +@ToString +class ReadableDTDelegProvider extends ProviderTrait<ReadableDataManager> { + + @Inject + BindingToNormalizedNodeCodec serializer + @Inject + SchemaService schemaService + @Inject + ModifiableReaderRegistryBuilder registry + @Inject + @Named("honeycomb-context") + DataBroker contextBroker + + def create() { + new ReadableDataTreeDelegator(serializer, schemaService.getGlobalContext(), registry.build(), contextBroker) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.groovy new file mode 100644 index 000000000..36f74d948 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.groovy @@ -0,0 +1,39 @@ +/* + * 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.infra.distro.data.oper + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.fd.honeycomb.translate.read.ReaderFactory +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder +import io.fd.honeycomb.translate.util.read.registry.CompositeReaderRegistryBuilder + +@Slf4j +@ToString +class ReaderRegistryProvider extends ProviderTrait<ModifiableReaderRegistryBuilder> { + + @Inject(optional = true) + Set<ReaderFactory> readerFactories = [] + + def create() { + def builder = new CompositeReaderRegistryBuilder() + readerFactories.forEach { it.init(builder) } + builder + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.groovy new file mode 100644 index 000000000..80b52f2b8 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.groovy @@ -0,0 +1,57 @@ +/* + * 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.infra.distro.initializer + +import com.google.inject.PrivateModule +import com.google.inject.Singleton +import com.google.inject.name.Names +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.ModifiableDataManager +import io.fd.honeycomb.data.init.InitializerRegistry +import io.fd.honeycomb.infra.distro.data.BindingDataBrokerProvider +import io.fd.honeycomb.infra.distro.data.HoneycombDOMDataBrokerProvider +import io.fd.honeycomb.infra.distro.data.ModifiableDTDelegProvider +import io.fd.honeycomb.translate.util.write.NoopWriterRegistry +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker + +@Slf4j +class InitializerPipelineModule extends PrivateModule { + + protected void configure() { + // Initializer hierarchy uses fake writer registry to not send restored configuration from plugins back to plugins + def registry = new NoopWriterRegistry() + bind(ModifiableWriterRegistryBuilder) + .annotatedWith(Names.named("honeycomb-initializer")) + .toInstance([build: { registry }]) + + // Then just build data tree delegator and DataBrokers on top of it + bind(ModifiableDataManager).toProvider(ModifiableDTDelegProvider).in(Singleton) + bind(DOMDataBroker).toProvider(HoneycombDOMDataBrokerProvider).in(Singleton) + bind(DataBroker).annotatedWith(Names.named("honeycomb-initializer")).toProvider(BindingDataBrokerProvider).in(Singleton) + expose(DataBroker).annotatedWith(Names.named("honeycomb-initializer")) + + // NOW do initializer registry + bind(InitializerRegistry) + .annotatedWith(Names.named("honeycomb-initializer")) + .toProvider(InitializerRegistryProvider) + .in(Singleton) + expose(InitializerRegistry) + .annotatedWith(Names.named("honeycomb-initializer")) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryProvider.groovy new file mode 100644 index 000000000..5f75fc026 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryProvider.groovy @@ -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.infra.distro.initializer + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.init.DataTreeInitializer +import io.fd.honeycomb.data.init.InitializerRegistry +import io.fd.honeycomb.data.init.InitializerRegistryImpl +import io.fd.honeycomb.infra.distro.ProviderTrait + +@Slf4j +@ToString +class InitializerRegistryProvider extends ProviderTrait<InitializerRegistry> { + + @Inject + @Named("honeycomb-context") + DataTreeInitializer contextInitializer + @Inject + @Named("honeycomb-config") + DataTreeInitializer configInitializer + @Inject(optional = true) + Set<DataTreeInitializer> pluginInitializers = [] + + @Override + def create() { + return new InitializerRegistry() { + + @Override + void initialize() throws DataTreeInitializer.InitializeException { + log.info("Config initialization started"); + + final InitializerRegistry initializer = new InitializerRegistryImpl(new ArrayList<>(pluginInitializers)) + + try { + // Initialize contexts first so that other initializers can find any relevant mapping before initializing + // configuration to what is already in VPP + contextInitializer.initialize(); + log.info("Persisted context restored successfully"); + // Initialize all registered initializers + initializer.initialize(); + log.info("Configuration initialized successfully"); + // Initialize stored configuration on top + configInitializer.initialize(); + log.info("Persisted configuration restored successfully"); + } catch (Exception e) { + log.warn("Failed to initialize config", e); + } + + log.info("Honeycomb initialized"); + } + + @Override + void close() throws Exception {} + } + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/PersistedFileInitializerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/PersistedFileInitializerProvider.groovy new file mode 100644 index 000000000..c2448d234 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/initializer/PersistedFileInitializerProvider.groovy @@ -0,0 +1,67 @@ +/* + * 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.infra.distro.initializer + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.data.init.RestoringInitializer +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker +import org.opendaylight.controller.sal.core.api.model.SchemaService +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.data.init.rev160407.RestorationType + +import java.nio.file.Paths +/** + * Mirror of org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.data.initializer.rev160407.PersistedFileInitializerModule + */ +@Slf4j +@ToString +abstract class PersistedFileInitializerProvider extends ProviderTrait<RestoringInitializer> { + + @Inject + SchemaService schemaService + @Inject + HoneycombConfiguration cfgAttributes + + @Inject + DOMDataBroker domDataBroker + + @Override + def create() { + new RestoringInitializer(schemaService, Paths.get(getPersistPath()), + domDataBroker, RestorationType.valueOf(restorationType), getDataStoreType()) + } + + abstract String getPersistPath() + abstract LogicalDatastoreType getDataStoreType() + abstract String getRestorationType() + + static class PersistedContextInitializerProvider extends PersistedFileInitializerProvider { + String getPersistPath() { cfgAttributes.peristContextPath } + LogicalDatastoreType getDataStoreType() { LogicalDatastoreType.OPERATIONAL } + String getRestorationType() { cfgAttributes.persistedContextRestorationType } + } + + static class PersistedConfigInitializerProvider extends PersistedFileInitializerProvider { + String getPersistPath() { cfgAttributes.peristConfigPath } + LogicalDatastoreType getDataStoreType() { LogicalDatastoreType.CONFIGURATION } + String getRestorationType() { cfgAttributes.persistedConfigRestorationType } + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/HoneycombNotification2NetconfProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/HoneycombNotification2NetconfProvider.groovy new file mode 100644 index 000000000..a18d2c4f0 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/HoneycombNotification2NetconfProvider.groovy @@ -0,0 +1,94 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.fd.honeycomb.notification.NotificationCollector +import io.fd.honeycomb.notification.impl.NotificationProducerRegistry +import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter +import org.opendaylight.controller.sal.core.api.model.SchemaService +import org.opendaylight.netconf.notifications.NetconfNotificationCollector +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.notification.impl.rev160601.HoneycombNotificationToNetconfTranslatorModule as Mirror +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714.netconf.streams.StreamBuilder +import org.opendaylight.yangtools.yang.model.api.SchemaPath +/** + * Mirror of org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.notification.impl.rev160601.HoneycombNotificationToNetconfTranslatorModule + */ +@Slf4j +@ToString +class HoneycombNotification2NetconfProvider extends ProviderTrait<HoneycombNotification2Netconf> { + + @Inject + @Named("honeycomb") + DOMNotificationRouter notificationRouter + @Inject + SchemaService schemaService + @Inject + HoneycombConfiguration cfgAttributes + @Inject + NotificationCollector hcNotificationCollector + @Inject + NetconfNotificationCollector netconfNotificationCollector + + // TODO refactor HoneycombNotificationToNetconfTranslatorModule for easier reuse here + + @Override + def create() { + def streamType = new StreamNameType(cfgAttributes.netconfNotificationStreamName); + + // Register as NETCONF notification publisher under configured name + def netconfNotifReg = netconfNotificationCollector.registerNotificationPublisher(new StreamBuilder() + .setName(streamType) + .setReplaySupport(false) + .setDescription(cfgAttributes.netconfNotificationStreamName).build()); + + // Notification Translator, get notification from HC producers and put into NETCONF notification collector + def domNotificationListener = { notif -> + log.debug "Propagating notification: {} into NETCONF", notif.type + netconfNotifReg.onNotification(streamType, Mirror.notificationToXml(notif, schemaService.globalContext)) + } + + // NotificationManager is used to provide list of available notifications (which are all of the notifications registered) + // TODO make available notifications configurable here so that any number of notification streams for NETCONF + // can be configured on top of a single notification manager + log.debug "Current notifications to be exposed over NETCONF: {}", hcNotificationCollector.notificationTypes + def currentNotificationSchemaPaths = hcNotificationCollector.notificationTypes + .collect {SchemaPath.create(true, NotificationProducerRegistry.getQName(it))} + + // Register as listener to HC'OPERATIONAL DOM notification service + // TODO This should only be triggered when NETCONF notifications are activated + // Because this way we actually start all notification producers + // final Collection<QName> notificationQNames = + def domNotifListenerReg = notificationRouter + .registerNotificationListener(domNotificationListener, currentNotificationSchemaPaths); + + log.info "Exposing NETCONF notification stream: {}", streamType.value + + new HoneycombNotification2Netconf(domNotifListenerReg: domNotifListenerReg, netconfNotifReg: netconfNotifReg) + } + + static class HoneycombNotification2Netconf { + def domNotifListenerReg + def netconfNotifReg + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfBindingBrokerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfBindingBrokerProvider.groovy new file mode 100644 index 000000000..8226c8d9e --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfBindingBrokerProvider.groovy @@ -0,0 +1,41 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.honeycomb.impl.rev141210.NetconfBindingBrokerModule + +/** + * Mirror of {@link org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.honeycomb.impl.rev141210.NetconfBindingBrokerModule} + */ +@Slf4j +@ToString +class NetconfBindingBrokerProvider extends ProviderTrait<BindingAwareBroker> { + + @Inject + @Named(NetconfModule.NETCONF) + DataBroker dataBroker + + @Override + def create() { new NetconfBindingBrokerModule.FakeBindingAwareBroker(dataBroker) } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMdsalMapperProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMdsalMapperProvider.groovy new file mode 100644 index 000000000..d84af61a8 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMdsalMapperProvider.groovy @@ -0,0 +1,55 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.sal.core.api.Broker +import org.opendaylight.controller.sal.core.api.model.SchemaService +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener +import org.opendaylight.netconf.mdsal.connector.MdsalNetconfOperationServiceFactory +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext +/** + * Mirror of org.opendaylight.controller.config.yang.netconf.mdsal.mapper.NetconfMdsalMapperModule + */ +@Slf4j +@ToString +class NetconfMdsalMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> { + + @Inject + SchemaService schemaService + @Inject + NetconfOperationServiceFactoryListener aggregator + @Inject + ModuleInfoBackedContext moduleInfoBackedContext + + @Inject + @Named("honeycomb") + Broker domBroker + + def create() { + def mdsalNetconfOperationServiceFactory = + new MdsalNetconfOperationServiceFactory(schemaService, moduleInfoBackedContext) + domBroker.registerConsumer(mdsalNetconfOperationServiceFactory); + aggregator.onAddNetconfOperationServiceFactory(mdsalNetconfOperationServiceFactory); + return mdsalNetconfOperationServiceFactory; + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfModule.groovy new file mode 100644 index 000000000..effa50cfd --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfModule.groovy @@ -0,0 +1,130 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.PrivateModule +import com.google.inject.Singleton +import com.google.inject.name.Names +import io.fd.honeycomb.infra.distro.data.BindingDataBrokerProvider +import io.fd.honeycomb.infra.distro.data.DataStoreProvider +import io.fd.honeycomb.infra.distro.data.HoneycombNotificationManagerProvider +import io.fd.honeycomb.infra.distro.data.InmemoryDOMDataBrokerProvider +import io.fd.honeycomb.notification.NotificationCollector +import io.netty.channel.nio.NioEventLoopGroup +import io.netty.util.Timer +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker +import org.opendaylight.netconf.api.NetconfServerDispatcher +import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService +import org.opendaylight.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener +import org.opendaylight.netconf.notifications.NetconfNotificationCollector +import org.opendaylight.netconf.notifications.NetconfNotificationListener +import org.opendaylight.netconf.notifications.NetconfNotificationRegistry +import org.opendaylight.netconf.notifications.impl.NetconfNotificationManager + +import static InmemoryDOMDataBrokerProvider.CONFIG +import static InmemoryDOMDataBrokerProvider.OPERATIONAL + +class NetconfModule extends PrivateModule { + + public static final String NETCONF = "netconf" + public static final String NETCONF_MAPPER_AGGREGATOR = "netconf-mapper-aggregator" + public static final String NETCONF_MAPPER_NOTIFICATION = "netconf-mapper-notification" + public static final String NETCONF_MAPPER_MONITORING = "netconf-mapper-monitoring" + public static final String NETCONF_MAPPER_HONEYCOMB = "netconf-mapper-honeycomb" + + @Override + protected void configure() { + bind(InMemoryDOMDataStore) + .annotatedWith(Names.named(CONFIG)) + .toProvider(new DataStoreProvider(type: LogicalDatastoreType.CONFIGURATION, name: CONFIG)) + .in(Singleton) + bind(InMemoryDOMDataStore) + .annotatedWith(Names.named(OPERATIONAL)) + .toProvider(new DataStoreProvider(type: LogicalDatastoreType.OPERATIONAL, name: OPERATIONAL)) + .in(Singleton) + bind(DOMDataBroker).toProvider(InmemoryDOMDataBrokerProvider).in(Singleton) + + bind(DataBroker) + .annotatedWith(Names.named(NETCONF)) + .toProvider(BindingDataBrokerProvider) + .in(Singleton) + expose(DataBroker).annotatedWith(Names.named(NETCONF)) + bind(BindingAwareBroker) + .annotatedWith(Names.named(NETCONF)) + .toProvider(NetconfBindingBrokerProvider) + .in(Singleton) + + // Mirror of org.opendaylight.controller.config.yang.config.netconf.northbound.impl.NetconfMapperAggregatorModule + def factory = new AggregatedNetconfOperationServiceFactory() + bind(NetconfOperationServiceFactory) + .annotatedWith(Names.named(NETCONF_MAPPER_AGGREGATOR)) + .toInstance(factory) + bind(NetconfOperationServiceFactoryListener).toInstance(factory) + + // Mirror of org.opendaylight.controller.config.yang.netconf.northbound.notification.impl.NetconfNotificationManagerModule + def manager = new NetconfNotificationManager() + bind(NetconfNotificationCollector).toInstance(manager) + bind(NetconfNotificationRegistry).toInstance(manager) + bind(NetconfNotificationListener).toInstance(manager) + + // Netconf notification part + bind(NetconfOperationServiceFactory) + .annotatedWith(Names.named(NETCONF_MAPPER_NOTIFICATION)) + .toProvider(NetconfNotificationMapperProvider) + .in(Singleton) + expose(NetconfOperationServiceFactory).annotatedWith(Names.named(NETCONF_MAPPER_NOTIFICATION)) + + // Netconf core part - mapping between Honeycomb and Netconf + bind(NetconfOperationServiceFactory) + .annotatedWith(Names.named(NETCONF_MAPPER_HONEYCOMB)) + .toProvider(NetconfMdsalMapperProvider) + .in(Singleton) + expose(NetconfOperationServiceFactory).annotatedWith(Names.named(NETCONF_MAPPER_HONEYCOMB)) + + // Netconf monitoring part + bind(NetconfMonitoringService).toProvider(NetconfMonitoringServiceProvider).in(Singleton) + bind(NetconfOperationServiceFactory) + .annotatedWith(Names.named(NETCONF_MAPPER_MONITORING)) + .toProvider(NetconfMonitoringMapperProvider) + .in(Singleton) + expose(NetconfOperationServiceFactory).annotatedWith(Names.named(NETCONF_MAPPER_MONITORING)) + + bind(NotificationCollector).toProvider(HoneycombNotificationManagerProvider).in(Singleton) + bind(HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf) + .toProvider(HoneycombNotification2NetconfProvider) + .in(Singleton) + expose(HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf) + + configureServer() + } + + def configureServer() { + bind(NioEventLoopGroup).toProvider(NettyThreadGroupProvider).in(Singleton) + bind(Timer).toProvider(NettyTimerProvider).in(Singleton) + bind(NetconfServerDispatcher).toProvider(NetconfServerDispatcherProvider).in(Singleton) + bind(NetconfTcpServerProvider.NetconfTcpServer).toProvider(NetconfTcpServerProvider).in(Singleton) + expose(NetconfTcpServerProvider.NetconfTcpServer) + bind(NetconfSshServerProvider.NetconfSshServer).toProvider(NetconfSshServerProvider).in(Singleton) + expose(NetconfSshServerProvider.NetconfSshServer) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringMapperProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringMapperProvider.groovy new file mode 100644 index 000000000..8f53c9d83 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringMapperProvider.groovy @@ -0,0 +1,55 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.MonitoringToMdsalWriter +import org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.NetconfMdsalMonitoringMapperModule +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker +import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener +/** + * Mirror of org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.NetconfMdsalMonitoringMapperModule + */ +@Slf4j +@ToString +class NetconfMonitoringMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> { + + @Inject + @Named(NetconfModule.NETCONF) + BindingAwareBroker bindingAwareBroker + @Inject + NetconfOperationServiceFactoryListener aggregator + @Inject + NetconfMonitoringService monitoringService + + def create() { + def monitoringToMdsalWriter = new MonitoringToMdsalWriter(monitoringService) + bindingAwareBroker.registerProvider(monitoringToMdsalWriter) + + def mdSalMonitoringMapperFactory = new NetconfMdsalMonitoringMapperModule.MdSalMonitoringMapperFactory( + new NetconfMdsalMonitoringMapperModule.MdsalMonitoringMapper(monitoringService)) + + aggregator.onAddNetconfOperationServiceFactory(mdSalMonitoringMapperFactory) + return mdSalMonitoringMapperFactory + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringReaderFactoryProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringReaderFactoryProvider.groovy new file mode 100644 index 000000000..2945ae6d8 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringReaderFactoryProvider.groovy @@ -0,0 +1,37 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.fd.honeycomb.translate.read.ReaderFactory +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.honeycomb.impl.rev141210.NetconfMonitoringReaderModule + +@Slf4j +@ToString +class NetconfMonitoringReaderFactoryProvider extends ProviderTrait<ReaderFactory> { + + @Inject + @Named(NetconfModule.NETCONF) + DataBroker netconfDataBroker + + def create() { new NetconfMonitoringReaderModule.NetconfMonitoringReaderFactory(netconfDataBroker) } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringServiceProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringServiceProvider.groovy new file mode 100644 index 000000000..5762a0a7f --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringServiceProvider.groovy @@ -0,0 +1,42 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService +import org.opendaylight.netconf.impl.osgi.NetconfMonitoringServiceImpl +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory +/** + * Mirror of org.opendaylight.controller.config.yang.config.netconf.northbound.impl.NetconfServerMonitoringModule + */ +@Slf4j +@ToString +class NetconfMonitoringServiceProvider extends ProviderTrait<NetconfMonitoringService> { + + @Inject + @Named(NetconfModule.NETCONF_MAPPER_AGGREGATOR) + NetconfOperationServiceFactory aggregator + + @Override + def create() { + new NetconfMonitoringServiceImpl(aggregator) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationMapperProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationMapperProvider.groovy new file mode 100644 index 000000000..57f7038ab --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationMapperProvider.groovy @@ -0,0 +1,72 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.config.yang.netconf.mdsal.notification.BaseCapabilityChangeNotificationPublisher +import org.opendaylight.controller.config.yang.netconf.mdsal.notification.NotificationToMdsalWriter +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener +import org.opendaylight.netconf.mdsal.notification.NetconfNotificationOperationServiceFactory +import org.opendaylight.netconf.notifications.NetconfNotificationCollector +import org.opendaylight.netconf.notifications.NetconfNotificationRegistry +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Capabilities +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +/** + * Mirror of org.opendaylight.controller.config.yang.netconf.mdsal.notification.NetconfMdsalNotificationMapperModule + */ +@Slf4j +@ToString +class NetconfNotificationMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> { + + public static final capabilitiesIdentifier = + InstanceIdentifier.create(NetconfState.class).child(Capabilities.class).builder().build() + + @Inject + NetconfNotificationCollector notificationCollector + @Inject + NetconfNotificationRegistry notificationRegistry + @Inject + @Named(NetconfModule.NETCONF) + BindingAwareBroker bindingAwareBroker + @Inject + @Named(NetconfModule.NETCONF) + DataBroker dataBroker + @Inject + NetconfOperationServiceFactoryListener aggregator + + def create() { + def notificationToMdsalWriter = new NotificationToMdsalWriter(notificationCollector) + bindingAwareBroker.registerProvider(notificationToMdsalWriter) + + def capabilityChangeListenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, capabilitiesIdentifier, + new BaseCapabilityChangeNotificationPublisher(notificationCollector.registerBaseNotificationPublisher()), AsyncDataBroker.DataChangeScope.SUBTREE) + + def netconfNotificationOperationServiceFactory = new NetconfNotificationOperationServiceFactory(notificationRegistry) + aggregator.onAddNetconfOperationServiceFactory(netconfNotificationOperationServiceFactory) + netconfNotificationOperationServiceFactory + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationsReaderFactoryProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationsReaderFactoryProvider.groovy new file mode 100644 index 000000000..45b7a1c7e --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationsReaderFactoryProvider.groovy @@ -0,0 +1,53 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.fd.honeycomb.translate.read.ReaderFactory +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder +import io.fd.honeycomb.translate.util.read.BindingBrokerReader +import org.opendaylight.controller.md.sal.binding.api.DataBroker +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714.Netconf +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714.NetconfBuilder +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier + +import javax.annotation.Nonnull + +// TODO backport to karaf distro +@Slf4j +@ToString +class NetconfNotificationsReaderFactoryProvider extends ProviderTrait<ReaderFactory> { + + @Inject + @Named(NetconfModule.NETCONF) + DataBroker netconfDataBroker + + def create() { + new ReaderFactory() { + @Override + void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { + registry.add(new BindingBrokerReader<>(InstanceIdentifier.create(Netconf.class), + netconfDataBroker, LogicalDatastoreType.OPERATIONAL, NetconfBuilder.class)); + } + } + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfReadersModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfReadersModule.groovy new file mode 100644 index 000000000..91a280857 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfReadersModule.groovy @@ -0,0 +1,36 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.AbstractModule +import com.google.inject.Singleton +import com.google.inject.multibindings.Multibinder +import groovy.util.logging.Slf4j +import io.fd.honeycomb.translate.read.ReaderFactory + +@Slf4j +class NetconfReadersModule extends AbstractModule { + + protected void configure() { + // This should be part of NetconfModule, but that one is Private and Multibinders + private BASE_MODULES + // do not work together, that's why there's a dedicated module here + Multibinder.newSetBinder(binder(), ReaderFactory.class).with { + addBinding().toProvider(NetconfMonitoringReaderFactoryProvider).in(Singleton) + addBinding().toProvider(NetconfNotificationsReaderFactoryProvider).in(Singleton) + } + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfServerDispatcherProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfServerDispatcherProvider.groovy new file mode 100644 index 000000000..072a7f6ae --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfServerDispatcherProvider.groovy @@ -0,0 +1,68 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.netty.channel.nio.NioEventLoopGroup +import io.netty.util.Timer +import org.opendaylight.netconf.api.NetconfServerDispatcher +import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService +import org.opendaylight.netconf.impl.NetconfServerDispatcherImpl +import org.opendaylight.netconf.impl.NetconfServerSessionNegotiatorFactory +import org.opendaylight.netconf.impl.SessionIdProvider +import org.opendaylight.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory +import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory + +import java.util.concurrent.TimeUnit +/** + * Mirror of org.opendaylight.controller.config.yang.config.netconf.northbound.impl.NetconfServerDispatcherModule + */ +@Slf4j +@ToString +class NetconfServerDispatcherProvider extends ProviderTrait<NetconfServerDispatcher> { + + // TODO make configurable + private static final long CONNECTION_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20) + + @Inject + @Named(NetconfModule.NETCONF_MAPPER_AGGREGATOR) + NetconfOperationServiceFactory aggregator + @Inject + NetconfMonitoringService monitoringService + @Inject + Timer timer + @Inject + NioEventLoopGroup nettyThreadgroup + + + def create() { + def netconfOperationProvider = new AggregatedNetconfOperationServiceFactory() + netconfOperationProvider.onAddNetconfOperationServiceFactory(aggregator) + + def serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( + timer, netconfOperationProvider, new SessionIdProvider(), CONNECTION_TIMEOUT_MILLIS, monitoringService); + def serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer( + serverNegotiatorFactory); + + new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup) + } + +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfSshServerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfSshServerProvider.groovy new file mode 100644 index 000000000..bce4f261a --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfSshServerProvider.groovy @@ -0,0 +1,98 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.netty.channel.ChannelFuture +import io.netty.channel.local.LocalAddress +import io.netty.channel.nio.NioEventLoopGroup +import io.netty.util.concurrent.GenericFutureListener +import io.netty.util.concurrent.GlobalEventExecutor +import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider +import org.opendaylight.netconf.api.NetconfServerDispatcher +import org.opendaylight.netconf.ssh.SshProxyServer +import org.opendaylight.netconf.ssh.SshProxyServerConfigurationBuilder + +import java.util.concurrent.Executors +import java.util.concurrent.ScheduledExecutorService +/** + * Mirror of org.opendaylight.controller.config.yang.netconf.northbound.ssh.NetconfNorthboundSshModule + */ +@Slf4j +@ToString +class NetconfSshServerProvider extends ProviderTrait<NetconfSshServer> { + + @Inject + NetconfServerDispatcher dispatcher + @Inject + HoneycombConfiguration cfgAttributes + @Inject + NioEventLoopGroup nettyThreadgroup + + // TODO merge with other executors .. one of the brokers creates also 2 internal executors + private ScheduledExecutorService pool = Executors.newScheduledThreadPool(1) + + @Override + def create() { + def name = InetAddress.getByName(cfgAttributes.netconfSshBindingAddress) + def bindingAddress = new InetSocketAddress(name, cfgAttributes.netconfSshBindingPort) + + def localAddress = new LocalAddress(cfgAttributes.netconfSshBindingPort.toString()) + def localServer = dispatcher.createLocalServer(localAddress) + + def sshProxyServer = new SshProxyServer(pool, nettyThreadgroup, GlobalEventExecutor.INSTANCE) + + def sshConfigBuilder = new SshProxyServerConfigurationBuilder() + sshConfigBuilder.bindingAddress = bindingAddress + sshConfigBuilder.localAddress = localAddress + // TODO only simple authProvider checking ConfigAttributes + sshConfigBuilder.authenticator = { String uname, String passwd -> + cfgAttributes.username == uname && cfgAttributes.password == passwd + } + sshConfigBuilder.idleTimeout = Integer.MAX_VALUE + sshConfigBuilder.keyPairProvider = new PEMGeneratorHostKeyProvider() + + localServer.addListener(new GenericFutureListener<ChannelFuture>() { + + @Override + public void operationComplete(final ChannelFuture future) { + if(future.isDone() && !future.isCancelled()) { + try { + sshProxyServer.bind(sshConfigBuilder.createSshProxyServerConfiguration()) + log.info "Netconf SSH endpoint started successfully at {}", bindingAddress + } catch (final IOException e) { + throw new RuntimeException("Unable to start SSH netconf server", e) + } + } else { + log.warn "Unable to start SSH netconf server at {}", bindingAddress, future.cause() + throw new RuntimeException("Unable to start SSH netconf server", future.cause()) + } + } + }) + + return new NetconfSshServer(localServer: localServer, sshProxyServer: sshProxyServer) + } + + static class NetconfSshServer { + def localServer + def sshProxyServer + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfTcpServerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfTcpServerProvider.groovy new file mode 100644 index 000000000..c4e3523d0 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfTcpServerProvider.groovy @@ -0,0 +1,65 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.netty.channel.ChannelFuture +import io.netty.util.concurrent.GenericFutureListener +import org.opendaylight.netconf.api.NetconfServerDispatcher +/** + * Mirror of org.opendaylight.controller.config.yang.netconf.northbound.tcp.NetconfNorthboundTcpModule + */ +@Slf4j +@ToString +class NetconfTcpServerProvider extends ProviderTrait<NetconfTcpServer> { + + @Inject + NetconfServerDispatcher dispatcher + @Inject + HoneycombConfiguration cfgAttributes + + @Override + def create() { + + def name = InetAddress.getByName(cfgAttributes.netconfTcpBindingAddress.get()) + def unresolved = new InetSocketAddress(name, cfgAttributes.netconfTcpBindingPort.get()) + + def tcpServer = dispatcher.createServer(unresolved) + + tcpServer.addListener(new GenericFutureListener<ChannelFuture>() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isDone() && future.isSuccess()) { + log.info("Netconf TCP endpoint started successfully at {}", unresolved) + } else { + log.warn("Unable to start TCP netconf server at {}", unresolved, future.cause()) + throw new RuntimeException("Unable to start TCP netconf server", future.cause()) + } + } + }) + + new NetconfTcpServer(tcpServer: tcpServer) + } + + static class NetconfTcpServer { + def tcpServer + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyThreadGroupProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyThreadGroupProvider.groovy new file mode 100644 index 000000000..da5f3d5b2 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyThreadGroupProvider.groovy @@ -0,0 +1,42 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.netty.channel.nio.NioEventLoopGroup + +/** + * Mirror of org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModule + */ +@Slf4j +@ToString +class NettyThreadGroupProvider extends ProviderTrait<NioEventLoopGroup> { + + @Inject + HoneycombConfiguration cfgAttributes + + @Override + def create() { + cfgAttributes.netconfNettyThreads.isPresent() ? + new NioEventLoopGroup(cfgAttributes.netconfNettyThreads.get()) : + new NioEventLoopGroup() + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyTimerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyTimerProvider.groovy new file mode 100644 index 000000000..347417bd2 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyTimerProvider.groovy @@ -0,0 +1,41 @@ +/* + * 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.infra.distro.netconf + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import io.netty.util.HashedWheelTimer +import io.netty.util.Timer +/** + * Mirror of org.opendaylight.controller.config.yang.netty.timer.HashedWheelTimerModule + */ +@Slf4j +@ToString +class NettyTimerProvider extends ProviderTrait<Timer> { + + @Inject + HoneycombConfiguration cfgAttributes + + @Override + def create() { + // TODO expose configuration, + new HashedWheelTimer() + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfModule.groovy new file mode 100644 index 000000000..1aa4efa9f --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfModule.groovy @@ -0,0 +1,30 @@ +/* + * 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.infra.distro.restconf + +import com.google.inject.AbstractModule +import com.google.inject.Singleton +import groovy.util.logging.Slf4j +import org.opendaylight.netconf.sal.rest.api.RestConnector + +@Slf4j +class RestconfModule extends AbstractModule { + + protected void configure() { + bind(RestConnector).toProvider(RestconfProvider).in(Singleton) + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfProvider.groovy new file mode 100644 index 000000000..f3b0852c1 --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfProvider.groovy @@ -0,0 +1,62 @@ +/* + * 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.infra.distro.restconf + +import com.google.inject.Inject +import com.google.inject.name.Named +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.eclipse.jetty.server.Server +import org.eclipse.jetty.webapp.WebAppContext +import org.opendaylight.controller.sal.core.api.Broker +import org.opendaylight.netconf.sal.rest.api.RestConnector +import org.opendaylight.netconf.sal.restconf.impl.RestconfProviderImpl +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber + +@Slf4j +@ToString +class RestconfProvider extends ProviderTrait<RestConnector> { + + @Inject + HoneycombConfiguration cfg + + @Inject + @Named("honeycomb") + Broker domBroker + + def create() { + RestconfProviderImpl instance = new RestconfProviderImpl() + instance.setWebsocketPort(new PortNumber(cfg.restconfWebsocketPort)) + domBroker.registerProvider(instance) + + Server server = new Server(cfg.restconfPort); + final URL resource = getClass().getResource("/"); + WebAppContext webapp = new WebAppContext(resource.getPath(), cfg.restconfRootPath); + server.setHandler(webapp); + + try { + server.start(); + } catch (Exception e) { + log.error "Unable to start Restconf", e + throw new RuntimeException("Unable to start Restconf", e) + } + + return instance + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.groovy new file mode 100644 index 000000000..a319bb8af --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.groovy @@ -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.infra.distro.schema + +import com.google.common.base.MoreObjects +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext +import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider + +@Slf4j +@ToString +class ModuleInfoBackedCtxProvider extends ProviderTrait<ModuleInfoBackedContext> { + + @Inject(optional = true) + Set<YangModelBindingProvider> moduleInfos = [] + + def create() { + def create = ModuleInfoBackedContext.create() + create.addModuleInfos(moduleInfos.collect {it.getModuleInfo()}) + log.debug "ModuleInfoBackedContext created from {}", moduleInfos + create + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("writerFactories", moduleInfos) + .toString(); + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.groovy new file mode 100644 index 000000000..8bb9fc65f --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.groovy @@ -0,0 +1,35 @@ +/* + * 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.infra.distro.schema + +import com.google.inject.AbstractModule +import com.google.inject.Singleton +import groovy.util.logging.Slf4j +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec +import org.opendaylight.controller.sal.core.api.model.SchemaService +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext + +@Slf4j +class SchemaModule extends AbstractModule { + + protected void configure() { + bind(ModuleInfoBackedContext).toProvider(ModuleInfoBackedCtxProvider).in(Singleton) + bind(SchemaService).toProvider(SchemaServiceProvider).in(Singleton) + bind(BindingToNormalizedNodeCodec).toProvider(SerializerProvider).in(Singleton) + } + +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.groovy new file mode 100644 index 000000000..c020d399b --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.groovy @@ -0,0 +1,79 @@ +/* + * 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.infra.distro.schema + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import org.opendaylight.controller.sal.core.api.model.SchemaService +import org.opendaylight.yangtools.concepts.ListenerRegistration +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext +import org.opendaylight.yangtools.yang.model.api.Module +import org.opendaylight.yangtools.yang.model.api.SchemaContext +import org.opendaylight.yangtools.yang.model.api.SchemaContextListener + +@Slf4j +@ToString +class SchemaServiceProvider extends ProviderTrait<SchemaService> { + + @Inject + ModuleInfoBackedContext mibCtx; + + def create() { new StaticSchemaService(mibCtx.getSchemaContext()) } + + /** + * Static schema context provider service. + */ + static class StaticSchemaService implements SchemaService { + + private final SchemaContext schemaContext + + StaticSchemaService(SchemaContext schemaContext) { + this.schemaContext = schemaContext + } + + @Override + void addModule(final Module module) { + throw new UnsupportedOperationException("Static service") + } + + @Override + void removeModule(final Module module) { + throw new UnsupportedOperationException("Static service") + } + + @Override + SchemaContext getSessionContext() { + schemaContext + } + + @Override + SchemaContext getGlobalContext() { + schemaContext + } + + @Override + ListenerRegistration<SchemaContextListener> registerSchemaContextListener(final SchemaContextListener listener) { + listener.onGlobalContextUpdated schemaContext + return new ListenerRegistration<SchemaContextListener>() { + void close() {} + SchemaContextListener getInstance() { listener } + } + } + } +} diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.groovy new file mode 100644 index 000000000..01ea006ec --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.groovy @@ -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.infra.distro.schema + +import com.google.inject.Inject +import groovy.transform.ToString +import groovy.util.logging.Slf4j +import io.fd.honeycomb.infra.distro.ProviderTrait +import javassist.ClassPool +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec +import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator +import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext +import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext +import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils + +@Slf4j +@ToString +class SerializerProvider extends ProviderTrait<BindingToNormalizedNodeCodec> { + + @Inject + ModuleInfoBackedContext mibCtx; + + def create() { + def serializerGenerator = new StreamWriterGenerator(JavassistUtils.forClassPool(ClassPool.getDefault())) + def codecRegistry = new BindingNormalizedNodeCodecRegistry(serializerGenerator) + def ctx = BindingRuntimeContext.create(mibCtx, mibCtx.getSchemaContext()) + codecRegistry.onBindingRuntimeContextUpdated(ctx) + def codec = new BindingToNormalizedNodeCodec(mibCtx, codecRegistry) + codec.onGlobalContextUpdated(mibCtx.getSchemaContext()) + codec + } +}
\ No newline at end of file diff --git a/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.groovy b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.groovy new file mode 100644 index 000000000..ebf473a3b --- /dev/null +++ b/infra/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.groovy @@ -0,0 +1,49 @@ +/* + * 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.infra.distro.schema + +import com.google.common.base.Charsets +import com.google.inject.AbstractModule +import com.google.inject.multibindings.Multibinder +import groovy.util.logging.Slf4j +import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider +/** + * Load all YangModelBindingProvider classes from classpath. + * <p/> + * Relying on /META-INF/services/ metadata. + */ +@Slf4j +class YangBindingProviderModule extends AbstractModule { + + static final String YANG_BA_PROVIDER_PATH = "META-INF/services/" + YangModelBindingProvider.class.getName(); + + void configure() { + Multibinder.newSetBinder(binder(), YangModelBindingProvider.class).with { + def resources = Collections.list(getClass().getClassLoader().getResources(YANG_BA_PROVIDER_PATH)) + log.debug "ModuleProviders found at {}", resources + resources.forEach { + it.getText(Charsets.UTF_8.displayName()).split("\n") + .findAll { it != null && !it.isEmpty() && !it.isAllWhitespace()} + .collect { this.getClass().forName(it) } + .forEach { + log.debug "ModuleProvider found for {}", it + addBinding().to(it) + } + } + } + } +} |