Honeynode test tool 53/73553/5
authorMartial COULIBALY <martial.coulibaly@gfi.fr>
Thu, 7 Jun 2018 14:25:47 +0000 (16:25 +0200)
committerguillaume.lambert <guillaume.lambert@orange.com>
Wed, 18 Jul 2018 14:40:45 +0000 (16:40 +0200)
- Add honeynode folder in tests module.
- Add some operational config files.
- Add README file.

Honeynode is base on FD.io project https://fd.io/.
Due to checkstyle warnings cause by FD.io licence
you have to compile this projects with:
mvn clean install -DskipTests=true -Dcheckstyle.skip

Change-Id: I43b94db04f27c2e93b096aa4c7488dc51ca104a2
Signed-off-by: Martial COULIBALY <martial.coulibaly@gfi.fr>
153 files changed:
tests/build.sh
tests/honeynode/README [new file with mode: 0644]
tests/honeynode/honeynode-common/asciidoc/Readme.adoc [new file with mode: 0644]
tests/honeynode/honeynode-common/pom.xml [new file with mode: 0644]
tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/AbstractDataObjectConverter.java [new file with mode: 0644]
tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/JSONDataObjectConverter.java [new file with mode: 0644]
tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/XMLDataObjectConverter.java [new file with mode: 0644]
tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/api/DataObjectConverter.java [new file with mode: 0644]
tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/test/common/DataStoreContext.java [new file with mode: 0644]
tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/test/common/DataStoreContextImpl.java [new file with mode: 0644]
tests/honeynode/honeynode-distribution/asciidoc/Readme.adoc [new file with mode: 0644]
tests/honeynode/honeynode-distribution/pom.xml [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/asciidoc/Readme.adoc [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/pom.xml [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/java/org/opendaylight/yang/gen/v1/http/org/openroadm/pm/types/rev161014/PmDataTypeBuilder.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/iana-afn-safi@2013-07-04.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/ietf-netconf@2011-06-01.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-common-types@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-common-types@2017-09-29.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-device@2017-02-06.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-equipment-states-types.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-ethernet-interfaces.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-interfaces.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-layerRate@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-lldp.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance-loopback.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance-testsignal.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-channel-interfaces.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-multiplex-interfaces.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-transport-interfaces.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-otn-odu-interfaces@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-otn-otu-interfaces@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-physical-types.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-pm-types@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-pm@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-port-types@2017-09-29.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-resource-types@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-resource@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-swdl.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-user-mgmt.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-wavelength-map@2016-10-14.yang [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/asciidoc/Readme.adoc [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/pom.xml [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceBindingDataBrokerProvider.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceConfiguration.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceConfigurationModule.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceModule.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceReaderModule.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceRpcModule.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceWriterModule.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/read/DeviceReaderFactory.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/rpcs/ConnectionPortTrailService.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/tools/DefaultDeviceFactory.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/write/DeviceWriterFactory.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/NamespaceTrimmer.xslt [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/OperToConfig.xsl [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/config.xsl [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/CreateDeviceFromXMLFileTest.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/DeviceOperToConfig.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/DirectoryWatchTest.java [new file with mode: 0644]
tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/RestAPICallsTest.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/asciidoc/Readme.adoc [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/pom.xml [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/InitializationException.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationConfig.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationModule.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModuleProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModules.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombBindingDataBrokerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMRpcServiceProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistedConfigInitializerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistingDataTreeProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryBuilderProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/PersistedContextInitializerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/RealtimeMappingContextProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/DeviceChangeListener.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapter.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapterProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/ModifiableDTDelegInitProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ResourceLoader.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModuleMappingIndex.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModulesProvider.java [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/cert/honeycomb-keystore [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/WEB-INF/web.xml [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/activation.json [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/honeycomb.json [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/logback.xml [new file with mode: 0644]
tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/honeycomb-tpce [new file with mode: 0755]
tests/honeynode/minimal-distribution/asciidoc/Readme.adoc [new file with mode: 0644]
tests/honeynode/minimal-distribution/pom.xml [new file with mode: 0644]
tests/honeynode/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/Main.java [new file with mode: 0644]
tests/honeynode/netconf/asciidoc/Readme.adoc [new file with mode: 0644]
tests/honeynode/netconf/pom.xml [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/HoneycombNotification2NetconfProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfBindingBrokerProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfConfigurationModule.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMdsalMapperProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfModule.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringMapperProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringReaderFactoryProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringServiceProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationMapperProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationsReaderFactoryProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfReadersModule.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfServerDispatcherProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfSshServerProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfTcpServerProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NettyThreadGroupProvider.java [new file with mode: 0644]
tests/honeynode/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf-whitelist.xml [new file with mode: 0644]
tests/honeynode/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf.json [new file with mode: 0644]
tests/honeynode/pom.xml [new file with mode: 0644]
tests/honeynode/restconf/asciidoc/Readme.adoc [new file with mode: 0644]
tests/honeynode/restconf/pom.xml [new file with mode: 0644]
tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpConnectorProvider.java [new file with mode: 0644]
tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpsConnectorProvider.java [new file with mode: 0644]
tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerProvider.java [new file with mode: 0644]
tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerStarter.java [new file with mode: 0644]
tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfiguration.java [new file with mode: 0644]
tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfigurationModule.java [new file with mode: 0644]
tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfModule.java [new file with mode: 0644]
tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfProvider.java [new file with mode: 0644]
tests/honeynode/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf-whitelist.xml [new file with mode: 0644]
tests/honeynode/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf.json [new file with mode: 0644]
tests/sample_configs/ord_2.1/oper-ROADMA.xml [new file with mode: 0644]
tests/sample_configs/ord_2.1/oper-ROADMC.xml [new file with mode: 0644]
tests/sample_configs/ord_2.1/oper-XPDRA.xml [new file with mode: 0644]
tests/sample_configs/ord_2.1/oper-XPDRC.xml [new file with mode: 0644]

index 676dc1c2011a16dea4b56bf36e2069877f3ddffa..a9118397bdcacd310516322288cb4b24540497ca 100755 (executable)
@@ -16,6 +16,10 @@ rm -rf netconf mdsal && git submodule update --init
 (cd netconf && patch -p1 < ../netconf.patch && patch -p1 < ../get_connection_port_trail.patch)
 
 (cd netconf/netconf/tools/netconf-testtool &&  mvn clean install -DskipTests)
+#Honeynode build
+(cd honeynode && mvn clean install -Dcheckstyle.skip -DskipTests)
+chmod +x ./honeynode/honeynode-distribution/target/honeynode-distribution-1.18.01-hc/honeynode-distribution-1.18.01/honeycomb-tpce
+>>>>>>> 196dd32... Honeynode test tool
 rm -rf schemas && mkdir -p schemas
 #sample config for ordm 2.x are not yet ready
 #cp -r ../ordmodels/common/src/main/yang/org-openroadm-* schemas
diff --git a/tests/honeynode/README b/tests/honeynode/README
new file mode 100644 (file)
index 0000000..f7158d9
--- /dev/null
@@ -0,0 +1,30 @@
+= This is a Honeycomb distribution
+
+Built from: io.fd.honeycomb.transportpce/honeynode-distribution
+Version: 1.18.01
+
+https://wiki.fd.io/view/Honeycomb
+
+== Structure
+(under folder honeynode-distribution/target/honeynode-distribution-1.18.0.1-hc/honeynode-distribution-1.18.0.1)
+
+Structure of the distribution:
+
+=== Config
+Folder config contains any configuration that's exposed by Honeycomb and its plugins
+
+=== Cert
+Keystore/Truststore for Restconf's HTTPS endpoint
+
+=== Modules
+Folder modules contains text files with list of modules to be installed into Honeycomb.
+Those modules bring up Honeycomb's infrastructure as well as modules.
+
+=== Shell scripts
+honeycomb - Start Honeycomb
+honeycomb-debug - Start Honeycomb with JVM remote debug capabilities
+honeycomb-start - Start Honeycomb in background
+honeycomb-kill - Kill all running Honeycomb instances
+honeycomb-tpce - Start Honeycomb with port and initial config files options
+Eg : honeycomb-tpce 17830 sample-config-ROADM.xml
+
diff --git a/tests/honeynode/honeynode-common/asciidoc/Readme.adoc b/tests/honeynode/honeynode-common/asciidoc/Readme.adoc
new file mode 100644 (file)
index 0000000..f8b7862
--- /dev/null
@@ -0,0 +1,3 @@
+= honeynode-common
+
+Overview of honeynode-common
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-common/pom.xml b/tests/honeynode/honeynode-common/pom.xml
new file mode 100644 (file)
index 0000000..31d8fc8
--- /dev/null
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- Copyright Â© 2017 Orange and others. All rights reserved. This program and the accompanying materials 
+    are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, 
+    and is available at http://www.eclipse.org/legal/epl-v10.html Author: Martial Coulibaly <martial.coulibaly@gfi.com> 
+    on behalf of Orange -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>io.fd.honeycomb.common</groupId>
+        <artifactId>impl-parent</artifactId>
+        <version>1.18.01</version>
+    </parent>
+
+    <groupId>io.fd.honeycomb.transportpce</groupId>
+    <artifactId>honeynode-common</artifactId>
+    <version>1.18.01</version>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <version>1.6.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.6.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-codec-xml</artifactId>
+            <version>1.2.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-codec-gson</artifactId>
+            <version>1.2.0</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/AbstractDataObjectConverter.java b/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/AbstractDataObjectConverter.java
new file mode 100644 (file)
index 0000000..8808891
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright Â© 2016 AT&T and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.fd.honeycomb.transportpce.binding.converter;
+
+import com.google.common.base.Preconditions;
+
+import io.fd.honeycomb.transportpce.binding.converter.api.DataObjectConverter;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Converts XML and {@link DataObject} vice versa.
+ *
+ */
+public abstract class AbstractDataObjectConverter implements DataObjectConverter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractDataObjectConverter.class);
+
+    private final SchemaContext schemaContext;
+    private final BindingNormalizedNodeSerializer codecRegistry;
+
+    /**
+     * This is the default constructor, which should be used.
+     *
+     * @param schemaContext schema context for converter
+     * @param codecRegistry codec registry used for converting
+     *
+     */
+    protected AbstractDataObjectConverter(SchemaContext schemaContext, BindingNormalizedNodeSerializer codecRegistry) {
+        this.schemaContext = schemaContext;
+        this.codecRegistry = codecRegistry;
+    }
+
+    public SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
+    public BindingNormalizedNodeSerializer getCodecRegistry() {
+        return codecRegistry;
+    }
+
+    /**
+     * Transforms the given input {@link NormalizedNode} into the given
+     * {@link DataObject}.
+     *
+     * @param normalizedNode normalized node you want to convert
+     * @param rootNode {@link QName} of converted normalized node root
+     *
+     * <p>
+     * The input object should be {@link ContainerNode}
+     * </p>
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends DataObject> Optional<T> getDataObject(
+            @Nonnull NormalizedNode<?, ?> normalizedNode,
+            @Nonnull QName rootNode) {
+        Preconditions.checkNotNull(normalizedNode);
+        if (normalizedNode instanceof ContainerNode) {
+            YangInstanceIdentifier.PathArgument directChildIdentifier =
+                    YangInstanceIdentifier.of(rootNode).getLastPathArgument();
+            Optional<NormalizedNode<?, ?>> directChild =
+                    NormalizedNodes.getDirectChild(normalizedNode, directChildIdentifier).toJavaUtil();
+            if (!directChild.isPresent()) {
+                throw new IllegalStateException(String.format("Could not get the direct child of %s", rootNode));
+            }
+            normalizedNode = directChild.get();
+        }
+        YangInstanceIdentifier rootNodeYangInstanceIdentifier = YangInstanceIdentifier.of(rootNode);
+
+        Map.Entry<?, ?> bindingNodeEntry =
+                codecRegistry.fromNormalizedNode(rootNodeYangInstanceIdentifier, normalizedNode);
+        if (bindingNodeEntry == null) {
+            return Optional.empty();
+        }
+        return Optional.ofNullable((T) bindingNodeEntry.getValue());
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends DataObject> Optional<T> getDataObjectFromRpc(
+            @Nonnull NormalizedNode<?, ?> normalizedNode,
+            @Nonnull SchemaPath rpcSchemaPath) {
+
+        if (! (normalizedNode instanceof ContainerNode)) {
+            LOG.error("converting normalized node is not ContainerNode. It's actual type is {}",
+                    normalizedNode.getClass().getSimpleName());
+            return Optional.empty();
+        }
+        T rpcDataObject = (T) codecRegistry.fromNormalizedNodeRpcData(rpcSchemaPath, (ContainerNode) normalizedNode);
+        return Optional.ofNullable(rpcDataObject);
+    }
+
+    @Override
+    public <T extends DataObject> Optional<NormalizedNode<?, ?>> toNormalizedNodes(@Nonnull T object,
+            Class<T> dataObjectClass) {
+        Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedNode =
+                codecRegistry.toNormalizedNode(InstanceIdentifier.create(dataObjectClass), object);
+        return Optional.ofNullable(normalizedNode.getValue());
+    }
+
+    @Override
+    public <T extends DataObject> ConvertType<T> dataContainer() {
+        return (object, objectClass) -> {
+            NormalizedNode<?, ?> value =
+                    getCodecRegistry().toNormalizedNode(InstanceIdentifier.create(objectClass), object).getValue();
+            return Optional.ofNullable(value);
+        };
+    }
+
+    @Override
+    public <T extends DataContainer> ConvertType<T> rpcData() {
+        return (object, objectClass) -> {
+            ContainerNode normalizedNodeRpcData = getCodecRegistry().toNormalizedNodeRpcData(object);
+            return Optional.ofNullable(normalizedNodeRpcData);
+        };
+    }
+
+    @Override
+    public <T extends Notification> ConvertType<T> notification() {
+        return (object, objectClass) -> {
+            ContainerNode normalizedNodeNotification = getCodecRegistry().toNormalizedNodeNotification(object);
+            return Optional.ofNullable(normalizedNodeNotification);
+        };
+    }
+}
diff --git a/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/JSONDataObjectConverter.java b/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/JSONDataObjectConverter.java
new file mode 100644 (file)
index 0000000..b878cfa
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright Â© 2016 AT&T and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.fd.honeycomb.transportpce.binding.converter;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import io.fd.honeycomb.transportpce.binding.converter.api.DataObjectConverter;
+import io.fd.honeycomb.transportpce.test.common.DataStoreContext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactory;
+import org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JSONDataObjectConverter extends AbstractDataObjectConverter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(JSONDataObjectConverter.class);
+
+    private JSONDataObjectConverter(SchemaContext schemaContext, BindingNormalizedNodeCodecRegistry codecRegistry) {
+        super(schemaContext, codecRegistry);
+    }
+
+    /**
+     * extracts codec and schema context (?).
+     *
+     * @param dataStoreContextUtil datastore context util used to extract codec and schema context
+     * @return {@link AbstractDataObjectConverter}
+     */
+    public static DataObjectConverter createWithDataStoreUtil(@Nonnull DataStoreContext dataStoreContextUtil) {
+        return new JSONDataObjectConverter(dataStoreContextUtil.getSchemaContext(),
+                dataStoreContextUtil.getBindingToNormalizedNodeCodec());
+    }
+
+    /**
+     * extracts codec and schema context (?).
+     *
+     * @param schemaContext schema context for converter
+     * @param codecRegistry codec registry used for converting
+     * @return converter
+     */
+    public static DataObjectConverter createWithSchemaContext(@Nonnull SchemaContext schemaContext,
+            @Nonnull BindingNormalizedNodeCodecRegistry codecRegistry) {
+        return new JSONDataObjectConverter(schemaContext, codecRegistry);
+    }
+
+    /**
+     * Transforms the JSON input stream into normalized nodes.
+     *
+     * @param inputStream of the given JSON
+     * @return {@link Optional} instance of {@link NormalizedNode}.
+     */
+    @Override
+    public Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull InputStream inputStream) {
+        try {
+            JsonReader reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8"));
+            return parseInputJSON(reader);
+        } catch (IOException e) {
+            LOG.warn(e.getMessage(), e);
+            return Optional.empty();
+        }
+    }
+
+    @Override
+    public Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull Reader inputReader, SchemaNode parentSchema) {
+        throw new UnsupportedOperationException("Not Implemented yet");
+    }
+
+    @Override
+    public Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull Reader inputReader) {
+        JsonReader reader = new JsonReader(inputReader);
+        return parseInputJSON(reader);
+    }
+
+    @Override
+    public <T extends DataObject> Writer writerFromDataObject(@Nonnull DataObject object, Class<T> dataObjectClass,
+            ConvertType<T> convertType) {
+        Writer writer = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(writer);
+        JSONCodecFactory jsonCodecFactory = JSONCodecFactory.createLazy(getSchemaContext());
+        NormalizedNodeStreamWriter create =
+                JSONNormalizedNodeStreamWriter.createExclusiveWriter(jsonCodecFactory, null, null, jsonWriter);
+
+        try (NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(create);) {
+            normalizedNodeWriter
+                    .write(convertType.toNormalizedNodes(dataObjectClass.cast(object), dataObjectClass).get());
+        } catch (IOException ioe) {
+            throw new IllegalStateException(ioe);
+        }
+        return writer;
+    }
+
+    @Override
+    public <T extends DataObject> Writer writerFromRpcDataObject(@Nonnull DataObject object, Class<T> dataObjectClass,
+            ConvertType<T> convertType, QName rpcOutputQName, String rpcName) {
+        return null;
+    }
+
+    /**
+     * Parses the input json with concrete implementation of {@link JsonParserStream}.
+     *
+     * @param reader of the given JSON
+     *
+     */
+    private Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> parseInputJSON(
+            JsonReader reader) {
+        NormalizedNodeResult result = new NormalizedNodeResult();
+        try (NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+            JsonParserStream jsonParser = JsonParserStream.create(streamWriter, getSchemaContext(),
+            getSchemaContext())) {
+            jsonParser.parse(reader);
+        } catch (IOException e) {
+            LOG.warn("An error {} occured during parsing Json input stream", e.getMessage(), e);
+            return Optional.empty();
+        }
+        return Optional.ofNullable(result.getResult());
+    }
+
+}
diff --git a/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/XMLDataObjectConverter.java b/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/XMLDataObjectConverter.java
new file mode 100644 (file)
index 0000000..3a95b83
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright Â© 2016 AT&T and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.fd.honeycomb.transportpce.binding.converter;
+
+import io.fd.honeycomb.transportpce.test.common.DataStoreContext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URISyntaxException;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+public class XMLDataObjectConverter extends AbstractDataObjectConverter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(XMLDataObjectConverter.class);
+
+    private final XMLInputFactory xmlInputFactory;
+
+    /**
+     * This is the default constructor, which should be used.
+     *
+     * @param schemaContext schema context for converter
+     * @param codecRegistry codec registry used for converting
+     *
+     */
+    private XMLDataObjectConverter(SchemaContext schemaContext, BindingNormalizedNodeSerializer codecRegistry) {
+        super(schemaContext, codecRegistry);
+        this.xmlInputFactory = XMLInputFactory.newInstance();
+    }
+
+    /**
+     * Extract codec and schema context (?).
+     *
+     * @param dataStoreContextUtil datastore context util used to extract codec and schema context
+     * @return {@link AbstractDataObjectConverter}
+     */
+    public static XMLDataObjectConverter createWithDataStoreUtil(@Nonnull DataStoreContext dataStoreContextUtil) {
+        BindingNormalizedNodeSerializer bindingToNormalizedNodeCodec =
+                dataStoreContextUtil.getBindingToNormalizedNodeCodec();
+        return new XMLDataObjectConverter(dataStoreContextUtil.getSchemaContext(), bindingToNormalizedNodeCodec);
+    }
+
+    /**
+     * Extract codec and schema context (?).
+     *
+     * @param schemaContext schema context for converter
+     * @param codecRegistry codec registry used for converting
+     * @return new {@link XMLDataObjectConverter}
+     */
+    public static XMLDataObjectConverter createWithSchemaContext(@Nonnull SchemaContext schemaContext,
+            @Nonnull BindingNormalizedNodeSerializer codecRegistry) {
+        return new XMLDataObjectConverter(schemaContext, codecRegistry);
+    }
+
+    /**
+     * Transforms the XML input stream into normalized nodes.
+     *
+     * @param inputStream of the given XML
+     * @return {@link Optional} instance of {@link NormalizedNode}.
+     */
+    @Override
+    public Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull InputStream inputStream) {
+        try {
+            XMLStreamReader reader = this.xmlInputFactory.createXMLStreamReader(inputStream);
+            return parseInputXML(reader);
+        } catch (XMLStreamException e) {
+            LOG.warn(e.getMessage(), e);
+            return Optional.empty();
+        }
+    }
+
+    public Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull Reader inputReader, SchemaNode parentSchema) {
+        try {
+            XMLStreamReader reader = this.xmlInputFactory.createXMLStreamReader(inputReader);
+            return parseInputXML(reader, parentSchema);
+        } catch (XMLStreamException e) {
+            LOG.warn(e.getMessage(), e);
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Transforms the XML input stream into normalized nodes.
+     *
+     * @param inputReader of the given XML
+     * @return {@link Optional} instance of {@link NormalizedNode}.
+     */
+    @Override
+    public Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull Reader inputReader) {
+        try {
+            XMLStreamReader reader = this.xmlInputFactory.createXMLStreamReader(inputReader);
+            return parseInputXML(reader);
+        } catch (XMLStreamException e) {
+            LOG.warn(e.getMessage(), e);
+            return Optional.empty();
+        }
+    }
+
+    @Override
+    public <T extends DataObject> Writer writerFromRpcDataObject(@Nonnull DataObject object, Class<T> dataObjectClass,
+            ConvertType<T> convertType, QName rpcOutputQName, String rpcName) {
+        Writer writer = new StringWriter();
+        XMLStreamWriter xmlStreamWriter = createXmlStreamWriter(writer);
+        SchemaPath rpcOutputSchemaPath = SchemaPath.create(true, QName.create(rpcOutputQName.getModule(), rpcName),
+                rpcOutputQName);
+        try (NormalizedNodeWriter normalizedNodeWriter = createWriterBackedNormalizedNodeWriter(xmlStreamWriter,
+                rpcOutputSchemaPath)) {
+            xmlStreamWriter.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX,
+                    rpcOutputQName.getLocalName(), rpcOutputQName.getNamespace().toString());
+            xmlStreamWriter.writeDefaultNamespace(rpcOutputQName.getNamespace().toString());
+            NormalizedNode<?, ?> rpcOutputNormalizedNode = convertType.toNormalizedNodes(dataObjectClass.cast(object),
+                    dataObjectClass).get();
+            for (final NormalizedNode<?, ?> child : ((ContainerNode)rpcOutputNormalizedNode).getValue()) {
+                normalizedNodeWriter.write(child);
+            }
+            normalizedNodeWriter.flush();
+            xmlStreamWriter.writeEndElement();
+            xmlStreamWriter.flush();
+        } catch (IOException | XMLStreamException ioe) {
+            throw new IllegalStateException(ioe);
+        }
+        return writer;
+    }
+
+    /**
+     * Returns a {@link Writer}.
+     *
+     * @param convertType converter used of converting into normalized node
+     * @param dataObjectClass class of converting object
+     * @param object object you want to convert
+     *
+     */
+    @Override
+    public <T extends DataObject> Writer writerFromDataObject(@Nonnull DataObject object, Class<T> dataObjectClass,
+            ConvertType<T> convertType) {
+        Writer writer = new StringWriter();
+
+        try (NormalizedNodeWriter normalizedNodeWriter = createWriterBackedNormalizedNodeWriter(writer, null)) {
+            normalizedNodeWriter
+                    .write(convertType.toNormalizedNodes(dataObjectClass.cast(object), dataObjectClass).get());
+            normalizedNodeWriter.flush();
+        } catch (IOException ioe) {
+            throw new IllegalStateException(ioe);
+        }
+        return writer;
+    }
+
+    private Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> parseInputXML(
+            XMLStreamReader reader) {
+        return parseInputXML(reader, getSchemaContext());
+    }
+
+    private Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> parseInputXML(
+            XMLStreamReader reader, SchemaNode parentSchemaNode) {
+        NormalizedNodeResult result = new NormalizedNodeResult();
+        try (NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+             XmlParserStream xmlParser = XmlParserStream.create(streamWriter, getSchemaContext(), parentSchemaNode)) {
+            xmlParser.parse(reader);
+        } catch (XMLStreamException | URISyntaxException | IOException | ParserConfigurationException
+                | SAXException e) {
+            LOG.warn("An error {} occured during parsing XML input stream", e.getMessage(), e);
+            return Optional.empty();
+        }
+        return Optional.ofNullable(result.getResult());
+    }
+
+    private NormalizedNodeWriter createWriterBackedNormalizedNodeWriter(Writer backingWriter, SchemaPath pathToParent) {
+        XMLStreamWriter createXMLStreamWriter = createXmlStreamWriter(backingWriter);
+        NormalizedNodeStreamWriter streamWriter;
+        if (pathToParent == null) {
+            streamWriter = XMLStreamNormalizedNodeStreamWriter.create(createXMLStreamWriter,
+                    getSchemaContext());
+        } else {
+            streamWriter = XMLStreamNormalizedNodeStreamWriter.create(createXMLStreamWriter,
+                    getSchemaContext(), pathToParent);
+        }
+        return NormalizedNodeWriter.forStreamWriter(streamWriter);
+    }
+
+    private NormalizedNodeWriter createWriterBackedNormalizedNodeWriter(XMLStreamWriter backingWriter,
+            SchemaPath pathToParent) {
+        NormalizedNodeStreamWriter streamWriter;
+        if (pathToParent == null) {
+            streamWriter = XMLStreamNormalizedNodeStreamWriter.create(backingWriter,
+                    getSchemaContext());
+        } else {
+            streamWriter = XMLStreamNormalizedNodeStreamWriter.create(backingWriter,
+                    getSchemaContext(), pathToParent);
+        }
+        return NormalizedNodeWriter.forStreamWriter(streamWriter);
+    }
+
+    private static XMLStreamWriter createXmlStreamWriter(Writer backingWriter) {
+        XMLStreamWriter xmlStreamWriter;
+        try {
+            XMLOutputFactory factory = XMLOutputFactory.newFactory();
+            factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
+            xmlStreamWriter = factory.createXMLStreamWriter(backingWriter);
+        } catch (XMLStreamException | FactoryConfigurationError e) {
+            LOG.error("Error [{}] while creating XML writer", e.getMessage(), e);
+            throw new IllegalStateException(e);
+        }
+        return xmlStreamWriter;
+    }
+}
diff --git a/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/api/DataObjectConverter.java b/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/binding/converter/api/DataObjectConverter.java
new file mode 100644 (file)
index 0000000..0c3a56c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright Â© 2016 AT&T and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.fd.honeycomb.transportpce.binding.converter.api;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public interface DataObjectConverter {
+
+    <T extends DataObject> Optional<T> getDataObject(
+            @Nonnull NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?> normalizedNode,
+            @Nonnull QName rootNode);
+
+    <T extends DataObject> Optional<T> getDataObjectFromRpc(
+            @Nonnull NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?> normalizedNode,
+            @Nonnull SchemaPath rpcSchemaPath);
+
+    Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull InputStream inputStream);
+
+    Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull Reader inputReader, SchemaNode parentSchema);
+
+    Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> transformIntoNormalizedNode(
+            @Nonnull Reader inputReader);
+
+    <T extends DataObject> Writer writerFromDataObject(@Nonnull DataObject object, Class<T> dataObjectClass,
+            ConvertType<T> convertType);
+
+    <T extends DataObject> Writer writerFromRpcDataObject(@Nonnull DataObject object, Class<T> dataObjectClass,
+            ConvertType<T> convertType, QName rpcOutputQName, String rpcName);
+
+    <T extends DataObject> Optional<NormalizedNode<?, ?>> toNormalizedNodes(@Nonnull T object,
+            Class<T> dataObjectClass);
+
+    public interface ConvertType<T> {
+        Optional<NormalizedNode<?, ?>> toNormalizedNodes(T object, Class<T> clazz);
+    }
+
+    /**
+     * Returns a converter for {@link DataObject} container type.
+     *
+     * @return {@link ConvertType} converter for {@link DataContainer}
+     */
+    <T extends DataObject> ConvertType<T> dataContainer();
+
+    /**
+     * Returns converter for {@link DataContainer} rpc type.
+     *
+     * @return {@link ConvertType} converter for {@link DataContainer}
+     * representing rpc data
+     */
+    <T extends DataContainer> ConvertType<T> rpcData();
+
+    /**
+     * Return converter for {@link Notification}.
+     *
+     * @return {@link ConvertType} converter for {@link Notification}
+     */
+    <T extends Notification> ConvertType<T> notification();
+
+}
diff --git a/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/test/common/DataStoreContext.java b/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/test/common/DataStoreContext.java
new file mode 100644 (file)
index 0000000..b92fe9d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright Â© 2016 AT&T and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.fd.honeycomb.transportpce.test.common;
+
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public interface DataStoreContext {
+
+//    DataBroker getDataBroker();
+//
+//    DOMDataBroker getDOMDataBroker();
+//
+//    NotificationService createNotificationService();
+//
+//    NotificationPublishService createNotificationPublishService();
+
+    SchemaContext getSchemaContext();
+
+    BindingNormalizedNodeCodecRegistry getBindingToNormalizedNodeCodec();
+
+//    NotificationService getNotificationService();
+//
+//    NotificationPublishService getNotificationPublishService();
+
+}
diff --git a/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/test/common/DataStoreContextImpl.java b/tests/honeynode/honeynode-common/src/main/java/io/fd/honeycomb/transportpce/test/common/DataStoreContextImpl.java
new file mode 100644 (file)
index 0000000..2900e9e
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright Â© 2016 AT&T and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.fd.honeycomb.transportpce.test.common;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.ServiceLoader;
+
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javassist.ClassPool;
+
+public class DataStoreContextImpl implements DataStoreContext {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DataStoreContextImpl.class);
+
+//    private final Map<LogicalDatastoreType, DOMStore> datastores;
+    private final SchemaContextHolder mockedSchemaContext;
+//    private final DOMNotificationRouter domNotificationRouter;
+//    private final DOMDataBroker domDataBroker;
+//    private final DataBroker dataBroker;
+//    private final NotificationService notificationService;
+//    private final NotificationPublishService notificationPublishService;
+
+    public DataStoreContextImpl() {
+        this(false);
+    }
+
+    public DataStoreContextImpl(boolean fromClasspath) {
+        this.mockedSchemaContext = new SchemaContextHolder(fromClasspath);
+//        this.datastores = createDatastores();
+//        this.domNotificationRouter = DOMNotificationRouter.create(16);
+//        this.domDataBroker = createDOMDataBroker();
+//        this.dataBroker = createDataBroker();
+//        this.notificationService = createNotificationService();
+//        this.notificationPublishService = createNotificationPublishService();
+//        for (ListenerRegistration<SchemaContextListener> listener : this.mockedSchemaContext.listeners) {
+//            listener.getInstance().onGlobalContextUpdated(this.mockedSchemaContext.schemaContext);
+//        }
+    }
+
+//    @Override
+//    public DataBroker getDataBroker() {
+//        return this.dataBroker;
+//    }
+//
+//    @Override
+//    public DOMDataBroker getDOMDataBroker() {
+//        return this.domDataBroker;
+//    }
+//
+//    @Override
+//    public NotificationService createNotificationService() {
+//        return new BindingDOMNotificationServiceAdapter(this.mockedSchemaContext.bindingStreamCodecs,
+//                this.domNotificationRouter);
+//    }
+//
+//    @Override
+//    public NotificationPublishService createNotificationPublishService() {
+//        return new BindingDOMNotificationPublishServiceAdapter(this.mockedSchemaContext.bindingToNormalized,
+//                this.domNotificationRouter);
+//    }
+
+    @Override
+    public SchemaContext getSchemaContext() {
+        return this.mockedSchemaContext.schemaContext;
+    }
+
+    @Override
+    public BindingNormalizedNodeCodecRegistry getBindingToNormalizedNodeCodec() {
+        return this.mockedSchemaContext.bindingStreamCodecs;
+    }
+
+//    @Override
+//    public NotificationService getNotificationService() {
+//        return this.notificationService;
+//    }
+//
+//    @Override
+//    public NotificationPublishService getNotificationPublishService() {
+//        return this.notificationPublishService;
+//    }
+//
+//    private DOMDataBroker createDOMDataBroker() {
+//        return new SerializedDOMDataBroker(this.datastores,
+//                MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
+//    }
+//
+//    private ListeningExecutorService getDataTreeChangeListenerExecutor() {
+//        return MoreExecutors.newDirectExecutorService();
+//    }
+//
+//    private DataBroker createDataBroker() {
+//        return new BindingDOMDataBrokerAdapter(getDOMDataBroker(), this.mockedSchemaContext.bindingToNormalized);
+//    }
+//
+//    private Map<LogicalDatastoreType, DOMStore> createDatastores() {
+//        return ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
+//                .put(LogicalDatastoreType.OPERATIONAL, createOperationalDatastore())
+//                .put(LogicalDatastoreType.CONFIGURATION, createConfigurationDatastore()).build();
+//    }
+//
+//    private DOMStore createConfigurationDatastore() {
+//        final InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG", getDataTreeChangeListenerExecutor());
+//        this.mockedSchemaContext.registerSchemaContextListener(store);
+//        return store;
+//    }
+//
+//    private DOMStore createOperationalDatastore() {
+//        final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", getDataTreeChangeListenerExecutor());
+//        this.mockedSchemaContext.registerSchemaContextListener(store);
+//        return store;
+//    }
+
+    private class SchemaContextHolder implements DOMSchemaService, SchemaContextProvider {
+
+        private final SchemaContext schemaContext;
+        private final ListenerRegistry<SchemaContextListener> listeners;
+        private final BindingNormalizedNodeCodecRegistry bindingStreamCodecs;
+        private final BindingToNormalizedNodeCodec bindingToNormalized;
+        private final ModuleInfoBackedContext moduleInfoBackedCntxt;
+
+        private SchemaContextHolder(boolean fromClasspath) {
+            List<YangModuleInfo> moduleInfos = loadModuleInfos();
+            this.moduleInfoBackedCntxt = ModuleInfoBackedContext.create();
+            this.schemaContext = getSchemaContext(moduleInfos);
+            this.listeners = ListenerRegistry.create();
+            this.bindingStreamCodecs = createBindingRegistry();
+            GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
+            this.bindingToNormalized = new BindingToNormalizedNodeCodec(loading, this.bindingStreamCodecs);
+            registerSchemaContextListener(this.bindingToNormalized);
+        }
+
+        @Override
+        public SchemaContext getSchemaContext() {
+            return this.schemaContext;
+        }
+
+        /**
+         * Get the schemacontext from loaded modules on classpath.
+         *
+         * @param moduleInfos a list of Yang module Infos
+         * @return SchemaContext a schema context
+         */
+        private SchemaContext getSchemaContext(List<YangModuleInfo> moduleInfos) {
+            this.moduleInfoBackedCntxt.addModuleInfos(moduleInfos);
+            Optional<SchemaContext> tryToCreateSchemaContext =
+                    this.moduleInfoBackedCntxt.tryToCreateSchemaContext().toJavaUtil();
+            if (!tryToCreateSchemaContext.isPresent()) {
+                LOG.error("Could not create the initial schema context. Schema context is empty");
+                throw new IllegalStateException();
+            }
+            return tryToCreateSchemaContext.get();
+        }
+
+        @Override
+        public SchemaContext getGlobalContext() {
+            return this.schemaContext;
+        }
+
+        @Override
+        public SchemaContext getSessionContext() {
+            return this.schemaContext;
+        }
+
+        @Override
+        public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
+                SchemaContextListener listener) {
+            return this.listeners.register(listener);
+        }
+
+        /**
+         * Loads all {@link YangModelBindingProvider} on the classpath.
+         *
+         * @return list of known {@link YangModuleInfo}
+         */
+        private List<YangModuleInfo> loadModuleInfos() {
+            List<YangModuleInfo> moduleInfos = new LinkedList<>();
+            ServiceLoader<YangModelBindingProvider> yangProviderLoader =
+                    ServiceLoader.load(YangModelBindingProvider.class);
+            for (YangModelBindingProvider yangModelBindingProvider : yangProviderLoader) {
+                moduleInfos.add(yangModelBindingProvider.getModuleInfo());
+                LOG.debug("Adding [{}] module into known modules", yangModelBindingProvider.getModuleInfo());
+            }
+            return moduleInfos;
+        }
+
+        /**
+         * Creates binding registry.
+         *
+         * @return BindingNormalizedNodeCodecRegistry the resulting binding registry
+         */
+        private BindingNormalizedNodeCodecRegistry createBindingRegistry() {
+            BindingRuntimeContext bindingContext = BindingRuntimeContext.create(this.moduleInfoBackedCntxt, this.schemaContext);
+            BindingNormalizedNodeCodecRegistry bindingNormalizedNodeCodecRegistry =
+                    new BindingNormalizedNodeCodecRegistry(
+                            StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault())));
+            bindingNormalizedNodeCodecRegistry.onBindingRuntimeContextUpdated(bindingContext);
+            return bindingNormalizedNodeCodecRegistry;
+        }
+    }
+}
diff --git a/tests/honeynode/honeynode-distribution/asciidoc/Readme.adoc b/tests/honeynode/honeynode-distribution/asciidoc/Readme.adoc
new file mode 100644 (file)
index 0000000..608fb53
--- /dev/null
@@ -0,0 +1,3 @@
+= honeynode-distribution
+
+Overview of honeynode-distribution
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-distribution/pom.xml b/tests/honeynode/honeynode-distribution/pom.xml
new file mode 100644 (file)
index 0000000..28ef548
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <parent>
+    <groupId>io.fd.honeycomb.common</groupId>
+    <artifactId>minimal-distribution-parent</artifactId>
+    <version>1.18.01</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>io.fd.honeycomb.transportpce</groupId>
+  <artifactId>honeynode-distribution</artifactId>
+  <version>1.18.01</version>
+
+  <properties>
+    <exec.parameters>-Xms128m -Xmx128m</exec.parameters>
+    <main.class>io.fd.honeycomb.infra.distro.Main</main.class>
+    <interfaces.mapping.version>1.18.01</interfaces.mapping.version>
+    <honeycomb.min.distro.version>1.18.01</honeycomb.min.distro.version>
+    <!--
+       Defines list of specific modules provided by the distribution
+       (adds them to base modules like NetconfModule and RestconfModule).
+
+       Module configuration is placed in 'modules' subdir of the target distro folder.
+       Modules can be disabled by commenting them out in the pom.xml
+       or modules configuration file.
+     -->
+    <distribution.modules>
+        io.fd.honeycomb.transportpce.device.DeviceModule,
+        io.fd.honeycomb.transportpce.device.DeviceWriterModule,
+        io.fd.honeycomb.transportpce.device.DeviceReaderModule,
+        io.fd.honeycomb.transportpce.device.DeviceRpcModule,
+    </distribution.modules>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.gmaven</groupId>
+        <artifactId>groovy-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <!-- Dependency on honeynode plugin -->
+    <dependency>
+      <groupId>io.fd.honeycomb.transportpce</groupId>
+      <artifactId>honeynode-plugin-impl</artifactId>
+      <version>${interfaces.mapping.version}</version>
+    </dependency>
+    <!-- Dependency on TPCE distribution base -->
+    <dependency>
+      <groupId>io.fd.honeycomb.transportpce</groupId>
+      <artifactId>minimal-distribution</artifactId>
+      <version>${honeycomb.min.distro.version}</version>
+    </dependency>
+
+  </dependencies>
+</project>
+
diff --git a/tests/honeynode/honeynode-plugin-api/asciidoc/Readme.adoc b/tests/honeynode/honeynode-plugin-api/asciidoc/Readme.adoc
new file mode 100644 (file)
index 0000000..ebe40ce
--- /dev/null
@@ -0,0 +1,3 @@
+= honeynode-plugin-api
+
+Overview of honeynode-plugin-api
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-plugin-api/pom.xml b/tests/honeynode/honeynode-plugin-api/pom.xml
new file mode 100644 (file)
index 0000000..5f38f09
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 Cisco and/or its affiliates.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>io.fd.honeycomb.common</groupId>
+    <artifactId>api-parent</artifactId>
+    <version>1.18.01</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>io.fd.honeycomb.transportpce</groupId>
+  <artifactId>honeynode-plugin-api</artifactId>
+  <name>honeynode-plugin-api</name>
+  <version>1.18.01</version>
+  <packaging>bundle</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>iana-if-type-2014-05-08</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-yang-types-20130715</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-interfaces</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-inet-types-2013-07-15</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>yang-ext</artifactId>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/java/org/opendaylight/yang/gen/v1/http/org/openroadm/pm/types/rev161014/PmDataTypeBuilder.java b/tests/honeynode/honeynode-plugin-api/src/main/java/org/opendaylight/yang/gen/v1/http/org/openroadm/pm/types/rev161014/PmDataTypeBuilder.java
new file mode 100644 (file)
index 0000000..8a3ec14
--- /dev/null
@@ -0,0 +1,18 @@
+package org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ *
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ *
+ */
+public class PmDataTypeBuilder {
+
+    public static PmDataType getDefaultInstance(java.lang.String defaultValue) {
+        throw new java.lang.UnsupportedOperationException("Not yet implemented");
+    }
+
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/iana-afn-safi@2013-07-04.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/iana-afn-safi@2013-07-04.yang
new file mode 100644 (file)
index 0000000..c076260
--- /dev/null
@@ -0,0 +1,526 @@
+module iana-afn-safi {
+  namespace "urn:ietf:params:xml:ns:yang:iana-afn-safi";
+  prefix "ianaaf";
+
+  organization
+    "IANA";
+  contact
+    "        Internet Assigned Numbers Authority
+
+     Postal: ICANN
+             4676 Admiralty Way, Suite 330
+             Marina del Rey, CA 90292
+
+     Tel:    +1 310 823 9358
+     E-Mail: iana&iana.org";
+  description
+    "This YANG module provides two typedefs containing YANG
+     definitions for the following IANA-registered enumerations:
+
+     - Address Family Numbers (AFN)
+
+     - Subsequent Address Family Identifiers (SAFI)
+
+     The latest revision of this YANG module can be obtained from the
+     IANA web site.
+
+     Copyright (c) 2012 IETF Trust and the persons identified as
+     authors of the code. All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject to
+     the license terms contained in, the Simplified BSD License set
+     forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see the
+     RFC itself for full legal notices.";
+  // RFC Ed.: replace XXXX with actual RFC number and remove this
+  // note.
+
+  // RFC Ed.: update the date below with the date of RFC publication
+  // and remove this note.
+  revision 2013-07-04 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: IANA Address Family Numbers and
+                 Subsequent Address Family Identifiers YANG Module";
+  }
+
+  typedef address-family {
+    type enumeration {
+      // value 0 is reserved by IANA
+      enum ipV4 {
+        value "1";
+        description
+          "IP version 4";
+      }
+      enum ipV6 {
+        value "2";
+        description
+          "IP version 6";
+      }
+      enum nsap {
+        value "3";
+        description
+          "NSAP";
+      }
+      enum hdlc {
+        value "4";
+        description
+          "HDLC (8-bit multidrop)";
+      }
+      enum bbn1822 {
+        value "5";
+        description
+          "BBN 1822";
+      }
+      enum all802 {
+        value "6";
+        description
+          "802 (includes all 802 media plus Ethernet 'canonical
+           format')";
+      }
+      enum e163 {
+        value "7";
+        description
+          "E.163";
+      }
+      enum e164 {
+        value "8";
+        description
+          "E.164 (SMDS, FrameRelay, ATM)";
+      }
+      enum f69 {
+        value "9";
+        description
+          "F.69 (Telex)";
+      }
+      enum x121 {
+        value "10";
+        description
+          "X.121 (X.25, Frame Relay)";
+      }
+      enum ipx {
+        value "11";
+        description
+          "IPX (Internetwork Packet Exchange)";
+      }
+      enum appletalk {
+        value "12";
+        description
+          "Appletalk";
+      }
+      enum decnetIV {
+        value "13";
+        description
+          "DECnet IV";
+      }
+      enum banyanVines {
+        value "14";
+        description
+          "Banyan Vines";
+      }
+      enum e164withNsap {
+        value "15";
+        description
+          "E.164 with NSAP format subaddress";
+        reference
+          "ATM Forum UNI 3.1";
+      }
+      enum dns {
+        value "16";
+        description
+          "DNS (Domain Name System)";
+      }
+      enum distinguishedName {
+        value "17";
+        description
+          "Distinguished Name (per X.500)";
+      }
+      enum asNumber {
+        value "18";
+        description
+          "Autonomous System Number";
+      }
+      enum xtpOverIpv4 {
+        value "19";
+        description
+          "XTP over IP version 4";
+      }
+      enum xtpOverIpv6 {
+        value "20";
+        description
+          "XTP over IP version 6";
+      }
+      enum xtpNativeModeXTP {
+        value "21";
+        description
+          "XTP native mode XTP";
+      }
+      enum fibreChannelWWPN {
+        value "22";
+        description
+          "Fibre Channel World-Wide Port Name";
+      }
+      enum fibreChannelWWNN {
+        value "23";
+        description
+          "Fibre Channel World-Wide Node Name";
+      }
+      enum gwid {
+        value "24";
+        description
+          "Gateway Identifier";
+      }
+      // FIXME: This one is actually called "afi" in the MIB, but
+      // that must be a mistake.
+      enum l2vpn {
+        value "25";
+        description
+          "AFI for L2VPN information";
+        reference
+          "RFC 4761: Virtual Private LAN Service (VPLS): Using BGP
+           for Auto-Discovery and Signaling
+
+           RFC 6074: Provisioning, Auto-Discovery, and Signaling in
+           Layer 2 Virtual Private Networks (L2VPNs)";
+      }
+      enum mplsTpSectionEndpointIdentifier {
+        value "26";
+        description
+          "MPLS-TP Section Endpoint Identifier";
+        reference
+          "draft-ietf-mpls-gach-adv";
+      }
+      enum mplsTpLspEndpointIdentifier {
+        value "27";
+        description
+          "MPLS-TP LSP Endpoint Identifier";
+        reference
+          "draft-ietf-mpls-gach-adv";
+      }
+      enum mplsTpPseudowireEndpointIdentifier {
+        value "28";
+        description
+          "MPLS-TP Pseudowire Endpoint Identifier";
+        reference
+          "draft-ietf-mpls-gach-adv";
+      }
+      enum eigrpCommonServiceFamily {
+        value "16384";
+        description
+          "EIGRP Common Service Family";
+      }
+      enum eigrpIpv4ServiceFamily {
+        value "16385";
+        description
+          "EIGRP IPv4 Service Family";
+      }
+      enum eigrpIpv6ServiceFamily {
+        value "16386";
+        description
+          "EIGRP IPv6 Service Family";
+      }
+      enum lispCanonicalAddressFormat {
+        value "16387";
+        description
+          "LISP Canonical Address Format (LCAF)";
+      }
+      enum bgpLs {
+        value "16388";
+        description
+          "BGP-LS";
+        reference
+          "draft-ietf-idr-ls-distribution";
+      }
+      enum 48BitMac {
+        value "16389";
+        description
+          "48-bit MAC";
+        reference
+          "draft-eastlake-rfc5342bis";
+      }
+      enum 64BitMac {
+        value "16390";
+        description
+          "64-bit MAC";
+        reference
+          "draft-eastlake-rfc5342bis";
+      }
+      // value 65535 is reserved by IANA
+    }
+    description
+      "This typedef is a YANG enumeration of IANA-registered address
+       family numbers (AFN).";
+    reference
+      "IANA Address Family Numbers registry.
+       <http://www.iana.org/assignments/address-family-numbers>";
+  }
+
+  typedef subsequent-address-family {
+    type enumeration {
+      // value 0 is reserved by IANA
+      enum nlriUnicast {
+        value "1";
+        description
+          "Network Layer Reachability Information used for unicast
+           forwarding";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum nlriMulticast {
+        value "2";
+        description
+          "Network Layer Reachability Information used for multicast
+           forwarding";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      // value 3 is reserved by IANA
+      enum nlriMpls {
+        value "4";
+        description
+          "Network Layer Reachability Information (NLRI) with MPLS
+           Labels";
+        reference
+          "RFC 3107: Carrying Label Information in BGP-4";
+      }
+      enum mcastVpn {
+        value "5";
+        description
+          "MCAST-VPN";
+        reference
+          "RFC 6514: BGP Encodings and Procedures for Multicast in
+           MPLS/BGP IP VPNs";
+      }
+      enum nlriDynamicMsPw {
+        value "6";
+        status "obsolete";
+        description
+          "Network Layer Reachability Information used for Dynamic
+           Placement of Multi-Segment Pseudowires (TEMPORARY -
+           Expires 2008-08-23)";
+        reference
+          "draft-ietf-pwe3-dynamic-ms-pw: Dynamic Placement of Multi
+           Segment Pseudowires";
+      }
+      enum encapsulation {
+        value "7";
+        description
+          "Encapsulation SAFI";
+        reference
+          "RFC 5512: The BGP Encapsulation Subsequent Address Family
+           Identifier (SAFI) and the BGP Tunnel Encapsulation
+           Attribute";
+      }
+      enum tunnel {
+        value "64";
+        status "obsolete";
+        description
+          "Tunnel SAFI";
+        reference
+          "draft-nalawade-kapoor-tunnel-safi: BGP Tunnel SAFI";
+      }
+      enum vpls {
+        value "65";
+        description
+          "Virtual Private LAN Service (VPLS)";
+        reference
+          "RFC 4761: Virtual Private LAN Service (VPLS): Using BGP
+           for Auto-Discovery and Signaling
+
+           RFC 6074: Provisioning, Auto-Discovery, and Signaling in
+           Layer 2 Virtual Private Networks (L2VPNs)";
+      }
+      enum bgpMdt {
+        value "66";
+        description
+          "BGP MDT SAFI";
+        reference
+          "RFC 6037: Cisco Systems' Solution for Multicast in
+           BGP/MPLS IP VPNs";
+      }
+      enum bgp4over6 {
+        value "67";
+        description
+          "BGP 4over6 SAFI";
+        reference
+          "RFC 5747: 4over6 Transit Solution Using IP Encapsulation
+           and MP-BGP Extensions";
+      }
+      enum bgp6over4 {
+        value "68";
+        description
+          "BGP 6over4 SAFI";
+      }
+      enum l1VpnAutoDiscovery {
+        value "69";
+        description
+          "Layer-1 VPN auto-discovery information";
+        reference
+          "RFC 5195: BGP-Based Auto-Discovery for Layer-1 VPNs";
+      }
+      enum mplsVpn {
+        value "128";
+        description
+          "MPLS-labeled VPN address";
+        reference
+          "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs)";
+      }
+      enum multicastBgpMplsVpn {
+        value "129";
+        description
+          "Multicast for BGP/MPLS IP Virtual Private Networks
+           (VPNs)";
+        reference
+          "RFC 6513: Multicast in MPLS/BGP IP VPNs
+
+           RFC 6514: BGP Encodings and Procedures for Multicast in
+           MPLS/BGP IP VPNs";
+      }
+      // values 130-131 are reserved by IANA
+      enum routeTargetConstraints {
+        value "132";
+        description
+          "Route Target constraints";
+        reference
+          "RFC 4684: Constrained Route Distribution for Border
+           Gateway Protocol/MultiProtocol Label Switching (BGP/MPLS)
+           Internet Protocol (IP) Virtual Private Networks (VPNs)";
+      }
+      enum ipv4DissFlow {
+        value "133";
+        description
+          "IPv4 dissemination of flow specification rules";
+        reference
+          "RFC 5575: Dissemination of Flow Specification Rules";
+      }
+      enum vpnv4DissFlow {
+        value "134";
+        description
+          "VPNv4 dissemination of flow specification rules";
+        reference
+          "RFC 5575: Dissemination of Flow Specification Rules";
+      }
+      // values 135-139 are reserved by IANA
+      enum vpnAutoDiscovery {
+        value "140";
+        status "obsolete";
+        description
+          "VPN auto-discovery";
+        reference
+          "draft-ietf-l3vpn-bgpvpn-auto: Using BGP as an
+           Auto-Discovery Mechanism for VR-based Layer-3 VPNs";
+      }
+      // values 141-240 are reserved by IANA
+      enum private241 {
+        value "241";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private242 {
+        value "242";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private243 {
+        value "243";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private244 {
+        value "244";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private245 {
+        value "245";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private246 {
+        value "246";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private247 {
+        value "247";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private248 {
+        value "248";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private249 {
+        value "249";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private250 {
+        value "250";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private251 {
+        value "251";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private252 {
+        value "252";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private253 {
+        value "253";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private254 {
+        value "254";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      // value 255 is reserved by IANA
+    }
+    description
+      "This typedef is a YANG enumeration of IANA-registered
+       subsequent address family identifiers (SAFI).";
+    reference
+      "IANA SAFI Values registry.
+       <http://www.iana.org/assignments/safi-namespace>";
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/ietf-netconf@2011-06-01.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/ietf-netconf@2011-06-01.yang
new file mode 100644 (file)
index 0000000..4bbb1c2
--- /dev/null
@@ -0,0 +1,928 @@
+module ietf-netconf {
+
+  // the namespace for NETCONF XML definitions is unchanged
+  // from RFC 4741, which this document replaces
+  namespace "urn:ietf:params:xml:ns:netconf:base:1.0";
+
+  prefix nc;
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  organization
+    "IETF NETCONF (Network Configuration) Working Group";
+
+  contact
+    "WG Web:   <http://tools.ietf.org/wg/netconf/>
+     WG List:  <netconf@ietf.org>
+
+     WG Chair: Bert Wijnen
+               <bertietf@bwijnen.net>
+
+     WG Chair: Mehmet Ersue
+               <mehmet.ersue@nsn.com>
+
+     Editor:   Martin Bjorklund
+               <mbj@tail-f.com>
+
+     Editor:   Juergen Schoenwaelder
+               <j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Andy Bierman
+               <andy.bierman@brocade.com>";
+  description
+    "NETCONF Protocol Data Types and Protocol Operations.
+
+     Copyright (c) 2011 IETF Trust and the persons identified as
+     the document authors.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6241; see
+     the RFC itself for full legal notices.";
+
+  revision 2011-06-01 {
+    description
+      "Initial revision;";
+    reference
+      "RFC 6241: Network Configuration Protocol";
+  }
+
+  extension get-filter-element-attributes {
+    description
+      "If this extension is present within an 'anyxml'
+       statement named 'filter', which must be conceptually
+       defined within the RPC input section for the <get>
+       and <get-config> protocol operations, then the
+       following unqualified XML attribute is supported
+       within the <filter> element, within a <get> or
+       <get-config> protocol operation:
+
+         type : optional attribute with allowed
+                value strings 'subtree' and 'xpath'.
+                If missing, the default value is 'subtree'.
+
+       If the 'xpath' feature is supported, then the
+       following unqualified XML attribute is
+       also supported:
+
+         select: optional attribute containing a
+                 string representing an XPath expression.
+                 The 'type' attribute must be equal to 'xpath'
+                 if this attribute is present.";
+  }
+
+  // NETCONF capabilities defined as features
+  feature writable-running {
+    description
+      "NETCONF :writable-running capability;
+       If the server advertises the :writable-running
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.2";
+  }
+
+  feature candidate {
+    description
+      "NETCONF :candidate capability;
+       If the server advertises the :candidate
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.3";
+  }
+
+  feature confirmed-commit {
+    if-feature candidate;
+    description
+      "NETCONF :confirmed-commit:1.1 capability;
+       If the server advertises the :confirmed-commit:1.1
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+
+    reference "RFC 6241, Section 8.4";
+  }
+
+  feature rollback-on-error {
+    description
+      "NETCONF :rollback-on-error capability;
+       If the server advertises the :rollback-on-error
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.5";
+  }
+
+  feature validate {
+    description
+      "NETCONF :validate:1.1 capability;
+       If the server advertises the :validate:1.1
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.6";
+  }
+
+  feature startup {
+    description
+      "NETCONF :startup capability;
+       If the server advertises the :startup
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.7";
+  }
+
+  feature url {
+    description
+      "NETCONF :url capability;
+       If the server advertises the :url
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.8";
+  }
+
+  feature xpath {
+    description
+      "NETCONF :xpath capability;
+       If the server advertises the :xpath
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.9";
+  }
+
+  // NETCONF Simple Types
+
+  typedef session-id-type {
+    type uint32 {
+      range "1..max";
+    }
+    description
+      "NETCONF Session Id";
+  }
+
+  typedef session-id-or-zero-type {
+    type uint32;
+    description
+      "NETCONF Session Id or Zero to indicate none";
+  }
+  typedef error-tag-type {
+    type enumeration {
+       enum in-use {
+         description
+           "The request requires a resource that
+            already is in use.";
+       }
+       enum invalid-value {
+         description
+           "The request specifies an unacceptable value for one
+            or more parameters.";
+       }
+       enum too-big {
+         description
+           "The request or response (that would be generated) is
+            too large for the implementation to handle.";
+       }
+       enum missing-attribute {
+         description
+           "An expected attribute is missing.";
+       }
+       enum bad-attribute {
+         description
+           "An attribute value is not correct; e.g., wrong type,
+            out of range, pattern mismatch.";
+       }
+       enum unknown-attribute {
+         description
+           "An unexpected attribute is present.";
+       }
+       enum missing-element {
+         description
+           "An expected element is missing.";
+       }
+       enum bad-element {
+         description
+           "An element value is not correct; e.g., wrong type,
+            out of range, pattern mismatch.";
+       }
+       enum unknown-element {
+         description
+           "An unexpected element is present.";
+       }
+       enum unknown-namespace {
+         description
+           "An unexpected namespace is present.";
+       }
+       enum access-denied {
+         description
+           "Access to the requested protocol operation or
+            data model is denied because authorization failed.";
+       }
+       enum lock-denied {
+         description
+           "Access to the requested lock is denied because the
+            lock is currently held by another entity.";
+       }
+       enum resource-denied {
+         description
+           "Request could not be completed because of
+            insufficient resources.";
+       }
+       enum rollback-failed {
+         description
+           "Request to roll back some configuration change (via
+            rollback-on-error or <discard-changes> operations)
+            was not completed for some reason.";
+
+       }
+       enum data-exists {
+         description
+           "Request could not be completed because the relevant
+            data model content already exists.  For example,
+            a 'create' operation was attempted on data that
+            already exists.";
+       }
+       enum data-missing {
+         description
+           "Request could not be completed because the relevant
+            data model content does not exist.  For example,
+            a 'delete' operation was attempted on
+            data that does not exist.";
+       }
+       enum operation-not-supported {
+         description
+           "Request could not be completed because the requested
+            operation is not supported by this implementation.";
+       }
+       enum operation-failed {
+         description
+           "Request could not be completed because the requested
+            operation failed for some reason not covered by
+            any other error condition.";
+       }
+       enum partial-operation {
+         description
+           "This error-tag is obsolete, and SHOULD NOT be sent
+            by servers conforming to this document.";
+       }
+       enum malformed-message {
+         description
+           "A message could not be handled because it failed to
+            be parsed correctly.  For example, the message is not
+            well-formed XML or it uses an invalid character set.";
+       }
+     }
+     description "NETCONF Error Tag";
+     reference "RFC 6241, Appendix A";
+  }
+
+  typedef error-severity-type {
+    type enumeration {
+      enum error {
+        description "Error severity";
+      }
+      enum warning {
+        description "Warning severity";
+      }
+    }
+    description "NETCONF Error Severity";
+    reference "RFC 6241, Section 4.3";
+  }
+
+  typedef edit-operation-type {
+    type enumeration {
+      enum merge {
+        description
+          "The configuration data identified by the
+           element containing this attribute is merged
+           with the configuration at the corresponding
+           level in the configuration datastore identified
+           by the target parameter.";
+      }
+      enum replace {
+        description
+          "The configuration data identified by the element
+           containing this attribute replaces any related
+           configuration in the configuration datastore
+           identified by the target parameter.  If no such
+           configuration data exists in the configuration
+           datastore, it is created.  Unlike a
+           <copy-config> operation, which replaces the
+           entire target configuration, only the configuration
+           actually present in the config parameter is affected.";
+      }
+      enum create {
+        description
+          "The configuration data identified by the element
+           containing this attribute is added to the
+           configuration if and only if the configuration
+           data does not already exist in the configuration
+           datastore.  If the configuration data exists, an
+           <rpc-error> element is returned with an
+           <error-tag> value of 'data-exists'.";
+      }
+      enum delete {
+        description
+          "The configuration data identified by the element
+           containing this attribute is deleted from the
+           configuration if and only if the configuration
+           data currently exists in the configuration
+           datastore.  If the configuration data does not
+           exist, an <rpc-error> element is returned with
+           an <error-tag> value of 'data-missing'.";
+      }
+      enum remove {
+        description
+          "The configuration data identified by the element
+           containing this attribute is deleted from the
+           configuration if the configuration
+           data currently exists in the configuration
+           datastore.  If the configuration data does not
+           exist, the 'remove' operation is silently ignored
+           by the server.";
+      }
+    }
+    default "merge";
+    description "NETCONF 'operation' attribute values";
+    reference "RFC 6241, Section 7.2";
+  }
+
+  // NETCONF Standard Protocol Operations
+
+  rpc get-config {
+    description
+      "Retrieve all or part of a specified configuration.";
+
+    reference "RFC 6241, Section 7.1";
+
+    input {
+      container source {
+        description
+          "Particular configuration to retrieve.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration to retrieve.";
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.
+               This is optional-to-implement on the server because
+               not all servers will support filtering for this
+               datastore.";
+          }
+        }
+      }
+
+      anyxml filter {
+        description
+          "Subtree or XPath filter to use.";
+        nc:get-filter-element-attributes;
+      }
+    }
+
+    output {
+      anyxml data {
+        description
+          "Copy of the source datastore subset that matched
+           the filter criteria (if any).  An empty data container
+           indicates that the request did not produce any results.";
+      }
+    }
+  }
+
+  rpc edit-config {
+    description
+      "The <edit-config> operation loads all or part of a specified
+       configuration to the specified target configuration.";
+
+    reference "RFC 6241, Section 7.2";
+
+    input {
+      container target {
+        description
+          "Particular configuration to edit.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            if-feature writable-running;
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+        }
+      }
+
+      leaf default-operation {
+        type enumeration {
+          enum merge {
+            description
+              "The default operation is merge.";
+          }
+          enum replace {
+            description
+              "The default operation is replace.";
+          }
+          enum none {
+            description
+              "There is no default operation.";
+          }
+        }
+        default "merge";
+        description
+          "The default operation to use.";
+      }
+
+      leaf test-option {
+        if-feature validate;
+        type enumeration {
+          enum test-then-set {
+            description
+              "The server will test and then set if no errors.";
+          }
+          enum set {
+            description
+              "The server will set without a test first.";
+          }
+
+          enum test-only {
+            description
+              "The server will only test and not set, even
+               if there are no errors.";
+          }
+        }
+        default "test-then-set";
+        description
+          "The test option to use.";
+      }
+
+      leaf error-option {
+        type enumeration {
+          enum stop-on-error {
+            description
+              "The server will stop on errors.";
+          }
+          enum continue-on-error {
+            description
+              "The server may continue on errors.";
+          }
+          enum rollback-on-error {
+            description
+              "The server will roll back on errors.
+               This value can only be used if the 'rollback-on-error'
+               feature is supported.";
+          }
+        }
+        default "stop-on-error";
+        description
+          "The error option to use.";
+      }
+
+      choice edit-content {
+        mandatory true;
+        description
+          "The content for the edit operation.";
+
+        anyxml config {
+          description
+            "Inline Config content.";
+        }
+        leaf url {
+          if-feature url;
+          type inet:uri;
+          description
+            "URL-based config content.";
+        }
+      }
+    }
+  }
+
+  rpc copy-config {
+    description
+      "Create or replace an entire configuration datastore with the
+       contents of another complete configuration datastore.";
+
+    reference "RFC 6241, Section 7.3";
+
+    input {
+      container target {
+        description
+          "Particular configuration to copy to.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target of the copy operation.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            if-feature writable-running;
+            type empty;
+            description
+              "The running configuration is the config target.
+               This is optional-to-implement on the server.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config target.";
+          }
+        }
+      }
+
+      container source {
+        description
+          "Particular configuration to copy from.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration source for the copy operation.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config source.";
+          }
+          anyxml config {
+            description
+              "Inline Config content: <config> element.  Represents
+               an entire configuration datastore, not
+               a subset of the running datastore.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc delete-config {
+    description
+      "Delete a configuration datastore.";
+
+    reference "RFC 6241, Section 7.4";
+
+    input {
+      container target {
+        description
+          "Particular configuration to delete.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to delete.";
+
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc lock {
+    description
+      "The lock operation allows the client to lock the configuration
+       system of a device.";
+
+    reference "RFC 6241, Section 7.5";
+
+    input {
+      container target {
+        description
+          "Particular configuration to lock.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to lock.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config target.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc unlock {
+    description
+      "The unlock operation is used to release a configuration lock,
+       previously obtained with the 'lock' operation.";
+
+    reference "RFC 6241, Section 7.6";
+
+    input {
+      container target {
+        description
+          "Particular configuration to unlock.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to unlock.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config target.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc get {
+    description
+      "Retrieve running configuration and device state information.";
+
+    reference "RFC 6241, Section 7.7";
+
+    input {
+      anyxml filter {
+        description
+          "This parameter specifies the portion of the system
+           configuration and state data to retrieve.";
+        nc:get-filter-element-attributes;
+      }
+    }
+
+    output {
+      anyxml data {
+        description
+          "Copy of the running datastore subset and/or state
+           data that matched the filter criteria (if any).
+           An empty data container indicates that the request did not
+           produce any results.";
+      }
+    }
+  }
+
+  rpc close-session {
+    description
+      "Request graceful termination of a NETCONF session.";
+
+    reference "RFC 6241, Section 7.8";
+  }
+
+  rpc kill-session {
+    description
+      "Force the termination of a NETCONF session.";
+
+    reference "RFC 6241, Section 7.9";
+
+    input {
+      leaf session-id {
+        type session-id-type;
+        mandatory true;
+        description
+          "Particular session to kill.";
+      }
+    }
+  }
+
+  rpc commit {
+    if-feature candidate;
+
+    description
+      "Commit the candidate configuration as the device's new
+       current configuration.";
+
+    reference "RFC 6241, Section 8.3.4.1";
+
+    input {
+      leaf confirmed {
+        if-feature confirmed-commit;
+        type empty;
+        description
+          "Requests a confirmed commit.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf confirm-timeout {
+        if-feature confirmed-commit;
+        type uint32 {
+          range "1..max";
+        }
+        units "seconds";
+        default "600";   // 10 minutes
+        description
+          "The timeout interval for a confirmed commit.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf persist {
+        if-feature confirmed-commit;
+        type string;
+        description
+          "This parameter is used to make a confirmed commit
+           persistent.  A persistent confirmed commit is not aborted
+           if the NETCONF session terminates.  The only way to abort
+           a persistent confirmed commit is to let the timer expire,
+           or to use the <cancel-commit> operation.
+
+           The value of this parameter is a token that must be given
+           in the 'persist-id' parameter of <commit> or
+           <cancel-commit> operations in order to confirm or cancel
+           the persistent confirmed commit.
+
+           The token should be a random string.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf persist-id {
+        if-feature confirmed-commit;
+        type string;
+        description
+          "This parameter is given in order to commit a persistent
+           confirmed commit.  The value must be equal to the value
+           given in the 'persist' parameter to the <commit> operation.
+           If it does not match, the operation fails with an
+          'invalid-value' error.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+    }
+  }
+
+  rpc discard-changes {
+    if-feature candidate;
+
+    description
+      "Revert the candidate configuration to the current
+       running configuration.";
+    reference "RFC 6241, Section 8.3.4.2";
+  }
+
+  rpc cancel-commit {
+    if-feature confirmed-commit;
+    description
+      "This operation is used to cancel an ongoing confirmed commit.
+       If the confirmed commit is persistent, the parameter
+       'persist-id' must be given, and it must match the value of the
+       'persist' parameter.";
+    reference "RFC 6241, Section 8.4.4.1";
+
+    input {
+      leaf persist-id {
+        type string;
+        description
+          "This parameter is given in order to cancel a persistent
+           confirmed commit.  The value must be equal to the value
+           given in the 'persist' parameter to the <commit> operation.
+           If it does not match, the operation fails with an
+          'invalid-value' error.";
+      }
+    }
+  }
+
+  rpc validate {
+    if-feature validate;
+
+    description
+      "Validates the contents of the specified configuration.";
+
+    reference "RFC 6241, Section 8.6.4.1";
+
+    input {
+      container source {
+        description
+          "Particular configuration to validate.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration source to validate.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config source.";
+          }
+          anyxml config {
+            description
+              "Inline Config content: <config> element.  Represents
+               an entire configuration datastore, not
+               a subset of the running datastore.";
+          }
+        }
+      }
+    }
+  }
+
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-common-types@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-common-types@2016-10-14.yang
new file mode 100644 (file)
index 0000000..e52b12b
--- /dev/null
@@ -0,0 +1,282 @@
+module org-openroadm-common-types {
+  namespace "http://org/openroadm/common-types";
+  prefix org-openroadm-common-types;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of common types.
+
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+      AT&T Intellectual Property.  All other rights reserved.
+
+      Redistribution and use in source and binary forms, with or without modification,
+      are permitted provided that the following conditions are met:
+
+      * Redistributions of source code must retain the above copyright notice, this
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice,
+        this list of conditions and the following disclaimer in the documentation and/or
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+        contributors may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping physical-location {
+    leaf rack {
+      type string;
+      mandatory false;
+    }
+    leaf shelf {
+      type string;
+      mandatory false;
+    }
+    leaf slot {
+      type string;
+      mandatory false;
+    }
+    leaf subSlot {
+      type string;
+      mandatory false;
+    }
+  }
+
+  typedef node-types {
+    type enumeration {
+      enum "rdm" {
+        value 1;
+      }
+      enum "xpdr" {
+        value 2;
+      }
+    }
+    description
+      "3 digit identifier for node type
+       1. rdm for ROADM
+       2. xpdr for Transponder, Regen";
+  }
+
+  typedef power-dBm {
+    description
+      "Power value in dBm.";
+    type decimal64 {
+      fraction-digits 2;
+    }
+    units "dBm";
+  }
+
+  typedef ratio-dB {
+    description
+      "Power ratio in dB.";
+    type decimal64 {
+      fraction-digits 3;
+    }
+    units "dB";
+  }
+
+  typedef severity {
+    description
+      "Severity, based on X.733 perceived severity";
+    type enumeration {
+      enum "critical" {
+        value 1;
+      }
+      enum "major" {
+        value 2;
+      }
+      enum "minor" {
+        value 3;
+      }
+      enum "warning" {
+        value 4;
+      }
+      enum "clear" {
+        value 5;
+      }
+      enum "indeterminate" {
+        value 6;
+      }
+    }
+  }
+
+  typedef rpc-status {
+    description
+      "status of RPC ";
+    type enumeration {
+      enum "Successful" {
+        value 1;
+      }
+      enum "Failed" {
+        value 2;
+      }
+    }
+  }
+
+  grouping rpc-response-status {
+    leaf status {
+      type rpc-status;
+      mandatory true;
+      description
+        "Successful or Failed";
+    }
+    leaf status-message {
+      type string;
+      description
+        "Gives a more detailed reason for failure";
+    }
+  }
+
+  typedef lifecycle-state {
+    description
+      "Lifecycle state.";
+    type enumeration {
+      enum "deployed" {
+        value 1;
+      }
+      enum "planned" {
+        value 2;
+      }
+      enum "maintenance" {
+        value 3;
+      }
+      enum "deploying" {
+        value 4;
+      }
+      enum "undeploying" {
+        value 5;
+      }
+    }
+  }
+
+  typedef state {
+    description
+      "State that indicates whether the resource is able to provide fullfill its role - carry traffic, etc.";
+    type enumeration {
+      enum "inService" {
+        value 1;
+      }
+      enum "outOfService" {
+        value 2;
+      }
+      enum "degraded" {
+        value 3;
+      }
+    }
+  }
+
+  typedef optic-types {
+    type enumeration {
+      enum "gray" {
+        value 1;
+      }
+      enum "dwdm" {
+        value 2;
+      }
+    }
+  }
+  grouping equipment-type {
+    leaf type {
+      type equipment-type-enum;
+      mandatory true;
+      config false;
+    }
+    leaf extension {
+      description
+        "Populated with equipment type when enum value is set to vendorExtension";
+      type string;
+      mandatory false;
+      config false;
+    }
+  }
+
+  typedef equipment-type-enum {
+    type enumeration {
+      enum "other" {
+        value 1;
+      }
+      enum "powerSupply" {
+        value 2;
+      }
+      enum "shelfProcessor" {
+        value 3;
+      }
+      enum "crossConnect" {
+        value 4;
+      }
+      enum "fan" {
+        value 5;
+      }
+      enum "accessPanel" {
+        value 6;
+      }
+      enum "circuitPack" {
+        value 7;
+      }
+    }
+  }
+
+  typedef optical-control-mode {
+    description
+      "Optical Control Mode: identifies specific algorithm related to power management and general optical control.";
+    type enumeration {
+      enum "power" {
+        value 1;
+      }
+      enum "gainLoss" {
+        value 2;
+      }
+      enum "off" {
+        value 3;
+      }
+    }
+    reference "openroadm.org: Open ROADM MSA Specification.";
+  }
+
+  typedef direction {
+    type enumeration {
+      enum "tx" {
+        value 1;
+      }
+      enum "rx" {
+        value 2;
+      }
+      enum "bidirectional" {
+        value 3;
+      }
+    }
+  }
+
+  typedef pm-direction {
+    type enumeration {
+      enum "tx" {
+        value 1;
+      }
+      enum "rx" {
+        value 2;
+      }
+      enum "bidirectional" {
+        value 3;
+      }
+      enum "notApplicable" {
+        value 4;
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-common-types@2017-09-29.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-common-types@2017-09-29.yang
new file mode 100644 (file)
index 0000000..5957348
--- /dev/null
@@ -0,0 +1,629 @@
+module org-openroadm-common-types {
+  namespace "http://org/openroadm/common-types";
+  prefix org-openroadm-common-types;
+
+  organization
+    "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of common types.
+
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+      AT&T Intellectual Property.  All other rights reserved.
+
+      Redistribution and use in source and binary forms, with or without modification,
+      are permitted provided that the following conditions are met:
+
+      * Redistributions of source code must retain the above copyright notice, this
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice,
+        this list of conditions and the following disclaimer in the documentation and/or
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+        contributors may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2017-09-29 {
+    description
+      "Version 2.1";
+  }
+  revision 2017-06-26 {
+    description
+      "Version 2.0";
+  }
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping physical-location {
+    leaf rack {
+      type string;
+      mandatory false;
+    }
+    leaf shelf {
+      type string;
+      mandatory false;
+    }
+    leaf slot {
+      type string;
+      mandatory false;
+    }
+    leaf subSlot {
+      type string;
+      mandatory false;
+    }
+  }
+
+  typedef node-types {
+    type enumeration {
+      enum "rdm" {
+        value 1;
+      }
+      enum "xpdr" {
+        value 2;
+      }
+      enum "ila" {
+        value 3;
+      }
+      enum "extplug" {
+        value 4;
+      }
+    }
+    description
+      "Identifier for node type
+       1. rdm for ROADM
+       2. xpdr for Transponder, Regen
+       3. ila for in-line amplifier
+       4. extplug for external plugable";
+  }
+
+  typedef node-id-type {
+    type string {
+      length "7..63";
+      pattern "([a-zA-Z][a-zA-Z0-9-]{5,18}[a-zA-Z0-9])" {
+        error-message
+          "A node-id must be 7 to 63 characters in length.
+           A node-id can contain letters, numbers, and hyphens.
+           The first character must be a letter.
+           The last character must be a letter or number.";
+       }
+    }
+    description
+      "Globally unique identifer for a device.";
+  }
+
+  typedef xpdr-node-types {
+    type enumeration {
+      enum "tpdr" {
+        value 1;
+      }
+      enum "mpdr" {
+        value 2;
+      }
+      enum "switch" {
+        value 3;
+      }
+      enum "regen" {
+        value 4;
+      }
+      enum "regen-uni" {
+        value 5;
+      }
+    }
+    description
+      "Identifier for Xponder node type
+       1. Transponder
+       2. Muxponder
+       3. OTN switchponder
+       4. Regenerator
+       5. Regenerator based on unidirectional model";
+  }
+
+  typedef frequency-THz {
+    description
+      "Frequency value in THz.";
+    type decimal64 {
+      fraction-digits 8;
+    }
+    units "THz";
+  }
+
+  typedef frequency-GHz {
+    description
+      "Frequency value in GHz.";
+    type decimal64 {
+      fraction-digits 5;
+    }
+    units "GHz";
+  }
+
+  typedef power-dBm {
+    description
+      "Power value in dBm.";
+    type decimal64 {
+      fraction-digits 2;
+    }
+    units "dBm";
+  }
+
+  typedef ratio-dB {
+    description
+      "Power ratio in dB.";
+    type decimal64 {
+      fraction-digits 3;
+    }
+    units "dB";
+  }
+
+  typedef fiber-pmd {
+    description
+      "Polarization Mode Dispersion expressed in ps/km(1/2).";
+    type decimal64 {
+      fraction-digits 2;
+    }
+    units "ps/(km[1/2])";
+  }
+
+  typedef amplifier-types {
+    type enumeration {
+      enum "standard" {
+        value 1;
+      }
+    }
+    description
+      "identifier for amplifier type
+       1. standard for amplifier as defined initially in the ROADM MSA specifications
+       To be completed if/when additional amplifier types are required ";
+  }
+
+  typedef line-amplifier-control-mode {
+    description
+      "Identifies the line amplifier control mode, either off or gain.";
+    type enumeration {
+      enum "gainLoss" {
+        value 2;
+      }
+      enum "off" {
+        value 3;
+      }
+    }
+  }
+
+  typedef amplifier-gain-range {
+    description
+      "Operational mode for the amplifier:
+       this parameter allows modeling different operational modes (gain ranges) ,notably for switched-gain amplifiers.
+       It indicates which performance model shall be used by the path feasibility engine.
+       For standard amplifier, or when performance evaluation is based on incremental noise, use gain-range-1.
+       When performance evaluation is based on advanced parameters, specify used gain-range (1 to 4).
+       Up to release 2.1, only gain-range-1 is to be used (default value) ";
+    type enumeration {
+      enum "gain-range-1" {
+        value 1;
+      }
+      enum "gain-range-2" {
+        value 2;
+      }
+      enum "gain-range-3" {
+        value 3;
+      }
+      enum "gain-range-4" {
+        value 4;
+      }
+    }
+  }
+
+  typedef severity {
+    description
+      "Severity, based on X.733 perceived severity";
+    type enumeration {
+      enum "critical" {
+        value 1;
+      }
+      enum "major" {
+        value 2;
+      }
+      enum "minor" {
+        value 3;
+      }
+      enum "warning" {
+        value 4;
+      }
+      enum "clear" {
+        value 5;
+      }
+      enum "indeterminate" {
+        value 6;
+      }
+    }
+  }
+
+  typedef activate-notification-type {
+    description
+      "Type of notification on software or database activation events";
+    type enumeration {
+      enum "activate" {
+        value 1;
+        description
+          "software or database activation";
+      }
+      enum "commit" {
+        value 2;
+        description
+          "commit the software or database.
+           For software activate, this event can happen in the following scenarios:
+             1) immediately when user issue db-activate command without rollBackTimer
+                or if the rollBackTimer is specified as 00-00-00;
+             2) when user issue cancel-rollback-timer before it expires and with accept=true.
+           For database activate, this event can occur in the following scenarios:
+             1) immediately when user issue db-activate command without rollBackTimer
+                or if the rollBackTimer is specified as 00-00-00;
+             2) when user issue cancel-rollback-timer before it expires and with accept=true.";
+      }
+      enum "cancel" {
+        value 3;
+        description
+          "cancel the database or software activation operation.
+           For software activate, this event can happen in the following cases:
+             1) when the rollBackTimer expires;
+             2) when the user issues cancel-rollback-timer with accept=false.
+           For database activate, this event can happen in the following cases:
+             1) when the rollBackTimer expires;
+             2) when the user issues cancel-rollback-timer with accept=false.";
+      }
+    }
+  }
+
+  typedef rpc-status {
+    description
+      "status of RPC ";
+    type enumeration {
+      enum "Successful" {
+        value 1;
+      }
+      enum "Failed" {
+        value 2;
+      }
+    }
+  }
+
+  grouping rpc-response-status {
+    leaf status {
+      type rpc-status;
+      mandatory true;
+      description
+        "Successful or Failed";
+    }
+    leaf status-message {
+      type string;
+      description
+        "Gives a more detailed status";
+    }
+  }
+
+  typedef extended-rpc-status {
+    description
+      "status of RPC ";
+    type enumeration {
+      enum "Successful" {
+        value 1;
+      }
+      enum "Failed" {
+        value 2;
+      }
+      enum "In-progress" {
+        value 3;
+      }
+    }
+  }
+
+  grouping extended-rpc-response-status {
+    leaf status {
+      type extended-rpc-status;
+      mandatory true;
+      description
+        "Successful, Failed or In-progress";
+    }
+    leaf status-message {
+      type string;
+      description
+        "Gives a more detailed status.";
+    }
+  }
+
+  typedef lifecycle-state {
+    description
+      "Lifecycle state.";
+    type enumeration {
+      enum "deployed" {
+        value 1;
+      }
+      enum "planned" {
+        value 2;
+      }
+      enum "maintenance" {
+        value 3;
+      }
+      enum "deploying" {
+        value 4;
+      }
+      enum "undeploying" {
+        value 5;
+      }
+      enum "undeployed" {
+        value 6;
+      }
+      enum "proposed" {
+        value 7;
+      }
+      enum "draft" {
+        value 8;
+      }
+    }
+  }
+
+  typedef state {
+    description
+      "State that indicates whether the resource is able to provide fullfill its role - carry traffic, etc.";
+    type enumeration {
+      enum "inService" {
+        value 1;
+      }
+      enum "outOfService" {
+        value 2;
+      }
+      enum "degraded" {
+        value 3;
+      }
+    }
+  }
+
+  typedef optic-types {
+    type enumeration {
+      enum "gray" {
+        value 1;
+      }
+      enum "dwdm" {
+        value 2;
+      }
+    }
+  }
+
+  grouping equipment-type {
+    leaf type {
+      type equipment-type-enum;
+      mandatory true;
+      config false;
+    }
+    leaf extension {
+      description
+        "Populated with equipment type when enum value is set to vendorExtension";
+      type string;
+      mandatory false;
+      config false;
+    }
+  }
+
+  typedef equipment-type-enum {
+    type enumeration {
+      enum "other" {
+        value 1;
+      }
+      enum "powerSupply" {
+        value 2;
+      }
+      enum "shelfProcessor" {
+        value 3;
+      }
+      enum "crossConnect" {
+        value 4;
+      }
+      enum "fan" {
+        value 5;
+      }
+      enum "accessPanel" {
+        value 6;
+      }
+      enum "circuitPack" {
+        value 7;
+      }
+    }
+  }
+
+  typedef optical-control-mode {
+    description
+      "Optical Control Mode: identifies specific algorithm related to power management and general optical control.";
+    type enumeration {
+      enum "power" {
+        value 1;
+      }
+      enum "gainLoss" {
+        value 2;
+      }
+      enum "off" {
+        value 3;
+      }
+    }
+    reference "openroadm.org: Open ROADM MSA Specification.";
+  }
+
+  typedef direction {
+    type enumeration {
+      enum "tx" {
+        value 1;
+      }
+      enum "rx" {
+        value 2;
+      }
+      enum "bidirectional" {
+        value 3;
+      }
+      enum "notApplicable" {
+        value 4;
+      }
+    }
+  }
+
+  typedef location {
+    type enumeration {
+      enum "notApplicable" {
+        value 1;
+      }
+      enum "nearEnd" {
+        value 2;
+      }
+      enum "farEnd" {
+        value 3;
+      }
+    }
+  }
+
+  typedef wavelength-duplication-type {
+    description
+      "One per srg is applied to C/D add/drop group
+       one per degree is applied to C/D/C add drop group";
+    type enumeration {
+      enum "one-per-srg" {
+        description
+          "The SRG cannot handle wavelength duplication. Attempting to provision a connection on this SRG that uses the same wavelength as an existing service will result in failure.";
+        value 1;
+      }
+      enum "one-per-degree" {
+        description
+          "The SRG can handle wavelength duplication, but only one per degree. Attempting to provision a connection on this SRG that uses the same wavelength as an existing service will succeed, so long as the connections are not using the same degree.";
+        value 2;
+      }
+    }
+  }
+
+  typedef port-qual {
+    type enumeration {
+      enum "roadm-internal" {
+        value 1;
+      }
+      enum "roadm-external" {
+        value 2;
+      }
+      enum "xpdr-network" {
+        value 3;
+      }
+      enum "xpdr-client" {
+        value 4;
+      }
+      enum "otdr" {
+        value 5;
+      }
+      enum "switch-network" {
+        value 6;
+      }
+      enum "switch-client" {
+        value 7;
+      }
+      enum "ila-external" {
+        value 8;
+      }
+      enum "ila-internal" {
+        value 9;
+      }
+    }
+  }
+
+  identity och-rate-identity {
+    description
+      "A unique och rate identification";
+  }
+
+  identity R200G {
+    base och-rate-identity;
+    description
+      "Identity for 200G Rate";
+  }
+
+  identity R100G {
+    base och-rate-identity;
+    description
+      "Identity for 100G Rate";
+  }
+
+  identity R10.7G {
+    base och-rate-identity;
+    description
+      "Identity for 10.7G Rate";
+  }
+
+  identity R11.1G {
+    base och-rate-identity;
+    description
+      "Identity for 11.1G Rate";
+  }
+
+  typedef modulation-format {
+    type enumeration {
+      enum "bpsk" {
+        value 0;
+        description
+          "binary phase-shift keying";
+      }
+      enum "dc-dp-bpsk" {
+        value 1;
+        description
+          "DC dual-polarization binary phase-shift keying";
+      }
+      enum "qpsk" {
+        value 2;
+        description
+          "quadrature phase-shift keying";
+      }
+      enum "dp-qpsk" {
+        value 3;
+        description
+          "dual-polarization binary phase-shift keying";
+      }
+      enum "qam16" {
+        value 4;
+        description
+          "quadrature amplitude modulation 16";
+      }
+      enum "dp-qam16" {
+        value 5;
+        description
+          "dual-polarization quadrature amplitude modulation 16";
+      }
+      enum "dc-dp-qam16" {
+        value 6;
+        description
+          "DC dual-polarization quadrature amplitude modulation 16";
+      }
+      enum "qam8" {
+        value 7;
+        description
+          "quadrature amplitude modulation 8";
+      }
+      enum "dp-qam8" {
+        value 8;
+        description
+          "dual-polarization quadrature amplitude modulation 8";
+      }
+      enum "dc-dp-qam8" {
+        value 9;
+        description
+          "DC dual-polarization quadrature amplitude modulation 8";
+      }
+    }
+    description
+      "Modulation format";
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-device@2017-02-06.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-device@2017-02-06.yang
new file mode 100644 (file)
index 0000000..18b05f8
--- /dev/null
@@ -0,0 +1,1215 @@
+module org-openroadm-device {
+  namespace "http://org/openroadm/device";
+  prefix org-openroadm-device;
+
+  import ietf-yang-types {
+    prefix ietf-yang-types;
+  }
+  import ietf-inet-types {
+    prefix ietf-inet-types;
+  }
+  import ietf-netconf {
+    prefix ietf-nc;
+  }
+  import org-openroadm-common-types {
+    prefix org-openroadm-common-types;
+    revision-date 2016-10-14;
+  }
+  import org-openroadm-resource-types {
+    prefix org-openroadm-resource-types;
+  }
+  import org-openroadm-wavelength-map {
+      prefix org-openroadm-wavelength-map;
+      revision-date 2016-10-14; 
+  }
+  import org-openroadm-physical-types {
+    prefix org-openroadm-physical-types;
+  }
+  import org-openroadm-user-mgmt {
+    prefix org-openroadm-user-mgmt;
+  }
+  import org-openroadm-port-types {
+    prefix org-openroadm-port-types;
+  }
+  import org-openroadm-interfaces {
+    prefix org-openroadm-interfaces;
+  }
+  import org-openroadm-swdl {
+    prefix org-openroadm-swdl;
+  }
+  import org-openroadm-equipment-states-types {
+    prefix org-openroadm-equipment-states-types;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of ROADM device
+
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+     AT&T Intellectual Property.  All other rights reserved.
+
+     Redistribution and use in source and binary forms, with or without modification,
+     are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice, this
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation and/or
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+       contributors may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+     POSSIBILITY OF SUCH DAMAGE.
+
+     Also contains code components extracted from IETF netconf.  These code components
+     are copyrighted and licensed as follows:
+
+     Copyright (c) 2016 IETF Trust and the persons identified as the document authors.
+     All rights reserved.
+
+     This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating
+     to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of
+     publication of this document. Please review these documents carefully, as they
+     describe your rights and restrictions with respect to this document. Code Components
+     extracted from this document must include Simplified BSD License text as described in
+     Section 4.e of the Trust Legal Provisions and are provided without warranty as
+     described in the Simplified BSD License.";
+
+  revision 2017-02-06 {
+    description
+      "Version 1.2.1 - removed pattern for current-datetime in info tree and rpc";
+  }
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  rpc get-connection-port-trail {
+    input {
+      leaf connection-number {
+        type string;
+        mandatory true;
+      }
+    }
+    output {
+      uses org-openroadm-common-types:rpc-response-status;
+      list ports {
+        uses org-openroadm-common-types:physical-location;
+        uses port-name {
+          refine "circuit-pack-name" {
+            mandatory true;
+          }
+          refine "port-name" {
+            mandatory true;
+          }
+        }
+      }
+    }
+  }
+  rpc disable-automatic-shutoff {
+    input {
+      leaf amp {
+        type leafref {
+          path "/org-openroadm-device/shelves/shelf-name";
+        }
+        mandatory true;
+        description
+          "The shelf where amp is located";
+      }
+      leaf degree-number {
+        type uint16;
+        mandatory true;
+      }
+      leaf support-timer {
+        type uint16 {
+          range "1..600";
+        }
+        default "20";
+      }
+    }
+    output {
+      uses org-openroadm-common-types:rpc-response-status;
+    }
+  }
+  rpc start-scan {
+    input {
+      leaf degree-number {
+        type uint16;
+        mandatory true;
+      }
+      leaf port-direction {
+        type org-openroadm-common-types:direction;
+      }
+      leaf distance {
+        type uint32;
+      }
+      leaf resolution {
+        type uint32;
+      }
+    }
+    output {
+      uses org-openroadm-common-types:rpc-response-status;
+    }
+  }
+
+  notification otdr-scan-result {
+    leaf status {
+      type enumeration {
+        enum "Completed" {
+          value 1;
+        }
+        enum "Failed" {
+          value 2;
+        }
+      }
+      mandatory true;
+      description
+        "Completed or Failed for the scan's final status";
+    }
+    leaf result-file {
+      type string;
+    }
+  }
+
+  rpc set-current-datetime {
+    description
+      "Set the info/current-datetime leaf to the specified value.";
+    input {
+     leaf current-datetime {
+        type ietf-yang-types:date-and-time;
+        mandatory true;
+        description
+          "The current system date and time in UTC. Format: YYYY-MM-DDTHH:MM:SS";
+      }
+    }
+
+    output {
+      uses org-openroadm-common-types:rpc-response-status;
+    }
+  }
+
+  grouping device-common {
+    leaf node-id {
+      type string;
+      description
+        "Globally unique identifer for a device.";
+      default "openroadm";
+    }
+    leaf node-number {
+      type uint32;
+      description
+        "Number assigned to a ROADM node at a
+         given office";
+    }
+    leaf node-type {
+      type org-openroadm-common-types:node-types;
+      description
+        "Identifier for node-type e.g Roadm, xponder";
+      config false;
+      mandatory true;
+    }
+    leaf clli {
+      type string;
+      description
+        "Common Language Location Identifier.";
+    }
+    uses org-openroadm-physical-types:node-info;
+    leaf ipAddress {
+      type ietf-inet-types:ip-address;
+      description
+        "IP Address of device";
+    }
+    leaf prefix-length {
+      type uint8 {
+        range "0..128";
+      }
+      description
+        "The length of the subnet prefix";
+    }
+    leaf defaultGateway {
+      type ietf-inet-types:ip-address;
+      description
+        "Default Gateway";
+    }
+    leaf source {
+      type enumeration {
+        enum "static" {
+          value 1;
+        }
+        enum "dhcp" {
+          value 2;
+        }
+      }
+      config false;
+    }
+    leaf current-ipAddress {
+      type ietf-inet-types:ip-address;
+      config false;
+      description
+        "Current IP Address of device";
+    }
+    leaf current-prefix-length {
+      type uint8 {
+        range "0..128";
+      }
+      config false;
+      description
+        "The current length of the subnet prefix";
+    }
+    leaf current-defaultGateway {
+      type ietf-inet-types:ip-address;
+      config false;
+      description
+        "Current Default Gateway";
+    }
+    leaf macAddress {
+      type ietf-yang-types:mac-address;
+      description
+        "MAC Address of device";
+      config false;
+    }
+    leaf softwareVersion {
+      type string;
+      config false;
+      description
+        "Software version";
+    }
+    leaf template {
+      type string;
+      description
+        "Template information used in the deployment.";
+    }
+    leaf current-datetime {
+      type ietf-yang-types:date-and-time;
+      config false;
+      description
+        "The current system date and time in UTC. Format: YYYY-MM-DDTHH:MM:SS.mm+ ";
+    }
+    container geoLocation {
+      description
+        "GPS location";
+      leaf latitude {
+        type decimal64 {
+          fraction-digits 16;
+          range "-90 .. 90";
+        }
+        description
+          "[From wikipedia] Latitude is an angle (defined below)
+           which ranges from 0° at the Equator to 90° (North or
+           South) at the poles";
+      }
+      leaf longitude {
+        type decimal64 {
+          fraction-digits 16;
+          range "-180 .. 180";
+        }
+        description
+          "[From wikipedia] The longitude is measured as the
+           angle east or west from the Prime Meridian, ranging
+           from 0° at the Prime Meridian to +180° eastward and
+           âˆ’180° westward.";
+      }
+    }
+  }
+
+  grouping slot-info {
+    description
+      "slots information. To be populated by NE during retrieval.";
+    leaf slot-name {
+      type string;
+      description
+        "The name of this slot.";
+    }
+    leaf label {
+      type string;
+      description
+        "Faceplate label";
+    }
+    leaf provisioned-circuit-pack {
+      type leafref {
+        path "/org-openroadm-device/circuit-packs/circuit-pack-name";
+      }
+      description
+        "The supported circuit-pack. It will be empty if no provision on this slot.";
+    }
+  }
+  grouping shelves {
+    list shelves {
+      key "shelf-name";
+      uses shelf;
+    }
+  }
+  grouping shelf {
+    leaf shelf-name {
+      description
+        "Unique identifier for this shelf within a device";
+      type string;
+    }
+    leaf shelf-type {
+      description
+        "The shelf type: describe the shelf with a unique string.";
+      type string;
+      mandatory true;
+    }
+    leaf rack {
+      description
+        "Reflect the shelf physical location data including floor, aisle, bay values.";
+      type string;
+    }
+    leaf shelf-position {
+      description
+        "Reflect the shelf vertical position within an equipment bay.";
+      type string;
+    }
+    leaf administrative-state {
+      description
+        "Admin State of the shelf";
+      type org-openroadm-equipment-states-types:admin-states;
+    }
+    uses org-openroadm-physical-types:common-info;
+    leaf equipment-state {
+      type org-openroadm-equipment-states-types:states;
+      description
+        "equipment state for the shelf, used to track the lifecycle state.";
+    }
+    leaf due-date {
+      type ietf-yang-types:date-and-time;
+      description
+        "due date for the shelf.";
+    }
+    list slots {
+      description
+          "List of slots on this shelf. To be populated by NE during retrieval.";
+      key "slot-name";
+      config false;
+      uses slot-info;
+    }
+  }
+
+  grouping circuit-packs {
+    list circuit-packs {
+      description
+        "List of circuit packs. This includes common equipment, like fans, power supplies, etc.";
+      key "circuit-pack-name";
+      leaf circuit-pack-type {
+        description
+          "Type of circuit-pack";
+        type string;
+        mandatory true;
+      }
+      leaf circuit-pack-product-code {
+        description
+          "Product Code for the circuit-pack";
+        type string;
+      }
+      uses circuit-pack;
+    }
+  }
+
+  grouping circuit-pack {
+    leaf circuit-pack-name {
+      description
+        "Unique identifier for this circuit-pack within a device";
+      type string;
+    }
+    leaf administrative-state {
+      description
+        "Administrative state of circuit-pack";
+      type org-openroadm-equipment-states-types:admin-states;
+    }
+    uses org-openroadm-physical-types:common-info;
+    container circuit-pack-category {
+      description
+        "General type of circuit-pack";
+      uses org-openroadm-common-types:equipment-type;
+      config false;
+    }
+    leaf equipment-state {
+      description
+        "Equipment state, which complements operational state.";
+      type org-openroadm-equipment-states-types:states;
+    }
+    leaf circuit-pack-mode {
+      description
+        "Circuit-pack mode allowed. e.g. NORMAL or REGEN";
+      type string;
+      default "NORMAL";
+    }
+    leaf shelf {
+      type leafref {
+        path "/org-openroadm-device/shelves/shelf-name";
+      }
+      mandatory true;
+    }
+    leaf slot {
+      type string;
+      mandatory true;
+    }
+    leaf subSlot {
+      type string;
+      mandatory false;
+    }
+    leaf due-date {
+      type ietf-yang-types:date-and-time;
+      description
+        "due date for this circuit-pack.";
+    }
+    container parent-circuit-pack {
+      description
+        "In the case of circuit packs that contain other equipment (modules or pluggables), this captures the hierarchy of that equipment.  It is a vendor specific design decision if the ports for single-port pluggables are modeled as children of the parent circuit-pack, or as children of the pluggable circuit-pack contained in the parent circuit-pack.  For modules with multiple ports, it is recommended that ports be children of the module and not the carrier, to help in fault correlation and isolation in the case of a module failure.";
+      uses circuit-pack-name;
+      leaf cp-slot-name {
+        type string;
+        description
+          "Slot name on parent-circuit-pack.";
+      }
+    }
+    list cp-slots {
+      description
+          "List of circuit-pack slots on this circuit-pack. To be populated by NE during retrieval.";
+      key "slot-name";
+      config false;
+      uses slot-info;
+    }
+    list ports {
+      key "port-name";
+      description
+        "List of ports on this circuit-pack.  For single port pluggables, the port may be modeled against the pluggable itself, or against the parent-circuit-pack.  For mulit-port pluggables, it is recommended that ports be modeled against the module itself.  Modeling ports as close to the equipment hierarchy as possible will help in fault correlation and isolation since common failures associated with supporting equipment can be used to help identify symptomatic failures on the contained ports.";
+      uses port;
+      container roadm-port {
+        when "../port-qual='roadm-external'";
+        uses org-openroadm-port-types:roadm-port;
+      }
+      container transponder-port {
+        when "../port-qual='xpdr-network' or ../port-qual='xpdr-client'";
+        uses org-openroadm-port-types:common-port;
+      }
+      container otdr-port {
+        when "../port-qual='otdr'";
+        description
+          "Settings for otdr port.";
+        leaf launch-cable-length {
+          type uint32;
+          default "30";
+          units "m";
+        }
+        leaf port-direction {
+          type org-openroadm-common-types:direction;
+        }
+      }
+    }
+  }
+
+  grouping connection {
+    description
+      "Grouping used to define connections.";
+    leaf connection-number {
+      type string;
+    }
+    leaf wavelength-number {
+      type uint32;
+      mandatory true;
+      description
+        "wavelength-number, can be used to access wavelength-map
+         to get wavelength value in nm.";
+    }
+    leaf opticalControlMode {
+      description
+        "Whether connection is currently in power or gain/loss mode";
+      type org-openroadm-common-types:optical-control-mode;
+      reference "openroadm.org: Open ROADM MSA Specification.";
+      default "off";
+    }
+    leaf target-output-power {
+      type org-openroadm-common-types:power-dBm;
+      description
+        "The output target power for this connection. When set, the ROADM will work to ensure that current-output-power reaches this level.";
+    }
+    container source {
+      leaf src-if {
+        type leafref {
+          path "/org-openroadm-device/interface/name";
+        }
+        mandatory true;
+      }
+    }
+    container destination {
+      leaf dst-if {
+        type leafref {
+          path "/org-openroadm-device/interface/name";
+        }
+        mandatory true;
+      }
+    }
+  }
+
+  grouping degree {
+    leaf degree-number {
+      type uint16;
+      must "not( current() > /org-openroadm-device/info/max-degrees) and current() > 0" {
+        error-message "Degree not supported by device ";
+        description
+          "Validating if the degree is supported by device";
+      }
+    }
+    leaf max-wavelengths {
+      type uint16;
+      description
+        "maximum number of wavelengths";
+      config false;
+      mandatory true;
+    }
+    list circuit-packs {
+      key "index";
+      description
+        "list for Cards associated with a degree";
+      leaf index {
+        type uint32;
+      }
+      uses circuit-pack-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+      }
+    }
+    list connection-ports {
+      description
+        "Port associated with degree: One if bi-directional; two if uni-directional";
+      key "index";
+      leaf index {
+        type uint32;
+      }
+      uses port-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+        refine "port-name" {
+          mandatory true;
+        }
+      }
+    }
+    container otdr-port {
+      description
+        "otdr port associated with degree.";
+      uses port-name;
+    }
+  }
+
+  grouping external-links {
+    description
+      "YANG definitions for external links..
+       - physical links between ROADMs and between the ROADMs and XPonders, which can be added and removed maually.";
+    list external-link {
+      key "external-link-name";
+      uses external-link;
+    }
+  }
+
+  grouping external-link {
+    leaf external-link-name {
+      type string;
+    }
+    container source {
+      uses org-openroadm-resource-types:device-id {
+        refine "node-id" {
+          mandatory true;
+        }
+      }
+      uses org-openroadm-resource-types:port-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+        refine "port-name" {
+          mandatory true;
+        }
+      }
+    }
+    container destination {
+      uses org-openroadm-resource-types:device-id {
+        refine "node-id" {
+          mandatory true;
+        }
+      }
+      uses org-openroadm-resource-types:port-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+        refine "port-name" {
+          mandatory true;
+        }
+      }
+    }
+  }
+
+  grouping internal-links {
+    list internal-link {
+      key "internal-link-name";
+      config false;
+      uses internal-link;
+    }
+  }
+
+  grouping internal-link {
+    leaf internal-link-name {
+      type string;
+    }
+    container source {
+      uses port-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+        refine "port-name" {
+          mandatory true;
+        }
+      }
+    }
+    container destination {
+      uses port-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+        refine "port-name" {
+          mandatory true;
+        }
+      }
+    }
+  }
+
+  grouping physical-links {
+    description
+      "YANG definitions for physical links.
+       - phyical links between cards within a ROADM, which are populated by the ROADM and cannot be added or removed manually. ";
+    list physical-link {
+      key "physical-link-name";
+      uses physical-link;
+    }
+  }
+
+  grouping physical-link {
+    leaf physical-link-name {
+      type string;
+    }
+    container source {
+      uses port-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+        refine "port-name" {
+          mandatory true;
+        }
+      }
+    }
+    container destination {
+      uses port-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+        refine "port-name" {
+          mandatory true;
+        }
+      }
+    }
+  }
+
+  grouping srg {
+    leaf max-add-drop-ports {
+      type uint16;
+      config false;
+      mandatory true;
+    }
+    leaf srg-number {
+      type uint16;
+      must "not(current()>/org-openroadm-device/info/max-srgs) and current()>0" {
+        error-message "invalid SRG";
+        description
+          "Validating if the srg is supported by add/drop group";
+      }
+    }
+    leaf wavelengthDuplication {
+      description
+        "Whether the SRG can handle duplicate wavelengths and if so to what extent.";
+      config false;
+      mandatory true;
+      type enumeration {
+        enum "onePerSRG" {
+          description
+            "The SRG cannot handle wavelength duplication. Attempting to provision a connection on this SRG that uses the same wavelength as an existing service will result in failure.";
+          value 1;
+        }
+        enum "onePerDegree" {
+          description
+            "The SRG can handle wavelength duplication, but only one per degree. Attempting to provision a connection on this SRG that uses the same wavelength as an existing service will succeed, so long as the connections are not using the same degree.";
+          value 2;
+        }
+      }
+    }
+    list circuit-packs {
+      key "index";
+      description
+        "list for Cards associated with an add/drop group and srg";
+      leaf index {
+        type uint32;
+      }
+      uses circuit-pack-name {
+        refine "circuit-pack-name" {
+          mandatory true;
+        }
+      }
+    }
+  }
+
+  grouping degree-number {
+    leaf degree-number {
+      description
+        "Degree identifier. Unique within the context of a device.";
+      type leafref {
+        path "/org-openroadm-device/degree/degree-number";
+      }
+    }
+  }
+
+  grouping circuit-pack-name {
+    leaf circuit-pack-name {
+      description
+        "Circuit-Pack identifier. Unique within the context of a device.";
+      type leafref {
+        path "/org-openroadm-device/circuit-packs/circuit-pack-name";
+      }
+    }
+  }
+
+  grouping port-name {
+    uses circuit-pack-name;
+    leaf port-name {
+      description
+        "Port identifier. Unique within the context of a circuit-pack.";
+      type leafref {
+        path "/org-openroadm-device/circuit-packs[circuit-pack-name=current()/../circuit-pack-name]/ports/port-name";
+      }
+    }
+  }
+
+  grouping srg-number {
+    leaf srg-number {
+      description
+        "Shared Risk Group identifier. Unique within the context of a device.";
+      type leafref {
+        path "/org-openroadm-device/shared-risk-group/srg-number";
+      }
+    }
+  }
+
+  grouping supporting-port-name {
+    leaf supporting-circuit-pack-name {
+      description
+        "Identifier of the supporting circuit-pack.";
+      type leafref {
+        path "/org-openroadm-device/circuit-packs/circuit-pack-name";
+      }
+      mandatory true;
+    }
+    leaf supporting-port {
+      description
+        "Identifier of the supporting port.";
+      mandatory true;
+      type leafref {
+        path "/org-openroadm-device/circuit-packs[circuit-pack-name=current()/../supporting-circuit-pack-name]/ports/port-name";
+      }
+    }
+  }
+
+  grouping interface-name {
+    leaf interface-name {
+      description
+        "Name of an interface. Unique within the context of a device.";
+      type leafref {
+        path "/org-openroadm-device/interface/name";
+      }
+      config false;
+    }
+  }
+
+  grouping interfaces-grp {
+    description
+      "OpenROADM Interface configuration parameters.";
+    list interface {
+      key "name";
+      description
+        "The list of configured interfaces on the device.";
+      leaf name {
+        type string;
+        description
+          "The name of the interface.";
+      }
+      leaf description {
+        type string;
+        description
+          "A textual description of the interface.";
+      }
+      leaf type {
+        type identityref {
+          base org-openroadm-interfaces:interface-type;
+        }
+        mandatory true;
+        description
+          "The type of the interface.";
+      }
+      leaf administrative-state {
+        type org-openroadm-equipment-states-types:admin-states;
+      }
+      leaf operational-state {
+        type org-openroadm-common-types:state;
+        config false;
+      }
+      leaf circuit-id {
+        type string {
+          length "0..45";
+        }
+        description
+          "circuit identifier/user label,
+           can be used in alarm correlation and/or connection management ";
+      }
+      leaf supporting-interface {
+        type leafref {
+          path "/org-openroadm-device/interface/name";
+        }
+      }
+      uses supporting-port-name;
+    }
+  }
+
+  grouping port {
+    description
+      "Grouping of attributes related to a port object.";
+    leaf port-name {
+      type string;
+      mandatory true;
+      description
+        "Identifier for a port, unique within a circuit pack";
+    }
+    leaf port-type {
+      type string;
+      description
+        "Type of the pluggable or fixed port.";
+    }
+    leaf port-qual {
+      type enumeration {
+        enum "roadm-internal" {
+          value 1;
+        }
+        enum "roadm-external" {
+          value 2;
+        }
+        enum "xpdr-network" {
+          value 3;
+        }
+        enum "xpdr-client" {
+          value 4;
+        }
+        enum "otdr" {
+          value 5;
+        }
+      }
+    }
+    leaf port-wavelength-type {
+      type org-openroadm-port-types:port-wavelength-types;
+      config false;
+      description
+        "Type of port - single, multiple-wavelength, etc.";
+    }
+    leaf port-direction {
+      type org-openroadm-common-types:direction;
+      config false;
+      mandatory true;
+      description
+        "Whether port is uni (tx/rx) or bi-directional and";
+    }
+    leaf label {
+      type string;
+      config false;
+      description
+        "Faceplate label";
+    }
+    leaf circuit-id{
+      type string{
+        length "0..45";
+      }
+      description
+          "circuit identifier/user label,
+           can be used in alarm correlation and/or connection management ";
+
+    }
+    leaf administrative-state {
+      type org-openroadm-equipment-states-types:admin-states;
+      description
+        "Administrative state of port. The value of this field independant of the state of its contained and containing resources.  Setting this a port to administratively down will impact both its operational state, as well the operational state of its contained resources.  If this port is an endpoint to a connection, internal-link, physical-link, etc, then administratevely disabling this port will impact the operational state of those items unless they are using some form of port-protection schema.";
+      default "outOfService";
+    }
+    leaf operational-state {
+      type org-openroadm-common-types:state;
+      config false;
+      mandatory true;
+      description
+        "Operational state of a port";
+    }
+    leaf-list supported-interface-capability {
+      description
+        "Interface types supported on this port";
+      config false;
+      type identityref {
+        base org-openroadm-port-types:supported-if-capability;
+      }
+    }
+    leaf logical-connection-point {
+      type string;
+      description
+        "delete or replace with list logical-ports or connections?";
+    }
+    container partner-port {
+      config false;
+      description
+        "For ports which are not identified as having a direction of bidirectional, this field is used to identify the port which corresponds to the reverse direction. A port pair should include a port for each direction (tx, rx) and report their mate as partner-port.";
+      uses port-name;
+    }
+    container parent-port {
+      config false;
+      description
+        "In the case of port hierarchy, this is the parent port, which is also modeled as port within this circuit-pack. This is used in the case of a port that supports a parallel connector that contains subports.  The parent-port of the subport will be the port that contains this subport.  This can be used to help isolate faults when a single fault on a parallel connector introduces symptomatic failures on the contained subports.";
+      uses port-name;
+    }
+    list interfaces {
+      config false;
+      description
+        "List of the interfaces this port supports.  This is a list of names of instances in the flat instance list";
+      uses interface-name;
+    }
+  }
+
+  uses org-openroadm-device-container;
+
+  grouping org-openroadm-device-container {
+    container org-openroadm-device {
+      container info {
+        uses device-common;
+        leaf max-degrees {
+          type uint16;
+          description
+            "Max. number of degrees supported by device";
+          config false;
+        }
+        leaf max-srgs {
+          type uint16;
+          description
+            "Max. number of SRGs in an add/drop group";
+          config false;
+        }
+      }
+      container users {
+        description
+          "Stores a list of users";
+        uses org-openroadm-user-mgmt:user-profile;
+      }
+      container pending-sw {
+        config false;
+        uses org-openroadm-swdl:sw-bank;
+      }
+      uses shelves;
+      uses circuit-packs;
+      uses interfaces-grp;
+      container protocols {
+        description
+          "Contains the supported protocols";
+      }
+      container wavelength-map {
+        description
+          "The wavelength-number and center frequency, wavelength mapping";
+        config false;
+        uses org-openroadm-wavelength-map:wavelength-map-g;
+      }
+      uses internal-links;
+      uses physical-links;
+      uses external-links;
+      list degree {
+        when "/org-openroadm-device/info/node-type='rdm'";
+        key "degree-number";
+        uses degree;
+      }
+      list shared-risk-group {
+        when "/org-openroadm-device/info/node-type='rdm'";
+        key "srg-number";
+        uses srg;
+      }
+      list roadm-connections {
+        when "/org-openroadm-device/info/node-type='rdm'";
+        key "connection-number";
+        uses connection;
+      }
+      list connection-map {
+        key "connection-map-number";
+        config false;
+        leaf connection-map-number {
+          description
+            "Unique identifier for this connection-map entry";
+          type uint32;
+        }
+        container source {
+          leaf circuit-pack-name {
+            type leafref {
+              path "/org-openroadm-device/circuit-packs/circuit-pack-name";
+            }
+            mandatory true;
+          }
+          leaf port-name {
+            description
+              "Port identifier. Unique within the context of a circuit-pack.";
+            type leafref {
+              path "/org-openroadm-device/circuit-packs[circuit-pack-name=current()/../circuit-pack-name]/ports/port-name";
+            }
+            mandatory true;
+          }
+        }
+        list destination {
+          key "circuit-pack-name port-name";
+          min-elements 1;
+          leaf circuit-pack-name {
+            type leafref {
+              path "/org-openroadm-device/circuit-packs/circuit-pack-name";
+            }
+            mandatory true;
+          }
+          leaf port-name {
+            description
+              "Port identifier. Unique within the context of a circuit-pack.";
+            type leafref {
+              path "/org-openroadm-device/circuit-packs[circuit-pack-name=current()/../circuit-pack-name]/ports/port-name";
+            }
+            mandatory true;
+          }
+        }
+      }
+    }
+  }
+
+  grouping common-session-parms {
+    description
+      "Common session parameters to identify a
+       management session.";
+
+    leaf username {
+      type string;
+      mandatory true;
+      description
+        "Name of the user for the session.";
+    }
+
+    leaf session-id {
+      type ietf-nc:session-id-or-zero-type;
+      mandatory true;
+      description
+        "Identifier of the session.
+         A NETCONF session MUST be identified by a non-zero value.
+         A non-NETCONF session MAY be identified by the value zero.";
+    }
+
+    leaf source-host {
+      type ietf-inet-types:ip-address;
+      description
+        "Address of the remote host for the session.";
+    }
+  }
+  grouping changed-by-parms {
+    description
+      "Common parameters to identify the source
+       of a change event, such as a configuration
+       or capability change.";
+
+     container changed-by {
+       description
+         "Indicates the source of the change.
+          If caused by internal action, then the
+          empty leaf 'server' will be present.
+          If caused by a management session, then
+          the name, remote host address, and session ID
+          of the session that made the change will be reported.";
+       choice server-or-user {
+         leaf server {
+           type empty;
+           description
+             "If present, the change was caused
+              by the server.";
+         }
+
+         case by-user {
+           uses common-session-parms;
+         }
+       } // choice server-or-user
+     } // container changed-by-parms
+  }
+  notification change-notification {
+    description
+      "The Notification that a resource has been added, modified or removed.
+       This notification can be triggered by changes in configuration and operational data.
+       It shall contain the changed field pointed by the xpath.
+       Typically it is not intended for frequently changing volatile data e.g. PM, power levels";
+
+    leaf change-time {
+      description "The time the change occurs.";
+      type ietf-yang-types:date-and-time;
+    }
+    uses changed-by-parms;
+
+    leaf datastore {
+      type enumeration {
+        enum running {
+          description "The <running> datastore has changed.";
+        }
+        enum startup {
+          description "The <startup> datastore has changed";
+        }
+      }
+      default "running";
+      description
+        "Indicates which configuration datastore has changed.";
+    }
+    list edit {
+      description
+        "An edit (change) record SHOULD be present for each distinct
+         edit operation that the server has detected on
+         the target datastore.  This list MAY be omitted
+         if the detailed edit operations are not known.
+         The server MAY report entries in this list for
+         changes not made by a NETCONF session.";
+
+      leaf target {
+        type instance-identifier;
+        description
+            "Topmost node associated with the configuration or operationa change.
+             A server SHOULD set this object to the node within
+             the datastore that is being altered.  A server MAY
+             set this object to one of the ancestors of the actual
+             node that was changed, or omit this object, if the
+             exact node is not known.";
+      }
+      leaf operation {
+        type ietf-nc:edit-operation-type;
+        description
+          "Type of edit operation performed.
+         A server MUST set this object to the NETCONF edit
+         operation performed on the target datastore.";
+      }
+    } // list edit
+  } // notification change-notification
+}
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-equipment-states-types.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-equipment-states-types.yang
new file mode 100644 (file)
index 0000000..b1b9936
--- /dev/null
@@ -0,0 +1,130 @@
+module org-openroadm-equipment-states-types {
+  namespace "http://org/openroadm/equipment/states/types";
+  prefix org-openroadm-equipment-states-types;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for types of states of equipment (slot/subslot).
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  typedef admin-states {
+    type enumeration {
+      enum "inService" {
+        value 1;
+      }
+      enum "outOfService" {
+        value 2;
+      }
+      enum "maintenance" {
+        value 3;
+      }
+    }
+  }
+
+  typedef states {
+    type enumeration {
+      enum "reserved-for-facility-planned" {
+        value 1;
+        description
+          "equipment is planned for use by a service";
+      }
+      enum "not-reserved-planned" {
+        value 2;
+        description
+          "equipment is planned by not reserved for any purpose";
+      }
+      enum "reserved-for-maintenance-planned" {
+        value 3;
+        description
+          "equipment is planned for use as a maintenance spare";
+      }
+      enum "reserved-for-facility-unvalidated" {
+        value 4;
+        description
+          "equipment is reserved for use by a service but not
+           validated against planned equipment";
+      }
+      enum "not-reserved-unvalidated" {
+        value 5;
+        description
+          "equipment is not reserved for any purpose and
+           not validated against planned equipment";
+      }
+      enum "unknown-unvalidated" {
+        value 6;
+        description
+          "unknown equipment not validated against planned equipment";
+      }
+      enum "reserved-for-maintenance-unvalidated" {
+        value 7;
+        description
+          "equipment is to be used for use as a maintenance spare
+           but not validated against planned equipment";
+      }
+      enum "reserved-for-facility-available" {
+        value 8;
+        description
+          "reserved for use by a service and available";
+      }
+      enum "not-reserved-available" {
+        value 9;
+        description
+          "not reserved for use by a service and available";
+      }
+      enum "reserved-for-maintenance-available" {
+        value 10;
+        description
+          "reserved as a maintenance spare and available";
+      }
+      enum "reserved-for-reversion-inuse" {
+        value 11;
+        description
+          "equipiment that is reserved as part of a home path
+           for a service that has been temporarily re-routed";
+      }
+      enum "not-reserved-inuse" {
+        value 12;
+        description
+          "equipment in use for a service";
+      }
+      enum "reserved-for-maintenance-inuse" {
+        value 13;
+        description
+          "maintenance spare equipment that is in use as a
+           maintenance spare";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-ethernet-interfaces.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-ethernet-interfaces.yang
new file mode 100644 (file)
index 0000000..869a2c9
--- /dev/null
@@ -0,0 +1,145 @@
+module org-openroadm-ethernet-interfaces {
+  namespace "http://org/openroadm/ethernet-interfaces";
+  prefix org-openroadm-eth-interfaces;
+
+  import org-openroadm-device {
+    prefix org-openroadm-device;
+  }
+  import org-openroadm-interfaces {
+    prefix openROADM-if;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for device facility ethernet interfaces.
+
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+     AT&T Intellectual Property.  All other rights reserved.
+
+     Redistribution and use in source and binary forms, with or without modification,
+     are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice, this
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation and/or
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+       contributors may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+     POSSIBILITY OF SUCH DAMAGE.
+
+     Also contains code components extracted from IETF Interfaces.  These code components
+     are copyrighted and licensed as follows:
+
+     Copyright (c) 2016 IETF Trust and the persons identified as the document authors.
+     All rights reserved.
+
+     This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating
+     to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of
+     publication of this document. Please review these documents carefully, as they
+     describe your rights and restrictions with respect to this document. Code Components
+     extracted from this document must include Simplified BSD License text as described in
+     Section 4.e of the Trust Legal Provisions and are provided without warranty as
+     described in the Simplified BSD License.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping eth-attributes {
+    leaf speed {
+      type uint32;
+      description
+        "Set speed of the interface, unit mbps.
+         This is for ETH facility. ";
+    }
+    leaf fec {
+      type enumeration {
+        enum off;
+        enum rsfec;
+      }
+      description "Forward Error Correction Choices. ";
+    }
+    leaf duplex {
+      type enumeration {
+        enum "half" {
+          value 0;
+          description
+            "half duplex";
+        }
+        enum "full" {
+          value 1;
+          description
+            "full duplex";
+        }
+      }
+      default "full";
+      description
+        "Set duplex selections.";
+    }
+    leaf mtu {
+      type uint32 {
+        range "1518..9000";
+      }
+      default "1522";
+      description
+        "Set Maximum Frame Size.";
+    }
+    leaf auto-negotiation {
+      type enumeration {
+        enum "enabled" {
+          value 1;
+          description
+            "Auto Negotiation enabled";
+        }
+        enum "disabled" {
+          value 0;
+          description
+            "Auto Negotiation disabled";
+        }
+      }
+      default "enabled";
+      description
+        "Set Auto Negotiation: Enabled/Disabled.";
+    }
+    leaf curr-speed {
+      config false;
+      type string;
+      description
+        "speed (UNKNOWN/AUTO/10/100/1000/10000) corresponding to the interface";
+    }
+    leaf curr-duplex {
+      config false;
+      type string;
+      description
+        "duplex (HALF/FULL) corresponding to the interface";
+    }
+  }
+
+  grouping ethernet-container {
+    container ethernet {
+      description
+        "Ethernet Interfaces";
+      uses eth-attributes;
+    }
+  }
+
+  augment "/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface" {
+    when "org-openroadm-device:type = 'openROADM-if:ethernetCsmacd'";
+    uses ethernet-container;
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-interfaces.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-interfaces.yang
new file mode 100644 (file)
index 0000000..347f963
--- /dev/null
@@ -0,0 +1,108 @@
+module org-openroadm-interfaces {
+  namespace "http://org/openroadm/interfaces";
+  prefix openROADM-if;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for device facility interfaces. 
+     Reused ietf-interfaces and some interface-type defined in iana-if-type.
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.
+     
+     Also contains code components extracted from IETF Interfaces.  These code components 
+     are copyrighted and licensed as follows:
+     
+     Copyright (c) 2016 IETF Trust and the persons identified as the document authors. 
+     All rights reserved. 
+     
+     This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating 
+     to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of 
+     publication of this document. Please review these documents carefully, as they 
+     describe your rights and restrictions with respect to this document. Code Components 
+     extracted from this document must include Simplified BSD License text as described in
+     Section 4.e of the Trust Legal Provisions and are provided without warranty as 
+     described in the Simplified BSD License.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  identity interface-type {
+    description
+      "Base identity from which specific interface types are
+       derived.";
+  }
+
+  identity ethernetCsmacd {
+    base interface-type;
+    description
+      "For all Ethernet-like interfaces, regardless of speed,
+       as per RFC 3635.";
+    reference
+      "RFC 3635 - Definitions of Managed Objects for the
+                  Ethernet-like Interface Types";
+  }
+
+  identity ip {
+    base interface-type;
+    description
+      "IP (for APPN HPR in IP networks).";
+  }
+
+  identity opticalChannel {
+    base interface-type;
+    description
+      "Optical Channel.";
+  }
+
+  identity opticalTransport {
+    base interface-type;
+    description
+      "Optical Transport.";
+  }
+
+  identity otnOdu {
+    base interface-type;
+    description
+      "OTN Optical Data Unit.";
+  }
+
+  identity otnOtu {
+    base interface-type;
+    description
+      "OTN Optical channel Transport Unit.";
+  }
+
+  identity openROADMOpticalMultiplex {
+    base interface-type;
+    description
+      "Optical Transport Multiplex type for openROADM";
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-layerRate@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-layerRate@2016-10-14.yang
new file mode 100644 (file)
index 0000000..e9c7eb0
--- /dev/null
@@ -0,0 +1,89 @@
+module org-openroadm-layerRate {
+  namespace "http://org/openroadm/layerRate";
+  prefix org-openroadm-layerRate;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of layer rates.
+
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+      AT&T Intellectual Property.  All other rights reserved.
+
+      Redistribution and use in source and binary forms, with or without modification,
+      are permitted provided that the following conditions are met:
+
+      * Redistributions of source code must retain the above copyright notice, this
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice,
+        this list of conditions and the following disclaimer in the documentation and/or
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+        contributors may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping layer-rate {
+    description
+      "Set list of layer rates, plus the ability to report layer rates not yet in set list.";
+    leaf type {
+      type layer-rate-enum;
+      mandatory true;
+    }
+    leaf extension {
+      type string;
+      mandatory false;
+    }
+  }
+
+  typedef layer-rate-enum {
+    type enumeration {
+      enum "vendorExtension" {
+        value 1;
+        description
+          "vendor extension";
+      }
+      enum "layer2" {
+        value 2;
+        description
+          "2";
+      }
+      enum "layer3" {
+        value 3;
+        description
+          "3";
+      }
+      enum "layer4" {
+        value 4;
+        description
+          "4";
+      }
+      enum "layer5" {
+        value 5;
+        description
+          "5";
+      }
+      enum "layer6" {
+        value 6;
+        description
+          "6";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-lldp.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-lldp.yang
new file mode 100644 (file)
index 0000000..d781330
--- /dev/null
@@ -0,0 +1,302 @@
+module org-openroadm-lldp {
+  namespace "http://org/openroadm/lldp";
+  prefix org-openroadm-lldp;
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+  import org-openroadm-device {
+    prefix org-openroadm-device;
+  }
+  import iana-afn-safi {
+    prefix ianaaf;
+  }
+  import org-openroadm-resource-types {
+    prefix org-openroadm-resource-types;
+  }
+  import ietf-yang-types {
+    prefix yang;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for lldp protocol.
+
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+     AT&T Intellectual Property.  All other rights reserved.
+
+     Redistribution and use in source and binary forms, with or without modification,
+     are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice, this
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation and/or
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+       contributors may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+     POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+  grouping nbr-info-grp {
+    description
+      "Display LLDP Neighbour ";
+
+    leaf remoteSysName {
+      type string;
+      description
+        "remote neighbour system name";
+    }
+    leaf remoteMgmtAddressSubType {
+      type ianaaf:address-family;
+      description
+        "remote neighbour Management Address Subtype Enumeration";
+    }
+    leaf remoteMgmtAddress {
+      type inet:ip-address;
+      description
+        "remote neighbour management address";
+    }
+    leaf remotePortIdSubType {
+      type enumeration {
+        enum "other" {
+          value 0;
+          description
+            "reserved";
+        }
+        enum "ifalias" {
+          value 1;
+          description
+            "Interface Alias (IfAlias - IETF RFC 2863) ";
+        }
+        enum "portcomponent" {
+          value 2;
+          description
+            "Port component (EntPhysicalAlias IETF RFC 4133)";
+        }
+        enum "macaddress" {
+          value 3;
+          description
+            "MAC address (IEEE Std 802) ";
+        }
+        enum "networkaddress" {
+          value 4;
+          description
+            "Network Address";
+        }
+        enum "ifname" {
+          value 5;
+          description
+            "Interface Name (ifName - IETF RFC 2863)";
+        }
+        enum "agentcircuitid" {
+          value 6;
+          description
+            "Agent Circuit Id (IETF RFC 3046)";
+        }
+        enum "local" {
+          value 7;
+          description
+            "Locally assigned";
+        }
+      }
+      description
+        "remote neighbour Port ID Subtype Enumeration";
+    }
+    leaf remotePortId {
+      type string;
+      description
+        "remote neighbour port Id";
+    }
+    leaf remoteChassisIdSubType {
+      type enumeration {
+        enum "reserved" {
+          value 0;
+          description
+            "reserved";
+        }
+        enum "chassiscomponent" {
+          value 1;
+          description
+            "Chassis component (EntPhysicalAlias IETF RFC 4133)";
+        }
+        enum "ifalias" {
+          value 2;
+          description
+            "Interface Alias (IfAlias - IETF RFC 2863) ";
+        }
+        enum "portcomponent" {
+          value 3;
+          description
+            "Port component (EntPhysicalAlias IETF RFC 4133)";
+        }
+        enum "macaddress" {
+          value 4;
+          description
+            "MAC address (IEEE Std 802) ";
+        }
+        enum "networkaddress" {
+          value 5;
+          description
+            "Network Address";
+        }
+        enum "ifname" {
+          value 6;
+          description
+            "Interface Name (ifName - IETF RFC 2863)";
+        }
+        enum "local" {
+          value 7;
+          description
+            "Locally assigned";
+        }
+      }
+      description
+        "Chassis ID Subtype Enumeration";
+    }
+    leaf remoteChassisId {
+      type string;
+      description
+        "remote neighbour Chassis Id";
+    }
+  }
+
+  grouping lldp-container {
+    container lldp {
+      description
+        "LLDP configurable and retrievable";
+      container global-config {
+        description
+          "LLDP global configurations";
+        leaf adminStatus {
+          type enumeration {
+            enum "disable" {
+              value 0;
+              description
+                "Disable the LLDP feature per NE";
+            }
+            enum "enable" {
+              value 1;
+              description
+                "Enable the LLDP feature per NE";
+            }
+          }
+          description
+            "LLDP feature Enable/Disable per NE";
+          default "enable";
+        }
+        leaf msgTxInterval {
+          type uint16 {
+            range "5..32768";
+          }
+          description
+            "LLDP frame Retransmit Interval in seconds";
+          default "30";
+        }
+        leaf msgTxHoldMultiplier {
+          type uint8 {
+            range "2..10";
+          }
+          description
+            "TTL value for the TLVs transmitter over wire in seconds";
+          default "4";
+        }
+      }
+      list port-config {
+        description
+          "LLDP port configurations";
+        key "ifName";
+        leaf ifName {
+          type leafref {
+            path "/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface/org-openroadm-device:name";
+          }
+          description
+            "Ethernet interface name where LLDP runs";
+        }
+        leaf adminStatus {
+          type enumeration {
+            enum "disable" {
+              value 0;
+              description
+                "Disables the LLDP frames transmit and receive on specific interface";
+            }
+            enum "txandrx" {
+              value 1;
+              description
+                "Enable Transmit and Receive LLDP frames on specific interface";
+            }
+          }
+          description
+            "LLDP enable per port basis";
+          default "txandrx";
+        }
+      }
+      container nbr-list {
+        description
+          "LLDP Oper data - Neighbour List information";
+        config false;
+        list if-name {
+          key "ifName";
+          leaf ifName {
+            type string;
+            description
+              "Ethernet interface name where LLDP runs";
+          }
+          uses nbr-info-grp;
+        }
+      }
+    }
+  }
+
+  augment "/org-openroadm-device:org-openroadm-device/org-openroadm-device:protocols" {
+    when "/org-openroadm-device:org-openroadm-device/org-openroadm-device:info/org-openroadm-device:node-type='rdm'";
+    uses lldp-container;
+  }
+
+  notification lldp-nbr-info-change {
+    description "LLDP: Neighbor Information Changed
+            remoteSysName
+            remoteSysMgmtAddressSubType
+            remoteSysMgmtAddress
+            remotePortIdSubType
+            remotePortId
+            remoteChassisIdSubType
+            remoteChassisId
+            All of the above attributes are sent in event";
+    leaf notification-type {
+      type org-openroadm-resource-types:resource-notification-type;
+    }
+    leaf resource-type {
+      type org-openroadm-resource-types:resource-type-enum;
+      description
+        "resource-type for this notification is interface";
+    }
+    leaf resource {
+      type string;
+      description
+        "resource interface-name";
+    }
+    container nbr-info {
+      uses nbr-info-grp;
+    }
+    leaf event-time {
+      type yang:date-and-time;
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance-loopback.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance-loopback.yang
new file mode 100644 (file)
index 0000000..519d937
--- /dev/null
@@ -0,0 +1,75 @@
+module org-openroadm-maintenance-loopback {
+  namespace "http://org/openroadm/maintenance-loopback";
+  prefix org-openroadm-maint-loopback;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for maintenance loopback.
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping maint-loopback {
+    container maint-loopback {
+      leaf enabled {
+        type boolean;
+        default "false";
+        description
+          "loopback operation enable flag";
+      }
+      leaf type {
+        when "../enabled = 'true'";
+        type enumeration {
+          enum "fac" {
+            value 0;
+            description
+              "pre-FEC Loopback in the facility direction";
+          }
+          enum "term" {
+            value 1;
+            description
+              "Loopback in the terminal direction";
+          }
+          enum "fac2" {
+            value 2;
+            description
+              "post-FEC Loopback in the facility direction";
+          }
+        }
+        default "fac";
+        description
+          "Set Loopback type (or direction).";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance-testsignal.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance-testsignal.yang
new file mode 100644 (file)
index 0000000..b28cd6b
--- /dev/null
@@ -0,0 +1,134 @@
+module org-openroadm-maintenance-testsignal {
+  namespace "http://org/openroadm/maintenance-testsignal";
+  prefix org-openroadm-maint-testsignal;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for maintenance testsignal.
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping maint-testsignal {
+    container maint-testsignal {
+      leaf enabled {
+        type boolean;
+        default "false";
+        description
+          "testsignal enabled flag";
+      }
+      leaf testPattern {
+        when "../enabled = 'true'";
+        type enumeration {
+          enum "PRBS" {
+            value 0;
+            description
+              "Unframed, inverted PN-31 pattern or PRBS31 pattern per IEEE 802.3 clause 50.3.8.2 (inverted PN-31at line rate)";
+          }
+          enum "PRBS31" {
+            value 1;
+            description
+              "PRBS31 with standard mapping per G.709";
+          }
+          enum "PRBS23" {
+            value 2;
+            description
+              "SONET/SDH Framed,inverted PN-23 pattern.";
+          }
+          enum "PRZEROS" {
+            value 3;
+            description
+              "pseudo-random with zeros data pattern per IEEE 802.3 clause 49.2.8";
+          }
+          enum "IDLE" {
+            value 4;
+            description
+              "Scrambled IDLE test-pattern per IEEE 802.3ba";
+          }
+        }
+        description
+          "Set test signal pattern";
+      }
+      leaf type {
+        when "../enabled = 'true'";
+        type enumeration {
+          enum "fac" {
+            value 0;
+            description
+              "test signal in the facility direction";
+          }
+          enum "term" {
+            value 1;
+            description
+              "test signal in the terminal direction";
+          }
+        }
+        default "fac";
+        description
+          "Set test signal type (or direction).";
+      }
+      leaf bitErrors {
+        when "../enabled = 'true' and ../type = 'fac'";
+        type uint32 {
+          range "0..4294967295";
+        }
+        config false;
+        description
+          "bit errors for test signal in facility direction.";
+      }
+      leaf bitErrorsTerminal {
+        when "../enabled = 'true' and ../type = 'term'";
+        type uint32 {
+          range "0..4294967295";
+        }
+        config false;
+        description
+          "bit errors for test signal in terminal direction.";
+      }
+      leaf syncSeconds {
+        when "../enabled = 'true' and ../type = 'fac'";
+        type string;
+        config false;
+        description
+          "number of seconds the received facility test signal is in sync.";
+      }
+      leaf syncSecondsTerminal {
+        when "../enabled = 'true' and ../type = 'term'";
+        type string;
+        config false;
+        description
+          "number of seconds the received terminal test signal is in sync.";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-maintenance.yang
new file mode 100644 (file)
index 0000000..f8c058a
--- /dev/null
@@ -0,0 +1,87 @@
+module org-openroadm-maintenance {
+  namespace "http://org/openroadm/maintenance";
+  prefix org-openroadm-mainteance;
+
+  import org-openroadm-resource {
+    prefix org-openroadm-resource;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of maintenace operations.
+       
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+      AT&T Intellectual Property.  All other rights reserved.
+      
+      Redistribution and use in source and binary forms, with or without modification, 
+      are permitted provided that the following conditions are met:
+      
+      * Redistributions of source code must retain the above copyright notice, this 
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice, 
+        this list of conditions and the following disclaimer in the documentation and/or 
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+        contributors may be used to endorse or promote products derived from this software 
+        without specific prior written permission.
+      
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping maintenance {
+    leaf id {
+      description
+        "Uniquely identify maintenance activity";
+      type string;
+      mandatory true;
+    }
+    container resource {
+      description
+        "Resource under maintenance";
+      uses org-openroadm-resource:resource;
+    }
+    leaf operation {
+      type maintenance-operation;
+    }
+  }
+
+  container maintenance-list {
+    description
+      "A list of active maintenance operations. Adding an entry to this list creates an active maintenance operation.  Removing an entry from this terminates a maintenance activity";
+    list maintenance {
+      key "id";
+      uses maintenance;
+    }
+  }
+
+  typedef maintenance-operation {
+    description
+      "Maintenance Operation.";
+    type enumeration {
+      enum "terminalLoopback" {
+        value 1;
+      }
+      enum "facilityLoopback" {
+        value 2;
+      }
+      enum "testSignal" {
+        value 3;
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-channel-interfaces.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-channel-interfaces.yang
new file mode 100644 (file)
index 0000000..37c54f4
--- /dev/null
@@ -0,0 +1,184 @@
+module org-openroadm-optical-channel-interfaces {
+  namespace "http://org/openroadm/optical-channel-interfaces";
+  prefix org-openroadm-optical-channel-interfaces;
+
+  import org-openroadm-device {
+    prefix org-openroadm-device;
+  }
+  import org-openroadm-interfaces {
+    prefix openROADM-if;
+  }
+  import org-openroadm-common-types {
+    prefix org-openroadm-common-types;
+  }   
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for device facility och interfaces.
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.
+     
+     Also contains code components extracted from IETF Interfaces.  These code components
+     are copyrighted and licensed as follows:
+     
+     Copyright (c) 2016 IETF Trust and the persons identified as the document authors.
+     All rights reserved.
+     
+     This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating
+     to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of
+     publication of this document. Please review these documents carefully, as they
+     describe your rights and restrictions with respect to this document. Code Components
+     extracted from this document must include Simplified BSD License text as described in
+     Section 4.e of the Trust Legal Provisions and are provided without warranty as
+     described in the Simplified BSD License.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  identity rate-identity {
+    description
+      "A unique rate identification";
+  }
+
+  identity R200G {
+    base rate-identity;
+    description
+      "Identity for 200G Rate";
+  }
+
+  identity R100G {
+    base rate-identity;
+    description
+      "Identity for 100G Rate";
+  }
+
+  identity R10.7G {
+    base rate-identity;
+    description
+      "Identity for 10.7G Rate";
+  }
+
+  identity R11.1G {
+    base rate-identity;
+    description
+      "Identity for 11.1G Rate";
+  }
+
+  grouping och-attributes {
+    description
+      "Optical Channel attributes";
+    leaf rate {
+      type identityref {
+        base rate-identity;
+      }
+      description
+        "rate";
+    }
+    leaf wavelength-number {
+      type uint32;
+    }
+    leaf modulation-format {
+      type enumeration {
+        enum "bpsk" {
+          value 0;
+          description
+            "binary phase-shift keying";
+        }
+        enum "dc-dp-bpsk" {
+          value 1;
+          description
+            "DC dual-polarization binary phase-shift keying";
+        }
+        enum "qpsk" {
+          value 2;
+          description
+            "quadrature phase-shift keying";
+        }
+        enum "dp-qpsk" {
+          value 3;
+          description
+            "dual-polarization binary phase-shift keying";
+        }
+        enum "qam16" {
+          value 4;
+          description
+            "quadrature amplitude modulation 16";
+        }
+        enum "dp-qam16" {
+          value 5;
+          description
+            "dual-polarization quadrature amplitude modulation 16";
+        }
+        enum "dc-dp-qam16" {
+          value 6;
+          description
+            "DC dual-polarization quadrature amplitude modulation 16";
+        }
+        enum "qam8" {
+          value 7;
+          description
+            "quadrature amplitude modulation 8";
+        }
+        enum "dp-qam8" {
+          value 8;
+          description
+            "dual-polarization quadrature amplitude modulation 8";
+        }
+        enum "dc-dp-qam8" {
+          value 9;
+          description
+            "DC dual-polarization quadrature amplitude modulation 8";
+        }
+      }
+      description
+        "modulation format";
+    }
+    leaf transmit-power {
+      type org-openroadm-common-types:power-dBm;
+      description
+        "The target transmit power for this channel. When set, the xponder will work to ensure that port-current-power reaches this level. Applicable only to channel on top of xpdr-network port";
+    }     
+  }
+
+  grouping och-container {
+    container och {
+      description
+        "Optical Channel (OCh):
+         Models the optical channel interfaces for an Optical White Box.";
+      uses och-attributes;
+    }
+  }
+
+  augment "/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface" {
+    when "org-openroadm-device:type = 'openROADM-if:opticalChannel'";
+    uses och-container;
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-multiplex-interfaces.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-multiplex-interfaces.yang
new file mode 100644 (file)
index 0000000..03be0d4
--- /dev/null
@@ -0,0 +1,66 @@
+module org-openroadm-optical-multiplex-interfaces {
+  namespace "http://org/openroadm/optical-multiplex-interfaces";
+  prefix org-openroadm-optical-multiplex-interfaces;
+
+  import org-openroadm-device {
+    prefix org-openroadm-device;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "This module contains YANG definitions
+     for the Optical multiplex Interfaces (OMS).
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.
+     
+     Also contains code components extracted from IETF Interfaces.  These code components
+     are copyrighted and licensed as follows:
+     
+     Copyright (c) 2016 IETF Trust and the persons identified as the document authors.
+     All rights reserved.
+     
+     This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating
+     to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of
+     publication of this document. Please review these documents carefully, as they
+     describe your rights and restrictions with respect to this document. Code Components
+     extracted from this document must include Simplified BSD License text as described in
+     Section 4.e of the Trust Legal Provisions and are provided without warranty as
+     described in the Simplified BSD License.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  augment "/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface" {
+    description
+      "Optical Multiplex Section (OMS)
+       allow setting of OMS in the openROADM interfaces tree.";
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-transport-interfaces.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-optical-transport-interfaces.yang
new file mode 100644 (file)
index 0000000..84ca453
--- /dev/null
@@ -0,0 +1,144 @@
+module org-openroadm-optical-transport-interfaces {
+  namespace "http://org/openroadm/optical-transport-interfaces";
+  prefix org-openroadm-optical-transport-interfaces;
+
+  import org-openroadm-device {
+    prefix org-openroadm-device;
+  }
+  import org-openroadm-interfaces {
+    prefix openROADM-if;
+  }
+  import org-openroadm-common-types {
+    prefix org-openroadm-common-types;
+  }       
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "This module contains YANG definitions
+     for the Optical Transport Interfaces.
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.
+     
+     Also contains code components extracted from IETF Interfaces.  These code components
+     are copyrighted and licensed as follows:
+     
+     Copyright (c) 2016 IETF Trust and the persons identified as the document authors.
+     All rights reserved.
+     
+     This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating
+     to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of
+     publication of this document. Please review these documents carefully, as they
+     describe your rights and restrictions with respect to this document. Code Components
+     extracted from this document must include Simplified BSD License text as described in
+     Section 4.e of the Trust Legal Provisions and are provided without warranty as
+     described in the Simplified BSD License.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping ots-attributes {
+    description
+      "Optical Transport Section (OTS) attributes";
+    leaf fiber-type {
+      type enumeration {
+        enum "smf" {
+          value 0;
+          description
+            "Single Mode Fiber";
+        }
+        enum "eleaf" {
+          value 1;
+          description
+            "ELEAF";
+        }
+        enum "oleaf" {
+          value 2;
+          description
+            "OLEAF";
+        }
+        enum "dsf" {
+          value 3;
+          description
+            "DSF";
+        }
+        enum "truewave" {
+          value 4;
+          description
+            "TRUEWAVE Reduced Slope";
+        }
+        enum "truewavec" {
+          value 5;
+          description
+            "TRUEWAVE Classic";
+        }
+        enum "nz-dsf" {
+          value 6;
+          description
+            "NZ-DSF";
+        }
+        enum "ull" {
+          value 7;
+          description
+            "Ultra Low Loss (ULL)";
+        }
+      }
+      default "smf";
+      description
+        "fiber type
+         Default    : SMF ";
+    }
+    leaf span-loss-receive {
+      description
+        "Span loss on the receiver side. Set by the controller and used by device to set AMP gain.";
+      type org-openroadm-common-types:ratio-dB;
+    }
+    leaf span-loss-transmit {
+      description
+        "Span loss on the transmitter side. Set by the controller and used by device to configure MSA compliant channel launch power";
+      type org-openroadm-common-types:ratio-dB;
+    }                                   
+  }
+
+  grouping ots-container {
+    container ots {
+      description
+        "Optical Transport Section (OTS):
+          Models the optical interfaces for an Optical White Box.
+          The network side is represented by the OTS/OMS.";
+      uses ots-attributes;
+    }
+  }
+
+  augment "/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface" {
+    when "org-openroadm-device:type = 'openROADM-if:opticalTransport'";
+    uses ots-container;
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-otn-odu-interfaces@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-otn-odu-interfaces@2016-10-14.yang
new file mode 100644 (file)
index 0000000..3b49eff
--- /dev/null
@@ -0,0 +1,387 @@
+module org-openroadm-otn-odu-interfaces {
+  namespace "http://org/openroadm/otn-odu-interfaces";
+  prefix org-openroadm-otn-odu-interfaces;
+
+  import org-openroadm-device {
+    prefix org-openroadm-device;
+  }
+  import org-openroadm-interfaces {
+    prefix openROADM-if;
+  }
+  import org-openroadm-maintenance-testsignal {
+    prefix org-openroadm-maint-testsignal;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for device facility otnodu interfaces.
+
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+     AT&T Intellectual Property.  All other rights reserved.
+
+     Redistribution and use in source and binary forms, with or without modification,
+     are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice, this
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation and/or
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+       contributors may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+     POSSIBILITY OF SUCH DAMAGE.
+
+     Also contains code components extracted from IETF Interfaces.  These code components
+     are copyrighted and licensed as follows:
+
+     Copyright (c) 2016 IETF Trust and the persons identified as the document authors.
+     All rights reserved.
+
+     This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating
+     to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of
+     publication of this document. Please review these documents carefully, as they
+     describe your rights and restrictions with respect to this document. Code Components
+     extracted from this document must include Simplified BSD License text as described in
+     Section 4.e of the Trust Legal Provisions and are provided without warranty as
+     described in the Simplified BSD License.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  identity odu-rate-identity {
+    description
+      "A unique rate identification of the ODUk.";
+  }
+
+  identity ODU4 {
+    base odu-rate-identity;
+    description
+      "Identity for an ODU4";
+  }
+
+  identity ODU3 {
+    base odu-rate-identity;
+    description
+      "Identity for an ODU3";
+  }
+
+  identity ODU2 {
+    base odu-rate-identity;
+    description
+      "Identity for an ODU2";
+  }
+
+  identity ODU2e {
+    base odu-rate-identity;
+    description
+      "Identity for an ODU2e";
+  }
+
+  identity ODU1 {
+    base odu-rate-identity;
+    description
+      "Identity for an ODU1";
+  }
+
+  identity ODU0 {
+    base odu-rate-identity;
+    description
+      "Identity for an ODU0";
+  }
+
+  identity ODUflex {
+    base odu-rate-identity;
+    description
+      "Identity for an ODUflex";
+  }
+
+  identity odtu-type-identity {
+    description
+      "A unique identification for the MSI odtu type.";
+  }
+
+  identity ODTU4.ts-Allocated {
+    base odtu-type-identity;
+    description
+      "OPU4 MSI - ODTU4.ts, TS is occupied/allocated";
+  }
+
+  identity ODTU4.1 {
+    base odtu-type-identity;
+    description
+      "ODTU4.1 MSI type";
+  }
+
+  identity ODTU4.2 {
+    base odtu-type-identity;
+    description
+      "ODTU4.2 MSI type";
+  }
+
+  identity ODTU4.8 {
+    base odtu-type-identity;
+    description
+      "ODTU4.8 MSI type";
+  }
+
+  identity ODTU4.31 {
+    base odtu-type-identity;
+    description
+      "ODTU4.31 MSI type";
+  }
+
+  identity ODTU01 {
+    base odtu-type-identity;
+    description
+      "ODTU01 MSI type";
+  }
+
+  identity ODTU12 {
+    base odtu-type-identity;
+    description
+      "ODTU12 MSI type";
+  }
+
+  identity ODTU13 {
+    base odtu-type-identity;
+    description
+      "ODTU13 MSI type";
+  }
+
+  identity ODTU23 {
+    base odtu-type-identity;
+    description
+      "ODTU23 MSI type";
+  }
+
+  identity ODTU2.ts {
+    base odtu-type-identity;
+    description
+      "ODTU2.ts MSI type";
+  }
+
+  identity ODTU3.ts {
+    base odtu-type-identity;
+    description
+      "ODTU3.ts MSI type";
+  }
+
+  identity unallocated {
+    base odtu-type-identity;
+    description
+      "Unallocated MSI type";
+  }
+
+  grouping msi-entry {
+    leaf trib-slot {
+      type uint16;
+      description
+        "tributary slot (TS)";
+    }
+    leaf odtu-type {
+      type identityref {
+        base odtu-type-identity;
+      }
+      description
+        "ODTU type, part of the MSI (Multiplex Structure Identifier)";
+    }
+    leaf trib-port {
+      type uint8;
+      description
+        "Tributray Port Number (0-based), part of the MSI";
+    }
+    leaf trib-port-payload {
+      type string;
+      description
+        "interface name being mapped to trib-port";
+    }
+  }
+
+  grouping odu-attributes {
+    description
+      "ODU attributes";
+    leaf rate {
+      type identityref {
+        base odu-rate-identity;
+      }
+      description
+        "rate identity of the ODU. 'identityref' is used
+         to allow to extend for future higher rates";
+    }
+    leaf monitoring-mode {
+      type enumeration {
+        enum "not-terminated" {
+          description
+            "Not Terminated: no detection or generation.
+             Overhead is passed through the interface transparently in receive direction";
+        }
+        enum "terminated" {
+          description
+            "Terminated: detection and generation enabled.
+             Overhead is erased (replaced with all zeros) in receive direction";
+        }
+        enum "monitored" {
+          description
+            "Monitored: detection enabled.
+             Overhead is passed through the interface transparently in receive direction";
+        }
+      }
+      description
+        "Monitoring mode of the ODU Overhead";
+    }
+    leaf proactive-delay-measurement-enabled {
+      type boolean;
+      description
+        "enable/disable proactive Delay Measurement";
+    }
+    list tcm {
+      key "layer";
+      uses tcm-attributes;
+      max-elements "6";
+      description
+        "Tandem Connection Management";
+    }
+    uses opu;
+  }
+
+  grouping opu {
+    container opu {
+      when "../monitoring-mode = 'terminated' or ../monitoring-mode = 'monitored'";
+      description
+        "Optical Channel Payload Unit (OPU)";
+      leaf payload-type {
+        type string {
+          length "2";
+          pattern "[0-9a-fA-F]*";
+        }
+        description
+          "Payload Type";
+      }
+      leaf rx-payload-type {
+        type string {
+          length "2";
+          pattern "[0-9a-fA-F]*";
+        }
+        description
+          "Received Payload Type";
+      }
+      leaf exp-payload-type {
+        type string {
+          length "2";
+          pattern "[0-9a-fA-F]*";
+        }
+        description
+          "Expected Payload Type";
+      }
+      leaf payload-interface {
+        type string;
+        description
+          "Expected Payload of OPU. It designates client interface name";
+      }
+      container msi {
+        when "../payload-type = '20' or ../payload-type = '21'";
+        list tx-msi {
+          key "trib-slot";
+          uses msi-entry;
+          description
+            "Transmit MSI";
+        }
+        list rx-msi {
+          key "trib-slot";
+          uses msi-entry;
+          description
+            "Receive MSI";
+        }
+        list exp-msi {
+          key "trib-slot";
+          uses msi-entry;
+          description
+            "Expected MSI";
+        }
+      }
+    }
+  }
+
+  grouping tcm-attributes {
+    description
+      "Tandem Connection Monitoring (TCM) attributes";
+    leaf layer {
+      type uint8 {
+        range "1..6";
+      }
+      description
+        "TCM layer";
+    }
+    leaf monitoring-mode {
+      type enumeration {
+        enum "not-terminated" {
+          description
+            "Not Terminated: no detection or generation.
+             Overhead is passed through the interface transparently in receive direction
+             unless extension is set for erase";
+        }
+        enum "terminated" {
+          description
+            "Terminated: detection and generation enabled.
+             Overhead is erased (replaced with all zeros) in receive direction, unless
+             extension is set to passthrough";
+        }
+        enum "monitored" {
+          description
+            "Monitored: detection enabled.
+             Overhead is passed through the interface transparently in receive direction
+             unless extension is set for erase";
+        }
+      }
+      description
+        "Monitoring mode of the TCM layer";
+    }
+    leaf ltc-act-enabled {
+      type boolean;
+      description
+        "enable/disable alarm transfer on detection of Loss of Tandem Connection (LTC)";
+    }
+    leaf proactive-delay-measurement-enabled {
+      type boolean;
+      description
+        "enable/disable proactive Delay Measurement";
+    }
+  }
+
+  grouping odu-container {
+    container odu {
+      presence "Attribute Nodes for Optical Data Unit (ODU)";
+      description
+        "Optical Channel Data Unit (ODU)";
+      uses odu-attributes {
+        refine "opu/rx-payload-type" {
+          config false;
+        }
+        refine "opu/msi" {
+          config false;
+        }
+      }
+      uses org-openroadm-maint-testsignal:maint-testsignal;
+    }
+  }
+
+  augment "/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface" {
+    when "org-openroadm-device:type = 'openROADM-if:otnOdu'";
+    uses odu-container;
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-otn-otu-interfaces@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-otn-otu-interfaces@2016-10-14.yang
new file mode 100644 (file)
index 0000000..4fe3bb3
--- /dev/null
@@ -0,0 +1,185 @@
+module org-openroadm-otn-otu-interfaces {
+  namespace "http://org/openroadm/otn-otu-interfaces";
+  prefix org-openroadm-otn-otu-interfaces;
+
+  import org-openroadm-device {
+    prefix org-openroadm-device;
+  }
+  import org-openroadm-interfaces {
+    prefix openROADM-if;
+  }
+  import org-openroadm-maintenance-loopback {
+    prefix org-openroadm-maint-loopback;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for device facility otnotu interfaces.
+
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+     AT&T Intellectual Property.  All other rights reserved.
+
+     Redistribution and use in source and binary forms, with or without modification,
+     are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice, this
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation and/or
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+       contributors may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+     POSSIBILITY OF SUCH DAMAGE.
+
+     Also contains code components extracted from IETF Interfaces.  These code components
+     are copyrighted and licensed as follows:
+
+     Copyright (c) 2016 IETF Trust and the persons identified as the document authors.
+     All rights reserved.
+
+     This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating
+     to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of
+     publication of this document. Please review these documents carefully, as they
+     describe your rights and restrictions with respect to this document. Code Components
+     extracted from this document must include Simplified BSD License text as described in
+     Section 4.e of the Trust Legal Provisions and are provided without warranty as
+     described in the Simplified BSD License.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  identity otu-rate-identity {
+    description
+      "A unique rate identification of the OTU.";
+  }
+
+  identity OTU4 {
+    base otu-rate-identity;
+    description
+      "Identity for an OTU4";
+  }
+
+  identity OTU3 {
+    base otu-rate-identity;
+    description
+      "Identity for an OTU3";
+  }
+
+  identity OTU2 {
+    base otu-rate-identity;
+    description
+      "Identity for an OTU2";
+  }
+
+  identity OTU2e {
+    base otu-rate-identity;
+    description
+      "Identity for an OTU2e";
+  }
+
+  identity OTU1 {
+    base otu-rate-identity;
+    description
+      "Identity for an OTU1";
+  }
+
+  identity OTU0 {
+    base otu-rate-identity;
+    description
+      "Identity for an OTU0";
+  }
+
+  identity OTUflex {
+    base otu-rate-identity;
+    description
+      "Identity for an OTUflex";
+  }
+
+  grouping otu-attributes {
+    description
+      "OTU attributes";
+    leaf rate {
+      type identityref {
+        base otu-rate-identity;
+      }
+      description
+        "rate identity of the OTU. 'identityref' is used
+         to allow to extend for future higher rates";
+    }
+    leaf fec {
+      type enumeration {
+        enum "off" {
+          value 0;
+          description
+            "fec off";
+        }
+        enum "rsfec" {
+          value 1;
+          description
+            "rsfec";
+        }
+        enum "sdfeca1" {
+          value 2;
+          description
+            "Clariphy SDFEC";
+        }
+        enum "efec" {
+          value 3;
+          description
+            "G.975.1 I.4";
+        }
+        enum "ufec" {
+          value 4;
+          description
+            "G.975.1 I.7";
+        }
+        enum "sdfec" {
+          value 5;
+          description
+            "Soft decision FEC";
+        }
+        enum "sdfecb1" {
+          value 6;
+          description
+            "SDFEC with SCFEC";
+        }
+        enum "scfec" {
+          value 7;
+          description
+            "Stair case FEC";
+        }
+      }
+      description
+        "Forward Error Correction";
+    }
+  }
+
+  grouping otu-container {
+    container otu {
+      description
+        "Optical Channel Transport Unit (OTU)";
+      uses otu-attributes;
+      uses org-openroadm-maint-loopback:maint-loopback;
+    }
+  }
+
+  augment "/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface" {
+    when "org-openroadm-device:type = 'openROADM-if:otnOtu'";
+    uses otu-container;
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-physical-types.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-physical-types.yang
new file mode 100644 (file)
index 0000000..100a443
--- /dev/null
@@ -0,0 +1,117 @@
+module org-openroadm-physical-types {
+  namespace "http://org/openroadm/physical/types";
+  prefix org-openroadm-physical-types;
+
+  import org-openroadm-common-types {
+    prefix org-openroadm-common-types;
+  }
+  import ietf-yang-types {
+    prefix yang;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of physical types.
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping node-info {
+    description
+      "Physical inventory data used by the node";
+    leaf vendor {
+      description
+        "Vendor of the equipment";
+      type string;
+      config false;
+      mandatory true;
+    }
+    leaf model {
+      type string;
+      description
+        "Physical resource model information.";
+      config false;
+      mandatory true;
+    }
+    leaf serial-id {
+      description
+        "Product Code for this physical resource";
+      type string;
+      config false;
+      mandatory true;
+    }
+  }
+
+  grouping common-info {
+    description
+      "Physical inventory data used by all other entities";
+    uses node-info;
+    leaf type {
+      description
+        "The specific type of this physical resource - ie the type of
+         shelf, type of circuit-pack, etc.";
+      type string;
+      config false;
+    }
+    leaf product-code {
+      description
+        "Product Code for this physical resource";
+      type string;
+      config false;
+    }
+    leaf manufacture-date {
+      description
+        "Manufactor date of physical resource";
+      type yang:date-and-time;
+      config false;
+    }
+    leaf clei {
+      description
+        "CLEI for this physical resource";
+      type string;
+      config false;
+    }
+    leaf hardware-version {
+      description
+        "The version of the hardware.";
+      type string;
+      config false;
+    }
+    leaf operational-state {
+      description
+        "Operational state of the physical resource";
+      type org-openroadm-common-types:state;
+      config false;
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-pm-types@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-pm-types@2016-10-14.yang
new file mode 100644 (file)
index 0000000..3a70362
--- /dev/null
@@ -0,0 +1,279 @@
+module org-openroadm-pm-types {
+  namespace "http://org/openroadm/pm-types";
+  prefix org-openroadm-pm-types;
+
+  import org-openroadm-common-types {
+    prefix org-openroadm-common-types;
+   revision-date 2016-10-14;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of performance management types.
+
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+      AT&T Intellectual Property.  All other rights reserved.
+
+      Redistribution and use in source and binary forms, with or without modification,
+      are permitted provided that the following conditions are met:
+
+      * Redistributions of source code must retain the above copyright notice, this
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice,
+        this list of conditions and the following disclaimer in the documentation and/or
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+        contributors may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  typedef pm-granularity {
+    description
+      "Granularity of PM bin";
+    type enumeration {
+      enum "notApplicable" {
+        description
+          "This is for total statistic counters on devices that support
+              them.";
+        value 1;
+      }
+      enum "15min" {
+        value 2;
+      }
+      enum "24Hour" {
+        value 3;
+      }
+    }
+  }
+
+  typedef pm-data-type {
+    type union {
+      type uint64;
+      type decimal64 {
+        fraction-digits 2;
+      }
+      type decimal64 {
+        fraction-digits 17;
+      }
+    }
+  }
+
+  grouping pm-measurement {
+    description
+      "Set of parameters related to a PM Measurement";
+    container pmParameterName {
+      uses pm-names;
+    }
+    leaf pmParameterValue {
+      type pm-data-type;
+      mandatory true;
+      config false;
+    }
+    leaf pmParameterUnit {
+      description
+        "Unit PM parameter has been measured - frames, packets, u, etc";
+      type string;
+      mandatory false;
+    }
+    leaf location {
+      description
+        "Location PM parameter measurement";
+      type enumeration {
+        enum "notApplicable" {
+          value 1;
+        }
+        enum "nearEnd" {
+          value 2;
+        }
+        enum "farEnd" {
+          value 3;
+        }
+      }
+      mandatory false;
+    }
+    leaf direction {
+      description
+        "Direction PM parameter measurement";
+      type org-openroadm-common-types:pm-direction;
+      mandatory false;
+    }
+    leaf validity {
+      description
+        "Validity of data";
+      type enumeration {
+        enum "complete" {
+          value 1;
+        }
+        enum "partial" {
+          value 2;
+        }
+        enum "suspect" {
+          value 3;
+        }
+      }
+      mandatory false;
+      config false;
+    }
+  }
+
+  grouping pm-names {
+    description
+      "Name of PM parameter. Consisists of a set list of parameters,
+       plus an extension field to support addition parameters.";
+    leaf type {
+      type pm-names-enum;
+      mandatory true;
+    }
+    leaf extension {
+      description
+        "name of parameter, when enum value set to vendorExtension because
+         name not found in pm-names-enum";
+      type string;
+      mandatory false;
+    }
+  }
+
+  typedef pm-names-enum {
+    type enumeration {
+      enum "vendorExtension" {
+        value 1;
+        description
+          "vendor extension";
+      }
+      enum "bitErrorRate" {
+        value 2;
+        description
+          "Bit error rate (BER)";
+      }
+      enum "opticalPowerOutput" {
+        value 3;
+        description
+          "Optical Power Output (OPOUT-OTS). Total optical power includes Variable Optical Attenuator (VOA) attenuation";
+      }
+      enum "opticalReturnLoss" {
+        value 4;
+        description
+          "Optical Return Loss (ORL-OTS) - at MW port(s) B";
+      }
+      enum "opticalPowerInput" {
+        value 5;
+        description
+          "Optical Power Input (OPIN-OTS). Total optical power";
+      }
+      enum "opticalPower" {
+        value 6;
+        description
+          "Optical Power Receive (OPR-OTS); Optical Power Transmit (OPT-OSC)";
+      }
+      enum "opticalChannelPowerTransmit" {
+        value 7;
+        description
+          "Optical Channel Power Transmit (OPT-OCH). Individual channel power includes Variable Optical Attenuator (VOA) attenuation";
+      }
+      enum "codeViolations" {
+        value 8;
+        description
+          "Code Violations (CV-PCS). 8B/10B errors";
+        reference "IEEE 802.3ah, Section 45.2.1.44";
+      }
+      enum "erroredSecondsSection" {
+        value 9;
+        description
+          "Errored Seconds Section (ES-PCS)";
+        reference "IEEE 802.3ah, Section 45.2.1.46";
+      }
+      enum "severlyErrorSeconds" {
+        value 10;
+        description
+          "Severely Errored Seconds (SES-PCS)";
+        reference "IEEE 802.3ah, Section 45.2.1.48";
+      }
+      enum "unavailableSecondsPCS" {
+        value 11;
+        description
+          "Unavailable Seconds PCS (UAS-PCS)";
+        reference "IEEE 802.3ah, Section 45.2.1.52";
+      }
+      enum "inFrames" {
+        value 12;
+        description
+          "In frames (INFRAMES-E)";
+      }
+      enum "inFramesErrored" {
+        value 13;
+        description
+          "In frames errored (INFRAMESERR-E)";
+      }
+      enum "outFrames" {
+        value 14;
+        description
+          "Out frames (OUTFRAMES-E)";
+      }
+      enum "erroredSecondsEthernet" {
+        value 15;
+        description
+          "Errored Seconds Ethernet (ES-E)";
+        reference "IEEE 802.3ah, Section 45.2.1.46";
+      }
+      enum "severelyErroredSecondsEthernet" {
+        value 16;
+        description
+          "Severly Errored Seconds, Ethernet (SES-E)";
+        reference "IEEE 802.3ah, Section 45.2.1.48";
+      }
+      enum "unavailableSecondsEthernet" {
+        value 17;
+        description
+          "Unavailable Seconds, Ethernet (UAS-E)";
+        reference "IEEE 802.3ah, Section 45.2.1.52";
+      }
+      enum "erroredBlockCount" {
+        value 18;
+        description
+          "Errored block count";
+        reference "G.798 : 6.5.1.1";
+      }
+      enum "delay" {
+        value 19;
+        description
+          "Number of frames between a DMValue toggle event and the received DMp signal value toggle event";
+        reference "G.798";
+      }
+      enum "defectSeconds" {
+        value 20;
+        description
+          "Defect Seconds (DS)";
+        reference "";
+      }
+      enum "backwardIncomingAlignmentError" {
+        value 21;
+        description
+          "Backward Incoming Alignment Error (BIAE)";
+        reference "Ref: G.798: 14.5.1.1.2";
+      }
+      enum "incomingAlignmentError" {
+        value 22;
+        description
+          "Incoming Alignment Error (IAE)";
+        reference "Ref: G.798: 14.5.1.1.2";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-pm@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-pm@2016-10-14.yang
new file mode 100644 (file)
index 0000000..8a75c58
--- /dev/null
@@ -0,0 +1,189 @@
+module org-openroadm-pm {
+  namespace "http://org/openroadm/pm";
+  prefix org-openroadm-pm;
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+  import org-openroadm-resource {
+    prefix org-openroadm-resource;
+  }
+  import org-openroadm-layerRate {
+    prefix org-openroadm-layerRate;
+  }
+  import org-openroadm-pm-types {
+    prefix org-openroadm-pm-types;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of performance management.
+
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+      AT&T Intellectual Property.  All other rights reserved.
+
+      Redistribution and use in source and binary forms, with or without modification,
+      are permitted provided that the following conditions are met:
+
+      * Redistributions of source code must retain the above copyright notice, this
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice,
+        this list of conditions and the following disclaimer in the documentation and/or
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+        contributors may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping current-pm {
+    description
+      "PM Data with current values - both realtime (granularity=notApplicable) and binned (granularity=15 minute, 24h))";
+    leaf id {
+      type string;
+      mandatory true;
+      config false;
+    }
+    container resource {
+      uses org-openroadm-resource:resource;
+    }
+    container layerRate {
+      uses org-openroadm-layerRate:layer-rate;
+    }
+    list measurements {
+      container measurement {
+        uses org-openroadm-pm-types:pm-measurement;
+      }
+    }
+    leaf retrievalTime {
+      type yang:date-and-time;
+      mandatory true;
+      config false;
+    }
+    leaf granularity {
+      type org-openroadm-pm-types:pm-granularity;
+    }
+  }
+
+  container currentPmlist {
+    description
+      "List of current PMs.";
+    list currentPm {
+      key "id";
+      uses current-pm;
+    }
+    config false;
+  }
+
+  grouping historical-pm {
+    description
+      "PM Data with historical values - binned (granularity=15 minute, 24h))";
+    leaf id {
+      type string;
+      mandatory true;
+      config false;
+    }
+    container resource {
+      uses org-openroadm-resource:resource;
+    }
+    container layerRate {
+      uses org-openroadm-layerRate:layer-rate;
+    }
+    list binned-pm {
+      key "bin-number";
+      uses bin-pm;
+    }
+    leaf granularity {
+      type org-openroadm-pm-types:pm-granularity;
+    }
+  }
+
+  grouping bin-pm {
+    description
+      "PM Data with historical values";
+    leaf bin-number {
+      type uint16 {
+        range "1..max";
+      }
+      mandatory true;
+      config false;
+    }
+    list measurements {
+      container measurement {
+        uses org-openroadm-pm-types:pm-measurement;
+      }
+    }
+    leaf completionTime {
+      type yang:date-and-time;
+      mandatory true;
+      config false;
+    }
+  }
+
+  container historicalPmlist {
+    description
+      "List of historical PM";
+    list historicalPm {
+      key "id";
+      uses historical-pm;
+    }
+    config false;
+  }
+  rpc clear-pm {
+    description "Command to initialize PM data";
+    input {
+      uses org-openroadm-resource:resource;
+      leaf pm-type {
+        default "current";
+        type enumeration {
+          enum "current" {
+            value 1;
+          }
+          enum "all" {
+            value 2;
+          }
+        }
+      }
+      leaf granularity {
+        default "15min";
+        type org-openroadm-pm-types:pm-granularity;
+      }
+    }
+    output {
+      leaf status {
+        type enumeration {
+          enum "Successful" {
+            value 1;
+          }
+          enum "Failed" {
+            value 2;
+          }
+        }
+        mandatory true;
+        description
+          "Successful or Failed";
+      }
+      leaf status-message {
+        type string;
+        description
+          "Gives a more detailed reason for success / failure";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-port-types@2017-09-29.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-port-types@2017-09-29.yang
new file mode 100644 (file)
index 0000000..fdae1d8
--- /dev/null
@@ -0,0 +1,181 @@
+module org-openroadm-port-types {
+  namespace "http://org/openroadm/port/types";
+  prefix org-openroadm-port-types;
+
+  import org-openroadm-common-types {
+    prefix org-openroadm-common-types;
+    revision-date 2017-09-29;
+  }
+
+  organization
+    "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for port types.
+
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+     AT&T Intellectual Property.  All other rights reserved.
+
+     Redistribution and use in source and binary forms, with or without modification,
+     are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice, this
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation and/or
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+       contributors may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+     POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2017-09-29 {
+    description
+      "Version 2.1";
+  }
+  revision 2017-07-28 {
+    description
+      "Version 2.0.1 - added revision-date to imports";
+  }
+  revision 2017-06-26 {
+    description
+      "Version 2.0";
+  }
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  identity supported-if-capability {
+    description
+      "Base identity from which specific supported interfaces are derived";
+  }
+
+  identity if-100GE {
+    base supported-if-capability;
+  }
+
+  identity if-OMS {
+    base supported-if-capability;
+  }
+
+  identity if-OTS {
+    base supported-if-capability;
+  }
+
+  identity if-OCH {
+    base supported-if-capability;
+  }
+
+  identity if-1GE {
+    base supported-if-capability;
+  }
+
+  identity if-10GE {
+    base supported-if-capability;
+  }
+
+  identity if-40GE {
+    base supported-if-capability;
+  }
+
+  identity if-OCH-OTU1-ODU1 {
+    base supported-if-capability;
+  }
+
+  identity if-OCH-OTU2-ODU2 {
+    base supported-if-capability;
+  }
+
+  identity if-OCH-OTU2E-ODU2E {
+    base supported-if-capability;
+  }
+
+  identity if-OCH-OTU3-ODU3 {
+    base supported-if-capability;
+  }
+
+  identity if-OCH-OTU4-ODU4 {
+    base supported-if-capability;
+  }
+
+  identity if-OTU4-ODU4 {
+    base supported-if-capability;
+  }
+
+  identity supported-xpdr-capability {
+    description
+      "Base identity from which specific supported xponder are derived";
+  }
+
+  identity Transponder {
+    base supported-xpdr-capability;
+  }
+
+  identity Regen {
+    base supported-xpdr-capability;
+  }
+
+  typedef port-wavelength-types {
+    type enumeration {
+      enum "wavelength" {
+        value 1;
+        description
+          "Port on a transponder or ROADM SRG add drop";
+      }
+      enum "multi-wavelength" {
+        value 2;
+        description
+          "External port connecting to other roadm.";
+      }
+    }
+    description
+      "Port types.";
+  }
+
+  grouping common-port {
+    leaf port-power-capability-min-rx {
+      type org-openroadm-common-types:power-dBm;
+      config false;
+      description
+        "Based on port capabilities, the minimum power in the system spec for this port to
+         provide optimum function in rx direction";
+    }
+    leaf port-power-capability-min-tx {
+      type org-openroadm-common-types:power-dBm;
+      config false;
+      description
+        "Based on port capabilities, the minimum power in the system spec for this port to
+         provide optimum function in tx direction.";
+    }
+    leaf port-power-capability-max-rx {
+      type org-openroadm-common-types:power-dBm;
+      config false;
+      description
+        "Based on port capabilities, the maximum power in the system spec for this port to
+         provide optimum function in rx direction.";
+    }
+    leaf port-power-capability-max-tx {
+      type org-openroadm-common-types:power-dBm;
+      config false;
+      description
+        "Based on port capabilities, the maximum power in the system spec for this port to
+         provide optimum function in tx direction.";
+    }
+  }
+
+  grouping roadm-port {
+    uses common-port;
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-resource-types@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-resource-types@2016-10-14.yang
new file mode 100644 (file)
index 0000000..bb6a80a
--- /dev/null
@@ -0,0 +1,252 @@
+module org-openroadm-resource-types {
+  namespace "http://org/openroadm/resource/types";
+  prefix org-openroadm-resource-types;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of common resource types.
+
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+      AT&T Intellectual Property.  All other rights reserved.
+
+      Redistribution and use in source and binary forms, with or without modification,
+      are permitted provided that the following conditions are met:
+
+      * Redistributions of source code must retain the above copyright notice, this
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice,
+        this list of conditions and the following disclaimer in the documentation and/or
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+        contributors may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping resource-type {
+    leaf type {
+      type resource-type-enum;
+      mandatory true;
+    }
+    leaf extension {
+      type string;
+      mandatory false;
+    }
+  }
+
+  typedef resource-type-enum {
+    type enumeration {
+      enum "other" {
+        value 1;
+        description
+          "Resource of type not found in list.";
+      }
+      enum "device" {
+        value 2;
+        description
+          "device - ROAMD, Xponder, etc";
+      }
+      enum "degree" {
+        value 3;
+        description
+          "degree";
+      }
+      enum "shared-risk-group" {
+        value 4;
+        description
+          "shared-risk-group";
+      }
+      enum "connection" {
+        value 5;
+        description
+          "connection";
+      }
+      enum "connection-map" {
+        value 6;
+        description
+          "connection-map";
+      }
+      enum "port" {
+        value 7;
+        description
+          "port";
+      }
+      enum "circuit-pack" {
+        value 8;
+        description
+          "circuit pack";
+      }
+      enum "internal-link" {
+        value 9;
+        description
+          "internal-link";
+      }
+      enum "physical-link" {
+        value 10;
+        description
+          "physical-link";
+      }
+      enum "interface" {
+        value 11;
+        description
+          "interface";
+      }
+      enum "shelf" {
+        value 12;
+        description
+          "shelf";
+      }
+      enum "service" {
+        value 13;
+        description
+          "service";
+      }
+    }
+  }
+
+  grouping device-id {
+    description
+      "Device identifier. Unique within the Controller.";
+    leaf node-id {
+      description
+        "Node Id is a globally unique identifier for a device.
+         Same as leafref value in model, if applicable.";
+      type string;
+    }
+  }
+
+  grouping circuit-pack-name {
+    leaf circuit-pack-name {
+      description
+        "Circuit-Pack identifier. Unique within the context of a device.
+         Same as leafref value in model, if applicable.";
+      type string;
+      mandatory true;
+    }
+  }
+
+  grouping port-name {
+    uses circuit-pack-name;
+    leaf port-name {
+      description
+        "Port identifier. Unique within the context of a circuit-pack.
+         Same as leafref value in model, if applicable.";
+      type string;
+    }
+  }
+
+  grouping physical-link-name {
+    leaf physical-link-name {
+      description
+        "Physical Link identifier. Unique within the context of a device.
+         Same as leafref value in model, if applicable.";
+      type string;
+      mandatory true;
+    }
+  }
+
+  grouping internal-link-name {
+    leaf internal-link-name {
+      description
+        "Internal Link identifier. Unique within the context of a device.
+         Same as leafref value in model, if applicable.";
+      type string;
+      mandatory true;
+    }
+  }
+
+  grouping connection-number {
+    leaf connection-number {
+      description
+        "Connection identifier. Unique within the context of a device.
+         Same as leafref value in model, if applicable.";
+      type string;
+    }
+  }
+
+  grouping degree-number {
+    leaf degree-number {
+      description
+        "Degree identifier. Unique within the context of a device.
+         Same as leafref value in model, if applicable.";
+      type uint16;
+    }
+  }
+
+  grouping srg-number {
+    leaf srg-number {
+      description
+        "Shared Risk Group identifier. Unique within the context of a device.
+         Same as leafref value in model, if applicable.";
+      type uint16;
+    }
+  }
+
+  grouping shelf-name {
+    leaf shelf-name {
+      description
+        "Shelf-id identifier. Unique within the context of a device.
+         Same as leafref value in model, if applicable.";
+      type string;
+      mandatory true;
+    }
+  }
+
+  grouping service-name {
+    leaf service-name {
+      description
+        "Service identifier. Unique within the context of a network.
+         Same as leafref value in model, if applicable.";
+      type string;
+      mandatory true;
+    }
+  }
+
+  grouping interface-name {
+    leaf interface-name {
+      description
+        "Interface identifier.";
+      type string;
+      mandatory true;
+    }
+  }
+
+  typedef resource-notification-type {
+    description
+      "Type of notification about a resource";
+    type enumeration {
+      enum "resourceCreation" {
+        value 1;
+        description
+          "A new instance of a resource has been created.";
+      }
+      enum "resourceModification" {
+        value 2;
+        description
+          "An exhisting instance of a resource has been modified. This shall be triggered by changes in configuration, state, status etc.
+           It shall not be triggered by changes in performance measurements, power and temperature readings or any other data that is highlyvolatile. ";
+      }
+      enum "resourceDeletion" {
+        value 3;
+        description
+          "An exhisting instance of a resource has been removed.";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-resource@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-resource@2016-10-14.yang
new file mode 100644 (file)
index 0000000..25cb9f1
--- /dev/null
@@ -0,0 +1,109 @@
+module org-openroadm-resource {
+  namespace "http://org/openroadm/resource";
+  prefix org-openroadm-resource;
+
+  import org-openroadm-resource-types {
+    prefix org-openroadm-resource-types;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of resources.
+
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+      AT&T Intellectual Property.  All other rights reserved.
+
+      Redistribution and use in source and binary forms, with or without modification,
+      are permitted provided that the following conditions are met:
+
+      * Redistributions of source code must retain the above copyright notice, this
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice,
+        this list of conditions and the following disclaimer in the documentation and/or
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+        contributors may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping resource {
+    description
+      "This resource identifier is intended to provide a generic identifer
+       for any resource that can be used without specific knowledge of
+       the resource.";
+    container device {
+      description
+        "Device of the resource, used only when the system using this
+         model report on more than one device. ";
+      uses org-openroadm-resource-types:device-id;
+    }
+    container resource {
+      choice resource {
+        case circuit-pack {
+          uses org-openroadm-resource-types:circuit-pack-name;
+        }
+        case port {
+          container port {
+            uses org-openroadm-resource-types:port-name;
+          }
+        }
+        case connection {
+          uses org-openroadm-resource-types:connection-number {
+            refine connection-number {
+              mandatory true;
+            }
+          }
+        }
+        case physical-link {
+          uses org-openroadm-resource-types:physical-link-name;
+        }
+        case internal-link {
+          uses org-openroadm-resource-types:internal-link-name;
+        }
+        case shelf {
+          uses org-openroadm-resource-types:shelf-name;
+        }
+        case srg {
+          uses org-openroadm-resource-types:srg-number {
+            refine srg-number {
+              mandatory true;
+            }
+          }
+        }
+        case degree {
+          uses org-openroadm-resource-types:degree-number {
+            refine degree-number {
+              mandatory true;
+            }
+          }
+        }
+        case service {
+          uses org-openroadm-resource-types:service-name;
+        }
+        case interface {
+          uses org-openroadm-resource-types:interface-name;
+        }
+      }
+    }
+    container resourceType {
+      uses org-openroadm-resource-types:resource-type;
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-swdl.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-swdl.yang
new file mode 100644 (file)
index 0000000..1a86412
--- /dev/null
@@ -0,0 +1,120 @@
+module org-openroadm-swdl {
+  namespace "http://org/openroadm/de/swdl";
+  prefix org-openroadm-swdl;
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+
+  import org-openroadm-common-types {
+    prefix org-openroadm-common-types;
+  }
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "Yang definitions for System Management.
+     
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+     AT&T Intellectual Property.  All other rights reserved.
+     
+     Redistribution and use in source and binary forms, with or without modification, 
+     are permitted provided that the following conditions are met:
+     
+     * Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation and/or 
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+       contributors may be used to endorse or promote products derived from this software 
+       without specific prior written permission.
+     
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+     POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping sw-bank {
+    leaf sw-version {
+      type string;
+      description
+        "Gissue of the SW in this bank";
+    }
+    leaf sw-validation-timer {
+      type string {
+        pattern "(([0-1][0-9]|2[0-3])-([0-5][0-9])-([0-5][0-9]))";
+      }
+      description
+        "value of validation timer in hh-mm-ss";
+    }
+    leaf activation-date-time {
+      type yang:date-and-time;
+      description
+        "activation date and time: The date load was activated";
+    }
+  }
+
+  rpc sw-stage {
+    description
+      "SW stage - copies the SW from repo to staging bank";
+    input {
+      leaf filename {
+        type string {
+          length "10..255";
+        }
+        description
+          "file name which has the load";
+      }
+    }
+    output {
+      uses org-openroadm-common-types:rpc-response-status;
+    }
+  }
+  rpc sw-activate {
+    description
+      "Activate new load";
+    input {
+      leaf version {
+        type string;
+        description
+          " software version of the new load which is being activated";
+      }
+      leaf validationTimer {
+        type string;
+        description
+          "validation timer hh-mm-ss";
+      }
+    }
+    output {
+      uses org-openroadm-common-types:rpc-response-status;
+    }
+  }
+  rpc cancel-validation-timer {
+    description
+      "Cancel validation timer which user provisioned as part of activate command";
+    input {
+      leaf accept {
+        type boolean;
+        default "true";
+        description
+          " TRUE means  validation timer is cancelled and new load is accepted";
+      }
+    }
+    output {
+      uses org-openroadm-common-types:rpc-response-status;
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-user-mgmt.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-user-mgmt.yang
new file mode 100644 (file)
index 0000000..4bf5edb
--- /dev/null
@@ -0,0 +1,109 @@
+module org-openroadm-user-mgmt {
+  namespace "http://org/openroadm/user-mgmt";
+  prefix org-openroadm-user-mgmt;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions of user managements.
+       
+      Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016, 
+      AT&T Intellectual Property.  All other rights reserved.
+      
+      Redistribution and use in source and binary forms, with or without modification, 
+      are permitted provided that the following conditions are met:
+      
+      * Redistributions of source code must retain the above copyright notice, this 
+        list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright notice, 
+        this list of conditions and the following disclaimer in the documentation and/or 
+        other materials provided with the distribution.
+      * Neither the Members of the Open ROADM MSA Agreement nor the names of its 
+        contributors may be used to endorse or promote products derived from this software 
+        without specific prior written permission.
+      
+      THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS'' 
+      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+      IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT, 
+      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, 
+      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+      POSSIBILITY OF SUCH DAMAGE";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping user-profile {
+    list user {
+      key "name";
+      description
+        "The list of local users configured on this device.";
+      leaf name {
+        type string;
+        description
+          "The user name string identifying this entry.";
+      }
+      leaf password {
+        type string;
+        description
+          "The password for this entry. This shouldn't be in clear text";
+      }
+      leaf group {
+        type enumeration {
+          enum "sudo";
+        }
+        description
+          "The group to which the user is associated to.";
+      }
+    }
+  }
+
+  rpc chg-password {
+    input {
+      leaf currentPassword {
+        type string;
+        description
+          "provide the current password";
+        mandatory true;
+      }
+      leaf newPassword {
+        type string;
+        description
+          "provide a new password";
+        mandatory true;
+      }
+      leaf newPasswordConfirm {
+        type string;
+        description
+          "re-enter the new password ";
+        mandatory true;
+      }
+    }
+    output {
+      leaf status {
+        type enumeration {
+          enum "Successful" {
+            value 1;
+          }
+          enum "Failed" {
+            value 2;
+          }
+        }
+        mandatory true;
+        description
+          "Successful or Failed";
+      }
+      leaf status-message {
+        type string;
+        description
+          "Gives a more detailed reason for success / failure";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-wavelength-map@2016-10-14.yang b/tests/honeynode/honeynode-plugin-api/src/main/yang/org-openroadm-wavelength-map@2016-10-14.yang
new file mode 100644 (file)
index 0000000..451cae6
--- /dev/null
@@ -0,0 +1,71 @@
+module org-openroadm-wavelength-map {
+  namespace "http://org/openroadm/wavelength-map";
+  prefix org-openroadm-wavelength-map;
+
+  organization "Open ROADM MSA";
+  contact
+    "OpenROADM.org";
+  description
+    "YANG definitions for mapping wavelength-number to center frequency and wavelength value.
+
+     Copyright of the Members of the Open ROADM MSA Agreement dated (c) 2016,
+     AT&T Intellectual Property.  All other rights reserved.
+
+     Redistribution and use in source and binary forms, with or without modification,
+     are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice, this
+       list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation and/or
+       other materials provided with the distribution.
+     * Neither the Members of the Open ROADM MSA Agreement nor the names of its
+       contributors may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT ''AS IS''
+     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     IN NO EVENT THE MEMBERS OF THE OPEN ROADM MSA  AGREEMENT BE LIABLE FOR ANY DIRECT,
+     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA,
+     OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+     POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2016-10-14 {
+    description
+      "Version 1.2";
+  }
+
+  grouping wavelength-map-g {
+    list wavelengths {
+      key "wavelength-number";
+      leaf wavelength-number {
+        type uint32;
+      }
+      config false;
+      leaf center-frequency {
+        type decimal64 {
+          fraction-digits 3;
+          range "191.350..196.100";
+        }
+        units "THz";
+        description
+          "Frequency of the transmit optical channel
+           Domain range:  191.350THz .. 196.100THz ";
+      }
+      leaf wavelength {
+        type decimal64 {
+          fraction-digits 2;
+          range "1528.77..1566.72";
+        }
+        units "nm";
+        description
+          "Lambda corresponding to transmit frequency
+           Domain range:  1528.72nm .. 1566.72nm ";
+      }
+    }
+  }
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/asciidoc/Readme.adoc b/tests/honeynode/honeynode-plugin-impl/asciidoc/Readme.adoc
new file mode 100644 (file)
index 0000000..5c2a93d
--- /dev/null
@@ -0,0 +1,3 @@
+= honeynode-plugin-impl
+
+Overview of honeynode-plugin-impl
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-plugin-impl/pom.xml b/tests/honeynode/honeynode-plugin-impl/pom.xml
new file mode 100644 (file)
index 0000000..a6cd757
--- /dev/null
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 Cisco and/or its affiliates.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>io.fd.honeycomb.common</groupId>
+        <artifactId>impl-parent</artifactId>
+        <version>1.18.01</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>io.fd.honeycomb.transportpce</groupId>
+    <artifactId>honeynode-plugin-impl</artifactId>
+    <name>honeynode-plugin-impl</name>
+    <version>1.18.01</version>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <honeycomb.infra.version>1.18.01</honeycomb.infra.version>
+    </properties>
+
+    <dependencies>
+        <!-- Transportpce -->
+       <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>honeynode-common</artifactId>
+            <version>${project.version}</version>
+       </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>honeynode-plugin-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>minimal-distribution-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Honeycomb infrastructure-->
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>translate-api</artifactId>
+            <version>${honeycomb.infra.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>translate-spi</artifactId>
+            <version>${honeycomb.infra.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>cfg-init</artifactId>
+            <version>${honeycomb.infra.version}</version>
+        </dependency>
+
+        <!-- DI -->
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.jmob</groupId>
+            <artifactId>guice.conf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject.extensions</groupId>
+            <artifactId>guice-multibindings</artifactId>
+        </dependency>
+
+        <!-- Testing Dependencies -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceBindingDataBrokerProvider.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceBindingDataBrokerProvider.java
new file mode 100644 (file)
index 0000000..f1452cd
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.binding.init.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;
+
+/**
+ * @author Martial COULIBALY ( mcoulibaly.ext@orange.com ) on behalf of Orange
+ */
+public final class DeviceBindingDataBrokerProvider  extends ProviderTrait<DataBroker> {
+
+    @Inject
+    @Named(DeviceModule.DEVICE_DATABROKER)
+    private DOMDataBroker domDataBroker;
+    @Inject
+    private BindingToNormalizedNodeCodec mappingService;
+
+    @Override
+    protected BindingDOMDataBrokerAdapter create() {
+        return new BindingDOMDataBrokerAdapter(domDataBroker, mappingService);
+    }
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceConfiguration.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceConfiguration.java
new file mode 100644 (file)
index 0000000..234e115
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * 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.transportpce.device;
+
+import io.fd.honeycomb.transportpce.device.tools.DefaultDeviceFactory;
+import io.fd.honeycomb.transportpce.test.common.DataStoreContext;
+import io.fd.honeycomb.transportpce.test.common.DataStoreContextImpl;
+
+import java.io.File;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+/**
+ * Class containing static configuration for honeynode-plugin module<br>
+ * <p/>
+ * Further documentation for the configuration injection can be found at:
+ * https://github.com/yyvess/gconf
+ */
+@BindConfig(value = "honeycomb", syntax = Syntax.JSON)
+public final class DeviceConfiguration {
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceConfiguration.class);
+    private static final String DEVICE_XSL = "device/OperToConfig.xsl";
+    private static final String CONFIG_XSL = "device/config.xsl";
+    private static final String NAMESPACE_TRIMER_XSL = "device/NamespaceTrimmer.xslt";
+    //private static final String DEVICE_DATA_SAMPLE_OPER_XML = "device/sample-config-ROADM.xml";
+
+    public String config_device;
+    public OrgOpenroadmDevice oper_device;
+    private DataStoreContext dataStoreContextUtil;
+    private DefaultDeviceFactory defaultDeviceFactory;
+    private ClassLoader classLoader;
+    private Boolean register;
+
+    @InjectConfig("persisted-config-path")
+    public String peristConfigPath;
+
+    @InjectConfig("netconf-initial-config-xml")
+    public String DEVICE_DATA_SAMPLE_OPER_XML;
+
+    public DeviceConfiguration() {
+        classLoader = Thread.currentThread().getContextClassLoader();
+        dataStoreContextUtil = new DataStoreContextImpl();
+        defaultDeviceFactory = new DefaultDeviceFactory();
+        register = false;
+    }
+
+
+    public String getConfigDevice() {
+        return operToConfig();
+    }
+
+    public String getPeristConfigPath() {
+        return peristConfigPath;
+    }
+
+    public String getNetconfInitialConfigXml() {
+        return DEVICE_DATA_SAMPLE_OPER_XML;
+    }
+
+    public Boolean getRegister() {
+        return register;
+    }
+
+    public void setRegister(Boolean reg) {
+        this.register = reg;
+    }
+
+    public OrgOpenroadmDevice getDataDevice() {
+        OrgOpenroadmDevice result = null;
+        File device_data = new File(classLoader.getResource(DEVICE_DATA_SAMPLE_OPER_XML).getFile());
+        result = defaultDeviceFactory.createDefaultDevice(dataStoreContextUtil,device_data);
+        if (result != null) {
+            LOG.info("result info : {}", result.getInfo().getNodeId());
+        }
+        return result;
+    }
+
+    public OrgOpenroadmDevice getDeviceFromXML(String xml) {
+        String config_result =null;
+        LOG.info("process to transform xml file to config data");
+        TransformerFactory factory = TransformerFactory.newInstance();
+        Source xslt = new StreamSource(new File(classLoader.getResource(CONFIG_XSL).getFile()));
+        Transformer transformer;
+        Source text;
+        StringWriter device_config = new StringWriter();
+        OrgOpenroadmDevice result = null;
+        try {
+            LOG.info("transforming xml string to config device ...");
+            transformer = factory.newTransformer(xslt);
+            text = new StreamSource(new StringReader(xml));
+            transformer.transform(text, new StreamResult(device_config));
+            config_result = device_config.toString();
+            //LOG.info("config_result: {}",config_result);
+            result  = defaultDeviceFactory.createDefaultDevice(dataStoreContextUtil,config_result);
+            if (result != null) {
+                LOG.info("result info : {}", result.getInfo().getNodeId());
+            }
+        } catch (TransformerException e) {
+            LOG.error("Transformer failed ");
+        }
+
+        return result;
+    }
+
+
+   /**
+    * Convert data xml to config xml device.
+    * @return String result
+    */
+    public String operToConfig() {
+        String result =null;
+        LOG.info("process to transform xml file ");
+        TransformerFactory factory = TransformerFactory.newInstance();
+        Source xslt = new StreamSource(new File(classLoader.getResource(DEVICE_XSL).getFile()));
+        Transformer transformer;
+        Source text;
+        StringWriter tmpwriter = new StringWriter();
+        StringReader reader;
+        try {
+            LOG.info("transforming xml data to config device ...");
+            transformer = factory.newTransformer(xslt);
+            text = new StreamSource(new File(classLoader.getResource(DEVICE_DATA_SAMPLE_OPER_XML).getFile()));
+            transformer.transform(text, new StreamResult(tmpwriter));
+            LOG.info("removing namespace ...");
+            xslt = new StreamSource(new File(classLoader.getResource(NAMESPACE_TRIMER_XSL).getFile()));
+            transformer = factory.newTransformer(xslt);
+            reader = new StringReader(tmpwriter.toString());
+            StringWriter device_config = new StringWriter();
+            text = new StreamSource(reader);
+            transformer.transform(text, new StreamResult(device_config));
+            result = device_config.toString();
+            //LOG.info(result);
+        } catch (TransformerException e) {
+            LOG.error("Transformer failed ");
+        }
+        return result;
+    }
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceConfigurationModule.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceConfigurationModule.java
new file mode 100644 (file)
index 0000000..4ed1443
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device;
+
+import com.google.inject.AbstractModule;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+/**
+ * @author Martial COULIBALY ( martial.coulibaly@gfi.com ) on behalf of Orange
+ */
+final class DeviceConfigurationModule extends AbstractModule {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceConfigurationModule.class);
+
+    @Override
+    protected void configure() {
+        LOG.info("Initializing Device Readers Module");
+        install(ConfigurationModule.create());
+        requestInjection(DeviceConfiguration.class);
+    }
+
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceModule.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceModule.java
new file mode 100644 (file)
index 0000000..5b2bd34
--- /dev/null
@@ -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.transportpce.device;
+
+import com.google.inject.PrivateModule;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+
+import io.fd.honeycomb.infra.distro.data.DataStoreProvider;
+import io.fd.honeycomb.infra.distro.data.InmemoryDOMDataBrokerProvider;
+
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Module class instantiating device-plugin plugin components.
+ */
+
+public final class DeviceModule extends PrivateModule {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceModule.class);
+    public static final String DEVICE_DATABROKER = "device-databroker";
+    public static final String DEVICE_DATABROKER_NONPERSIST = "device-databroker-nopersist";
+
+    @Override
+    protected void configure() {
+        LOG.info("Initializing Device Module");
+        // Create inmemory config data store for DEVICE
+        bind(InMemoryDOMDataStore.class).annotatedWith(Names.named(InmemoryDOMDataBrokerProvider.CONFIG))
+            .toProvider(new DataStoreProvider(InmemoryDOMDataBrokerProvider.CONFIG, LogicalDatastoreType.CONFIGURATION))
+            .in(Singleton.class);
+        // Create inmemory operational data store for DEVICE
+        bind(InMemoryDOMDataStore.class).annotatedWith(Names.named(InmemoryDOMDataBrokerProvider.OPERATIONAL))
+            .toProvider(new DataStoreProvider(InmemoryDOMDataBrokerProvider.OPERATIONAL, LogicalDatastoreType.OPERATIONAL))
+            .in(Singleton.class);
+
+        // Wrap datastores as DOMDataBroker
+        // TODO make executor service configurable
+        bind(DOMDataBroker.class).annotatedWith(Names.named(DEVICE_DATABROKER))
+            .toProvider(InmemoryDOMDataBrokerProvider.class).in(Singleton.class);
+        expose(DOMDataBroker.class).annotatedWith(Names.named(DEVICE_DATABROKER));
+
+        // Wrap DOMDataBroker as BA data broker
+        bind(DataBroker.class).annotatedWith(Names.named(DEVICE_DATABROKER)).toProvider(DeviceBindingDataBrokerProvider.class)
+            .in(Singleton.class);
+        expose(DataBroker.class).annotatedWith(Names.named(DEVICE_DATABROKER));
+
+        //install device configuration module
+        install(new DeviceConfigurationModule());
+        LOG.info("Device Module intitailized !");
+    }
+
+}
+
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceReaderModule.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceReaderModule.java
new file mode 100644 (file)
index 0000000..f1ed320
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.transportpce.device.read.DeviceReaderFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Martial COULIBALY ( martial.coulibaly@gfi.com ) on behalf of Orange
+ */
+public class DeviceReaderModule extends AbstractModule {
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceReaderModule.class);
+    /* (non-Javadoc)
+     * @see com.google.inject.AbstractModule#configure()
+     */
+    @Override
+    protected void configure() {
+        LOG.info("Initializing Device Readers Module");
+        final Multibinder<ReaderFactory> binder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
+        binder.addBinding().to(DeviceReaderFactory.class);
+
+    }
+
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceRpcModule.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceRpcModule.java
new file mode 100644 (file)
index 0000000..2700cff
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+
+import io.fd.honeycomb.rpc.RpcService;
+import io.fd.honeycomb.transportpce.device.rpcs.ConnectionPortTrailService;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Martial COULIBALY ( mcoulibaly.ext@orange.com ) on behalf of Orange
+ */
+public class DeviceRpcModule extends AbstractModule {
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceRpcModule.class);
+
+    /* (non-Javadoc)
+     * @see com.google.inject.AbstractModule#configure()
+     */
+    @Override
+    protected void configure() {
+        LOG.info("Initializing Device Rpcs Module");
+        // TODO Auto-generated method stub
+        final Multibinder<RpcService> rpcsBinder = Multibinder.newSetBinder(binder(), RpcService.class);
+        rpcsBinder.addBinding().to(ConnectionPortTrailService.class);
+    }
+
+}
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceWriterModule.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/DeviceWriterModule.java
new file mode 100644 (file)
index 0000000..2fa266c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.transportpce.device.write.DeviceWriterFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Martial COULIBALY ( martial.coulibaly@gfi.com ) on behalf of Orange
+ */
+public class DeviceWriterModule extends AbstractModule {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceWriterModule.class);
+
+    @Override
+    protected void configure() {
+        LOG.info("Initializing Device Writers Module");
+        final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
+        writerFactoryBinder.addBinding().to(DeviceWriterFactory.class);
+    }
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/read/DeviceReaderFactory.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/read/DeviceReaderFactory.java
new file mode 100644 (file)
index 0000000..c18042d
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device.read;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.honeycomb.translate.util.read.BindingBrokerReader;
+import io.fd.honeycomb.transportpce.device.DeviceConfiguration;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDeviceBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Martial COULIBALY ( martial.coulibaly@gfi.com ) on behalf of Orange
+ */
+public final class DeviceReaderFactory implements ReaderFactory {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceReaderFactory.class);
+    public static final InstanceIdentifier<OrgOpenroadmDevice> DEVICE_CONTAINER_ID =
+            InstanceIdentifier.create(OrgOpenroadmDevice.class);
+
+    @Inject
+    @Named("device-databroker")
+    private DataBroker dataBroker;
+
+    @Inject
+    private DeviceConfiguration deviceConfiguration;
+
+
+    @Override
+    public void init(final ModifiableReaderRegistryBuilder registry) {
+        registry.add(new BindingBrokerReader<>(DEVICE_CONTAINER_ID, dataBroker,LogicalDatastoreType.OPERATIONAL,
+                OrgOpenroadmDeviceBuilder.class));
+        if(writeXMLDataToOper()) {
+            loadConfigData();
+        }
+    }
+
+    /**
+     * Write xml data from {@link DeviceConfiguration}
+     * to operational data.
+     *
+     */
+    public boolean writeXMLDataToOper() {
+        Boolean res = false;
+        LOG.info("writting xml file data to oper datastore");
+        OrgOpenroadmDevice device = this.deviceConfiguration.getDataDevice();
+        if (device !=null) {
+            String deviceId = device.getInfo().getNodeId();
+            LOG.info("Getting device info from xml file for device '{}'", deviceId);
+            OrgOpenroadmDeviceBuilder result  = new OrgOpenroadmDeviceBuilder(device);
+            InstanceIdentifier<OrgOpenroadmDevice> iid = InstanceIdentifier.create(OrgOpenroadmDevice.class);
+            WriteTransaction writeTx = this.dataBroker.newWriteOnlyTransaction();
+            if (writeTx != null ) {
+                LOG.info("WriteTransaction is ok, copy device info to oper datastore");
+                writeTx.put(LogicalDatastoreType.OPERATIONAL, iid, result.build());
+                Future<Void> future = writeTx.submit();
+                try {
+                    Futures.getChecked(future, ExecutionException.class);
+                    LOG.info("device '{}' writed to oper datastore", deviceId);
+                    res = true;
+                } catch (ExecutionException e) {
+                    LOG.error("Failed to write Element '{}' to oper datastore", deviceId);
+                }
+            } else {
+                LOG.error("WriteTransaction object is null");
+            }
+        } else {
+            LOG.error("device data operation gets from xml file is null !");
+        }
+        return res;
+    }
+
+    /**
+     * Load data to config
+     * device datastore.
+     *
+     */
+    public boolean loadConfigData() {
+        Boolean res = false;
+        LOG.info("loading device configuration info from xml file...");
+        String xml = this.deviceConfiguration.getConfigDevice();
+        LOG.info("device info gets from xml file !");
+        if (xml != null) {
+            OrgOpenroadmDevice result  = this.deviceConfiguration.getDeviceFromXML(xml);
+            if (result != null) {
+                LOG.info("OrgOpenroadmDevice info gets : {}", result.getInfo().getNodeId());
+                WriteTransaction writeTx = this.dataBroker.newWriteOnlyTransaction();
+                if (writeTx != null ) {
+                    LOG.info("WriteTransaction is ok, copy device info to config datastore");
+                    writeTx.put(LogicalDatastoreType.CONFIGURATION, DEVICE_CONTAINER_ID, result);
+                    Future<Void> future = writeTx.submit();
+                    try {
+                        Futures.getChecked(future, ExecutionException.class);
+                        LOG.info("device writed to config datastore");
+                      } catch (ExecutionException e) {
+                          LOG.error("Failed to write device to config datastore");
+                      }
+                } else {
+                    LOG.error("WriteTransaction object is null");
+                }
+            } else {
+                LOG.error("device gets from xml is null !!");
+            }
+        } else {
+            LOG.error("device ID from input is not the same from xml file");
+        }
+        return res;
+    }
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/rpcs/ConnectionPortTrailService.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/rpcs/ConnectionPortTrailService.java
new file mode 100644 (file)
index 0000000..0f64086
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device.rpcs;
+
+import io.fd.honeycomb.rpc.RpcService;
+
+import java.util.Arrays;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.RpcStatus;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.GetConnectionPortTrailInput;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.GetConnectionPortTrailOutput;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.GetConnectionPortTrailOutputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.get.connection.port.trail.output.Ports;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.get.connection.port.trail.output.PortsBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class to simulate get-connection-port-trail rpc.
+ *
+ * @author Martial COULIBALY ( mcoulibaly.ext@orange.com ) on behalf of Orange
+ */
+public class ConnectionPortTrailService implements RpcService<GetConnectionPortTrailInput, GetConnectionPortTrailOutput> {
+    private static final Logger LOG = LoggerFactory.getLogger(ConnectionPortTrailService.class);
+    private static final String localName = "get-connection-port-trail";
+    private static final QName name = QName.create(GetConnectionPortTrailInput.QNAME, localName);
+    private static final SchemaPath schemaPath = SchemaPath.ROOT.createChild(name);
+
+    @Override
+    public SchemaPath getManagedNode() {
+        return schemaPath;
+    }
+
+    /* (non-Javadoc)
+     * @see io.fd.honeycomb.rpc.RpcService#invoke(org.opendaylight.yangtools.yang.binding.DataObject)
+     */
+    @Override
+    public CompletionStage<GetConnectionPortTrailOutput> invoke(GetConnectionPortTrailInput arg0) {
+        LOG.info("RPC GetConnectionPortTrail request received !");
+        Ports port = new PortsBuilder()
+                .setCircuitPackName("2/0")
+                .setPortName("L1")
+                .build();
+        GetConnectionPortTrailOutput output = new GetConnectionPortTrailOutputBuilder()
+                .setStatusMessage("OK")
+                .setStatus(RpcStatus.Successful)
+                .setPorts(Arrays.asList(port))
+                .build();
+        CompletableFuture<GetConnectionPortTrailOutput> result = new CompletableFuture<>();
+        result.complete(output);
+        return result;
+    }
+
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/tools/DefaultDeviceFactory.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/tools/DefaultDeviceFactory.java
new file mode 100644 (file)
index 0000000..1372de5
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device.tools;
+
+import io.fd.honeycomb.transportpce.binding.converter.XMLDataObjectConverter;
+import io.fd.honeycomb.transportpce.test.common.DataStoreContext;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.util.Optional;
+
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Factory for creating the default device from the XML stored in
+ * classpath.
+ *
+ * @author Martial COULIBALY ( martial.coulibaly@gfi.com ) on behalf of Orange
+ */
+public class DefaultDeviceFactory {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultDeviceFactory.class);
+
+    /**
+     * Returns a new instance of {@link OrgOpenroadmDevice} from the loaded XML stored
+     * in File.
+     *
+     * @return {@link OrgOpenroadmDevice}
+     */
+    public OrgOpenroadmDevice createDefaultDevice(DataStoreContext dataStoreContextUtil, File device_data_config) {
+        OrgOpenroadmDevice result = null;
+        if (device_data_config.exists()) {
+            String config = device_data_config.getName();
+            LOG.info("file '{}' exists at location : {}", config, device_data_config.getAbsolutePath());
+            InputStream targetStream;
+            try {
+                targetStream = new FileInputStream(device_data_config);
+                Optional<NormalizedNode<?, ?>> transformIntoNormalizedNode = null;
+                transformIntoNormalizedNode =
+                        XMLDataObjectConverter.createWithDataStoreUtil(dataStoreContextUtil)
+                        .transformIntoNormalizedNode(targetStream);
+                if (!transformIntoNormalizedNode.isPresent()) {
+                    throw new IllegalStateException(String.format("Could not transform the input %s into normalized nodes",
+                            config));
+                }
+                Optional<DataObject> dataObject = XMLDataObjectConverter.createWithDataStoreUtil(dataStoreContextUtil)
+                        .getDataObject(transformIntoNormalizedNode.get(), OrgOpenroadmDevice.QNAME);
+                if (!dataObject.isPresent()) {
+                    throw new IllegalStateException("Could not transform normalized nodes into data object");
+                }
+                result =  (OrgOpenroadmDevice) dataObject.get();
+            } catch (FileNotFoundException e) {
+                LOG.error("File not found : {} at {}", e.getMessage(), e.getLocalizedMessage());
+            }
+        } else {
+            LOG.info("xml file not existed at : '{}'", device_data_config.getAbsolutePath());
+        }
+        return result;
+    }
+    /**
+     * Returns a new instance of {@link OrgOpenroadmDevice} from the loaded XML stored
+     * in String.
+     *
+     * @return {@link OrgOpenroadmDevice}
+     */
+    public OrgOpenroadmDevice createDefaultDevice(DataStoreContext dataStoreContextUtil, String device_data_config) {
+        OrgOpenroadmDevice result = null;
+        if (device_data_config != null) {
+            LOG.info("device data config string is ok ");
+            InputStream targetStream;
+            targetStream = new ByteArrayInputStream(device_data_config.getBytes());
+            Optional<NormalizedNode<?, ?>> transformIntoNormalizedNode = null;
+            transformIntoNormalizedNode =
+                    XMLDataObjectConverter.createWithDataStoreUtil(dataStoreContextUtil)
+                    .transformIntoNormalizedNode(targetStream);
+            if (!transformIntoNormalizedNode.isPresent()) {
+                throw new IllegalStateException(String.format("Could not transform the input %s into normalized nodes"));
+            }
+            Optional<DataObject> dataObject = XMLDataObjectConverter.createWithDataStoreUtil(dataStoreContextUtil)
+                    .getDataObject(transformIntoNormalizedNode.get(), OrgOpenroadmDevice.QNAME);
+            if (!dataObject.isPresent()) {
+                throw new IllegalStateException("Could not transform normalized nodes into data object");
+            }
+            result =  (OrgOpenroadmDevice) dataObject.get();
+        } else {
+            LOG.info("device data config string is null!");
+        }
+        return result;
+    }
+
+
+    public void createXMLFromDevice(DataStoreContext dataStoreContextUtil, OrgOpenroadmDevice device, String output) {
+        if (device != null) {
+            Optional<NormalizedNode<?, ?>> transformIntoNormalizedNode = null;
+            transformIntoNormalizedNode =
+                    XMLDataObjectConverter.createWithDataStoreUtil(dataStoreContextUtil)
+                    .toNormalizedNodes(device, OrgOpenroadmDevice.class);
+            if (!transformIntoNormalizedNode.isPresent()) {
+                throw new IllegalStateException(String.format("Could not transform the input %s into normalized nodes",
+                        device));
+            }
+            XMLDataObjectConverter createWithDataStoreUtil = XMLDataObjectConverter.createWithDataStoreUtil(dataStoreContextUtil);
+            Writer writerFromDataObject =
+                    createWithDataStoreUtil.writerFromDataObject(device, OrgOpenroadmDevice.class, createWithDataStoreUtil.dataContainer());
+            try {
+                BufferedWriter writer = new BufferedWriter(new FileWriter(output));
+                writer.write(writerFromDataObject.toString());
+                writer.close();
+            } catch (IOException e) {
+                LOG.error("Bufferwriter error ");
+            }
+            LOG.info("device xml : {}", writerFromDataObject.toString());
+        }
+    }
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/write/DeviceWriterFactory.java b/tests/honeynode/honeynode-plugin-impl/src/main/java/io/fd/honeycomb/transportpce/device/write/DeviceWriterFactory.java
new file mode 100644 (file)
index 0000000..5d955d7
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device.write;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.translate.util.write.BindingBrokerWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class DeviceWriterFactory implements WriterFactory {
+    private static final InstanceIdentifier<OrgOpenroadmDevice> DEVICE_CONTAINER_ID = InstanceIdentifier
+            .create(OrgOpenroadmDevice.class);
+
+
+    @Inject
+    @Named("device-databroker")
+    private DataBroker deviceDataBroker;
+
+    @Override
+    public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+        registry.wildcardedSubtreeAdd(new BindingBrokerWriter<>(DEVICE_CONTAINER_ID, deviceDataBroker));
+    }
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/NamespaceTrimmer.xslt b/tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/NamespaceTrimmer.xslt
new file mode 100644 (file)
index 0000000..7667f57
--- /dev/null
@@ -0,0 +1,39 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+    <xsl:template match="*/*/*" name="nodes">
+        <xsl:element name="{local-name()}">
+            <xsl:apply-templates select="@*|node()" />
+        </xsl:element>
+    </xsl:template>
+    <xsl:template match="*/*/*/*">
+        <xsl:if test="not(name(.)='type' or name(.)='lldp' or name(.)='ethernet' or name(.)='ots')">
+            <xsl:element name="{local-name()}">
+                <xsl:apply-templates select="@*|node()" />
+            </xsl:element>
+        </xsl:if>
+        <xsl:if test="name(.)='type'" xmlns="http://org/openroadm/device">
+            <type xmlns:openROADM-if="http://org/openroadm/interfaces">
+                <xsl:apply-templates select="@*|node()"/>
+            </type>
+        </xsl:if>
+        <xsl:if test="name(.)='ots'">
+            <ots xmlns="http://org/openroadm/optical-transport-interfaces">
+                <xsl:apply-templates select="@*|node()"/>
+            </ots>
+        </xsl:if>
+        <xsl:if test="name(.)='lldp'">
+            <lldp xmlns="http://org/openroadm/lldp">
+                <xsl:apply-templates select="@*|node()"/>
+            </lldp>
+        </xsl:if>
+        <xsl:if test="name(.)='ethernet'">
+            <ethernet xmlns="http://org/openroadm/ethernet-interfaces">
+                <xsl:apply-templates select="@*|node()"/>
+            </ethernet>
+        </xsl:if>
+    </xsl:template>
+    <xsl:template match="/">
+        <org-openroadm-device xmlns="http://org/openroadm/device">
+            <xsl:apply-templates select="*"/>
+        </org-openroadm-device>
+    </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/OperToConfig.xsl b/tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/OperToConfig.xsl
new file mode 100644 (file)
index 0000000..8eac75f
--- /dev/null
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<xsl:stylesheet version="1.0"\r
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\r
+xmlns:d="urn:ietf:params:xml:ns:netconf:base:1.0"\r
+xmlns:oor="http://org/openroadm/device"\r
+exclude-result-prefixes="oor d">\r
+\r
+  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>\r
+  \r
+  <xsl:template match="/">\r
+    <xsl:element name="config" namespace="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+    <xsl:element name="org-openroadm-device" namespace="http://org/openroadm/device">\r
+    <xsl:element name="info">\r
+      <xsl:apply-templates select="d:data/oor:org-openroadm-device/oor:info"/>\r
+    </xsl:element>\r
+\r
+    <xsl:copy-of select="d:data/oor:org-openroadm-device/oor:users" />\r
+\r
+    <xsl:for-each select="d:data/oor:org-openroadm-device/oor:shelves">\r
+      <xsl:element name="shelves" >\r
+        <xsl:call-template name="shelve-body"/>\r
+      </xsl:element>\r
+    </xsl:for-each>\r
+\r
+    <xsl:for-each select="d:data/oor:org-openroadm-device/oor:circuit-packs">\r
+      <xsl:element name="circuit-packs" >\r
+        <xsl:call-template name="cp-body"/>\r
+      </xsl:element>\r
+    </xsl:for-each>\r
+    \r
+    <xsl:for-each select="d:data/oor:org-openroadm-device/oor:interface">\r
+        <xsl:element name="interface" >\r
+            <xsl:call-template name="inter-body"/>\r
+        </xsl:element>\r
+    </xsl:for-each>\r
+    \r
+    <xsl:for-each select="d:data/oor:org-openroadm-device/oor:protocols">\r
+        <xsl:element name="protocols" >\r
+            <xsl:call-template name="proto-body"/>\r
+        </xsl:element>\r
+    </xsl:for-each>\r
+\r
+    <xsl:for-each select="d:data/oor:org-openroadm-device/oor:degree">\r
+      <xsl:element name="degree" >\r
+        <xsl:call-template name="degree-body"/>\r
+      </xsl:element>\r
+    </xsl:for-each>\r
+\r
+    <xsl:for-each select="d:data/oor:org-openroadm-device/oor:shared-risk-group">\r
+      <xsl:element name="shared-risk-group" >\r
+        <xsl:call-template name="srg-body"/>\r
+      </xsl:element>\r
+    </xsl:for-each>\r
+\r
+    </xsl:element>\r
+    </xsl:element>\r
+  </xsl:template>\r
+  \r
+  <xsl:template match="oor:info">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="name(.) = 'node-id' or name(.) = 'node-number' or name(.) = 'clli' or name(.) = 'ipAddress' or name(.) = 'prefix-length' or name(.) = 'defaultGateway' or name(.) = 'template' or name(.) = 'geoLocation'">\r
+        <xsl:copy-of select="." />\r
+      </xsl:if>\r
+     </xsl:for-each> \r
+  </xsl:template>\r
+\r
+  <xsl:template name="shelve-body">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="name(.) ='shelf-name' or name(.) = 'shelf-type' or name(.) = 'rack' or name(.) = 'shelf-position' or name(.) = 'administrative-state' or name(.) = 'equipment-state' or name(.) = 'due-date'">\r
+        <xsl:copy-of select="." />\r
+      </xsl:if>\r
+    </xsl:for-each>\r
+  </xsl:template>\r
+\r
+  <xsl:template name="cp-body">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="name(.) = 'circuit-pack-type' or name(.) = 'circuit-pack-product-code' or name(.) = 'circuit-pack-name' or name(.) = 'administrative-state' or name(.) = 'equipment-state' or name(.) = 'circuit-pack-mode' or name(.) = 'shelf' or name(.) = 'slot' or name(.) = 'subSlot' or name(.) = 'due-date' or name(.) = 'parent-circuit-pack'">\r
+        <xsl:copy-of select="." />\r
+      </xsl:if>\r
+      <xsl:if test="name(.) = 'ports'">\r
+        <xsl:for-each select=".">\r
+          <xsl:element name="ports" >\r
+            <xsl:call-template name="ports-body"/>\r
+          </xsl:element>\r
+        </xsl:for-each>\r
+      </xsl:if>\r
+     </xsl:for-each> \r
+  </xsl:template>\r
+\r
+  <xsl:template name="inter-body">\r
+    <xsl:for-each select="./*">\r
+        <xsl:if test="not(name(.) = 'operational-state' or name(.)='ethernet')">\r
+         <xsl:copy-of select="." />\r
+        </xsl:if>\r
+        <xsl:if test="name(.)='ethernet'">\r
+            <xsl:element name="ethernet" >\r
+                <xsl:call-template name="eth-body"/>\r
+            </xsl:element>\r
+        </xsl:if>\r
+    </xsl:for-each>\r
+  </xsl:template>\r
+  \r
+   <xsl:template name="eth-body">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="not(name(.) = 'curr-speed' or name(.)='curr-duplex') ">\r
+         <xsl:copy-of select="." />\r
+      </xsl:if>\r
+    </xsl:for-each>\r
+  </xsl:template>\r
+  \r
+  <xsl:template name="proto-body">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="name(.) = 'lldp'">\r
+        <xsl:for-each select=".">\r
+          <xsl:element name="lldp" >\r
+            <xsl:call-template name="lldp-body"/>\r
+          </xsl:element>\r
+        </xsl:for-each>\r
+      </xsl:if>\r
+     </xsl:for-each> \r
+  </xsl:template>\r
+\r
+  <xsl:template name="ports-body">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="name(.) = 'port-name' or name(.) = 'port-type' or name(.) = 'port-qual' or name(.) = 'circuit-id' or name(.) = 'administrative-state' or name(.) = 'logical-connection-point' or name(.) = 'otdr-port' ">\r
+         <xsl:copy-of select="." />\r
+      </xsl:if>\r
+    </xsl:for-each>\r
+  </xsl:template>\r
+  \r
+  <xsl:template name="lldp-body">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="not(name(.) = 'nbr-list') ">\r
+         <xsl:copy-of select="." />\r
+      </xsl:if>\r
+    </xsl:for-each>\r
+  </xsl:template>\r
+  \r
+  <xsl:template name="degree-body">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="not(name(.) = 'max-wavelengths')">\r
+         <xsl:copy-of select="." />\r
+      </xsl:if>\r
+    </xsl:for-each>\r
+  </xsl:template>\r
+\r
+  <xsl:template name="srg-body">\r
+    <xsl:for-each select="./*">\r
+      <xsl:if test="not(name(.) = 'max-add-drop-ports' or name(.) = 'wavelengthDuplication')">\r
+         <xsl:copy-of select="." />\r
+      </xsl:if>\r
+    </xsl:for-each>\r
+  </xsl:template>\r
+\r
+ </xsl:stylesheet>\r
diff --git a/tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/config.xsl b/tests/honeynode/honeynode-plugin-impl/src/main/resources/honeycomb-minimal-resources/config/device/config.xsl
new file mode 100644 (file)
index 0000000..50350a8
--- /dev/null
@@ -0,0 +1,12 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+    <xsl:template match="@* | node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@* | node()"/>
+        </xsl:copy>
+    </xsl:template>
+    <xsl:template match="/">
+        <config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <xsl:apply-templates/>
+        </config>
+    </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/CreateDeviceFromXMLFileTest.java b/tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/CreateDeviceFromXMLFileTest.java
new file mode 100644 (file)
index 0000000..49ffed8
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device.test;
+
+import io.fd.honeycomb.transportpce.device.tools.DefaultDeviceFactory;
+import io.fd.honeycomb.transportpce.test.common.DataStoreContext;
+import io.fd.honeycomb.transportpce.test.common.DataStoreContextImpl;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test to create {@link OrgOpenroadmDevice} object
+ * from xml file or String using Yangtools
+ *
+ * @author Martial COULIBALY ( martial.coulibaly@gfi.com ) on behalf of Orange
+ */
+@RunWith(Parameterized.class)
+public class CreateDeviceFromXMLFileTest {
+    private static final Logger LOG = LoggerFactory.getLogger(CreateDeviceFromXMLFileTest.class);
+    private static final String DEVICE_OPER_IN = "src/main/resources/honeycomb-minimal-resources/config/device/sample-config-ROADM.xml";
+    private String xml;
+
+
+    public CreateDeviceFromXMLFileTest(String xmlData) {
+        this.xml = xmlData;
+    }
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> stringXML() {
+        return Arrays.asList(new Object[][]{
+            {DeviceOperToConfig.getDeviceFromXML(DeviceOperToConfig.operToConfig())}
+//                {DeviceOperToConfig.operToConfig()}
+
+        });
+    }
+
+    /**
+     * This test  create instance of
+     * {@link OrgOpenroadmDevice} with String xml
+     * from {@link DeviceOperToConfig#operToConfig()}
+     * function as parameters.
+     *
+     * @throws NullPointerException
+     */
+    @Test
+    public void createDeviceFromString() throws NullPointerException {
+        OrgOpenroadmDevice result = null;
+        LOG.info("Parameterized string is : {}", xml);
+        DataStoreContext dataStoreContextUtil = new DataStoreContextImpl();
+        DefaultDeviceFactory defaultDeviceFactory = new DefaultDeviceFactory();
+        result = defaultDeviceFactory.createDefaultDevice(dataStoreContextUtil,xml);
+        if (result != null) {
+            LOG.info("result info : {}", result.getInfo().getNodeId());
+            Assert.assertEquals("ROADMA", result.getInfo().getNodeId());
+        }
+        LOG.info("Test Succeed");
+    }
+
+
+    /**
+     * This test create Device from File
+     * located at {@link CreateDeviceFromXMLFileTest#DEVICE_OPER_IN}.
+     *
+     * @throws NullPointerException
+     */
+    @Test
+    public void createDeviceFromFile() throws NullPointerException{
+        LOG.info("test createDeviceFromFile ...");
+        OrgOpenroadmDevice result = null;
+        result = null;
+        File device_data = new File(DEVICE_OPER_IN);
+        DataStoreContext dataStoreContextUtil = new DataStoreContextImpl();
+        DefaultDeviceFactory defaultDeviceFactory = new DefaultDeviceFactory();
+        result = defaultDeviceFactory.createDefaultDevice(dataStoreContextUtil,device_data);
+        if (result != null) {
+            LOG.info("result info : {}", result.getInfo().getNodeId());
+            Assert.assertEquals("ROADMA", result.getInfo().getNodeId());
+        }
+        LOG.info("Test Succeed");
+    }
+}
\ No newline at end of file
diff --git a/tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/DeviceOperToConfig.java b/tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/DeviceOperToConfig.java
new file mode 100644 (file)
index 0000000..036ce8a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device.test;
+
+import io.fd.honeycomb.transportpce.device.tools.DefaultDeviceFactory;
+import io.fd.honeycomb.transportpce.test.common.DataStoreContext;
+import io.fd.honeycomb.transportpce.test.common.DataStoreContextImpl;
+
+import java.io.File;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Converts XML Data operation file  to Configuration file.
+ *
+ * @author Martial COULIBALY ( mcoulibaly.ext@orange.com ) on behalf of Orange
+ */
+public class DeviceOperToConfig {
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceOperToConfig.class);
+    private static final String DEVICE_OPER = "src/main/resources/honeycomb-minimal-resources/config/device/oper-ROADMA.xml";
+    private static final String CONFIG_XSL = "src/main/resources/honeycomb-minimal-resources/config/device/config.xsl";
+    private static final String DEVICE_XSL = "src/main/resources/honeycomb-minimal-resources/config/device/OperToConfig.xsl";
+    private static final String NAMESPACE_TRIMER_XSL = "src/main/resources/honeycomb-minimal-resources/config/device/NamespaceTrimmer.xslt";
+
+
+    /**
+     * Convert data xml to config xml device.
+     *
+     * @return String result
+     */
+    public static String operToConfig() {
+        String result =null;
+        LOG.info("process to transform xml file ");
+        TransformerFactory factory = TransformerFactory.newInstance();
+        Source xslt = new StreamSource(new File(DEVICE_XSL));
+        Transformer transformer;
+        Source text;
+        StringWriter tmpwriter = new StringWriter();
+        StringReader reader;
+        try {
+            LOG.info("transforming xml data to config device ...");
+            transformer = factory.newTransformer(xslt);
+            text = new StreamSource(new File(DEVICE_OPER));
+            transformer.transform(text, new StreamResult(tmpwriter));
+            LOG.info("removing namespace ...");
+            xslt = new StreamSource(new File(NAMESPACE_TRIMER_XSL));
+            transformer = factory.newTransformer(xslt);
+            reader = new StringReader(tmpwriter.toString());
+            StringWriter device_config = new StringWriter();
+            text = new StreamSource(reader);
+            transformer.transform(text, new StreamResult(device_config));
+            //LOG.info("xml transformed : {}\n", device_config.toString());
+            result = device_config.toString();
+        } catch (TransformerException e) {
+            LOG.error("Transformer failed ");
+        }
+        return result;
+    }
+
+    public static String getDeviceFromXML(String xml) {
+        String config_result =null;
+        LOG.info("process to transform xml file to config data");
+        TransformerFactory factory = TransformerFactory.newInstance();
+        Source xslt = new StreamSource(new File(CONFIG_XSL));
+        Transformer transformer;
+        Source text;
+        StringWriter device_config = new StringWriter();
+        try {
+            LOG.info("transforming xml string to config device ...");
+            transformer = factory.newTransformer(xslt);
+            text = new StreamSource(new StringReader(xml));
+            transformer.transform(text, new StreamResult(device_config));
+            config_result = device_config.toString();
+            LOG.info(config_result);
+        } catch (TransformerException e) {
+            LOG.error("Transformer failed ");
+        }
+        return config_result;
+    }
+
+    public static void createDeviceFromString(String xml) throws NullPointerException {
+        OrgOpenroadmDevice result = null;
+        LOG.info("Parameterized string is : {}", xml);
+        DataStoreContext dataStoreContextUtil = new DataStoreContextImpl();
+        DefaultDeviceFactory defaultDeviceFactory = new DefaultDeviceFactory();
+        result = defaultDeviceFactory.createDefaultDevice(dataStoreContextUtil,xml);
+        if (result != null) {
+            LOG.info("result info : {}", result.getInfo().getNodeId());
+        } else {
+            LOG.error("failed !");
+        }
+
+    }
+
+    public static void main(String[] args) {
+        String xml = DeviceOperToConfig.getDeviceFromXML(DeviceOperToConfig.operToConfig());
+        DeviceOperToConfig.createDeviceFromString(xml);
+    }
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/DirectoryWatchTest.java b/tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/DirectoryWatchTest.java
new file mode 100644 (file)
index 0000000..0c02003
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device.test;
+
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Martial COULIBALY ( mcoulibaly.ext@orange.com ) on behalf of Orange
+ */
+public class DirectoryWatchTest {
+    private static final Logger LOG = LoggerFactory.getLogger(DirectoryWatchTest.class);
+    private static final String DATA_JSON = "/var/lib/honeycomb/persist/config/data.json";
+
+    public static void main(String[] args) {
+        File data = new File(DATA_JSON);
+        String parent = data.getParent();
+        LOG.info("data.json directory : {}",parent);
+        try {
+            WatchService watcher = FileSystems.getDefault().newWatchService();
+            Path dir = Paths.get(data.getParent());
+            dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+            LOG.info("Watch Service registered for dir: {}", dir.getFileName());
+            while (true) {
+                WatchKey key;
+                try {
+                    key = watcher.take();
+                } catch (InterruptedException ex) {
+                    return;
+                }
+                for (WatchEvent<?> event : key.pollEvents()) {
+                    WatchEvent.Kind<?> kind = event.kind();
+                    @SuppressWarnings("unchecked")
+                    WatchEvent<Path> ev = (WatchEvent<Path>) event;
+                    Path fileName = ev.context();
+                    if (kind == ENTRY_MODIFY && fileName.toString().equals("data.json")) {
+                        LOG.info("My source file has changed ...");
+                        /**
+                         * merge honeycomb-config datastore to  device oper
+                         */
+                    }
+                }
+                boolean valid = key.reset();
+                if (!valid) {
+                    LOG.error("Key has been unregisterede");
+                    break;
+                }
+            }
+        } catch (IOException ex) {
+            LOG.error("WatchService Error",ex);
+        }
+    }
+
+}
diff --git a/tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/RestAPICallsTest.java b/tests/honeynode/honeynode-plugin-impl/src/test/java/io/fd/honeycomb/transportpce/device/test/RestAPICallsTest.java
new file mode 100644 (file)
index 0000000..8ad450b
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2018 Orange 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.transportpce.device.test;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collection;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Martial COULIBALY ( mcoulibaly.ext@orange.com ) on behalf of Orange
+ */
+@RunWith(Parameterized.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class RestAPICallsTest {
+    private static final String CONFIG_URI="http://localhost:8183/restconf/config/org-openroadm-device:org-openroadm-device";
+    private final String user = "admin";
+    private final String pass = "admin";
+    private String encodeUserPass;
+    private String uri;
+    private String input;
+    private static final Logger LOG = LoggerFactory.getLogger(RestAPICallsTest.class);
+
+    public RestAPICallsTest(String uriRest, String inputXml) {
+        uri = uriRest;
+        input = inputXml;
+        String usernameAndPassword = this.user+":"+this.pass;
+        try {
+            byte[] encodeBytes = Base64.getEncoder().encode(usernameAndPassword.getBytes());
+            this.encodeUserPass = new String(encodeBytes, "UTF-8");
+            LOG.info("encode : {}",encodeUserPass);
+        } catch (UnsupportedEncodingException e) {
+            LOG.error("encode usernameAndPassword failed !");
+        }
+    }
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> stringXML() {
+        return Arrays.asList(new Object[][]{
+                {CONFIG_URI,DeviceOperToConfig.operToConfig()}
+        });
+    }
+
+    /**
+     *send PUT request via REST API.
+     *
+     * @param uri request url
+     * @return String response
+     * @throws IOException
+     */
+    @Test
+    public void test1Put() throws IOException {
+        URL url = new URL(uri);
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        conn.setDoOutput(true);
+        conn.setRequestMethod("PUT");
+        conn.setRequestProperty ("Authorization", "Basic " + encodeUserPass);
+        conn.setRequestProperty("Content-Type", "application/xml");
+        LOG.info("input xml : {}",input);
+        if (input != null) {
+            OutputStream os = conn.getOutputStream();
+            os.write(input.getBytes());
+            os.flush();
+            Assert.assertEquals(HttpURLConnection.HTTP_CREATED,conn.getResponseCode());
+            conn.disconnect();
+        } else {
+            LOG.error("input xml gets is null !");
+        }
+        LOG.info("Test Succeed");
+    }
+
+    /**
+     * send GET request via REST API.
+     *
+     * @param uri request url
+     * @return String response
+     * @throws IOException
+     */
+    @Test
+    public void test2Get() throws IOException {
+        URL url = new URL(uri);
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        conn.setRequestProperty ("Authorization", "Basic " + encodeUserPass);
+        conn.setRequestMethod("GET");
+        conn.setRequestProperty("Accept", "application/json");
+        Assert.assertEquals(HttpURLConnection.HTTP_OK,conn.getResponseCode());
+//        Assert.assertThat(result, CoreMatchers.containsString("org-openroadm-device"));
+        conn.disconnect();
+        LOG.info("Test Succeed");
+    }
+
+    /**
+     *send DELETE request via REST API.
+     *
+     * @param uri request url
+     * @return String response
+     * @throws IOException
+     */
+    @Test
+    public void test3Delete() throws IOException {
+        URL url = new URL(uri);
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        conn.setDoOutput(true);
+        conn.setRequestMethod("DELETE");
+        conn.setRequestProperty ("Authorization", "Basic " + encodeUserPass);
+        Assert.assertEquals(HttpURLConnection.HTTP_OK,conn.getResponseCode());
+        conn.disconnect();
+    }
+}
\ No newline at end of file
diff --git a/tests/honeynode/minimal-distribution-core/asciidoc/Readme.adoc b/tests/honeynode/minimal-distribution-core/asciidoc/Readme.adoc
new file mode 100644 (file)
index 0000000..e8306c2
--- /dev/null
@@ -0,0 +1,3 @@
+= minimal-distribution-core
+
+Project contains core modules for minimal distribution
\ No newline at end of file
diff --git a/tests/honeynode/minimal-distribution-core/pom.xml b/tests/honeynode/minimal-distribution-core/pom.xml
new file mode 100644 (file)
index 0000000..f5bdf6a
--- /dev/null
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright (c) 2017 Cisco and/or its affiliates.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at:
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>impl-parent</artifactId>
+        <groupId>io.fd.honeycomb.common</groupId>
+        <version>1.18.01</version>
+        <relativePath/>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>io.fd.honeycomb.transportpce</groupId>
+    <artifactId>minimal-distribution-core</artifactId>
+    <version>1.18.01</version>
+    <name>${project.artifactId}</name>
+
+    <properties>
+        <commons-io.version>2.5</commons-io.version>
+        <osgi.core.version>5.0.0</osgi.core.version>
+        <!-- Core guice modules does not need any yang modules itself -->
+        <skip.module.list.generation>true</skip.module.list.generation>
+    </properties>
+
+    <dependencies>
+        <!-- TPCE dependencies -->
+        <dependency>
+            <groupId>io.fd.honeycomb.transportpce</groupId>
+            <artifactId>honeynode-plugin-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- DI-->
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.jmob</groupId>
+            <artifactId>guice.conf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject.extensions</groupId>
+            <artifactId>guice-multibindings</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>binding-init</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- ODL -->
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-api</artifactId>
+        </dependency>
+
+
+        <!-- OSGI Even tough not running in OSGI, dependency needs to be here since some deprecated MD-SAL APIs rely on osgi core -->
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>${osgi.core.version}</version>
+        </dependency>
+
+        <!-- Northbound -->
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound</groupId>
+            <artifactId>common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- HC -->
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>cfg-init</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>notification-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>rpc-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>data-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>honeycomb-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>notification-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Utilities -->
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons-io.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/InitializationException.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/InitializationException.java
new file mode 100644 (file)
index 0000000..0ed530c
--- /dev/null
@@ -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;
+
+/**
+ * Exception thrown when a failure occurs during HC initialization.
+ */
+public class InitializationException extends RuntimeException {
+
+    public InitializationException(final String s) {
+        super(s);
+    }
+
+    public InitializationException(final String s, final Throwable throwable) {
+        super(s, throwable);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationConfig.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationConfig.java
new file mode 100644 (file)
index 0000000..ecda4ae
--- /dev/null
@@ -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.activation;
+
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+import java.util.Optional;
+
+@BindConfig(value = "activation", syntax = Syntax.JSON)
+public class ActivationConfig {
+
+    @InjectConfig("modules-resource-path")
+    public String modulesResourcePath;
+
+    @InjectConfig("yang-modules-index-path")
+    public String yangModulesIndexPath;
+
+    public String getModulesResourcePath() {
+        return Optional.ofNullable(modulesResourcePath).orElse("../modules/");
+    }
+
+    public String getYangModulesIndexPath() {
+        return Optional.ofNullable(yangModulesIndexPath).orElse("../yang-mapping/");
+    }
+
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationModule.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationModule.java
new file mode 100644 (file)
index 0000000..00f77a6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.activation;
+
+import com.google.inject.AbstractModule;
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+/**
+ * Module that provides set of modules activated by distribution and binds this set to be available
+ */
+public class ActivationModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        install(ConfigurationModule.create());
+        requestInjection(ActivationConfig.class);
+        bind(ActiveModules.class).toProvider(ActiveModuleProvider.class).asEagerSingleton();
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModuleProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModuleProvider.java
new file mode 100644 (file)
index 0000000..643af16
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 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.activation;
+
+import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import io.fd.honeycomb.infra.distro.schema.ResourceLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides list of active modules for distribution
+ */
+public class ActiveModuleProvider implements Provider<ActiveModules>, ResourceLoader {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ActiveModuleProvider.class);
+
+    @Inject
+    private ActivationConfig config;
+
+    @Override
+    public ActiveModules get() {
+        return new ActiveModules(loadActiveModules(
+                aggregateResources(config.getModulesResourcePath())));
+    }
+
+    /**
+     * Provide unique set of active modules filtered from provided resources
+     */
+    static Set<Class<? extends Module>> loadActiveModules(@Nonnull final List<String> moduleNames) {
+        final ClassLoader classLoader = ActiveModuleProvider.class.getClassLoader();
+        LOG.info("Reading active modules configuration for distribution");
+
+        // process resources to resource modules
+        return moduleNames.stream()
+                .map(String::trim)
+                .filter(trimmedLine -> trimmedLine.length() != 0)
+                // filter out commented lines
+                .filter(nonEmptyLine -> !nonEmptyLine.startsWith("//"))
+                // filter duplicates
+                .distinct()
+                .map(validLine -> moduleNameToClass(validLine, classLoader))
+                // filters out classes that are not modules
+                .filter(ActiveModuleProvider::filterNonModules)
+                .collect(Collectors.toSet());
+    }
+
+    /**
+     * Aggregate all resources from provided relative path into a {@code List<String>}
+     */
+    public List<String> aggregateResources(final String relativePath) {
+        // must use universal approach of loading from folder/jar
+        // because of memory footprint benchmark
+        return new ArrayList<>(loadResourceContentsOnPath(relativePath));
+    }
+
+    private static boolean filterNonModules(final Class<?> clazz) {
+        final boolean isModule = Module.class.isAssignableFrom(clazz);
+        if (!isModule) {
+            LOG.warn("Class {} is provided in modules configuration, but is not a Module and will be ignored", clazz);
+        }
+        return isModule;
+    }
+
+    /**
+     * Loads class by provided name
+     */
+    private static Class<? extends Module> moduleNameToClass(final String name,
+                                                             final ClassLoader classLoader) {
+        try {
+            LOG.debug("Loading module class {}", name);
+            return (Class<? extends Module>) classLoader.loadClass(name);
+        } catch (ClassNotFoundException e) {
+            LOG.error("Unable to convert {} to class, make sure you've provided sources to classpath", name);
+            throw new IllegalStateException(
+                    "Unable to convert " + name + " to class, make sure you've provided sources to classpath", e);
+        }
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModules.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModules.java
new file mode 100644 (file)
index 0000000..601e9b6
--- /dev/null
@@ -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.activation;
+
+import com.google.inject.Module;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.lang.String.format;
+
+/**
+ * Provides static set of active activeModulesClasses
+ */
+public class ActiveModules {
+    private final Set<Class<? extends Module>> activeModulesClasses;
+
+    public ActiveModules(final Set<Class<? extends Module>> activeModulesClasses) {
+        this.activeModulesClasses = activeModulesClasses;
+    }
+
+    public Set<Class<? extends Module>> getActiveModulesClasses() {
+        return activeModulesClasses;
+    }
+
+    public Set<? extends Module> createModuleInstances() {
+        return activeModulesClasses.stream()
+                .map(moduleClass -> {
+                    try {
+                        return moduleClass.newInstance();
+                    } catch (InstantiationException | IllegalAccessException e) {
+                        throw new IllegalStateException(format("Unable to create instance of module %s", moduleClass),
+                                e);
+                    }
+                }).collect(Collectors.toSet());
+    }
+
+    @Override
+    public String toString() {
+        return "ActiveModules{" +
+                "activeModulesClasses=" + activeModulesClasses +
+                '}';
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.java
new file mode 100644 (file)
index 0000000..29e79a2
--- /dev/null
@@ -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.cfgattrs;
+
+import com.google.inject.AbstractModule;
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+/**
+ * Load the configuration from json into HoneycombConfiguration and make it available.
+ */
+public class CfgAttrsModule extends AbstractModule {
+
+    @Override
+    protected void configure() {
+        install(ConfigurationModule.create());
+        // Inject non-dependency configuration
+        requestInjection(HoneycombConfiguration.class);
+    }
+
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.java
new file mode 100644 (file)
index 0000000..cfe1408
--- /dev/null
@@ -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.cfgattrs;
+
+import com.google.common.base.MoreObjects;
+import java.util.Optional;
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+/**
+ * This is the Java equivalent for honeyconb.json file. We use guice-config library to load all the config attributes
+ * into this class instance.
+ *
+ * The BindConfig annotation tells that honeycomb.json file should be looked up on classpath root.
+ */
+@BindConfig(value = "honeycomb", syntax = Syntax.JSON)
+public class HoneycombConfiguration {
+
+    @InjectConfig("persist-context")
+    public Optional<String> persistContext = Optional.of("true");
+    @InjectConfig("persisted-context-path")
+    public String peristContextPath;
+    @InjectConfig("persisted-context-restoration-type")
+    public String persistedContextRestorationType;
+    @InjectConfig("persist-config")
+    public Optional<String> persistConfig = Optional.of("true");
+    @InjectConfig("persisted-config-path")
+    public String peristConfigPath;
+    @InjectConfig("persisted-config-restoration-type")
+    public String persistedConfigRestorationType;
+    @InjectConfig("notification-service-queue-depth")
+    public int notificationServiceQueueDepth;
+
+    public boolean isConfigPersistenceEnabled() {
+        return persistConfig.isPresent() && Boolean.valueOf(persistConfig.get());
+    }
+
+    public boolean isContextPersistenceEnabled() {
+        return persistContext.isPresent() && Boolean.valueOf(persistContext.get());
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("peristContextPath", peristContextPath)
+            .add("persistedContextRestorationType", persistedContextRestorationType)
+            .add("peristConfigPath", peristConfigPath)
+            .add("persistedConfigRestorationType", persistedConfigRestorationType)
+            .add("notificationServiceQueueDepth", notificationServiceQueueDepth)
+            .toString();
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.java
new file mode 100644 (file)
index 0000000..a99235e
--- /dev/null
@@ -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 io.fd.honeycomb.binding.init.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;
+
+public final class BindingDataBrokerProvider extends ProviderTrait<DataBroker> {
+
+    @Inject
+    private DOMDataBroker domDataBroker;
+    @Inject
+    private BindingToNormalizedNodeCodec mappingService;
+
+    @Override
+    protected BindingDOMDataBrokerAdapter create() {
+        return new BindingDOMDataBrokerAdapter(domDataBroker, mappingService);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.java
new file mode 100644 (file)
index 0000000..962f593
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016, 2017 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 io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.ReadableDataManager;
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.data.init.ShutdownHandler;
+import io.fd.honeycomb.impl.EmptyDomMountService;
+import io.fd.honeycomb.impl.ShutdownHandlerImpl;
+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.rpc.RpcRegistry;
+import io.fd.honeycomb.rpc.RpcRegistryBuilder;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+import io.fd.honeycomb.translate.write.registry.WriterRegistry;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public class ConfigAndOperationalPipelineModule extends PrivateModule {
+
+    public static final String HONEYCOMB_CONFIG_NONPERSIST = "honeycomb-config-nopersist";
+    public static final String HONEYCOMB_CONFIG = "honeycomb-config";
+
+    @Override
+    protected void configure() {
+        bind(ShutdownHandler.class).to(ShutdownHandlerImpl.class).in(Singleton.class);
+        expose(ShutdownHandler.class);
+
+        // Mount point service is required by notification service and restconf
+        bind(DOMMountPointService.class).to(EmptyDomMountService.class).in(Singleton.class);
+        expose(DOMMountPointService.class);
+
+        // Expose registries for plugin reader/writer factories
+        bind(WriterRegistry.class).toProvider(WriterRegistryProvider.class).in(Singleton.class);
+        expose(WriterRegistry.class);
+        bind(ReaderRegistry.class).toProvider(ReaderRegistryProvider.class).in(Singleton.class);
+        expose(ReaderRegistry.class);
+
+        // Non persisting data tree for config
+        bind(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONFIG_NONPERSIST))
+                .toProvider(DataTreeProvider.ConfigDataTreeProvider.class).in(Singleton.class);
+        expose(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONFIG_NONPERSIST));
+        // Persisting data tree wrapper for config
+        bind(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONFIG))
+                .toProvider(PersistingDataTreeProvider.ConfigPersistingDataTreeProvider.class).in(Singleton.class);
+        expose(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONFIG));
+
+        // Config Data Tree manager working on top of config data tree + writer registry
+        bind(ModifiableDataManager.class).toProvider(ModifiableDTDelegProvider.class).in(Singleton.class);
+        // Operational Data Tree manager working on top of reader registry
+        bind(ReadableDataManager.class).toProvider(ReadableDTDelegProvider.class).in(Singleton.class);
+        expose(ReadableDataManager.class);
+
+        // DOMDataBroker wrapper on top of data tree managers
+        HoneycombDOMDataBrokerProvider domBrokerProvider = new HoneycombDOMDataBrokerProvider();
+        bind(DOMDataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONFIG)).toProvider(domBrokerProvider).in(Singleton.class);
+        expose(DOMDataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONFIG));
+
+        // BA version of data broker
+        bind(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONFIG)).toProvider(HoneycombBindingDataBrokerProvider.class)
+                .in(Singleton.class);
+        expose(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONFIG));
+
+        // Create initializer to init persisted config data
+        bind(DataTreeInitializer.class).annotatedWith(Names.named(HONEYCOMB_CONFIG))
+                .toProvider(PersistedConfigInitializerProvider.class)
+                .in(Singleton.class);
+        expose(DataTreeInitializer.class).annotatedWith(Names.named(HONEYCOMB_CONFIG));
+
+        configureNotifications();
+        configureRpcs();
+    }
+
+    private void configureNotifications() {
+        // Create notification service
+        bind(DOMNotificationRouter.class).toProvider(DOMNotificationServiceProvider.class).in(Singleton.class);
+        expose(DOMNotificationRouter.class);
+        // Wrap notification service, data broker and schema service in a Broker MD-SAL API
+        bind(Broker.class).toProvider(HoneycombDOMBrokerProvider.class).in(Singleton.class);
+        expose(Broker.class);
+    }
+
+    private void configureRpcs() {
+        // Create rpc service
+        bind(DOMRpcService.class).toProvider(HoneycombDOMRpcServiceProvider.class).in(Singleton.class);
+        expose(DOMRpcService.class);
+
+        bind(RpcRegistryBuilder.class).toProvider(RpcRegistryBuilderProvider.class).in(Singleton.class);
+        expose(RpcRegistryBuilder.class);
+
+        bind(RpcRegistry.class).toProvider(RpcRegistryProvider.class).in(Singleton.class);
+        expose(RpcRegistry.class);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.java
new file mode 100644 (file)
index 0000000..4c419a8
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+
+public final class DOMNotificationServiceProvider extends ProviderTrait<DOMNotificationRouter> {
+
+    @Inject
+    private HoneycombConfiguration cfg;
+
+    @Override
+    protected DOMNotificationRouter create() {
+        return DOMNotificationRouter.create(cfg.notificationServiceQueueDepth);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.java
new file mode 100644 (file)
index 0000000..82b1ed3
--- /dev/null
@@ -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 io.fd.honeycomb.binding.init.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;
+
+public final class DataStoreProvider extends ProviderTrait<InMemoryDOMDataStore> {
+
+    @Inject
+    private SchemaService schemaService;
+    private String name;
+    private LogicalDatastoreType type;
+
+    public DataStoreProvider(final String name,
+                             final LogicalDatastoreType type) {
+        this.name = name;
+        this.type = type;
+    }
+
+    @Override
+    protected InMemoryDOMDataStore create() {
+        return InMemoryDOMDataStoreFactory.create(name, type, schemaService, false, null);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.java
new file mode 100644 (file)
index 0000000..039a0ad
--- /dev/null
@@ -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 io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+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.TipProducingDataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
+
+public abstract class DataTreeProvider extends ProviderTrait<DataTree> {
+
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    private HoneycombConfiguration config;
+
+    @Override
+    public TipProducingDataTree create() {
+        TipProducingDataTree delegate = InMemoryDataTreeFactory.getInstance().create(getType());
+        delegate.setSchemaContext(schemaService.getGlobalContext());
+        return delegate;
+    }
+
+    public abstract TreeType getType();
+
+    public static class ConfigDataTreeProvider extends DataTreeProvider {
+        @Override
+        public TreeType getType() {
+            return TreeType.CONFIGURATION;
+        }
+
+    }
+
+    public static class ContextDataTreeProvider extends DataTreeProvider {
+        @Override
+        public TreeType getType() {
+            return TreeType.OPERATIONAL;
+        }
+
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombBindingDataBrokerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombBindingDataBrokerProvider.java
new file mode 100644 (file)
index 0000000..bbcd409
--- /dev/null
@@ -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 static io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.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;
+
+/**
+ * Provides binding adapter for {@link io.fd.honeycomb.data.impl.DataBroker}.
+ */
+final class HoneycombBindingDataBrokerProvider extends ProviderTrait<DataBroker> {
+
+    @Inject
+    @Named(HONEYCOMB_CONFIG)
+    private DOMDataBroker domDataBroker;
+    @Inject
+    private BindingToNormalizedNodeCodec mappingService;
+
+    @Override
+    protected BindingDOMDataBrokerAdapter create() {
+
+        return new BindingDOMDataBrokerAdapter(domDataBroker, mappingService);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.java
new file mode 100644 (file)
index 0000000..7507686
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, 2017 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 static io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.impl.NorthboundFacadeHoneycombDOMBroker;
+
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+
+final class HoneycombDOMBrokerProvider extends ProviderTrait<Broker> {
+
+    @Inject
+    @Named(HONEYCOMB_CONFIG)
+    private DOMDataBroker domDataBroker;
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    private DOMNotificationRouter domNotificationService;
+    @Inject
+    private DOMRpcService domRpcService;
+    @Inject
+    private DOMMountPointService domMountPointService;
+
+    @Override
+    protected NorthboundFacadeHoneycombDOMBroker create() {
+        return new NorthboundFacadeHoneycombDOMBroker(domDataBroker, schemaService, domNotificationService,
+            domRpcService, domMountPointService);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.java
new file mode 100644 (file)
index 0000000..ca94350
--- /dev/null
@@ -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 io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.ReadableDataManager;
+import io.fd.honeycomb.data.impl.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+public final class HoneycombDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> {
+
+    @Inject
+    private ModifiableDataManager modDataManager;
+    @Inject(optional = true)
+    private ReadableDataManager readDataManager;
+
+    @Override
+    protected DataBroker create() {
+        return readDataManager != null
+                ? DataBroker.create(modDataManager, readDataManager)
+                : DataBroker.create(modDataManager);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMRpcServiceProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMRpcServiceProvider.java
new file mode 100644 (file)
index 0000000..324d636
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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 io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.rpc.HoneycombDOMRpcService;
+import io.fd.honeycomb.rpc.RpcRegistry;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+
+public final class HoneycombDOMRpcServiceProvider extends ProviderTrait<DOMRpcService> {
+
+    @Inject
+    private BindingToNormalizedNodeCodec serializer;
+
+    @Inject
+    private RpcRegistry rpcRegistry;
+
+    @Override
+    protected DOMRpcService create() {
+        return new HoneycombDOMRpcService(serializer, rpcRegistry);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.java
new file mode 100644 (file)
index 0000000..b318038
--- /dev/null
@@ -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.data;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.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 java.util.HashSet;
+import java.util.Set;
+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;
+
+public final class HoneycombNotificationManagerProvider extends ProviderTrait<NotificationCollector> {
+
+    @Inject
+    private DOMNotificationRouter notificationRouter;
+    @Inject(optional = true)
+    private Set<ManagedNotificationProducer> notificationProducers = new HashSet<>();
+    @Inject
+    private BindingToNormalizedNodeCodec codec;
+
+    @Override
+    protected HoneycombNotificationCollector create() {
+        // Create the registry to keep track of what'OPERATIONAL registered
+        NotificationProducerRegistry notificationProducerRegistry =
+                new NotificationProducerRegistry(Lists.newArrayList(notificationProducers));
+
+        // Create BA version of notification service (implementation is free from ODL)
+        BindingDOMNotificationPublishServiceAdapter bindingDOMNotificationPublishServiceAdapter =
+                new BindingDOMNotificationPublishServiceAdapter(codec, notificationRouter);
+
+        // Create Collector on top of BA notification service and registry
+        HoneycombNotificationCollector honeycombNotificationCollector =
+                new HoneycombNotificationCollector(bindingDOMNotificationPublishServiceAdapter,
+                        notificationProducerRegistry);
+
+        // Create tracker, responsible for starting and stopping registered notification producers whenever necessary
+        NotificationProducerTracker notificationProducerTracker =
+                new NotificationProducerTracker(notificationProducerRegistry, honeycombNotificationCollector,
+                        notificationRouter);
+
+        // DOMNotificationService is already provided by DOMBroker injected into RESTCONF, however RESTCONF
+        // only supports data-change notification, nothing else. So currently (Beryllium-SR2) honeycomb notifications
+        // won't be available over RESTCONF.
+
+        return honeycombNotificationCollector;
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.java
new file mode 100644 (file)
index 0000000..8e003c2
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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 io.fd.honeycomb.binding.init.ProviderTrait;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+
+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.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
+import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
+
+public final class InmemoryDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> {
+
+    public static final String CONFIG = "config";
+    public static final String OPERATIONAL = "operational";
+
+    @Inject
+    @Named(InmemoryDOMDataBrokerProvider.CONFIG)
+    private InMemoryDOMDataStore cfgDataStore;
+    @Inject
+    @Named(InmemoryDOMDataBrokerProvider.OPERATIONAL)
+    private InMemoryDOMDataStore operDataStore;
+
+    @Override
+    protected SerializedDOMDataBroker create() {
+        // This Databroker is dedicated for netconf metadata, not expected to be under heavy load
+        ExecutorService listenableFutureExecutor =
+                SpecialExecutors.newBlockingBoundedCachedThreadPool(1, 100, "commits");
+        ExecutorService commitExecutor = SpecialExecutors.newBoundedSingleThreadExecutor(100, "WriteTxCommit");
+        // TODO HONEYCOMB-164 try to provide more lightweight implementation of DataBroker
+
+        Map<LogicalDatastoreType, DOMStore> map = new LinkedHashMap<>();
+        map.put(LogicalDatastoreType.CONFIGURATION, cfgDataStore);
+        map.put(LogicalDatastoreType.OPERATIONAL, operDataStore);
+
+        return new SerializedDOMDataBroker(map, new DeadlockDetectingListeningExecutorService(commitExecutor,
+                TransactionCommitDeadlockException.DEADLOCK_EXCEPTION_SUPPLIER, listenableFutureExecutor));
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.java
new file mode 100644 (file)
index 0000000..b2ed417
--- /dev/null
@@ -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.data;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.impl.ModifiableDataTreeDelegator;
+import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule;
+import io.fd.honeycomb.translate.write.registry.WriterRegistry;
+
+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;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public final class ModifiableDTDelegProvider extends ProviderTrait<ModifiableDataManager> {
+
+    @Inject
+    private BindingToNormalizedNodeCodec serializer;
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    @Named(ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG)
+    private DataTree dataTree;
+    @Inject
+    private WriterRegistry registry;
+    @Inject
+    @Named(ContextPipelineModule.HONEYCOMB_CONTEXT)
+    private DataBroker contextBroker;
+
+    @Override
+    protected ModifiableDataTreeDelegator create() {
+        return new ModifiableDataTreeDelegator(serializer, dataTree, schemaService.getGlobalContext(),
+            registry, contextBroker);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistedConfigInitializerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistedConfigInitializerProvider.java
new file mode 100644 (file)
index 0000000..caa5199
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 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 io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.init.RestoringInitializer;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+
+import java.nio.file.Paths;
+
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class PersistedConfigInitializerProvider extends ProviderTrait<RestoringInitializer> {
+    private static final Logger LOG = LoggerFactory.getLogger(PersistedConfigInitializerProvider.class);
+
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    protected HoneycombConfiguration cfgAttributes;
+    @Inject
+//    @Named(ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG)
+    //mofified to be able to restore config to device config datastore
+    @Named("device-databroker")
+    private DOMDataBroker domDataBroker;
+
+    @Override
+    public RestoringInitializer create() {
+        LOG.info("RestoringInitializer ...");
+        return new RestoringInitializer(schemaService, Paths.get(cfgAttributes.peristConfigPath), domDataBroker,
+                RestoringInitializer.RestorationType.valueOf(cfgAttributes.persistedConfigRestorationType),
+                LogicalDatastoreType.CONFIGURATION);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistingDataTreeProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistingDataTreeProvider.java
new file mode 100644 (file)
index 0000000..95c07cf
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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 io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.impl.PersistingDataTreeAdapter;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule;
+
+import java.nio.file.Paths;
+
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class PersistingDataTreeProvider extends ProviderTrait<DataTree> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PersistingDataTreeProvider.class);
+
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    protected HoneycombConfiguration config;
+
+    @Override
+    public DataTree create() {
+        return isEnabled()
+                ? new PersistingDataTreeAdapter(getDelegate(), schemaService, Paths.get(getPath()))
+                : getDelegate();
+    }
+
+    public abstract String getPath();
+
+    public abstract TreeType getType();
+
+    public abstract DataTree getDelegate();
+
+    protected abstract boolean isEnabled();
+
+    public static final class ConfigPersistingDataTreeProvider extends PersistingDataTreeProvider {
+
+        @Inject
+        @Named(ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG_NONPERSIST)
+        private DataTree delegate;
+
+        @Override
+        public String getPath() {
+            return config.peristConfigPath;
+        }
+
+        @Override
+        public TreeType getType() {
+            return TreeType.CONFIGURATION;
+        }
+
+        @Override
+        public DataTree getDelegate() {
+            return delegate;
+        }
+
+        @Override
+        protected boolean isEnabled() {
+            return config.isConfigPersistenceEnabled();
+        }
+    }
+
+    public static final class ContextPersistingDataTreeProvider extends PersistingDataTreeProvider {
+
+        @Inject
+        @Named(ContextPipelineModule.HONEYCOMB_CONTEXT_NOPERSIST)
+        private DataTree delegate;
+
+        @Override
+        public String getPath() {
+            return config.peristContextPath;
+        }
+
+        @Override
+        public TreeType getType() {
+            return TreeType.OPERATIONAL;
+        }
+
+        @Override
+        public DataTree getDelegate() {
+            return delegate;
+        }
+
+        @Override
+        protected boolean isEnabled() {
+            return config.isContextPersistenceEnabled();
+        }
+
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryBuilderProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryBuilderProvider.java
new file mode 100644 (file)
index 0000000..3184363
--- /dev/null
@@ -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 io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.rpc.RpcRegistryBuilder;
+import io.fd.honeycomb.rpc.RpcService;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class RpcRegistryBuilderProvider extends ProviderTrait<RpcRegistryBuilder> {
+
+    @Inject(optional = true)
+    private Set<RpcService> rpcServices = new HashSet<>();
+
+    @Override
+    protected RpcRegistryBuilder create() {
+        final RpcRegistryBuilder builder = new RpcRegistryBuilder();
+        rpcServices.stream()
+                .forEach(service -> builder.addService(service));
+        return builder;
+    }
+
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryProvider.java
new file mode 100644 (file)
index 0000000..fd6499b
--- /dev/null
@@ -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 io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.rpc.RpcRegistry;
+import io.fd.honeycomb.rpc.RpcRegistryBuilder;
+
+public final class RpcRegistryProvider extends ProviderTrait<RpcRegistry> {
+
+    @Inject
+    private RpcRegistryBuilder builder;
+
+    @Override
+    protected RpcRegistry create() {
+        return builder.build();
+    }
+
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.java
new file mode 100644 (file)
index 0000000..fa37d10
--- /dev/null
@@ -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.data.config;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder;
+import io.fd.honeycomb.translate.util.YangDAG;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.WriterRegistry;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class WriterRegistryProvider extends ProviderTrait<WriterRegistry> {
+
+    @Inject(optional = true)
+    private Set<WriterFactory> writerFactories = new HashSet<>();
+
+    @Override
+    protected WriterRegistry create() {
+        final FlatWriterRegistryBuilder builder = new FlatWriterRegistryBuilder(new YangDAG());
+        writerFactories
+                .stream()
+                .forEach(it -> it.init(builder));
+        return builder.build();
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.java
new file mode 100644 (file)
index 0000000..b004efd
--- /dev/null
@@ -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.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.data.PersistingDataTreeProvider;
+import io.fd.honeycomb.translate.MappingContext;
+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;
+
+public class ContextPipelineModule extends PrivateModule {
+
+    public static final String HONEYCOMB_CONTEXT_NOPERSIST = "honeycomb-context-nopersist";
+    public static final String HONEYCOMB_CONTEXT = "honeycomb-context";
+
+    @Override
+    protected void configure() {
+        // Non persisting data tree for context
+        DataTreeProvider.ContextDataTreeProvider noPersistDataTreeProvider =
+                new DataTreeProvider.ContextDataTreeProvider();
+        bind(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT_NOPERSIST))
+                .toProvider(noPersistDataTreeProvider).in(Singleton.class);
+        expose(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT_NOPERSIST));
+        // Persisting data tree wrapper for context
+        PersistingDataTreeProvider.ContextPersistingDataTreeProvider dataTreeProvider =
+                new PersistingDataTreeProvider.ContextPersistingDataTreeProvider();
+        bind(DataTree.class).toProvider(dataTreeProvider).in(Singleton.class);
+
+        // Data Tree manager (without any delegation) on top of context data tree
+        bind(ModifiableDataManager.class).toProvider(ModifiableDTMgrProvider.class).in(Singleton.class);
+
+        // DOMDataBroker interface on top of data tree manager
+        HoneycombContextDOMDataBrokerProvider domBrokerProvider = new HoneycombContextDOMDataBrokerProvider();
+        bind(DOMDataBroker.class).toProvider(domBrokerProvider).in(Singleton.class);
+
+        // BA version of data broker for context
+        bind(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT)).toProvider(BindingDataBrokerProvider.class)
+                .in(Singleton.class);
+        expose(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT));
+
+        // Create initializer to init persisted config data
+        bind(DataTreeInitializer.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT))
+                .toProvider(PersistedContextInitializerProvider.class)
+                .in(Singleton.class);
+        expose(DataTreeInitializer.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT));
+
+        // Mapping context is just a small adapter on top of BA data broker to simplify CRUD of context data
+        bind(MappingContext.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT))
+                .toProvider(RealtimeMappingContextProvider.class).in(Singleton.class);
+        expose(MappingContext.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT));
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.java
new file mode 100644 (file)
index 0000000..4c3965f
--- /dev/null
@@ -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.context;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.impl.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+public final class HoneycombContextDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> {
+
+    @Inject
+    private ModifiableDataManager modDataManager;
+
+    @Override
+    public DataBroker create() {
+        return DataBroker.create(modDataManager);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.java
new file mode 100644 (file)
index 0000000..c703e95
--- /dev/null
@@ -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.context;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.impl.ModifiableDataTreeManager;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public final class ModifiableDTMgrProvider extends ProviderTrait<ModifiableDataManager> {
+
+    @Inject
+    private DataTree dataTree;
+
+    @Override
+    public ModifiableDataTreeManager create() {
+        return new ModifiableDataTreeManager(dataTree);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/PersistedContextInitializerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/PersistedContextInitializerProvider.java
new file mode 100644 (file)
index 0000000..6d256d8
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 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 io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.init.RestoringInitializer;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import java.nio.file.Paths;
+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;
+
+final class PersistedContextInitializerProvider extends ProviderTrait<RestoringInitializer> {
+
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    protected HoneycombConfiguration cfgAttributes;
+    // injects data broker from within context of private module
+    @Inject
+    private DOMDataBroker domDataBroker;
+
+    @Override
+    public RestoringInitializer create() {
+        return new RestoringInitializer(schemaService, Paths.get(cfgAttributes.peristContextPath), domDataBroker,
+                RestoringInitializer.RestorationType.valueOf(cfgAttributes.persistedContextRestorationType),
+                LogicalDatastoreType.OPERATIONAL);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/RealtimeMappingContextProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/RealtimeMappingContextProvider.java
new file mode 100644 (file)
index 0000000..3f39ce1
--- /dev/null
@@ -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.data.context;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.util.RealtimeMappingContext;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+
+public final class RealtimeMappingContextProvider extends ProviderTrait<MappingContext> {
+
+    @Inject
+    @Named(ContextPipelineModule.HONEYCOMB_CONTEXT)
+    private DataBroker contextDataBroker;
+
+    @Override
+    public RealtimeMappingContext create() {
+        return new RealtimeMappingContext(contextDataBroker);
+    }
+
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.java
new file mode 100644 (file)
index 0000000..cdd3596
--- /dev/null
@@ -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.data.oper;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.ReadableDataManager;
+import io.fd.honeycomb.data.impl.ReadableDataTreeDelegator;
+import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+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;
+
+public final class ReadableDTDelegProvider extends ProviderTrait<ReadableDataManager> {
+
+    @Inject
+    private BindingToNormalizedNodeCodec serializer;
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    private ReaderRegistry registry;
+    @Inject
+    @Named(ContextPipelineModule.HONEYCOMB_CONTEXT)
+    private DataBroker contextBroker;
+
+    @Override
+    protected ReadableDataTreeDelegator create() {
+        return new ReadableDataTreeDelegator(serializer, schemaService.getGlobalContext(),
+                registry, contextBroker);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.java
new file mode 100644 (file)
index 0000000..8e0b776
--- /dev/null
@@ -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.data.oper;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+import io.fd.honeycomb.translate.util.YangDAG;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class ReaderRegistryProvider extends ProviderTrait<ReaderRegistry> {
+
+    @Inject(optional = true)
+    private Set<ReaderFactory> readerFactories = new HashSet<>();
+
+    @Override
+    protected ReaderRegistry create() {
+        final CompositeReaderRegistryBuilder builder = new CompositeReaderRegistryBuilder(new YangDAG());
+        readerFactories.stream()
+            .forEach(it -> it.init(builder));
+        return builder.build();
+    }
+
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/DeviceChangeListener.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/DeviceChangeListener.java
new file mode 100644 (file)
index 0000000..555b56c
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2018 Orange 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.common.base.Preconditions;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.Interface;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.RoadmConnections;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.RoadmConnectionsKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Martial COULIBALY ( mcoulibaly.ext@orange.com ) on behalf of Orange
+ */
+final class DeviceChangeListener implements DataTreeChangeListener<OrgOpenroadmDevice> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceChangeListener.class);
+    private final DataBroker honeyCombDB;
+    private final DataBroker dataBroker;
+
+    public DeviceChangeListener(DataBroker deviceDataBroker, DataBroker honeycombDB) {
+        this.dataBroker = deviceDataBroker;
+        this.honeyCombDB = honeycombDB;
+        Preconditions.checkArgument(this.dataBroker != null, "Device datastore is null");
+        Preconditions.checkArgument(this.honeyCombDB != null, "HC datastore is null");
+    }
+
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<OrgOpenroadmDevice>> changes) {
+        LOG.info("onDataTreeChanged");
+        for (DataTreeModification<OrgOpenroadmDevice> change : changes) {
+            final DataObjectModification<OrgOpenroadmDevice> rootNode = change.getRootNode();
+            final DataTreeIdentifier<OrgOpenroadmDevice> rootPath = change.getRootPath();
+            if (rootNode != null ) {
+                final OrgOpenroadmDevice dataBefore = rootNode.getDataBefore();
+                final OrgOpenroadmDevice dataAfter = rootNode.getDataAfter();
+                LOG.info("Received Device change({}):\n before={} \n after={}", rootNode.getModificationType(), dataBefore,
+                        dataAfter);
+                Collection<DataObjectModification<? extends DataObject>> modifiedChildren = rootNode.getModifiedChildren();
+                switch (rootNode.getModificationType()) {
+                    case SUBTREE_MODIFIED:
+                        if (!modifiedChildren.isEmpty()) {
+                            Iterator<DataObjectModification<? extends DataObject>> iterator = modifiedChildren.iterator();
+                            while (iterator.hasNext()) {
+                                DataObjectModification<? extends DataObject> modified = iterator.next();
+                                LOG.info("modified = \ndataType : {}\nid : {}\nmodifiedType : {}\noldData : {}\nnewData : {} \n",
+                                        modified.getDataType(), modified.getIdentifier(),modified.getModificationType(),
+                                        modified.getDataBefore(), modified.getDataAfter());
+                                switch (modified.getModificationType()) {
+                                  case SUBTREE_MODIFIED:
+                                  case WRITE :
+                                      processChange(rootPath.getRootIdentifier(), dataAfter);
+                                      break;
+                                  case DELETE:
+                                      deleteContainer(rootPath, modified, dataAfter);
+                                      break;
+                                  default:
+                                      break;
+                               }
+                            }
+                        }
+                        processChange(rootPath.getRootIdentifier(), dataAfter);
+                        break;
+                    case WRITE :
+                        processChange(rootPath.getRootIdentifier(), dataAfter);
+                        break;
+                    case DELETE:
+                        deleteChange(rootPath.getRootIdentifier(),dataBefore);
+                        break;
+                    default:
+                        break;
+                }
+            } else {
+                LOG.error("rootNode is null !");
+            }
+        }
+    }
+
+    /**
+     * Delete change from device
+     * oper datastore.
+     *
+     * @param id container identifier
+     */
+    private void deleteContainer(DataTreeIdentifier<OrgOpenroadmDevice> rootPath,
+            DataObjectModification<? extends DataObject> modified, final OrgOpenroadmDevice dataAfter) {
+        final String ROADM_CONNECTIONS = "interface org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206"
+                + ".org.openroadm.device.container.org.openroadm.device.RoadmConnections";
+        final String INTERFACE_GRP = "interface org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206"
+                + ".interfaces.grp.Interface";
+        Class<? extends DataObject> type = modified.getDataType();
+        PathArgument path = modified.getIdentifier();
+        LOG.info("deleting container type '{}' with id '{}' ...", type.toString(), path);
+        String key = extractKey(path.toString());
+        if ( key != null) {
+            InstanceIdentifier<?> iid = null;
+            switch (type.toString()) {
+                case ROADM_CONNECTIONS:
+                    LOG.info("roadm-connections ...");
+                    iid = rootPath.getRootIdentifier().child(RoadmConnections.class,
+                        new RoadmConnectionsKey(key));
+                    break;
+                case INTERFACE_GRP:
+                    LOG.info("interface ....");
+                    iid = rootPath.getRootIdentifier().child(Interface.class,
+                            new InterfaceKey(key));
+                default:
+                    break;
+            }
+            LOG.info("iid : {}", iid);
+            WriteTransaction writeTx = this.dataBroker.newWriteOnlyTransaction();
+            WriteTransaction writeHCTx = this.honeyCombDB.newWriteOnlyTransaction();
+            if (writeTx != null && writeHCTx != null) {
+                LOG.info("WriteTransaction is ok, delete container device from device oper datastore");
+                try {
+                    LOG.info("deleting container element from device oper DS ...");
+                    writeTx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+                    Future<Void> future = writeTx.submit();
+                    future.get();
+                    LOG.info("container element '{}' deleted from device oper datastore", iid);
+                    LOG.info("deleting from HC config DS ...");
+                    writeHCTx.put(LogicalDatastoreType.CONFIGURATION, rootPath.getRootIdentifier(),dataAfter);
+                    future = writeHCTx.submit();
+                    future.get();
+                    LOG.info("device config DS '{}' updated to HC config DS", rootPath.getRootIdentifier());
+                } catch (InterruptedException | ExecutionException e) {
+                    LOG.error("Failed to process WriteTransactions",e);
+                }
+            } else {
+                LOG.error("WriteTransaction object is null");
+            }
+        } else {
+            LOG.error("extract key is null");
+        }
+    }
+
+    private String extractKey(String path) {
+        LOG.info("getting key from pathArgument ...");
+        String result = null;
+        if (path != null && path.length() > 2) {
+            result = path.substring(path.lastIndexOf("=") + 1, path.length()-2);
+            LOG.info("result : {}", result);
+        } else {
+            LOG.error("String pathArgument is not compliant !!");
+        }
+        return result;
+    }
+
+    /**
+     * Delete change from Honeycomb
+     * config datastore.
+     *
+     * @param id OrgOpenroadmDevice identifier
+     * @param dataBefore OrgOpenroadmDevice before delete action
+     */
+    private void deleteChange(final InstanceIdentifier<OrgOpenroadmDevice> id, final OrgOpenroadmDevice dataBefore) {
+        LOG.info("deleting change ...");
+        WriteTransaction writeHCTx = this.honeyCombDB.newWriteOnlyTransaction();
+        if (writeHCTx != null) {
+            LOG.info("WriteTransaction is ok, delete device info from HC config datastore");
+            if(dataBefore != null) {
+                String deviceId = dataBefore.getInfo().getNodeId();
+                try {
+                    writeHCTx.delete(LogicalDatastoreType.CONFIGURATION, id);
+                    Future<Void> future = writeHCTx.submit();
+                    future.get();
+                    LOG.info("device '{}' deleted from HC config  datastore", deviceId);
+                } catch (InterruptedException | ExecutionException e) {
+                    LOG.error("Failed to delete Element '{}' from datastore", deviceId);
+                }
+            } else {
+                LOG.error("OrgOpenroadmDevice is null");
+            }
+        } else {
+            LOG.error("WriteTransaction object is null");
+        }
+
+    }
+
+    /**
+     * Merge change to Honeycomb
+     * config datastore and device
+     * config datastore.
+     *
+     * @param id OrgOpenroadmDevice identifier
+     * @param dataAfter OrgOpenroadmDevice to be merged
+     */
+    private void processChange(final InstanceIdentifier<OrgOpenroadmDevice> id, final OrgOpenroadmDevice dataAfter) {
+        LOG.info("processing change ...");
+        WriteTransaction writeTx = this.dataBroker.newWriteOnlyTransaction();
+        WriteTransaction writeHCTx = this.honeyCombDB.newWriteOnlyTransaction();
+        if (writeTx != null && writeHCTx != null) {
+            LOG.info("WriteTransactions are ok, merge device info to datastores");
+            if(dataAfter != null) {
+                String deviceId = dataAfter.getInfo().getNodeId();
+                writeTx.merge(LogicalDatastoreType.OPERATIONAL, id, dataAfter);
+                Future<Void> future = writeTx.submit();
+                try {
+                    future.get();
+                    LOG.info("device '{}' merged to device oper datastore", deviceId);
+                    writeHCTx.merge(LogicalDatastoreType.CONFIGURATION, id, dataAfter);
+                    future = writeHCTx.submit();
+                    future.get();
+                    LOG.info("device '{}' merged to HC config datastore", deviceId);
+                } catch (InterruptedException | ExecutionException e) {
+                    LOG.error("Failed to merge Element '{}' to datastores", deviceId);
+                }
+            } else {
+                LOG.error("device is null");
+            }
+        } else {
+            LOG.error("WriteTransaction object is null");
+        }
+    }
+
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.java
new file mode 100644 (file)
index 0000000..0ddcf2e
--- /dev/null
@@ -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.initializer;
+
+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.InitializerRegistry;
+import io.fd.honeycomb.infra.distro.data.BindingDataBrokerProvider;
+import io.fd.honeycomb.infra.distro.data.HoneycombDOMDataBrokerProvider;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+public final class InitializerPipelineModule extends PrivateModule {
+
+    public static final String HONEYCOMB_INITIALIZER = "honeycomb-initializer";
+
+    @Override
+    protected void configure() {
+        // Create data tree manager on top of non-persisting config data tree
+        bind(ModifiableDataManager.class).toProvider(ModifiableDTDelegInitProvider.class).in(Singleton.class);
+        // Wrap as DOMDataBroker
+        bind(DOMDataBroker.class).toProvider(HoneycombDOMDataBrokerProvider.class).in(Singleton.class);
+        // Wrap as BA data broker
+        bind(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_INITIALIZER))
+                .toProvider(BindingDataBrokerProvider.class).in(Singleton.class);
+        expose(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_INITIALIZER));
+
+        // Create initializer registry so that plugins can provide their initializers
+        bind(InitializerRegistry.class).annotatedWith(Names.named(HONEYCOMB_INITIALIZER))
+                .toProvider(InitializerRegistryAdapterProvider.class).in(Singleton.class);
+        expose(InitializerRegistry.class).annotatedWith(Names.named(HONEYCOMB_INITIALIZER));
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapter.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapter.java
new file mode 100644 (file)
index 0000000..1d8b53a
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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 io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.data.init.InitializerRegistry;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.registry.InitRegistry;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class InitializerRegistryAdapter implements InitializerRegistry {
+
+    private static final Logger LOG = LoggerFactory.getLogger(InitializerRegistryAdapter.class);
+
+    private final DataTreeInitializer configInitializer;
+    private final DataTreeInitializer contextInitializer;
+    private final InitRegistry initRegistry;
+    private final DataBroker dataBroker;
+    private final MappingContext realtimeMappingContext;
+    /** Add by Martial. */
+    private final DataBroker deviceDataBroker;
+    private final DataBroker hcConfigDataBroker;
+    private final InstanceIdentifier<OrgOpenroadmDevice> DEVICE_CONTAINER_ID = InstanceIdentifier
+            .create(OrgOpenroadmDevice.class);
+
+    InitializerRegistryAdapter(final DataTreeInitializer configInitializer,
+                               final DataTreeInitializer contextInitializer,
+                               final InitRegistry initRegistry,
+                               final DataBroker noopConfigDataBroker,
+                               final MappingContext realtimeMappingContext,
+                               final DataBroker deviceDataBroker,
+                               final DataBroker hcConfigDataBroker) {
+        this.configInitializer = configInitializer;
+        this.contextInitializer = contextInitializer;
+        this.initRegistry = initRegistry;
+        this.dataBroker = noopConfigDataBroker;
+        this.realtimeMappingContext = realtimeMappingContext;
+        this.deviceDataBroker = deviceDataBroker;
+        this.hcConfigDataBroker = hcConfigDataBroker;
+    }
+
+    @Override
+    public void initialize() throws DataTreeInitializer.InitializeException {
+        LOG.info("Config initialization started");
+        try {
+            LOG.info("Register device databroker listener ...");
+            deviceDataBroker
+            .registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                    DEVICE_CONTAINER_ID), new DeviceChangeListener(deviceDataBroker, hcConfigDataBroker));
+            LOG.info("Device databroker listener registered");
+            // 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
+            initRegistry.initAll(dataBroker, new InitReadContext(realtimeMappingContext));
+            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");
+    }
+
+    private static final class InitReadContext implements ReadContext {
+
+        private final ModificationCache modificationCache;
+        private final MappingContext realtimeMappingContext;
+
+        InitReadContext(final MappingContext realtimeMappingContext) {
+            modificationCache = new ModificationCache();
+            this.realtimeMappingContext = realtimeMappingContext;
+        }
+
+        @Nonnull
+        @Override
+        public ModificationCache getModificationCache() {
+            return modificationCache;
+        }
+
+        @Nonnull
+        @Override
+        public MappingContext getMappingContext() {
+            return realtimeMappingContext;
+        }
+
+        @Override
+        public void close() {
+            modificationCache.close();
+        }
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapterProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapterProvider.java
new file mode 100644 (file)
index 0000000..0f5c44a
--- /dev/null
@@ -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.initializer;
+
+import static io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG;
+import static io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule.HONEYCOMB_CONTEXT;
+import static io.fd.honeycomb.infra.distro.initializer.InitializerPipelineModule.HONEYCOMB_INITIALIZER;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.data.init.InitializerRegistry;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+
+public final class InitializerRegistryAdapterProvider extends ProviderTrait<InitializerRegistry> {
+
+    @Inject
+    @Named(HONEYCOMB_CONTEXT)
+    private DataTreeInitializer contextInitializer;
+    @Inject
+    @Named(HONEYCOMB_CONFIG)
+    private DataTreeInitializer configInitializer;
+    @Inject
+    private ReaderRegistry initRegistry;
+    @Inject
+    @Named(HONEYCOMB_INITIALIZER)
+    private DataBroker noopConfigDataBroker;
+    @Inject
+    @Named(HONEYCOMB_CONTEXT)
+    private MappingContext realtimeMappingContext;
+    @Inject
+    @Named("device-databroker")
+    private DataBroker deviceDataBroker;
+    @Inject
+    @Named(HONEYCOMB_CONFIG)
+    private DataBroker configDataBroker;
+
+    @Override
+    protected InitializerRegistryAdapter create() {
+        return new InitializerRegistryAdapter(configInitializer, contextInitializer, initRegistry,
+                noopConfigDataBroker, realtimeMappingContext, deviceDataBroker, configDataBroker);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/ModifiableDTDelegInitProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/ModifiableDTDelegInitProvider.java
new file mode 100644 (file)
index 0000000..42c6838
--- /dev/null
@@ -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.initializer;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.impl.ModifiableDataTreeDelegator;
+import io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule;
+import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule;
+import io.fd.honeycomb.translate.util.write.NoopWriterRegistry;
+
+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;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public final class ModifiableDTDelegInitProvider extends ProviderTrait<ModifiableDataManager> {
+
+    @Inject
+    private BindingToNormalizedNodeCodec serializer;
+    @Inject
+    @Named(ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG_NONPERSIST)
+    //solve writing in ./persist/config/data.json
+    private DataTree dataTree;
+    @Inject
+    @Named(ContextPipelineModule.HONEYCOMB_CONTEXT)
+    private DataBroker contextBroker;
+    @Inject
+    private SchemaService schemaService;
+
+    @Override
+    public ModifiableDataTreeDelegator create() {
+        return new ModifiableDataTreeDelegator(serializer, dataTree, schemaService.getGlobalContext(),
+                new NoopWriterRegistry(), contextBroker);
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.java
new file mode 100644 (file)
index 0000000..01b03c4
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.infra.distro.schema;
+
+import static io.fd.honeycomb.infra.distro.schema.YangModulesProvider.YangModules;
+
+import com.google.common.base.MoreObjects;
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import java.util.stream.Collectors;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ModuleInfoBackedCtxProvider extends ProviderTrait<ModuleInfoBackedContext> {
+    private static final Logger LOG = LoggerFactory.getLogger(ModuleInfoBackedCtxProvider.class);
+
+    // optional in sense that list of modules inside can be empty if none was found
+    @Inject
+    private YangModules moduleInfos;
+
+    @Override
+    protected ModuleInfoBackedContext create() {
+        ModuleInfoBackedContext create = ModuleInfoBackedContext.create();
+        create.addModuleInfos(moduleInfos.getYangBindings().stream()
+                .map(YangModelBindingProvider::getModuleInfo)
+                .collect(Collectors.toList()));
+        LOG.debug("ModuleInfoBackedContext created from {}", moduleInfos);
+        return create;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).add("writerFactories", moduleInfos).toString();
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ResourceLoader.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ResourceLoader.java
new file mode 100644 (file)
index 0000000..88428e8
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2017 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 static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
+import com.google.common.io.Resources;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import org.apache.commons.io.IOUtils;
+
+/**
+ * Allows loading content of X amount of files from filesystem or archive
+ */
+public interface ResourceLoader {
+
+    default Set<String> loadResourceContentsOnPath(final String path) {
+        final URL folderUrl = getClass().getClassLoader().getResource(path);
+        checkState(folderUrl != null, "Resources %s not found", path);
+
+        if (ResourceLoaderIml.urlToUri(folderUrl).getScheme().equals("jar")) {
+            return ResourceLoaderIml.readFromJar(path, folderUrl);
+        } else {
+            return ResourceLoaderIml.readFromFolder(folderUrl);
+        }
+
+    }
+
+    final class ResourceLoaderIml {
+
+        private static Set<String> readFromFolder(final URL folderUrl) {
+            final File folder = new File(folderUrl.getPath());
+            final File[] files = checkNotNull(folder.listFiles(), "No files present on path %s", folderUrl);
+            return Arrays.stream(files)
+                    .map(ResourceLoaderIml::fileToUrl)
+                    .map(ResourceLoaderIml::urlToContentString)
+                    .flatMap(content -> Arrays.stream(content.split(System.lineSeparator())))
+                    .filter(ResourceLoaderIml::filterNonEmpty)
+                    .collect(Collectors.toSet());
+        }
+
+        private static Set<String> readFromJar(final String path, final URL url) {
+            final String uriString = urlToUri(url).toString();
+            final String fileReference = extractJarFilePath(uriString);
+            try (JarFile jar = new JarFile(new File(fileReference))) {
+                return Collections.list(jar.entries())
+                        .stream()
+                        .filter(jarEntry -> jarEntry.getName().contains(path))
+                        .map(jarEntry -> getJarEntryStream(jar, jarEntry))
+                        .map(ResourceLoaderIml::readJarEntryStream)
+                        .flatMap(content -> Arrays.stream(content.split(System.lineSeparator())))
+                        .filter(ResourceLoaderIml::filterNonEmpty)
+                        .collect(Collectors.toSet());
+            } catch (IOException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        private static String extractJarFilePath(final String uriString) {
+            return uriString.substring(0, uriString.indexOf("!")).replace("jar:file:", "");
+        }
+
+        private static boolean filterNonEmpty(final String line) {
+            return !Strings.isNullOrEmpty(line.trim());
+        }
+
+        private static String readJarEntryStream(final InputStream inputStream) {
+            try {
+                final String value = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+                IOUtils.closeQuietly(inputStream);
+                return value;
+            } catch (IOException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        private static InputStream getJarEntryStream(final JarFile jar, final JarEntry jarEntry) {
+            try {
+                return jar.getInputStream(jarEntry);
+            } catch (IOException e) {
+                throw new IllegalStateException(format("Unable to get stream for entry %s | jar %s", jar, jarEntry), e);
+            }
+        }
+
+        private static URI urlToUri(final URL url) {
+            try {
+                return url.toURI();
+            } catch (URISyntaxException e) {
+                throw new IllegalStateException(format("Unable to convert URL %s to URI", url), e);
+            }
+        }
+
+        private static String urlToContentString(final URL url) {
+            try {
+                return Resources.toString(url, Charsets.UTF_8);
+            } catch (IOException e) {
+                throw new IllegalArgumentException("Unable to read resource from: " + url, e);
+            }
+        }
+
+        private static URL fileToUrl(final File file) {
+            try {
+                return file.toURI().toURL();
+            } catch (MalformedURLException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.java
new file mode 100644 (file)
index 0000000..7e6b89d
--- /dev/null
@@ -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.schema;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+
+public class SchemaModule extends AbstractModule {
+
+    @Override
+    protected void configure() {
+        bind(ModuleInfoBackedContext.class).toProvider(ModuleInfoBackedCtxProvider.class).in(Singleton.class);
+        bind(SchemaService.class).toProvider(SchemaServiceProvider.class).in(Singleton.class);
+        bind(BindingToNormalizedNodeCodec.class).toProvider(SerializerProvider.class).in(Singleton.class);
+    }
+
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.java
new file mode 100644 (file)
index 0000000..4ed3698
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.infra.distro.schema;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+
+public final class SchemaServiceProvider extends ProviderTrait<SchemaService> {
+
+    @Inject
+    private ModuleInfoBackedContext mibCtx;
+
+    @Override
+    public StaticSchemaService create() {
+        return new StaticSchemaService(mibCtx.getSchemaContext());
+    }
+
+    /**
+     * Static schema context provider service.
+     */
+    private static final class StaticSchemaService implements SchemaService {
+        private final SchemaContext schemaContext;
+
+        StaticSchemaService(SchemaContext schemaContext) {
+            this.schemaContext = schemaContext;
+        }
+
+        @Override
+        public void addModule(final Module module) {
+            throw new UnsupportedOperationException("Static service");
+        }
+
+        @Override
+        public void removeModule(final Module module) {
+            throw new UnsupportedOperationException("Static service");
+        }
+
+        @Override
+        public SchemaContext getSessionContext() {
+            return schemaContext;
+        }
+
+        @Override
+        public SchemaContext getGlobalContext() {
+            return schemaContext;
+        }
+
+        @Override
+        public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
+                final SchemaContextListener listener) {
+            listener.onGlobalContextUpdated(schemaContext);
+            return new ListenerRegistration<SchemaContextListener>() {
+                @Override
+                public void close() {}
+
+                @Override
+                public SchemaContextListener getInstance() {
+                    return listener;
+                }
+
+            };
+        }
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.java
new file mode 100644 (file)
index 0000000..dbd08a4
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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 io.fd.honeycomb.binding.init.ProviderTrait;
+import javassist.ClassPool;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+
+public class SerializerProvider extends ProviderTrait<BindingToNormalizedNodeCodec> {
+
+    @Inject
+    private ModuleInfoBackedContext mibCtx;
+
+    @Override
+    protected BindingToNormalizedNodeCodec create() {
+        final DataObjectSerializerGenerator serializerGenerator =
+            StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()));
+        BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(serializerGenerator);
+        BindingRuntimeContext ctx = BindingRuntimeContext.create(mibCtx, mibCtx.getSchemaContext());
+        codecRegistry.onBindingRuntimeContextUpdated(ctx);
+        BindingToNormalizedNodeCodec codec = new BindingToNormalizedNodeCodec(mibCtx, codecRegistry);
+        codec.onGlobalContextUpdated(mibCtx.getSchemaContext());
+        return codec;
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.java
new file mode 100644 (file)
index 0000000..d43485f
--- /dev/null
@@ -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.schema;
+
+import com.google.inject.AbstractModule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class YangBindingProviderModule extends AbstractModule {
+    private static final Logger LOG = LoggerFactory.getLogger(YangBindingProviderModule.class);
+
+    @Override
+    protected void configure() {
+        LOG.info("Configuring YangBindingProviderModule");
+        bind(YangModulesProvider.YangModules.class).toProvider(YangModulesProvider.class).asEagerSingleton();
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModuleMappingIndex.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModuleMappingIndex.java
new file mode 100644 (file)
index 0000000..a483cfd
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.collect.ImmutableSet;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Multimap;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Stream;
+import javax.annotation.Nonnull;
+
+/**
+ * Index from guice module to yang module providers
+ */
+class YangModuleMappingIndex implements ResourceLoader {
+
+    private static final String G_MODULE_TOKEN = "GUICE_MODULE:";
+    private static final String KEY_VALUE_SEPARATOR = "|";
+    private static final String Y_MODULE_TOKEN = "YANG_MODULES:";
+    private static final String Y_MODULE_SEPARATOR = ",";
+
+    /**
+     * key - module class name
+     * value  - yang module provider
+     */
+    private final Multimap<String, String> index;
+
+    YangModuleMappingIndex(final String indexPath) {
+        this.index = LinkedListMultimap.create();
+        loadResourceContentsOnPath(indexPath)
+                .forEach(line -> {
+                    final String moduleName = parseModuleName(line);
+                    parseYangModules(line).forEach(yModuleProvider -> index.put(moduleName, yModuleProvider));
+                });
+    }
+
+    Set<String> getByModuleName(@Nonnull final String moduleName) {
+        return ImmutableSet.copyOf(index.get(moduleName));
+    }
+
+    int applicationModulesCount() {
+        return index.keySet().size();
+    }
+
+    private static String parseModuleName(final String rawLine) {
+        return rawLine.substring(rawLine.indexOf(G_MODULE_TOKEN) + G_MODULE_TOKEN.length(),
+                rawLine.indexOf(KEY_VALUE_SEPARATOR));
+    }
+
+    private static Stream<String> parseYangModules(final String rawLine) {
+        return Arrays.stream(rawLine.substring(rawLine.indexOf(Y_MODULE_TOKEN) + Y_MODULE_TOKEN.length())
+                .split(Y_MODULE_SEPARATOR));
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModulesProvider.java b/tests/honeynode/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModulesProvider.java
new file mode 100644 (file)
index 0000000..5acc1ea
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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 com.google.inject.Provider;
+import io.fd.honeycomb.infra.distro.activation.ActivationConfig;
+import io.fd.honeycomb.infra.distro.activation.ActiveModules;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+
+import javax.annotation.Nonnull;
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.lang.String.format;
+
+/**
+ * Loads active yang modules
+ * Relying on generate yang-module-index
+ */
+public class YangModulesProvider implements Provider<YangModulesProvider.YangModules> {
+
+    @Inject
+    private ActiveModules activeModules;
+
+    @Inject
+    private ActivationConfig config;
+
+    @Override
+    public YangModules get() {
+        // no need to bind this, pretty big map and its needed just here
+        final YangModuleMappingIndex index = new YangModuleMappingIndex(config.getYangModulesIndexPath());
+
+        return new YangModules(activeModules.getActiveModulesClasses().stream()
+                .map(Class::getName)
+                .map(index::getByModuleName)
+                .flatMap(Collection::stream)
+                .map(YangModulesProvider::loadClass)
+                .map(aClass -> (Class<? extends YangModelBindingProvider>) aClass)
+                .collect(Collectors.toSet()));
+    }
+
+    static class YangModules {
+        private final Set<Class<? extends YangModelBindingProvider>> yangBindings;
+
+        YangModules(final Set<Class<? extends YangModelBindingProvider>> yangBindings) {
+            this.yangBindings = yangBindings;
+        }
+
+        Set<YangModelBindingProvider> getYangBindings() {
+            return yangBindings.stream()
+                    .map(providerClass -> {
+                        try {
+                            return providerClass.newInstance();
+                        } catch (InstantiationException | IllegalAccessException e) {
+                            throw new IllegalStateException(format("Unable to create instance of %s", providerClass),
+                                    e);
+                        }
+                    }).collect(Collectors.toSet());
+        }
+    }
+
+    private static Class<?> loadClass(@Nonnull final String className) {
+        try {
+            return Class.forName(className);
+        } catch (ClassNotFoundException e) {
+            throw new IllegalArgumentException("Unable to load class: " + className, e);
+        }
+    }
+}
diff --git a/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/cert/honeycomb-keystore b/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/cert/honeycomb-keystore
new file mode 100644 (file)
index 0000000..27a2633
Binary files /dev/null and b/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/cert/honeycomb-keystore differ
diff --git a/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/WEB-INF/web.xml b/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..6cf4871
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+    version="3.0">
+
+    <servlet>
+        <servlet-name>JAXRSRestconf</servlet-name>
+        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+        <init-param>
+            <param-name>javax.ws.rs.Application</param-name>
+            <param-value>org.opendaylight.netconf.sal.rest.impl.RestconfApplication</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>JAXRSRestconf</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+    <filter>
+        <filter-name>cross-origin-restconf</filter-name>
+        <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
+        <init-param>
+            <param-name>allowedOrigins</param-name>
+            <param-value>*</param-value>
+        </init-param>
+        <init-param>
+            <param-name>allowedMethods</param-name>
+            <param-value>GET,POST,OPTIONS,DELETE,PUT,HEAD</param-value>
+        </init-param>
+        <init-param>
+            <param-name>allowedHeaders</param-name>
+            <param-value>origin, content-type, accept, authorization</param-value>
+        </init-param>
+        <init-param>
+            <param-name>exposedHeaders</param-name>
+            <param-value>location</param-value>
+        </init-param>
+    </filter>
+    <filter-mapping>
+        <filter-name>cross-origin-restconf</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</url-pattern>
+            <http-method>POST</http-method>
+            <http-method>GET</http-method>
+            <http-method>PUT</http-method>
+            <http-method>PATCH</http-method>
+            <http-method>DELETE</http-method>
+            <http-method>HEAD</http-method>
+        </web-resource-collection>
+    </security-constraint>
+
+</web-app>
diff --git a/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/activation.json b/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/activation.json
new file mode 100644 (file)
index 0000000..8dd1687
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "modules-resource-path": "../modules/",
+  "yang-modules-index-path": "../yang-mapping/"
+}
\ No newline at end of file
diff --git a/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/honeycomb.json b/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/honeycomb.json
new file mode 100644 (file)
index 0000000..0a1b76c
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "persist-context": "true",
+  "persisted-context-path": "./persist/context/data.json",
+  "persisted-context-restoration-type": "Merge",
+  "persist-config": "true",
+  "persisted-config-path": "./persist/config/data.json",
+  "persisted-config-restoration-type": "Merge",
+  "notification-service-queue-depth": 1,
+  "netconf-initial-config-xml": ""
+}
\ No newline at end of file
diff --git a/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/logback.xml b/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/config/logback.xml
new file mode 100644 (file)
index 0000000..800d761
--- /dev/null
@@ -0,0 +1,32 @@
+ <configuration scan="true">
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+  <appender name="honeycomb.log" class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <file>./log/honeycomb/honeycomb.log</file>
+
+    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+      <fileNamePattern>./log/honeycomb/logs/honeycomb.%d.log.zip</fileNamePattern>
+      <maxHistory>1</maxHistory>
+    </rollingPolicy>
+
+    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+      <maxFileSize>10MB</maxFileSize>
+    </triggeringPolicy>
+
+    <encoder>
+      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="warn">
+    <appender-ref ref="STDOUT" />
+    <appender-ref ref="honeycomb.log" />
+  </root>
+
+  <logger name="org.opendaylight" level="INFO"/>
+  <logger name="io.fd" level="INFO"/>
+</configuration>
diff --git a/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/honeycomb-tpce b/tests/honeynode/minimal-distribution-core/src/main/resources/honeycomb-minimal-resources/honeycomb-tpce
new file mode 100755 (executable)
index 0000000..a70fe6e
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/sh -
+STATUS=100
+
+if [ "$#" -eq 2 ]
+then
+    PORT=$1
+    CONFIG=$2
+    if [ -e $CONFIG ]
+    then
+        rm -rf $(dirname $0)/persist
+        cp $CONFIG $(dirname $0)/config/device/
+        filename=$(basename -- "$CONFIG")
+        echo "changing netconf port with $PORT in netconf.json file ..."
+        sed -i "/netconf-ssh-binding-port/c\  \"netconf-ssh-binding-port\" : "$PORT"," $(dirname $0)/config/netconf.json
+        echo "changing context and config path in honeycomb.json file ..."
+        sed -i "/persisted-context-path/c\  \"persisted-context-path\" : \"./persist/"$PORT"/context/data.json\"," $(dirname $0)/config/honeycomb.json
+        sed -i "/persisted-config-path/c\  \"persisted-config-path\" : \"./persist/"$PORT"/config/data.json\"," $(dirname $0)/config/honeycomb.json
+        echo "changing netconf-initial-config-xml location with $CONFIG in honeycomb.json file ..."
+        sed -i "/netconf-initial-config-xml/c\  \"netconf-initial-config-xml\" : \"device/$filename\"" $(dirname $0)/config/honeycomb.json
+        while [ $STATUS -eq 100 ]
+        do
+          java -Xms32m -Xmn90m -Xmx128m -XX:MetaspaceSize=32m -XX:MaxMetaspaceSize=128m -jar $(dirname $0)/honeynode-distribution-1.18.01.jar
+          STATUS=$?
+          echo "Honeycomb exited with status: $STATUS"
+          if [ $STATUS -eq 100 ]
+          then
+            echo "Restarting..."
+          fi
+        done
+    else
+        echo "initial config file doesn't exist !"
+    fi
+else 
+    echo "honeycomb-tpce port initial-config-xml "
+    echo "Eg : honeycomb-tpce 17830 sample-config-ROADM.xml"
+fi
diff --git a/tests/honeynode/minimal-distribution/asciidoc/Readme.adoc b/tests/honeynode/minimal-distribution/asciidoc/Readme.adoc
new file mode 100644 (file)
index 0000000..1da86ca
--- /dev/null
@@ -0,0 +1,3 @@
+= minimal-distribution
+
+Overview of minimal-distribution
\ No newline at end of file
diff --git a/tests/honeynode/minimal-distribution/pom.xml b/tests/honeynode/minimal-distribution/pom.xml
new file mode 100644 (file)
index 0000000..c382fa0
--- /dev/null
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 Cisco and/or its affiliates.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>io.fd.honeycomb.common</groupId>
+        <artifactId>minimal-distribution-parent</artifactId>
+        <version>1.18.01</version>
+        <relativePath/>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>io.fd.honeycomb.transportpce</groupId>
+    <artifactId>minimal-distribution</artifactId>
+    <name>${project.artifactId}</name>
+    <version>1.18.01</version>
+
+    <properties>
+        <main.class>io.fd.honeycomb.infra.distro.Main</main.class>
+        <distribution.modules>
+            io.fd.honeycomb.infra.distro.schema.YangBindingProviderModule,
+            io.fd.honeycomb.infra.distro.schema.SchemaModule,
+            io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule,
+            io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule,
+            io.fd.honeycomb.infra.distro.initializer.InitializerPipelineModule,
+            io.fd.honeycomb.northbound.CredentialsModule,
+            io.fd.honeycomb.northbound.netconf.NetconfModule,
+            io.fd.honeycomb.northbound.netconf.NetconfReadersModule,
+            //io.fd.honeycomb.northbound.restconf.RestconfModule,
+            io.fd.honeycomb.infra.distro.cfgattrs.CfgAttrsModule,
+            // io.fd.honeycomb.infra.bgp.BgpModule,
+            // io.fd.honeycomb.infra.bgp.BgpReadersModule,
+            // io.fd.honeycomb.infra.bgp.BgpWritersModule,
+            // io.fd.honeycomb.northbound.bgp.extension.EvpnModule,
+            // io.fd.honeycomb.northbound.bgp.extension.InetModule,
+            // io.fd.honeycomb.northbound.bgp.extension.L3VpnV4Module,
+            // io.fd.honeycomb.northbound.bgp.extension.L3VpnV6Module,
+            // io.fd.honeycomb.northbound.bgp.extension.LabeledUnicastModule,
+            // io.fd.honeycomb.northbound.bgp.extension.LinkstateModule,
+            // io.fd.honeycomb.footprint.FootprintModule
+        </distribution.modules>
+    </properties>
+
+    <dependencies>
+        <!-- DI-->
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+        </dependency>
+
+        <!-- TPCE Distribution core -->
+        <dependency>
+            <groupId>io.fd.honeycomb.transportpce</groupId>
+            <artifactId>minimal-distribution-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb.transportpce</groupId>
+            <artifactId>restconf</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb.transportpce</groupId>
+            <artifactId>netconf</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Northbound interfaces -->
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound</groupId>
+            <artifactId>common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- <dependency>
+            <groupId>io.fd.honeycomb.northbound</groupId>
+            <artifactId>restconf</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound</groupId>
+            <artifactId>netconf</artifactId>
+            <version>${project.version}</version>
+        </dependency>-->
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound</groupId>
+            <artifactId>bgp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Bgp extension modules -->
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound.bgp</groupId>
+            <artifactId>extension-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound.bgp</groupId>
+            <artifactId>evpn</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound.bgp</groupId>
+            <artifactId>inet</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound.bgp</groupId>
+            <artifactId>l3-vpn-v4</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound.bgp</groupId>
+            <artifactId>l3-vpn-v6</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound.bgp</groupId>
+            <artifactId>linkstate</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound.bgp</groupId>
+            <artifactId>labeled-unicast</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Footprint api -->
+        <dependency>
+            <groupId>io.fd.honeycomb.footprint</groupId>
+            <artifactId>impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/tests/honeynode/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/Main.java b/tests/honeynode/minimal-distribution/src/main/java/io/fd/honeycomb/infra/distro/Main.java
new file mode 100644 (file)
index 0000000..5082604
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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 static com.google.inject.Guice.createInjector;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.ConfigurationException;
+import com.google.inject.CreationException;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.ProvisionException;
+import com.google.inject.name.Names;
+
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.data.init.InitializerRegistry;
+import io.fd.honeycomb.infra.distro.activation.ActivationModule;
+import io.fd.honeycomb.infra.distro.activation.ActiveModules;
+import io.fd.honeycomb.infra.distro.initializer.InitializerPipelineModule;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class Main {
+
+    private static final Logger LOG = LoggerFactory.getLogger(Main.class);
+
+    private Main() {
+    }
+
+    public static void main(String[] args) {
+        init(new ActivationModule());
+    }
+
+    /**
+     * Initialize the Honeycomb with provided modules
+     */
+    public static Injector init(final ActivationModule activationModule) {
+        try {
+            LOG.info("Starting honeycomb");
+            // creating child injector does not work in this case, so just create injector, and does not store ref
+            // to it, or its active modules instance
+            Injector injector = createInjector(ImmutableSet.<Module>builder()
+                    .add(activationModule)
+                    .addAll(createInjector(activationModule).getInstance(ActiveModules.class).createModuleInstances())
+                    .build());
+
+            // Log all bindings
+            injector.getAllBindings().entrySet().stream()
+                    .forEach(e -> LOG.trace("Component available under: {} is {}", e.getKey(), e.getValue()));
+
+            try {
+                LOG.info("Initializing configuration");
+                injector.getInstance(Key.get(InitializerRegistry.class,
+                        Names.named(InitializerPipelineModule.HONEYCOMB_INITIALIZER))).initialize();
+                LOG.info("Configuration initialized successfully");
+            } catch (DataTreeInitializer.InitializeException e) {
+                LOG.error("Unable to initialize configuration", e);
+            }
+
+
+            LOG.info("Honeycomb started successfully!");
+            return injector;
+        } catch (CreationException | ProvisionException | ConfigurationException e) {
+            LOG.error("Failed to initialize Honeycomb components", e);
+            throw e;
+        } catch (RuntimeException e) {
+            LOG.error("Unexpected initialization failure", e);
+            throw e;
+        } finally {
+            // Trigger gc to force collect initial garbage + dedicated classloader
+            System.gc();
+        }
+    }
+
+}
diff --git a/tests/honeynode/netconf/asciidoc/Readme.adoc b/tests/honeynode/netconf/asciidoc/Readme.adoc
new file mode 100644 (file)
index 0000000..525b0b4
--- /dev/null
@@ -0,0 +1,3 @@
+= netconf
+
+Provides binding support to start NETCONF SSH/TCP
\ No newline at end of file
diff --git a/tests/honeynode/netconf/pom.xml b/tests/honeynode/netconf/pom.xml
new file mode 100644 (file)
index 0000000..f8924ed
--- /dev/null
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright (c) 2017 Cisco and/or its affiliates.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at:
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>impl-parent</artifactId>
+        <groupId>io.fd.honeycomb.common</groupId>
+        <version>1.18.01</version>
+        <relativePath/>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>io.fd.honeycomb.transportpce</groupId>
+    <artifactId>netconf</artifactId>
+    <version>1.18.01</version>
+
+    <properties>
+        <yang.modules.whitelist>
+            ${project.basedir}/src/main/resources/honeycomb-minimal-resources/config/netconf-whitelist.xml
+        </yang.modules.whitelist>
+    </properties>
+
+    <dependencies>
+        <!-- TPCE dependencies  -->
+        <dependency>
+            <groupId>io.fd.honeycomb.transportpce</groupId>
+            <artifactId>honeynode-plugin-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb.transportpce</groupId>
+            <artifactId>minimal-distribution-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- DI-->
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.jmob</groupId>
+            <artifactId>guice.conf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject.extensions</groupId>
+            <artifactId>guice-multibindings</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>binding-init</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- Northbound -->
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound</groupId>
+            <artifactId>common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- ODL-Netconf -->
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>netconf-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>netconf-ssh</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>mdsal-netconf-notification</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>mdsal-netconf-monitoring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>mdsal-netconf-connector</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>ietf-netconf-monitoring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>ietf-netconf-monitoring-extension</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>data-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>honeycomb-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>notification-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/HoneycombNotification2NetconfProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/HoneycombNotification2NetconfProvider.java
new file mode 100644 (file)
index 0000000..26ecf3a
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.fd.honeycomb.notification.NotificationCollector;
+import io.fd.honeycomb.notification.impl.NotificationProducerRegistry;
+import io.fd.honeycomb.notification.impl.TranslationUtil;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
+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.netconf.notifications.NotificationPublisherRegistration;
+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.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class HoneycombNotification2NetconfProvider
+        extends ProviderTrait<HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HoneycombNotification2NetconfProvider.class);
+
+    @Inject
+    private DOMNotificationRouter notificationRouter;
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    private NetconfConfiguration cfgAttributes;
+    @Inject
+    private NotificationCollector hcNotificationCollector;
+    @Inject
+    private NetconfNotificationCollector netconfNotificationCollector;
+
+    @Override
+    protected HoneycombNotification2Netconf create() {
+        final StreamNameType streamType = new StreamNameType(cfgAttributes.netconfNotificationStreamName.get());
+
+        // Register as HONEYCOMB_NETCONF notification publisher under configured name
+        final NotificationPublisherRegistration netconfNotifReg = netconfNotificationCollector
+                .registerNotificationPublisher(new StreamBuilder().setName(streamType).setReplaySupport(false)
+                        .setDescription(cfgAttributes.netconfNotificationStreamName.get()).build());
+
+        // Notification Translator, get notification from HC producers and put into HONEYCOMB_NETCONF notification collector
+        final DOMNotificationListener domNotificationListener =
+                new TranslatingNotificationListener(netconfNotifReg, streamType, schemaService);
+
+        // NotificationManager is used to provide list of available notifications (which are all of the notifications registered)
+        // TODO HONEYCOMB-165 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 HONEYCOMB_NETCONF: {}",
+                hcNotificationCollector.getNotificationTypes());
+        List<SchemaPath> currentNotificationSchemaPaths = hcNotificationCollector.getNotificationTypes().stream()
+                .map(notifType -> SchemaPath.create(true, NotificationProducerRegistry.getQName(notifType)))
+                .collect(Collectors.toList());
+
+        // Register as listener to HC'OPERATIONAL DOM notification service
+        // TODO HONEYCOMB-166 This should only be triggered when HONEYCOMB_NETCONF notifications are activated
+        // Because this way we actually start all notification producers
+        // final Collection<QName> notificationQNames =
+        ListenerRegistration<DOMNotificationListener> domNotifListenerReg = notificationRouter
+                .registerNotificationListener(domNotificationListener, currentNotificationSchemaPaths);
+
+        LOG.info("Exposing HONEYCOMB_NETCONF notification stream: {}", streamType.getValue());
+        return new HoneycombNotification2Netconf(domNotifListenerReg, netconfNotifReg);
+    }
+
+    public static final class HoneycombNotification2Netconf {
+        private final ListenerRegistration<DOMNotificationListener> domNotifListenerReg;
+        private final NotificationPublisherRegistration netconfNotifReg;
+
+        public HoneycombNotification2Netconf(final ListenerRegistration<DOMNotificationListener> domNotifListenerReg,
+                                             final NotificationPublisherRegistration netconfNotifReg) {
+            this.domNotifListenerReg = domNotifListenerReg;
+            this.netconfNotifReg = netconfNotifReg;
+        }
+
+        public ListenerRegistration<DOMNotificationListener> getDomNotifListenerReg() {
+            return domNotifListenerReg;
+        }
+
+        public NotificationPublisherRegistration getNetconfNotifReg() {
+            return netconfNotifReg;
+        }
+    }
+
+    private static final class TranslatingNotificationListener implements DOMNotificationListener {
+
+        private static final Logger LOG = LoggerFactory.getLogger(TranslatingNotificationListener.class);
+
+        private final NotificationPublisherRegistration netconfNotifReg;
+        private final StreamNameType streamType;
+        private final SchemaService schemaService;
+
+        TranslatingNotificationListener(final NotificationPublisherRegistration netconfNotifReg,
+                                               final StreamNameType streamType, final SchemaService schemaService) {
+            this.netconfNotifReg = netconfNotifReg;
+            this.streamType = streamType;
+            this.schemaService = schemaService;
+        }
+
+        @Override
+        public void onNotification(@Nonnull final DOMNotification notif) {
+            LOG.debug("Propagating notification: {} into HONEYCOMB_NETCONF", notif.getType());
+            netconfNotifReg.onNotification(streamType, TranslationUtil.notificationToXml(notif, schemaService.getGlobalContext()));
+        }
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfBindingBrokerProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfBindingBrokerProvider.java
new file mode 100644 (file)
index 0000000..bafd4ea
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.impl.FakeBindingAwareBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+
+public final class NetconfBindingBrokerProvider extends ProviderTrait<BindingAwareBroker> {
+
+    @Inject
+    @Named(NetconfModule.HONEYCOMB_NETCONF)
+    private DataBroker dataBroker;
+
+    @Override
+    protected FakeBindingAwareBroker create() {
+        return new FakeBindingAwareBroker(dataBroker);
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfConfigurationModule.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfConfigurationModule.java
new file mode 100644 (file)
index 0000000..aba254b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 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.northbound.netconf;
+
+import com.google.inject.AbstractModule;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+public class NetconfConfigurationModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        install(ConfigurationModule.create());
+        requireBinding(NetconfConfiguration.class);
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMdsalMapperProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMdsalMapperProvider.java
new file mode 100644 (file)
index 0000000..cd2867f
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.binding.init.ProviderTrait;
+
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener;
+import org.opendaylight.netconf.mdsal.connector.MdsalNetconfOperationServiceFactory;
+
+public final class NetconfMdsalMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> {
+
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    private NetconfOperationServiceFactoryListener aggregator;
+    @Inject
+    private ModuleInfoBackedContext moduleInfoBackedContext;
+    @Inject
+//    @Named(HONEYCOMB_CONFIG)
+    //Modified in order to connect TPCE to device config datastore
+    @Named("device-databroker")
+    private DOMDataBroker domBroker;
+    @Inject
+    private NetconfOperationServiceFactoryListener netconfOperationServiceFactoryListener;
+    @Inject
+    private DOMRpcService rpcService;
+
+    @Override
+    protected MdsalNetconfOperationServiceFactory create() {
+        MdsalNetconfOperationServiceFactory mdsalNetconfOperationServiceFactory =
+                new MdsalNetconfOperationServiceFactory(schemaService, moduleInfoBackedContext, netconfOperationServiceFactoryListener, domBroker, rpcService);
+        return mdsalNetconfOperationServiceFactory;
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfModule.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfModule.java
new file mode 100644 (file)
index 0000000..5b522af
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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.northbound.netconf;
+
+import com.google.inject.Singleton;
+import com.google.inject.binder.AnnotatedElementBuilder;
+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.northbound.NetconfConfiguration;
+import io.fd.honeycomb.northbound.NorthboundPrivateModule;
+import io.fd.honeycomb.notification.NotificationCollector;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfModule extends NorthboundPrivateModule<NetconfConfiguration> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfModule.class);
+
+    public static final String HONEYCOMB_NETCONF = "honeycomb-netconf";
+    public static final String HONEYCOMB_NETCONF_MAPPER_AGGR = "netconf-mapper-aggregator";
+    public static final String HONEYCOMB_NETCONF_MAPPER_NOTIF = "netconf-mapper-notification";
+    public static final String HONEYCOMB_NETCONF_MAPPER_CORE = "netconf-mapper-honeycomb";
+    public static final String HONEYCOMB_NETCONF_MAPPER_OPER = "netconf-mapper-monitoring";
+
+    public NetconfModule() {
+        super(new NetconfConfigurationModule(), NetconfConfiguration.class);
+    }
+
+    @Override
+    protected void configure() {
+        if (!getConfiguration().isNetconfEnabled()) {
+            LOG.debug("Netconf disabled, skipping initialization");
+            return;
+        }
+        install(getConfigurationModule());
+        LOG.info("Starting NETCONF Northbound");
+        // Create inmemory data store for HONEYCOMB_NETCONF config metadata
+        bind(InMemoryDOMDataStore.class).annotatedWith(Names.named(InmemoryDOMDataBrokerProvider.CONFIG))
+                .toProvider(
+                        new DataStoreProvider(InmemoryDOMDataBrokerProvider.CONFIG, LogicalDatastoreType.CONFIGURATION))
+                .in(Singleton.class);
+
+        // Create inmemory data store for HONEYCOMB_NETCONF operational metadata
+        bind(InMemoryDOMDataStore.class).annotatedWith(Names.named(InmemoryDOMDataBrokerProvider.OPERATIONAL))
+                .toProvider(new DataStoreProvider(InmemoryDOMDataBrokerProvider.OPERATIONAL,
+                        LogicalDatastoreType.OPERATIONAL))
+                .in(Singleton.class);
+        // Wrap datastores as DOMDataBroker
+        bind(DOMDataBroker.class).toProvider(InmemoryDOMDataBrokerProvider.class).in(Singleton.class);
+
+        // Wrap DOMDataBroker as BA data broker
+        bind(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_NETCONF)).toProvider(BindingDataBrokerProvider.class)
+                .in(Singleton.class);
+        expose(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_NETCONF));
+
+        // Wrap BA data broker as BindingAwareBroker (requied by HONEYCOMB_NETCONF)
+        bind(BindingAwareBroker.class).annotatedWith(Names.named(HONEYCOMB_NETCONF))
+                .toProvider(NetconfBindingBrokerProvider.class).in(Singleton.class);
+
+        // Create netconf operation service factory aggregator to aggregate different services
+        AggregatedNetconfOperationServiceFactory factory = new AggregatedNetconfOperationServiceFactory();
+        bind(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_AGGR))
+                .toInstance(factory);
+        bind(NetconfOperationServiceFactoryListener.class).toInstance(factory);
+
+        // Create netconf notification manager
+        NetconfNotificationManager manager = new NetconfNotificationManager();
+        bind(NetconfNotificationCollector.class).toInstance(manager);
+        bind(NetconfNotificationRegistry.class).toInstance(manager);
+        bind(NetconfNotificationListener.class).toInstance(manager);
+
+        // Netconf notification service factory
+        bind(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_NOTIF))
+                .toProvider(NetconfNotificationMapperProvider.class).asEagerSingleton();
+        expose(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_NOTIF));
+
+        // Netconf core part - mapping between Honeycomb and Netconf
+        bind(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_CORE))
+                .toProvider(NetconfMdsalMapperProvider.class).asEagerSingleton();
+        expose(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_CORE));
+
+        // Netconf monitoring service factory
+        bind(NetconfMonitoringService.class).toProvider(NetconfMonitoringServiceProvider.class).in(Singleton.class);
+        bind(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_OPER))
+                .toProvider(NetconfMonitoringMapperProvider.class).asEagerSingleton();
+        expose(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_OPER));
+
+        // Create HC notification manager + HC2Netconf translator
+        bind(NotificationCollector.class).toProvider(HoneycombNotificationManagerProvider.class).in(Singleton.class);
+        bind(HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf.class)
+                .toProvider(HoneycombNotification2NetconfProvider.class).asEagerSingleton();
+        expose(HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf.class);
+
+        configureServer();
+    }
+
+    /**
+     * Provide HONEYCOMB_NETCONF TCP and SSH servers.
+     */
+    private AnnotatedElementBuilder configureServer() {
+        bind(NioEventLoopGroup.class).toProvider(NettyThreadGroupProvider.class).in(Singleton.class);
+        bind(Timer.class).toInstance(new HashedWheelTimer());
+        bind(NetconfServerDispatcher.class).toProvider(NetconfServerDispatcherProvider.class).in(Singleton.class);
+        bind(NetconfTcpServerProvider.NetconfTcpServer.class).toProvider(NetconfTcpServerProvider.class)
+                .asEagerSingleton();
+        expose(NetconfTcpServerProvider.NetconfTcpServer.class);
+        bind(NetconfSshServerProvider.NetconfSshServer.class).toProvider(NetconfSshServerProvider.class)
+                .asEagerSingleton();
+        return expose(NetconfSshServerProvider.NetconfSshServer.class);
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringMapperProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringMapperProvider.java
new file mode 100644 (file)
index 0000000..e7b5edb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.MdsalMonitoringMapperFactory;
+import org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.MonitoringToMdsalWriter;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class NetconfMonitoringMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfMonitoringMapperProvider.class);
+
+    @Inject
+    @Named(NetconfModule.HONEYCOMB_NETCONF)
+    private DataBroker dataBroker;
+    @Inject
+    private NetconfOperationServiceFactoryListener aggregator;
+    @Inject
+    private NetconfMonitoringService monitoringService;
+
+    @Override
+    protected NetconfOperationServiceFactory create() {
+        LOG.trace("Initializing MonitoringToMdsalWriter");
+        final MonitoringToMdsalWriter writer = new MonitoringToMdsalWriter(monitoringService, dataBroker);
+        writer.start();
+
+        LOG.trace("Providing MdsalMonitoringMapperFactory");
+        return new MdsalMonitoringMapperFactory(aggregator, monitoringService, writer);
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringReaderFactoryProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringReaderFactoryProvider.java
new file mode 100644 (file)
index 0000000..50e0e8a
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.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.yang.ietf.netconf.monitoring.rev101004.NetconfState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfStateBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+
+public final class NetconfMonitoringReaderFactoryProvider extends ProviderTrait<ReaderFactory> {
+
+    @Inject
+    @Named(NetconfModule.HONEYCOMB_NETCONF)
+    private DataBroker netconfDataBroker;
+
+    @Override
+    protected NetconfMonitoringReaderFactory create() {
+        return new NetconfMonitoringReaderFactory(netconfDataBroker);
+    }
+
+    /**
+     * {@link io.fd.honeycomb.translate.read.ReaderFactory} initiating reader into NETCONF's dedicated data store.
+     * Making NETCONF operational data available over NETCONF/RESTCONF
+     */
+    private static final class NetconfMonitoringReaderFactory implements ReaderFactory {
+
+        private final DataBroker netconfMonitoringBindingBrokerDependency;
+
+        NetconfMonitoringReaderFactory(final DataBroker netconfMonitoringBindingBrokerDependency) {
+            this.netconfMonitoringBindingBrokerDependency = netconfMonitoringBindingBrokerDependency;
+        }
+
+        @Override
+        public void init(final ModifiableReaderRegistryBuilder registry) {
+            registry.add(new BindingBrokerReader<>(InstanceIdentifier.create(NetconfState.class),
+                    netconfMonitoringBindingBrokerDependency,
+                    LogicalDatastoreType.OPERATIONAL, NetconfStateBuilder.class));
+        }
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringServiceProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringServiceProvider.java
new file mode 100644 (file)
index 0000000..1a99dd1
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.netconf.impl.osgi.NetconfMonitoringServiceImpl;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+
+
+public class NetconfMonitoringServiceProvider extends ProviderTrait<NetconfMonitoringService> {
+
+    @Inject
+    @Named(NetconfModule.HONEYCOMB_NETCONF_MAPPER_AGGR)
+    private NetconfOperationServiceFactory aggregator;
+
+    @Override
+    protected NetconfMonitoringServiceImpl create() {
+        return new NetconfMonitoringServiceImpl(aggregator);
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationMapperProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationMapperProvider.java
new file mode 100644 (file)
index 0000000..e402f04
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.init.ShutdownHandler;
+import org.opendaylight.controller.config.yang.netconf.mdsal.notification.CapabilityChangeNotificationProducer;
+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.binding.api.DataTreeChangeListener;
+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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NetconfNotificationMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfNotificationMapperProvider.class);
+
+    public static final InstanceIdentifier<Capabilities> capabilitiesIdentifier =
+            InstanceIdentifier.create(NetconfState.class).child(Capabilities.class).builder().build();
+    @Inject
+    private NetconfNotificationCollector notificationCollector;
+    @Inject
+    private NetconfNotificationRegistry notificationRegistry;
+    @Inject
+    @Named(NetconfModule.HONEYCOMB_NETCONF)
+    private BindingAwareBroker bindingAwareBroker;
+    @Inject
+    @Named(NetconfModule.HONEYCOMB_NETCONF)
+    private DataBroker dataBroker;
+    @Inject
+    private NetconfOperationServiceFactoryListener aggregator;
+    @Inject
+    private ShutdownHandler shutdownHandler;
+
+    @Override
+    protected NetconfNotificationOperationServiceFactory create() {
+        LOG.trace("Initializing NotificationToMdsalWriter");
+        final NotificationToMdsalWriter writer = new NotificationToMdsalWriter(notificationCollector, dataBroker);
+        writer.start();
+
+        LOG.trace("Initializing CapabilityChangeNotificationProducer");
+        final DataTreeChangeListener<Capabilities> publisher =
+            new CapabilityChangeNotificationProducer(notificationCollector, dataBroker);
+
+        LOG.trace("Providing NetconfNotificationOperationServiceFactory");
+        NetconfNotificationOperationServiceFactory netconfNotificationOperationServiceFactory =
+            new NetconfNotificationOperationServiceFactory(notificationRegistry, aggregator);
+
+        shutdownHandler.register("netconf-notification-service-factory", netconfNotificationOperationServiceFactory);
+        shutdownHandler.register("notification-to-mdsal-writer", writer);
+        return netconfNotificationOperationServiceFactory;
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationsReaderFactoryProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationsReaderFactoryProvider.java
new file mode 100644 (file)
index 0000000..4ed682f
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.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 javax.annotation.Nonnull;
+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;
+
+public final class NetconfNotificationsReaderFactoryProvider extends ProviderTrait<ReaderFactory> {
+
+    @Inject
+    @Named(NetconfModule.HONEYCOMB_NETCONF)
+    private DataBroker netconfDataBroker;
+
+    @Override
+    protected ReaderFactory create() {
+        return new NotificationReaderFactory(netconfDataBroker);
+    }
+
+    private static final class NotificationReaderFactory implements ReaderFactory {
+        private final DataBroker netconfDataBroker;
+
+        NotificationReaderFactory(final DataBroker netconfDataBroker) {
+            this.netconfDataBroker = netconfDataBroker;
+        }
+
+        @Override
+        public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+            registry.add(new BindingBrokerReader<>(InstanceIdentifier.create(Netconf.class), netconfDataBroker,
+                    LogicalDatastoreType.OPERATIONAL, NetconfBuilder.class));
+        }
+
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfReadersModule.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfReadersModule.java
new file mode 100644 (file)
index 0000000..377ce6e
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.fd.honeycomb.northbound.NorthboundAbstractModule;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfReadersModule extends NorthboundAbstractModule<NetconfConfiguration> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfReadersModule.class);
+
+    public NetconfReadersModule() {
+        super(new NetconfConfigurationModule(), NetconfConfiguration.class);
+    }
+
+    @Override
+    protected void configure() {
+        if (!getConfiguration().isNetconfEnabled()) {
+            LOG.debug("NETCONF Northbound disabled, skipping readers initialization");
+            return;
+        }
+        LOG.info("Initializing NETCONF Northbound readers");
+        // 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
+        // https://github.com/google/guice/issues/906
+        final Multibinder<ReaderFactory> binder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
+        binder.addBinding().toProvider(NetconfMonitoringReaderFactoryProvider.class).in(Singleton.class);
+        binder.addBinding().toProvider(NetconfNotificationsReaderFactoryProvider.class).in(Singleton.class);
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfServerDispatcherProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfServerDispatcherProvider.java
new file mode 100644 (file)
index 0000000..b6c22bf
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.Timer;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.netconf.api.NetconfServerDispatcher;
+import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.netconf.impl.NetconfServerDispatcherImpl;
+import org.opendaylight.netconf.impl.SessionIdProvider;
+import org.opendaylight.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+
+public final class NetconfServerDispatcherProvider extends ProviderTrait<NetconfServerDispatcher> {
+    private static final long CONNECTION_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20);
+
+    @Inject
+    @Named(NetconfModule.HONEYCOMB_NETCONF_MAPPER_AGGR)
+    private NetconfOperationServiceFactory aggregator;
+    @Inject
+    private NetconfMonitoringService monitoringService;
+    @Inject
+    private Timer timer;
+    @Inject
+    private NioEventLoopGroup nettyThreadgroup;
+
+    @Override
+    protected NetconfServerDispatcherImpl create() {
+        AggregatedNetconfOperationServiceFactory netconfOperationProvider =
+                new AggregatedNetconfOperationServiceFactory();
+        netconfOperationProvider.onAddNetconfOperationServiceFactory(aggregator);
+
+        NetconfServerSessionNegotiatorFactory serverNegotiatorFactory =
+                new NetconfServerSessionNegotiatorFactory(timer, netconfOperationProvider, new SessionIdProvider(),
+                        CONNECTION_TIMEOUT_MILLIS, monitoringService);
+        NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer =
+                new NetconfServerDispatcherImpl.ServerChannelInitializer(serverNegotiatorFactory);
+
+        return new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
+    }
+
+    private static final class NetconfServerSessionNegotiatorFactory extends
+            org.opendaylight.netconf.impl.NetconfServerSessionNegotiatorFactory {
+
+        NetconfServerSessionNegotiatorFactory(final Timer timer,
+                                                     final AggregatedNetconfOperationServiceFactory netconfOperationProvider,
+                                                     final SessionIdProvider sessionIdProvider,
+                                                     final long connectionTimeoutMillis,
+                                                     final NetconfMonitoringService monitoringService) {
+            super(timer, netconfOperationProvider, sessionIdProvider, connectionTimeoutMillis, monitoringService,
+                    org.opendaylight.netconf.impl.NetconfServerSessionNegotiatorFactory.DEFAULT_BASE_CAPABILITIES);
+        }
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfSshServerProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfSshServerProvider.java
new file mode 100644 (file)
index 0000000..02847d7
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017 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.northbound.netconf;
+
+import com.google.common.net.InetAddresses;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.infra.distro.InitializationException;
+import io.fd.honeycomb.northbound.CredentialsConfiguration;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+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 java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
+import org.opendaylight.netconf.api.NetconfServerDispatcher;
+import org.opendaylight.netconf.auth.AuthProvider;
+import org.opendaylight.netconf.ssh.SshProxyServer;
+import org.opendaylight.netconf.ssh.SshProxyServerConfigurationBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public final class NetconfSshServerProvider extends ProviderTrait<NetconfSshServerProvider.NetconfSshServer> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfSshServerProvider.class);
+
+    // Use RSA for ssh server, see https://git.opendaylight.org/gerrit/#/c/60138/
+    private static final String DEFAULT_PRIVATE_KEY_PATH = null; // disable private key serialization
+    private static final String DEFAULT_ALGORITHM = "RSA";
+    private static final int DEFAULT_KEY_SIZE = 4096;
+
+    @Inject
+    private NetconfServerDispatcher dispatcher;
+    @Inject
+    private NetconfConfiguration cfgAttributes;
+    @Inject
+    private NioEventLoopGroup nettyThreadgroup;
+    @Inject
+    private CredentialsConfiguration credentialsCfg;
+
+    private ScheduledExecutorService pool =
+            Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNameFormat("netconf-ssh-%d").build());
+
+    @Override
+    protected NetconfSshServer create() {
+        if (!cfgAttributes.isNetconfSshEnabled()) {
+            LOG.info("NETCONF SSH disabled, skipping initialization");
+            return null;
+        }
+        LOG.info("Starting NETCONF SSH");
+
+        // TODO(HONEYCOMB-414):  the logic below is very similar to
+        // org.opendaylight.netconf.ssh.NetconfNorthboundSshServer (introduced in Carbon), so consider reusing it
+        // (requires fixing hardcoded private key path).
+        final InetAddress sshBindingAddress = InetAddresses.forString(cfgAttributes.netconfSshBindingAddress.get());
+        final InetSocketAddress bindingAddress =
+                new InetSocketAddress(sshBindingAddress, cfgAttributes.netconfSshBindingPort.get());
+
+        LocalAddress localAddress = new LocalAddress(cfgAttributes.netconfSshBindingPort.toString());
+        ChannelFuture localServer = dispatcher.createLocalServer(localAddress);
+
+        final SshProxyServer sshProxyServer = new SshProxyServer(pool, nettyThreadgroup, GlobalEventExecutor.INSTANCE);
+
+        final SshProxyServerConfigurationBuilder sshConfigBuilder = new SshProxyServerConfigurationBuilder();
+        sshConfigBuilder.setBindingAddress(bindingAddress);
+        sshConfigBuilder.setLocalAddress(localAddress);
+        // Only simple authProvider checking ConfigAttributes, checking the config file
+        sshConfigBuilder.setAuthenticator(new SimplelAuthProvider(credentialsCfg));
+        sshConfigBuilder.setIdleTimeout(Integer.MAX_VALUE);
+        sshConfigBuilder.setKeyPairProvider(new PEMGeneratorHostKeyProvider(DEFAULT_PRIVATE_KEY_PATH,
+            DEFAULT_ALGORITHM, DEFAULT_KEY_SIZE));
+
+        localServer.addListener(new SshServerBinder(sshProxyServer, sshConfigBuilder, bindingAddress));
+
+        return new NetconfSshServer(localServer, sshProxyServer);
+    }
+
+    public static final class NetconfSshServer {
+        private ChannelFuture localServer;
+        private SshProxyServer sshProxyServer;
+
+        NetconfSshServer(final ChannelFuture localServer,
+                         final SshProxyServer sshProxyServer) {
+            this.localServer = localServer;
+            this.sshProxyServer = sshProxyServer;
+        }
+
+        public Object getLocalServer() {
+            return localServer;
+        }
+
+        public Object getSshProxyServer() {
+            return sshProxyServer;
+        }
+    }
+
+    private static final class SimplelAuthProvider implements AuthProvider {
+
+        private final CredentialsConfiguration cfgAttributes;
+
+        SimplelAuthProvider(final CredentialsConfiguration cfgAttributes) {
+            this.cfgAttributes = cfgAttributes;
+        }
+
+        @Override
+        public boolean authenticated(final String uname, final String passwd) {
+            return cfgAttributes.username.equals(uname) && cfgAttributes.password.equals(passwd);
+        }
+    }
+
+    private static final class SshServerBinder implements GenericFutureListener<ChannelFuture> {
+        private final SshProxyServer sshProxyServer;
+        private final SshProxyServerConfigurationBuilder sshConfigBuilder;
+        private final InetSocketAddress bindingAddress;
+
+        SshServerBinder(final SshProxyServer sshProxyServer,
+                        final SshProxyServerConfigurationBuilder sshConfigBuilder,
+                        final InetSocketAddress bindingAddress) {
+            this.sshProxyServer = sshProxyServer;
+            this.sshConfigBuilder = sshConfigBuilder;
+            this.bindingAddress = bindingAddress;
+        }
+
+        @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 InitializationException("Unable to start SSH netconf server", e);
+                }
+
+            } else {
+                LOG.warn("Unable to start SSH netconf server at {}", bindingAddress, future.cause());
+                throw new InitializationException("Unable to start SSH netconf server", future.cause());
+            }
+
+        }
+
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfTcpServerProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfTcpServerProvider.java
new file mode 100644 (file)
index 0000000..031f0f9
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.northbound.netconf;
+
+import com.google.common.net.InetAddresses;
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.infra.distro.InitializationException;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.netty.channel.ChannelFuture;
+import io.netty.util.concurrent.GenericFutureListener;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import org.opendaylight.netconf.api.NetconfServerDispatcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class NetconfTcpServerProvider extends ProviderTrait<NetconfTcpServerProvider.NetconfTcpServer> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfTcpServerProvider.class);
+
+    @Inject
+    private NetconfServerDispatcher dispatcher;
+    @Inject
+    private NetconfConfiguration cfgAttributes;
+
+    @Override
+    protected NetconfTcpServer create() {
+        if (!cfgAttributes.isNetconfTcpEnabled()) {
+            LOG.debug("NETCONF TCP disabled, skipping initalization");
+            return null;
+        }
+        LOG.info("Starting NETCONF TCP");
+        final InetAddress name = InetAddresses.forString(cfgAttributes.netconfTcpBindingAddress.get());
+        final InetSocketAddress unresolved = new InetSocketAddress(name, cfgAttributes.netconfTcpBindingPort.get());
+
+        ChannelFuture tcpServer = dispatcher.createServer(unresolved);
+        tcpServer.addListener(new TcpLoggingListener(unresolved));
+        return new NetconfTcpServer(tcpServer);
+    }
+
+    public static final class NetconfTcpServer {
+        private Object tcpServer;
+
+        NetconfTcpServer(final ChannelFuture tcpServer) {
+            this.tcpServer = tcpServer;
+        }
+
+        public Object getTcpServer() {
+            return tcpServer;
+        }
+    }
+
+    private static final class TcpLoggingListener implements GenericFutureListener<ChannelFuture> {
+        private final InetSocketAddress unresolved;
+
+        TcpLoggingListener(final InetSocketAddress unresolved) {
+            this.unresolved = unresolved;
+        }
+
+        @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 InitializationException("Unable to start TCP netconf server", future.cause());
+            }
+        }
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NettyThreadGroupProvider.java b/tests/honeynode/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NettyThreadGroupProvider.java
new file mode 100644 (file)
index 0000000..b36a31d
--- /dev/null
@@ -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.northbound.netconf;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.netty.channel.nio.NioEventLoopGroup;
+
+public final class NettyThreadGroupProvider extends ProviderTrait<NioEventLoopGroup> {
+
+    @Inject
+    private NetconfConfiguration cfgAttributes;
+
+    @Override
+    protected NioEventLoopGroup create() {
+        return new NioEventLoopGroup(cfgAttributes.netconfNettyThreads,
+                new ThreadFactoryBuilder().setNameFormat("netconf-netty-%d").build());
+    }
+}
diff --git a/tests/honeynode/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf-whitelist.xml b/tests/honeynode/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf-whitelist.xml
new file mode 100644 (file)
index 0000000..371ee2b
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<yangModuleWhitelist>
+    <modules>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715</package>
+            <description>
+                This module contains a collection of generally useful derived
+                YANG data types for Internet addresses and related things.
+
+                Dependency for network-topology,ietf-netconf-notifications,network-topology
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160621</package>
+            <description>
+                This module contains monitoring information about the YANG
+                modules and submodules that are used within a YANG-based
+                server.
+
+                Required for mounting of netconf devices(Operational read does not work without it)
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601</package>
+            <description>
+                NETCONF Protocol Data Types and Protocol Operations.
+
+                Dependency of ietf-netconf-notifications
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206
+            </package>
+            <description>
+                This module defines a YANG data model for use with the
+                NETCONF protocol that allows the NETCONF client to
+                receive common NETCONF base event notifications.
+
+                Directly used for netconf notification binding
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712</package>
+            <description>
+                Required for mounting of netconf devices(Operational read does not work without it)
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714</package>
+            <description>
+                Conversion of the 'ncEvent' XSD in the
+                NETCONF Notifications RFC.
+
+                Directly used for netconf notification binding
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714</package>
+            <description>
+                Conversion of the 'manageEvent' XSD in the NETCONF
+                Notifications RFC.
+
+                Directly used for netconf notification binding
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004
+            </package>
+            <description>
+                NETCONF Monitoring Module.
+                All elements in this module are read-only.
+
+                Required for mounting of netconf devices(Operational read does not work without it)
+            </description>
+        </module>
+        <module>
+            <package>
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210
+            </package>
+            <description>
+                Required for mounting of netconf devices(Operational read does not work without it)
+            </description>
+        </module>
+    </modules>
+</yangModuleWhitelist>
diff --git a/tests/honeynode/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf.json b/tests/honeynode/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf.json
new file mode 100644 (file)
index 0000000..a5b592b
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "netconf-netty-threads": 2,
+  "netconf-tcp-enabled": "false",
+  "netconf-tcp-binding-address": "127.0.0.1",
+  "netconf-tcp-binding-port": 7777,
+  "netconf-ssh-enabled": "true",
+  "netconf-ssh-binding-address": "0.0.0.0",
+  "netconf-ssh-binding-port": 2831,
+  "netconf-notification-stream-name": "honeycomb"
+}
\ No newline at end of file
diff --git a/tests/honeynode/pom.xml b/tests/honeynode/pom.xml
new file mode 100644 (file)
index 0000000..0f173df
--- /dev/null
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 Cisco and/or its affiliates.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <groupId>io.fd.honeycomb.transportpce</groupId>
+  <artifactId>honeynode-plugin-aggregator</artifactId>
+  <version>1.18.01</version>
+  <name>honeynode-plugin-aggregator</name>
+  <packaging>pom</packaging>
+  <modelVersion>4.0.0</modelVersion>
+
+  <modules>
+    <module>minimal-distribution-core</module>
+    <module>minimal-distribution</module>
+    <module>honeynode-common</module>
+    <module>honeynode-plugin-api</module>
+    <module>honeynode-plugin-impl</module>
+    <module>netconf</module>
+    <module>restconf</module>
+    <module>honeynode-distribution</module>
+    
+  </modules>
+
+  <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/tests/honeynode/restconf/asciidoc/Readme.adoc b/tests/honeynode/restconf/asciidoc/Readme.adoc
new file mode 100644 (file)
index 0000000..957949a
--- /dev/null
@@ -0,0 +1,14 @@
+= restconf
+
+Provides modules and configuration for RESTCONF northbound interface.
+
+* To start RESTCONF HTTP use
+ ** "restconf-http-enabled": "true"
+* To start RESTCONF HTTPS use
+ ** "restconf-https-enabled": "true"
+* To disable RESTCONF start use
+ ** "restconf-http-enabled": "false"
+ ** "restconf-https-enabled": "false"
+* To disable RESTCONF fully
+ ** comment/remove io.fd.honeycomb.northbound.restconf.RestconfModule
+from distribution module configuration
\ No newline at end of file
diff --git a/tests/honeynode/restconf/pom.xml b/tests/honeynode/restconf/pom.xml
new file mode 100644 (file)
index 0000000..3e68a0d
--- /dev/null
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright (c) 2017 Cisco and/or its affiliates.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at:
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>impl-parent</artifactId>
+        <groupId>io.fd.honeycomb.common</groupId>
+        <version>1.18.01</version>
+        <relativePath/>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>io.fd.honeycomb.transportpce</groupId>
+    <artifactId>restconf</artifactId>
+    <version>1.18.01</version>
+
+    <properties>
+        <jersey.version>1.19.1</jersey.version>
+        <servlet.version>3.1.0</servlet.version>
+        <jetty.version>9.3.11.v20160721</jetty.version>
+        <yang.modules.whitelist>
+            ${project.basedir}/src/main/resources/honeycomb-minimal-resources/config/restconf-whitelist.xml
+        </yang.modules.whitelist>
+    </properties>
+
+    <dependencies>
+        <!-- TPCE dependencies  -->
+        <dependency>
+            <groupId>io.fd.honeycomb.transportpce</groupId>
+            <artifactId>honeynode-plugin-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+         <dependency>
+            <groupId>io.fd.honeycomb.transportpce</groupId>
+            <artifactId>minimal-distribution-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- DI-->
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.jmob</groupId>
+            <artifactId>guice.conf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>binding-init</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Northbound common -->
+        <dependency>
+            <groupId>io.fd.honeycomb.northbound</groupId>
+            <artifactId>common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- ODL-Restconf -->
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>sal-rest-connector</artifactId>
+        </dependency>
+
+        <!-- Jersey + Jetty for RESTCONF -->
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>${servlet.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-webapp</artifactId>
+            <version>${jetty.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-servlets</artifactId>
+            <version>${jetty.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-server</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-core</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-servlet</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+
+        <!-- javax.annotation -->
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpConnectorProvider.java b/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpConnectorProvider.java
new file mode 100644 (file)
index 0000000..04a767c
--- /dev/null
@@ -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.northbound.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class HttpConnectorProvider extends ProviderTrait<ServerConnector> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpConnectorProvider.class);
+
+    @Inject
+    private RestconfConfiguration cfg;
+    @Inject
+    private Server server;
+
+    @Override
+    protected ServerConnector create() {
+        if (!cfg.isRestconfHttpEnabled()) {
+            LOG.debug("RESTCONF HTTP disabled, skipping initialization");
+            return null;
+        }
+
+        LOG.info("Starting RESTCONF HTTP");
+        ServerConnector httpConnector = new ServerConnector(server, cfg.acceptorsSize.get(), cfg.selectorsSize.get());
+        httpConnector.setHost(cfg.restconfBindingAddress.get());
+        httpConnector.setPort(cfg.restconfPort.get());
+        server.addConnector(httpConnector);
+        return httpConnector;
+    }
+}
diff --git a/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpsConnectorProvider.java b/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpsConnectorProvider.java
new file mode 100644 (file)
index 0000000..5a27bcb
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.northbound.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+
+import java.net.URL;
+
+import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class HttpsConnectorProvider extends ProviderTrait<ServerConnector> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpsConnectorProvider.class);
+
+    @Inject
+    private RestconfConfiguration cfg;
+    @Inject
+    private Server server;
+
+    @Override
+    protected ServerConnector create() {
+        if (!cfg.isRestconfHttpsEnabled()) {
+            LOG.debug("RESTCONF HTTPS disabled, skipping initialization");
+            return null;
+        }
+        LOG.info("Starting RESTCONF HTTPS");
+        // SSL Context Factory
+        // Based on:
+        // https://github.com/eclipse/jetty.project/blob/jetty-9.3.x/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java
+        // https://wiki.eclipse.org/Jetty/Howto/Configure_SSL#Loading_Keys_and_Certificates_via_PKCS12
+        // Keystore created with:
+        // openssl genrsa -des3 -out honeycomb.key
+        // openssl req -new -x509 -key honeycomb.key -out honeycomb.crt
+        // openssl pkcs12 -inkey honeycomb.key -in honeycomb.crt -export -out honeycomb.pkcs12
+        // keytool -importkeystore -srckeystore honeycomb.pkcs12 -srcstoretype PKCS12 -destkeystore honeycomb-keystore
+        SslContextFactory sslContextFactory = new SslContextFactory();
+        URL keystoreURL = getClass().getResource(cfg.restconfKeystore.get());
+        sslContextFactory.setKeyStorePath(keystoreURL.getPath());
+        sslContextFactory.setKeyStorePassword(cfg.keystorePassword.get());
+        sslContextFactory.setKeyManagerPassword((cfg.keystoreManagerPassword.get()));
+        URL truststoreURL = getClass().getResource(cfg.restconfTruststore.get());
+        sslContextFactory.setTrustStorePath(truststoreURL.getPath());
+        sslContextFactory.setTrustStorePassword((cfg.truststorePassword.get()));
+        // TODO HONEYCOMB-167 make this more configurable
+        sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA", "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+                "SSL_DHE_DSS_WITH_DES_CBC_SHA", "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+                "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+                "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
+
+        // SSL Connector
+        ServerConnector sslConnector =
+                new ServerConnector(server, cfg.httpsAcceptorsSize.get(), cfg.httpsSelectorsSize.get(),
+                        // The ssl connection factory delegates the real processing to http connection factory
+                        new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
+                        // That's why http connection factory is also required here
+                        // Order is IMPORTANT here
+                        new HttpConnectionFactory()
+                );
+        sslConnector.setHost(cfg.restconfHttpsBindingAddress.get());
+        sslConnector.setPort(cfg.restconfHttpsPort.get());
+        server.addConnector(sslConnector);
+        return sslConnector;
+    }
+}
diff --git a/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerProvider.java b/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerProvider.java
new file mode 100644 (file)
index 0000000..a874595
--- /dev/null
@@ -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.northbound.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.northbound.CredentialsConfiguration;
+import java.net.URL;
+import java.util.Collections;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.HashLoginService;
+import org.eclipse.jetty.security.authentication.BasicAuthenticator;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.gzip.GzipHandler;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.util.security.Password;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+final class JettyServerProvider extends ProviderTrait<Server> {
+
+    private static final String REALM = "HCRealm";
+    // Mime types to be compressed when requested
+    private static final String[] GZIP_MIME_TYPES = {"application/xml",
+        "xml",
+        "application/yang.data+xml",
+        "application/json",
+        "application/yang.data+json"};
+
+    @Inject
+    private RestconfConfiguration cfg;
+
+    @Inject
+    private CredentialsConfiguration credentialsCfg;
+
+    @Override
+    protected Server create() {
+        Server server = new Server(new QueuedThreadPool(cfg.restPoolMaxSize.get(), cfg.restPoolMinSize.get()));
+
+        // Load Realm for basic auth
+        HashLoginService service = new HashLoginService(REALM);
+        // Reusing the name as role
+        service.putUser(credentialsCfg.username, new Password(credentialsCfg.password),
+                new String[]{credentialsCfg.username});
+        server.addBean(service);
+
+        final URL resource = getClass().getResource("/");
+        WebAppContext webapp = new WebAppContext(resource.getPath(), cfg.restconfRootPath.get());
+
+        server.setHandler(getGzip(service, webapp));
+        return server;
+    }
+
+    private GzipHandler getGzip(final HashLoginService service, final WebAppContext webapp) {
+        final GzipHandler gzipHandler = new GzipHandler();
+        gzipHandler.setIncludedMimeTypes(GZIP_MIME_TYPES);
+        gzipHandler.setHandler(getBaseAuth(service, webapp));
+        return gzipHandler;
+    }
+
+    private ConstraintSecurityHandler getBaseAuth(HashLoginService service, WebAppContext webapp) {
+        Constraint constraint = new Constraint();
+        constraint.setName("auth");
+        constraint.setAuthenticate(true);
+        constraint.setRoles(new String[]{credentialsCfg.username});
+
+        ConstraintMapping mapping = new ConstraintMapping();
+        mapping.setPathSpec("/*");
+        mapping.setConstraint(constraint);
+
+        ConstraintSecurityHandler security = new ConstraintSecurityHandler();
+        security.setConstraintMappings(Collections.singletonList(mapping));
+        security.setAuthenticator(new BasicAuthenticator());
+        security.setLoginService(service);
+
+        security.setHandler(webapp);
+        return security;
+    }
+}
diff --git a/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerStarter.java b/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerStarter.java
new file mode 100644 (file)
index 0000000..1bd50bb
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 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.northbound.restconf;
+
+import static io.fd.honeycomb.northbound.restconf.RestconfModule.RESTCONF_HTTP;
+import static io.fd.honeycomb.northbound.restconf.RestconfModule.RESTCONF_HTTPS;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+
+import javax.annotation.Nullable;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.opendaylight.netconf.sal.rest.api.RestConnector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class JettyServerStarter extends ProviderTrait<JettyServerStarter.ServerInit> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(JettyServerStarter.class);
+
+    @Inject
+    private Server server;
+
+    // injecting all connectors to make sure that server is started after they are added
+    @Inject
+    private RestConnector connector;
+
+    // if HTTP is disabled, null will be injected
+    @Nullable
+    @Inject(optional = true)
+    @Named(RESTCONF_HTTP)
+    private ServerConnector httpConnectorInit;
+
+    // if HTTPS is disabled, null will be injected
+    @Nullable
+    @Inject(optional = true)
+    @Named(RESTCONF_HTTPS)
+    private ServerConnector httpsConnectorInit;
+
+    @Override
+    protected ServerInit create() {
+        try {
+            LOG.info("Starting RESTCONF Jetty server");
+            server.start();
+            LOG.info("RESTCONF Jetty server successfully started");
+        } catch (Exception e) {
+            LOG.error("Unable to start RESTCONF Jetty server", e);
+            throw new IllegalStateException("Unable to start RESTCONF Jetty server", e);
+        }
+
+        return new ServerInit() {
+        };
+    }
+
+    interface ServerInit {
+    }
+}
diff --git a/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfiguration.java b/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfiguration.java
new file mode 100644 (file)
index 0000000..b61287d
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017 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.northbound.restconf;
+
+import java.util.Optional;
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+//TODO - HONEYCOMB-377 - do not include module to active modules if disabled
+@BindConfig(value = "restconf", syntax = Syntax.JSON)
+public class RestconfConfiguration {
+
+    @InjectConfig("restconf-http-enabled")
+    public String restconfHttp;
+    @InjectConfig("restconf-binding-address")
+    public Optional<String> restconfBindingAddress;
+    @InjectConfig("restconf-port")
+    public Optional<Integer> restconfPort;
+    @InjectConfig("restconf-https-enabled")
+    public String restconfHttps;
+    @InjectConfig("restconf-https-binding-address")
+    public Optional<String> restconfHttpsBindingAddress;
+    @InjectConfig("restconf-https-port")
+    public Optional<Integer> restconfHttpsPort;
+    /**
+     * Restconf keystore file name. It will be loaded from the classpath so must be present in one of the folders
+     * packaged with the distribution e.g. cert/
+     */
+    @InjectConfig("restconf-keystore")
+    public Optional<String> restconfKeystore = Optional.of("/honeycomb-keystore");
+    @InjectConfig("restconf-keystore-password")
+    public Optional<String> keystorePassword;
+    @InjectConfig("restconf-keystore-manager-password")
+    public Optional<String> keystoreManagerPassword;
+    /**
+     * Restconf truststore file name. It will be loaded from the classpath so must be present in one of the folders
+     * packaged with the distribution e.g. cert/
+     */
+    @InjectConfig("restconf-truststore")
+    public Optional<String> restconfTruststore;
+    @InjectConfig("restconf-truststore-password")
+    public Optional<String> truststorePassword;
+    @InjectConfig("restconf-websocket-address")
+    public Optional<String> restconfWebsocketAddress;
+    @InjectConfig("restconf-websocket-port")
+    public Optional<Integer> restconfWebsocketPort;
+    @InjectConfig("restconf-root-path")
+    public Optional<String> restconfRootPath = Optional.of("/restconf");
+    @InjectConfig("restconf-pool-max-size")
+    public Optional<Integer> restPoolMaxSize = Optional.of(10);
+    @InjectConfig("restconf-pool-min-size")
+    public Optional<Integer> restPoolMinSize = Optional.of(1);
+    @InjectConfig("restconf-acceptors-size")
+    public Optional<Integer> acceptorsSize = Optional.of(1);
+    @InjectConfig("restconf-selectors-size")
+    public Optional<Integer> selectorsSize = Optional.of(1);
+    @InjectConfig("restconf-https-acceptors-size")
+    public Optional<Integer> httpsAcceptorsSize = Optional.of(1);
+    @InjectConfig("restconf-https-selectors-size")
+    public Optional<Integer> httpsSelectorsSize = Optional.of(1);
+
+    public boolean isRestconfHttpEnabled() {
+        return Boolean.valueOf(restconfHttp);
+    }
+
+    public boolean isRestconfHttpsEnabled() {
+        return Boolean.valueOf(restconfHttps);
+    }
+
+    public boolean isRestconfEnabled() {
+        return isRestconfHttpEnabled() || isRestconfHttpsEnabled();
+    }
+
+    @Override
+    public String toString() {
+        return "RestconfConfiguration{" +
+            "restconfHttp='" + restconfHttp + '\'' +
+            ", restconfBindingAddress=" + restconfBindingAddress +
+            ", restconfPort=" + restconfPort +
+            ", restconfHttps='" + restconfHttps + '\'' +
+            ", restconfHttpsBindingAddress=" + restconfHttpsBindingAddress +
+            ", restconfHttpsPort=" + restconfHttpsPort +
+            ", restconfKeystore=" + restconfKeystore +
+            ", keystorePassword=" + keystorePassword +
+            ", keystoreManagerPassword=" + keystoreManagerPassword +
+            ", restconfTruststore=" + restconfTruststore +
+            ", truststorePassword=" + truststorePassword +
+            ", restconfWebsocketAddress=" + restconfWebsocketAddress +
+            ", restconfWebsocketPort=" + restconfWebsocketPort +
+            ", restconfRootPath=" + restconfRootPath +
+            ", restPoolMaxSize=" + restPoolMaxSize +
+            ", restPoolMinSize=" + restPoolMinSize +
+            ", acceptorsSize=" + acceptorsSize +
+            ", selectorsSize=" + selectorsSize +
+            ", httpsAcceptorsSize=" + httpsAcceptorsSize +
+            ", httpsSelectorsSize=" + httpsSelectorsSize +
+            '}';
+    }
+}
diff --git a/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfigurationModule.java b/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfigurationModule.java
new file mode 100644 (file)
index 0000000..1e18a37
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 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.northbound.restconf;
+
+import com.google.inject.AbstractModule;
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+public class RestconfConfigurationModule extends AbstractModule {
+
+    @Override
+    protected void configure() {
+        install(ConfigurationModule.create());
+        requestInjection(RestconfConfiguration.class);
+    }
+}
diff --git a/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfModule.java b/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfModule.java
new file mode 100644 (file)
index 0000000..9f9ecf7
--- /dev/null
@@ -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.northbound.restconf;
+
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+import io.fd.honeycomb.northbound.NorthboundAbstractModule;
+import io.fd.honeycomb.northbound.restconf.JettyServerStarter.ServerInit;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.opendaylight.netconf.sal.rest.api.RestConnector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RestconfModule extends NorthboundAbstractModule<RestconfConfiguration> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RestconfModule.class);
+
+    public static final String RESTCONF_HTTP = "restconf-http";
+    public static final String RESTCONF_HTTPS = "restconf-https";
+
+    public RestconfModule() {
+        super(new RestconfConfigurationModule(), RestconfConfiguration.class);
+    }
+
+    @Override
+    protected void configure() {
+        if (!getConfiguration().isRestconfEnabled()) {
+            LOG.info("Restconf is disabled, skipping configuration");
+            return;
+        }
+
+        LOG.info("Starting RESTCONF Northbound");
+        install(new RestconfConfigurationModule());
+        bind(Server.class).toProvider(JettyServerProvider.class).in(Singleton.class);
+        bind(ServerConnector.class).annotatedWith(Names.named(RESTCONF_HTTP))
+                .toProvider(HttpConnectorProvider.class)
+                .in(Singleton.class);
+        bind(ServerConnector.class).annotatedWith(Names.named(RESTCONF_HTTPS))
+                .toProvider(HttpsConnectorProvider.class)
+                .in(Singleton.class);
+        bind(RestConnector.class).toProvider(RestconfProvider.class).in(Singleton.class);
+        bind(ServerInit.class).toProvider(JettyServerStarter.class).asEagerSingleton();
+    }
+}
diff --git a/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfProvider.java b/tests/honeynode/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfProvider.java
new file mode 100644 (file)
index 0000000..6650e31
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, 2017 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.northbound.restconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.data.init.ShutdownHandler;
+
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+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.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+
+final class RestconfProvider extends ProviderTrait<RestConnector> {
+
+    @Inject
+    private RestconfConfiguration cfg;
+    @Inject
+//    @Named(HONEYCOMB_CONFIG)
+    //Modified in order to connect TPCE to device config datastore
+    @Named("device-databroker")
+    private DOMDataBroker domDataBroker;
+    @Inject
+    private SchemaService schemaService;
+    @Inject
+    private DOMRpcService rpcService;
+    @Inject
+    private DOMNotificationRouter notificationService;
+    @Inject
+    private ShutdownHandler shutdownHandler;
+    @Inject
+    private DOMMountPointService mountPointService;
+
+    @Override
+    protected RestconfProviderImpl create() {
+        final RestconfProviderImpl instance = new RestconfProviderImpl(domDataBroker, schemaService, rpcService,
+            notificationService, mountPointService,
+            IpAddressBuilder.getDefaultInstance(cfg.restconfWebsocketAddress.get()),
+            new PortNumber(cfg.restconfWebsocketPort.get()));
+
+        // Required to properly initialize restconf (broker, schema ctx, etc.).
+        // Without that restconf would fail with 503 (service not available).
+        instance.start();
+
+        shutdownHandler.register(instance.getClass().getCanonicalName(), instance);
+        return instance;
+    }
+}
diff --git a/tests/honeynode/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf-whitelist.xml b/tests/honeynode/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf-whitelist.xml
new file mode 100644 (file)
index 0000000..5274cf4
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<yangModuleWhitelist>
+    <modules>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715</package>
+            <description>
+                This module contains a collection of generally useful derived
+                YANG data types for Internet addresses and related things.
+
+                Dependency for ietf-restconf-monitoring
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715</package>
+            <description>
+                This module contains a collection of generally useful derived
+                YANG data types.
+
+                Dependency for ietf-restconf-monitoring
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126
+            </package>
+            <description>
+                This module contains monitoring information for the
+                RESTCONF protocol.
+
+                Required for mounting of netconf devices
+            </description>
+        </module>
+        <module>
+            <package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160621</package>
+            <description>
+                This module contains monitoring information about the YANG
+                modules and submodules that are used within a YANG-based
+                server.
+
+                Required for mounting of netconf devices
+            </description>
+        </module>
+    </modules>
+</yangModuleWhitelist>
diff --git a/tests/honeynode/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf.json b/tests/honeynode/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf.json
new file mode 100644 (file)
index 0000000..ec4061c
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "restconf-http-enabled": "true",
+  "restconf-root-path": "/restconf",
+  "restconf-binding-address": "127.0.0.1",
+  "restconf-port": 8183,
+  "restconf-https-enabled": "true",
+  "restconf-https-binding-address": "0.0.0.0",
+  "restconf-https-port": 8445,
+  "restconf-keystore": "/honeycomb-keystore",
+  "restconf-keystore-password": "OBF:1v9s1unr1unn1vv51zlk1t331vg91x1b1vgl1t331zly1vu51uob1uo71v8u",
+  "restconf-keystore-manager-password": "OBF:1v9s1unr1unn1vv51zlk1t331vg91x1b1vgl1t331zly1vu51uob1uo71v8u",
+  "restconf-truststore": "/honeycomb-keystore",
+  "restconf-truststore-password": "OBF:1v9s1unr1unn1vv51zlk1t331vg91x1b1vgl1t331zly1vu51uob1uo71v8u",
+  "restconf-websocket-address": "0.0.0.0",
+  "restconf-websocket-port": 7779,
+  "restconf-pool-max-size": 10,
+  "restconf-pool-min-size": 1,
+  "restconf-acceptors-size": 1,
+  "restconf-selectors-size": 1,
+  "restconf-https-acceptors-size": 1,
+  "restconf-https-selectors-size": 1
+}
diff --git a/tests/sample_configs/ord_2.1/oper-ROADMA.xml b/tests/sample_configs/ord_2.1/oper-ROADMA.xml
new file mode 100644 (file)
index 0000000..728950d
--- /dev/null
@@ -0,0 +1,3855 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <org-openroadm-device xmlns="http://org/openroadm/device">
+    <info>
+      <node-id>ROADMA</node-id>
+      <node-number>2</node-number>
+      <node-type>rdm</node-type>
+      <clli>NodeA</clli>
+      <vendor>vendorA</vendor>
+      <model>2</model>
+      <serial-id>0002</serial-id>
+      <ipAddress>127.0.0.12</ipAddress>
+      <prefix-length>28</prefix-length>
+      <defaultGateway>127.0.0.20</defaultGateway>
+      <source>static</source>
+      <current-ipAddress>127.0.0.12</current-ipAddress>
+      <current-prefix-length>28</current-prefix-length>
+      <current-defaultGateway>127.0.0.20</current-defaultGateway>
+      <macAddress>aa:aa:aa:aa:aa:aa</macAddress>
+      <softwareVersion>1</softwareVersion>
+      <max-degrees>2</max-degrees>
+      <max-srgs>9</max-srgs>
+    </info>
+    <users>
+      <user>
+        <name>openroadm</name>
+        <password>openroadm</password>
+        <group>sudo</group>
+      </user>
+    </users>
+    <pending-sw>
+      <sw-version>1</sw-version>
+    </pending-sw>
+    <shelves>
+      <shelf-name>sdegE</shelf-name>
+      <shelf-type>pizza</shelf-type>
+      <rack>XYZ</rack>
+      <shelf-position>2</shelf-position>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>00002</serial-id>
+      <product-code>xxxxx</product-code>
+      <clei>degE</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <due-date>2016-10-25T09:00:00-00:00</due-date>
+      <slots>
+        <slot-name>0</slot-name>
+        <label>0</label>
+        <provisioned-circuit-pack>2/0</provisioned-circuit-pack>
+      </slots>
+    </shelves>
+    <shelves>
+      <shelf-name>sdegW</shelf-name>
+      <shelf-type>pizza</shelf-type>
+      <rack>XYZ</rack>
+      <shelf-position>3</shelf-position>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>00003</serial-id>
+      <product-code>xxxxx</product-code>
+      <clei>degW</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <due-date>2016-10-25T09:00:00-00:00</due-date>
+      <slots>
+        <slot-name>0</slot-name>
+        <label>0</label>
+        <provisioned-circuit-pack>3/0</provisioned-circuit-pack>
+      </slots>
+    </shelves>
+        <shelves>
+      <shelf-name>ssrg</shelf-name>
+      <shelf-type>pizza</shelf-type>
+      <rack>XYZ</rack>
+      <shelf-position>4</shelf-position>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>00004</serial-id>
+      <product-code>xxxxx</product-code>
+      <clei>srgW</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <due-date>2016-10-25T09:00:00-00:00</due-date>
+      <slots>
+        <slot-name>0</slot-name>
+        <label>0</label>
+        <provisioned-circuit-pack>4/0</provisioned-circuit-pack>
+      </slots>
+    </shelves>
+    <circuit-packs>
+      <circuit-pack-name>2/0</circuit-pack-name>
+      <circuit-pack-type>WSSDEG</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>WSS9</model>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>wss1</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>2</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <cp-slots>
+        <slot-name>OSC-SLOT</slot-name>
+        <label>OSC-SLOT</label>
+        <provisioned-circuit-pack>2/0/OSC-PLUG</provisioned-circuit-pack>
+      </cp-slots>
+         <cp-slots>
+        <slot-name>ETH-PLUG</slot-name>
+        <label>ETH-PLUG</label>
+        <provisioned-circuit-pack>2/0/ETH-PLUG</provisioned-circuit-pack>
+      </cp-slots>
+      <ports>
+        <port-name>C1</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C2</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C3</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C4</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C5</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C6</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C7</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C8</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C9</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>L1</port-name>
+        <port-type>LINE</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-TTP-TXRX</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-35.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-9.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>14.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>21.82</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>LOG1</port-name>
+        <port-type>Logical</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+      <ports>
+        <port-name>OSC-DEMUX</port-name>
+        <port-type>OSC</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>2/0/OSC-PLUG</circuit-pack-name>
+      <circuit-pack-type>port</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>SFP/SFP+</model>
+      <serial-id>00000163600843</serial-id>
+      <product-code>oooooo</product-code>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>oscplug</clei>
+      <hardware-version>01</hardware-version>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>2</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <parent-circuit-pack>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <cp-slot-name>OSC-SLOT</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>OSC-PORT</port-name>
+        <port-type>1GEX</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+       <circuit-packs>
+      <circuit-pack-name>2/0/ETH-PLUG</circuit-pack-name>
+      <circuit-pack-type>port</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>VENDORA</vendor>
+      <model>GIGAETHMGT</model>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>ETHE</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>2</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+         <parent-circuit-pack>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <cp-slot-name>ETH-PLUG</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>ETH-PLUG</port-name>
+        <port-type>1GEX</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>3/0</circuit-pack-name>
+      <circuit-pack-type>WSSDEG</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>WSS9</model>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>wss2</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>3</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <cp-slots>
+        <slot-name>OSC-SLOT</slot-name>
+        <label>OSC-SLOT</label>
+        <provisioned-circuit-pack>3/0/OSC-PLUG</provisioned-circuit-pack>
+      </cp-slots>
+         <cp-slots>
+        <slot-name>ETH-PLUG</slot-name>
+        <label>ETH-PLUG</label>
+        <provisioned-circuit-pack>3/0/ETH-PLUG</provisioned-circuit-pack>
+      </cp-slots>
+      <ports>
+        <port-name>C1</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C2</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C3</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C4</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C5</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C6</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C7</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C8</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C9</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>L1</port-name>
+        <port-type>LINE</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-TTP-TXRX</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-35.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-9.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>14.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>21.82</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>LOG1</port-name>
+        <port-type>Logical</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+      <ports>
+        <port-name>OSC-DEMUX</port-name>
+        <port-type>OSC</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>3/0/OSC-PLUG</circuit-pack-name>
+      <circuit-pack-type>port</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>SFP/SFP+</model>
+      <serial-id>00000163600843</serial-id>
+      <product-code>oooooo</product-code>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>oscplug</clei>
+      <hardware-version>01</hardware-version>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>3</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <parent-circuit-pack>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <cp-slot-name>OSC-SLOT</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>OSC-PORT</port-name>
+        <port-type>1GEX</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+       <circuit-packs>
+      <circuit-pack-name>3/0/ETH-PLUG</circuit-pack-name>
+      <circuit-pack-type>port</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>VENDORA</vendor>
+      <model>GIGAETHMGT</model>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>ETHW</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>3</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+         <parent-circuit-pack>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <cp-slot-name>ETH-PLUG</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>ETH-PLUG</port-name>
+        <port-type>1GEX</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>4/0</circuit-pack-name>
+      <circuit-pack-type>ADDDROP</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>16CX4D</model>
+      <clei>cccccccc</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>4</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <ports>
+        <port-name>C1</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP1</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C10</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP10</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C11</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP11</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C12</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP12</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C13</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP13</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C14</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP14</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C15</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP15</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C16</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP16</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C2</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP2</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C3</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP3</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C4</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP4</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C5</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP5</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C6</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP6</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C7</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP7</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C8</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP8</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C9</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP9</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>AD-DEG1</port-name>
+        <port-type>Edge</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-CP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>AD-DEG2</port-name>
+        <port-type>Edge</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-CP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>AD-DEG3</port-name>
+        <port-type>Edge</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-CP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>AD-DEG4</port-name>
+        <port-type>Edge</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-CP-TXRX</logical-connection-point>
+      </ports>
+    </circuit-packs>
+    <interface>
+      <name>oms-2/0/0/L1</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:openROADMOpticalMultiplex</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-interface>ots-2/0/0/L1</supporting-interface>
+      <supporting-circuit-pack-name>2/0</supporting-circuit-pack-name>
+      <supporting-port>L1</supporting-port>
+    </interface>
+    <interface>
+      <name>oms-3/0/0/L1</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:openROADMOpticalMultiplex</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <circuit-id>Link-1</circuit-id>
+      <supporting-interface>ots-3/0/0/L1</supporting-interface>
+      <supporting-circuit-pack-name>3/0</supporting-circuit-pack-name>
+      <supporting-port>L1</supporting-port>
+    </interface>
+    <interface>
+      <name>ots-2/0/0/L1</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:opticalTransport</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-circuit-pack-name>2/0</supporting-circuit-pack-name>
+      <supporting-port>L1</supporting-port>
+      <ots xmlns="http://org/openroadm/optical-transport-interfaces">
+        <fiber-type>smf</fiber-type>
+        <span-loss-receive>15</span-loss-receive>
+        <span-loss-transmit>15</span-loss-transmit>
+      </ots>
+    </interface>
+    <interface>
+      <name>ots-3/0/0/L1</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:opticalTransport</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-circuit-pack-name>3/0</supporting-circuit-pack-name>
+      <supporting-port>L1</supporting-port>
+      <ots xmlns="http://org/openroadm/optical-transport-interfaces">
+        <fiber-type>smf</fiber-type>
+        <span-loss-receive>10.0</span-loss-receive>
+        <span-loss-transmit>10.0</span-loss-transmit>
+      </ots>
+    </interface>
+       <interface>
+      <name>eth-2/0/ETH-PLUG</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:ethernetCsmacd</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-circuit-pack-name>2/0/ETH-PLUG</supporting-circuit-pack-name>
+      <supporting-port>ETH-PLUG</supporting-port>
+      <ethernet xmlns="http://org/openroadm/ethernet-interfaces">
+        <speed>1000</speed>
+        <duplex>full</duplex>
+        <mtu>1800</mtu>
+        <auto-negotiation>enabled</auto-negotiation>
+        <curr-speed>1000</curr-speed>
+        <curr-duplex>FULL</curr-duplex>
+      </ethernet>
+    </interface>
+    <interface>
+      <name>eth-3/0/ETH-PLUG</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:ethernetCsmacd</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-circuit-pack-name>3/0/ETH-PLUG</supporting-circuit-pack-name>
+      <supporting-port>ETH-PLUG</supporting-port>
+      <ethernet xmlns="http://org/openroadm/ethernet-interfaces">
+        <speed>1000</speed>
+        <duplex>full</duplex>
+        <mtu>1800</mtu>
+        <auto-negotiation>enabled</auto-negotiation>
+        <curr-speed>1000</curr-speed>
+        <curr-duplex>FULL</curr-duplex>
+      </ethernet>
+    </interface>
+       <protocols>
+      <lldp xmlns="http://org/openroadm/lldp">
+        <global-config>
+          <adminStatus>enable</adminStatus>
+          <msgTxInterval>20</msgTxInterval>
+          <msgTxHoldMultiplier>4</msgTxHoldMultiplier>
+        </global-config>
+        <port-config>
+          <ifName>eth-2/0/ETH-PLUG</ifName>
+          <adminStatus>txandrx</adminStatus>
+        </port-config>
+               <port-config>
+          <ifName>eth-3/0/ETH-PLUG</ifName>
+          <adminStatus>txandrx</adminStatus>
+        </port-config>
+        <nbr-list>
+          <if-name>
+            <ifName>eth-2/0/ETH-PLUG</ifName>
+            <remoteSysName>ROADMC</remoteSysName>
+            <remoteMgmtAddressSubType>ipV4</remoteMgmtAddressSubType>
+            <remoteMgmtAddress>1.1.1.1</remoteMgmtAddress>
+            <remotePortIdSubType>ifalias</remotePortIdSubType>
+            <remotePortId>eth-3/0/ETH-PLUG</remotePortId>
+            <remoteChassisIdSubType>chassiscomponent</remoteChassisIdSubType>
+            <remoteChassisId>1?</remoteChassisId>
+          </if-name>
+          <if-name>
+            <ifName>eth-3/0/ETH-PLUG</ifName>
+            <remoteSysName>ROADMB</remoteSysName>
+            <remoteMgmtAddressSubType>ipV4</remoteMgmtAddressSubType>
+            <remoteMgmtAddress>1.1.1.1</remoteMgmtAddress>
+            <remotePortIdSubType>ifalias</remotePortIdSubType>
+            <remotePortId>eth-2/0/ETH-PLUG</remotePortId>
+            <remoteChassisIdSubType>chassiscomponent</remoteChassisIdSubType>
+            <remoteChassisId>1?</remoteChassisId>
+          </if-name>
+        </nbr-list>
+      </lldp>
+    </protocols>
+    <wavelength-map>
+      <wavelengths>
+        <wavelength-number>1</wavelength-number>
+        <center-frequency>196.1</center-frequency>
+        <wavelength>1528.77</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>2</wavelength-number>
+        <center-frequency>196.05</center-frequency>
+        <wavelength>1529.16</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>3</wavelength-number>
+        <center-frequency>196.0</center-frequency>
+        <wavelength>1529.55</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>4</wavelength-number>
+        <center-frequency>195.95</center-frequency>
+        <wavelength>1529.94</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>5</wavelength-number>
+        <center-frequency>195.9</center-frequency>
+        <wavelength>1530.33</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>6</wavelength-number>
+        <center-frequency>195.85</center-frequency>
+        <wavelength>1530.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>7</wavelength-number>
+        <center-frequency>195.8</center-frequency>
+        <wavelength>1531.11</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>8</wavelength-number>
+        <center-frequency>195.75</center-frequency>
+        <wavelength>1531.5</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>9</wavelength-number>
+        <center-frequency>195.7</center-frequency>
+        <wavelength>1531.89</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>10</wavelength-number>
+        <center-frequency>195.65</center-frequency>
+        <wavelength>1532.28</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>11</wavelength-number>
+        <center-frequency>195.6</center-frequency>
+        <wavelength>1532.67</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>12</wavelength-number>
+        <center-frequency>195.55</center-frequency>
+        <wavelength>1533.06</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>13</wavelength-number>
+        <center-frequency>195.5</center-frequency>
+        <wavelength>1533.45</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>14</wavelength-number>
+        <center-frequency>195.45</center-frequency>
+        <wavelength>1533.84</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>15</wavelength-number>
+        <center-frequency>195.4</center-frequency>
+        <wavelength>1534.23</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>16</wavelength-number>
+        <center-frequency>195.35</center-frequency>
+        <wavelength>1534.62</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>17</wavelength-number>
+        <center-frequency>195.3</center-frequency>
+        <wavelength>1535.01</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>18</wavelength-number>
+        <center-frequency>195.25</center-frequency>
+        <wavelength>1535.4</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>19</wavelength-number>
+        <center-frequency>195.2</center-frequency>
+        <wavelength>1535.79</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>20</wavelength-number>
+        <center-frequency>195.15</center-frequency>
+        <wavelength>1536.18</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>21</wavelength-number>
+        <center-frequency>195.1</center-frequency>
+        <wavelength>1536.57</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>22</wavelength-number>
+        <center-frequency>195.05</center-frequency>
+        <wavelength>1536.96</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>23</wavelength-number>
+        <center-frequency>195.0</center-frequency>
+        <wavelength>1537.35</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>24</wavelength-number>
+        <center-frequency>194.95</center-frequency>
+        <wavelength>1537.74</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>25</wavelength-number>
+        <center-frequency>194.9</center-frequency>
+        <wavelength>1538.13</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>26</wavelength-number>
+        <center-frequency>194.85</center-frequency>
+        <wavelength>1538.52</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>27</wavelength-number>
+        <center-frequency>194.8</center-frequency>
+        <wavelength>1538.91</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>28</wavelength-number>
+        <center-frequency>194.75</center-frequency>
+        <wavelength>1539.3</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>29</wavelength-number>
+        <center-frequency>194.7</center-frequency>
+        <wavelength>1539.69</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>30</wavelength-number>
+        <center-frequency>194.65</center-frequency>
+        <wavelength>1540.08</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>31</wavelength-number>
+        <center-frequency>194.6</center-frequency>
+        <wavelength>1540.47</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>32</wavelength-number>
+        <center-frequency>194.55</center-frequency>
+        <wavelength>1540.86</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>33</wavelength-number>
+        <center-frequency>194.5</center-frequency>
+        <wavelength>1541.25</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>34</wavelength-number>
+        <center-frequency>194.45</center-frequency>
+        <wavelength>1541.64</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>35</wavelength-number>
+        <center-frequency>194.4</center-frequency>
+        <wavelength>1542.03</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>36</wavelength-number>
+        <center-frequency>194.35</center-frequency>
+        <wavelength>1542.42</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>37</wavelength-number>
+        <center-frequency>194.3</center-frequency>
+        <wavelength>1542.81</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>38</wavelength-number>
+        <center-frequency>194.25</center-frequency>
+        <wavelength>1543.2</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>39</wavelength-number>
+        <center-frequency>194.2</center-frequency>
+        <wavelength>1543.59</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>40</wavelength-number>
+        <center-frequency>194.15</center-frequency>
+        <wavelength>1543.98</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>41</wavelength-number>
+        <center-frequency>194.1</center-frequency>
+        <wavelength>1544.37</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>42</wavelength-number>
+        <center-frequency>194.05</center-frequency>
+        <wavelength>1544.76</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>43</wavelength-number>
+        <center-frequency>194.0</center-frequency>
+        <wavelength>1545.15</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>44</wavelength-number>
+        <center-frequency>193.95</center-frequency>
+        <wavelength>1545.54</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>45</wavelength-number>
+        <center-frequency>193.9</center-frequency>
+        <wavelength>1545.93</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>46</wavelength-number>
+        <center-frequency>193.85</center-frequency>
+        <wavelength>1546.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>47</wavelength-number>
+        <center-frequency>193.8</center-frequency>
+        <wavelength>1546.71</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>48</wavelength-number>
+        <center-frequency>193.75</center-frequency>
+        <wavelength>1547.1</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>49</wavelength-number>
+        <center-frequency>193.7</center-frequency>
+        <wavelength>1547.49</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>50</wavelength-number>
+        <center-frequency>193.65</center-frequency>
+        <wavelength>1547.88</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>51</wavelength-number>
+        <center-frequency>193.6</center-frequency>
+        <wavelength>1548.27</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>52</wavelength-number>
+        <center-frequency>193.55</center-frequency>
+        <wavelength>1548.66</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>53</wavelength-number>
+        <center-frequency>193.5</center-frequency>
+        <wavelength>1549.05</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>54</wavelength-number>
+        <center-frequency>193.45</center-frequency>
+        <wavelength>1549.44</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>55</wavelength-number>
+        <center-frequency>193.4</center-frequency>
+        <wavelength>1549.83</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>56</wavelength-number>
+        <center-frequency>193.35</center-frequency>
+        <wavelength>1550.22</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>57</wavelength-number>
+        <center-frequency>193.3</center-frequency>
+        <wavelength>1550.61</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>58</wavelength-number>
+        <center-frequency>193.25</center-frequency>
+        <wavelength>1551.0</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>59</wavelength-number>
+        <center-frequency>193.2</center-frequency>
+        <wavelength>1551.39</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>60</wavelength-number>
+        <center-frequency>193.15</center-frequency>
+        <wavelength>1551.78</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>61</wavelength-number>
+        <center-frequency>193.1</center-frequency>
+        <wavelength>1552.17</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>62</wavelength-number>
+        <center-frequency>193.05</center-frequency>
+        <wavelength>1552.56</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>63</wavelength-number>
+        <center-frequency>193.0</center-frequency>
+        <wavelength>1552.95</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>64</wavelength-number>
+        <center-frequency>192.95</center-frequency>
+        <wavelength>1553.34</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>65</wavelength-number>
+        <center-frequency>192.9</center-frequency>
+        <wavelength>1553.73</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>66</wavelength-number>
+        <center-frequency>192.85</center-frequency>
+        <wavelength>1554.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>67</wavelength-number>
+        <center-frequency>192.8</center-frequency>
+        <wavelength>1554.51</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>68</wavelength-number>
+        <center-frequency>192.75</center-frequency>
+        <wavelength>1554.9</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>69</wavelength-number>
+        <center-frequency>192.7</center-frequency>
+        <wavelength>1555.29</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>70</wavelength-number>
+        <center-frequency>192.65</center-frequency>
+        <wavelength>1555.68</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>71</wavelength-number>
+        <center-frequency>192.6</center-frequency>
+        <wavelength>1556.07</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>72</wavelength-number>
+        <center-frequency>192.55</center-frequency>
+        <wavelength>1556.46</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>73</wavelength-number>
+        <center-frequency>192.5</center-frequency>
+        <wavelength>1556.85</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>74</wavelength-number>
+        <center-frequency>192.45</center-frequency>
+        <wavelength>1557.24</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>75</wavelength-number>
+        <center-frequency>192.4</center-frequency>
+        <wavelength>1557.63</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>76</wavelength-number>
+        <center-frequency>192.35</center-frequency>
+        <wavelength>1558.02</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>77</wavelength-number>
+        <center-frequency>192.3</center-frequency>
+        <wavelength>1558.41</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>78</wavelength-number>
+        <center-frequency>192.25</center-frequency>
+        <wavelength>1558.8</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>79</wavelength-number>
+        <center-frequency>192.2</center-frequency>
+        <wavelength>1559.19</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>80</wavelength-number>
+        <center-frequency>192.15</center-frequency>
+        <wavelength>1559.58</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>81</wavelength-number>
+        <center-frequency>192.1</center-frequency>
+        <wavelength>1559.97</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>82</wavelength-number>
+        <center-frequency>192.05</center-frequency>
+        <wavelength>1560.36</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>83</wavelength-number>
+        <center-frequency>192.0</center-frequency>
+        <wavelength>1560.75</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>84</wavelength-number>
+        <center-frequency>191.95</center-frequency>
+        <wavelength>1561.14</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>85</wavelength-number>
+        <center-frequency>191.9</center-frequency>
+        <wavelength>1561.53</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>86</wavelength-number>
+        <center-frequency>191.85</center-frequency>
+        <wavelength>1561.92</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>87</wavelength-number>
+        <center-frequency>191.8</center-frequency>
+        <wavelength>1562.31</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>88</wavelength-number>
+        <center-frequency>191.75</center-frequency>
+        <wavelength>1562.7</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>89</wavelength-number>
+        <center-frequency>191.7</center-frequency>
+        <wavelength>1563.09</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>90</wavelength-number>
+        <center-frequency>191.65</center-frequency>
+        <wavelength>1563.48</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>91</wavelength-number>
+        <center-frequency>191.6</center-frequency>
+        <wavelength>1563.87</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>92</wavelength-number>
+        <center-frequency>191.55</center-frequency>
+        <wavelength>1564.26</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>93</wavelength-number>
+        <center-frequency>191.5</center-frequency>
+        <wavelength>1564.65</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>94</wavelength-number>
+        <center-frequency>191.45</center-frequency>
+        <wavelength>1565.04</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>95</wavelength-number>
+        <center-frequency>191.4</center-frequency>
+        <wavelength>1565.43</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>96</wavelength-number>
+        <center-frequency>191.35</center-frequency>
+        <wavelength>1565.82</wavelength>
+      </wavelengths>
+    </wavelength-map>
+    <internal-link>
+      <internal-link-name>2/0/C1-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C2-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C3-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C4-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C5-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C6-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C7-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C8-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C9-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C1-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C2-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C3-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C4-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C5-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C6-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C7-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C8-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C9-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C1-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C1-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C1-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C1-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C2-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C2-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C2-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C2-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C3-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C3-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C3-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C3-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C4-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C4-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C4-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C4-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C5-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C5-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C5-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C5-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C6-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C6-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C6-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C6-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C7-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C7-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C7-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C7-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C8-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C8-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C8-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C8-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C9-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C9-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C9-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C9-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C10-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C10-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C10-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C10-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C11-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C11-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C11-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C11-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C12-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C12-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C12-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C12-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C13-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C13-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C13-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C13-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C14-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C14-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C14-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C14-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C15-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C15-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C15-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C15-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C16-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C16-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C16-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C16-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C10</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C11</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C12</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C13</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C14</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C15</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C16</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C10</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C11</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C12</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C13</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C14</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C15</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C16</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C10</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C11</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C12</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C13</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C14</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C15</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C16</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C10</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C11</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C12</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C13</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C14</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C15</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C16</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </internal-link>
+    <physical-link>
+      <physical-link-name>phylink-1</physical-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-2</physical-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-3</physical-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-4</physical-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-5</physical-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-6</physical-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </physical-link>
+    <degree>
+      <degree-number>1</degree-number>
+      <max-wavelengths>96</max-wavelengths>
+      <circuit-packs>
+        <index>1</index>
+        <circuit-pack-name>2/0</circuit-pack-name>
+      </circuit-packs>
+         <circuit-packs>
+        <index>2</index>
+        <circuit-pack-name>2/0/OSC-PLUG</circuit-pack-name>
+      </circuit-packs>
+         <circuit-packs>
+        <index>3</index>
+        <circuit-pack-name>2/0/ETH-PLUG</circuit-pack-name>
+      </circuit-packs>
+      <connection-ports>
+        <index>1</index>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </connection-ports>
+    </degree>
+    <degree>
+      <degree-number>2</degree-number>
+      <max-wavelengths>96</max-wavelengths>
+      <circuit-packs>
+        <index>1</index>
+        <circuit-pack-name>3/0</circuit-pack-name>
+      </circuit-packs>
+         <circuit-packs>
+        <index>2</index>
+        <circuit-pack-name>3/0/OSC-PLUG</circuit-pack-name>
+      </circuit-packs>
+         <circuit-packs>
+        <index>3</index>
+        <circuit-pack-name>3/0/ETH-PLUG</circuit-pack-name>
+      </circuit-packs>
+      <connection-ports>
+        <index>1</index>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </connection-ports>
+    </degree>
+    <shared-risk-group>
+      <srg-number>1</srg-number>
+      <max-add-drop-ports>16</max-add-drop-ports>
+      <wavelengthDuplication>onePerSRG</wavelengthDuplication>
+      <circuit-packs>
+        <index>1</index>
+        <circuit-pack-name>4/0</circuit-pack-name>
+      </circuit-packs>
+    </shared-risk-group>
+    <connection-map>
+      <connection-map-number>1</connection-map-number>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>2</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>3</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>4</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>5</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>6</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>7</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>8</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>9</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>10</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>11</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>12</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>13</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>14</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>15</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>16</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>17</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>18</connection-map-number>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>19</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>20</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>21</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>22</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>23</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>24</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>25</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>26</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>27</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>28</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>29</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>30</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>31</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>32</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>33</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>34</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+  </org-openroadm-device>
+</data>
diff --git a/tests/sample_configs/ord_2.1/oper-ROADMC.xml b/tests/sample_configs/ord_2.1/oper-ROADMC.xml
new file mode 100644 (file)
index 0000000..d2dff64
--- /dev/null
@@ -0,0 +1,3855 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <org-openroadm-device xmlns="http://org/openroadm/device">
+    <info>
+      <node-id>ROADMC</node-id>
+      <node-number>2</node-number>
+      <node-type>rdm</node-type>
+      <clli>NodeC</clli>
+      <vendor>vendorA</vendor>
+      <model>2</model>
+      <serial-id>0002</serial-id>
+      <ipAddress>127.0.0.14</ipAddress>
+      <prefix-length>28</prefix-length>
+      <defaultGateway>127.0.0.20</defaultGateway>
+      <source>static</source>
+      <current-ipAddress>127.0.0.14</current-ipAddress>
+      <current-prefix-length>28</current-prefix-length>
+      <current-defaultGateway>127.0.0.20</current-defaultGateway>
+      <macAddress>cc:cc:cc:cc:cc:cc</macAddress>
+      <softwareVersion>1</softwareVersion>
+      <max-degrees>2</max-degrees>
+      <max-srgs>9</max-srgs>
+    </info>
+    <users>
+      <user>
+        <name>openroadm</name>
+        <password>openroadm</password>
+        <group>sudo</group>
+      </user>
+    </users>
+    <pending-sw>
+      <sw-version>1</sw-version>
+    </pending-sw>
+    <shelves>
+      <shelf-name>sdegE</shelf-name>
+      <shelf-type>pizza</shelf-type>
+      <rack>XYZ</rack>
+      <shelf-position>2</shelf-position>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>00002</serial-id>
+      <product-code>xxxxx</product-code>
+      <clei>degE</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <due-date>2016-10-25T09:00:00-00:00</due-date>
+      <slots>
+        <slot-name>0</slot-name>
+        <label>0</label>
+        <provisioned-circuit-pack>2/0</provisioned-circuit-pack>
+      </slots>
+    </shelves>
+    <shelves>
+      <shelf-name>sdegW</shelf-name>
+      <shelf-type>pizza</shelf-type>
+      <rack>XYZ</rack>
+      <shelf-position>3</shelf-position>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>00003</serial-id>
+      <product-code>xxxxx</product-code>
+      <clei>degW</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <due-date>2016-10-25T09:00:00-00:00</due-date>
+      <slots>
+        <slot-name>0</slot-name>
+        <label>0</label>
+        <provisioned-circuit-pack>3/0</provisioned-circuit-pack>
+      </slots>
+    </shelves>
+    <shelves>
+      <shelf-name>ssrg</shelf-name>
+      <shelf-type>pizza</shelf-type>
+      <rack>XYZ</rack>
+      <shelf-position>4</shelf-position>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>00004</serial-id>
+      <product-code>xxxxx</product-code>
+      <clei>srgW</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <due-date>2016-10-25T09:00:00-00:00</due-date>
+      <slots>
+        <slot-name>0</slot-name>
+        <label>0</label>
+        <provisioned-circuit-pack>4/0</provisioned-circuit-pack>
+      </slots>
+    </shelves>
+    <circuit-packs>
+      <circuit-pack-name>2/0</circuit-pack-name>
+      <circuit-pack-type>WSSDEG</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>WSS9</model>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>wss1</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>2</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <cp-slots>
+        <slot-name>OSC-SLOT</slot-name>
+        <label>OSC-SLOT</label>
+        <provisioned-circuit-pack>2/0/OSC-PLUG</provisioned-circuit-pack>
+      </cp-slots>
+         <cp-slots>
+        <slot-name>ETH-PLUG</slot-name>
+        <label>ETH-PLUG</label>
+        <provisioned-circuit-pack>2/0/ETH-PLUG</provisioned-circuit-pack>
+      </cp-slots>
+      <ports>
+        <port-name>C1</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C2</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C3</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C4</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C5</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C6</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C7</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C8</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C9</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>L1</port-name>
+        <port-type>LINE</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG1-TTP-TXRX</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-35.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-9.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>14.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>21.82</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>LOG1</port-name>
+        <port-type>Logical</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+      <ports>
+        <port-name>OSC-DEMUX</port-name>
+        <port-type>OSC</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>2/0/OSC-PLUG</circuit-pack-name>
+      <circuit-pack-type>port</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>SFP/SFP+</model>
+      <serial-id>00000163600843</serial-id>
+      <product-code>oooooo</product-code>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>oscplug</clei>
+      <hardware-version>01</hardware-version>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>2</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <parent-circuit-pack>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <cp-slot-name>OSC-SLOT</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>OSC-PORT</port-name>
+        <port-type>1GEX</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+       <circuit-packs>
+      <circuit-pack-name>2/0/ETH-PLUG</circuit-pack-name>
+      <circuit-pack-type>port</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>VENDORA</vendor>
+      <model>GIGAETHMGT</model>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>ETHE</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>2</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+         <parent-circuit-pack>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <cp-slot-name>ETH-PLUG</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>ETH-PLUG</port-name>
+        <port-type>1GEX</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+       </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>3/0</circuit-pack-name>
+      <circuit-pack-type>WSSDEG</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>WSS9</model>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>wss2</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>3</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <cp-slots>
+        <slot-name>OSC-SLOT</slot-name>
+        <label>OSC-SLOT</label>
+        <provisioned-circuit-pack>3/0/OSC-PLUG</provisioned-circuit-pack>
+      </cp-slots>
+         <cp-slots>
+        <slot-name>ETH-PLUG</slot-name>
+        <label>ETH-PLUG</label>
+        <provisioned-circuit-pack>3/0/ETH-PLUG</provisioned-circuit-pack>
+      </cp-slots>
+      <ports>
+        <port-name>C1</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C2</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C3</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C4</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C5</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C6</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C7</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C8</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>C9</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-CTP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>L1</port-name>
+        <port-type>LINE</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>1</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>DEG2-TTP-TXRX</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-35.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-9.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>14.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>21.82</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>LOG1</port-name>
+        <port-type>Logical</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+      <ports>
+        <port-name>OSC-DEMUX</port-name>
+        <port-type>OSC</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>3/0/OSC-PLUG</circuit-pack-name>
+      <circuit-pack-type>port</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>SFP/SFP+</model>
+      <serial-id>00000163600843</serial-id>
+      <product-code>oooooo</product-code>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>oscplug</clei>
+      <hardware-version>01</hardware-version>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>3</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <parent-circuit-pack>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <cp-slot-name>OSC-SLOT</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>OSC-PORT</port-name>
+        <port-type>1GEX</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+       <circuit-packs>
+      <circuit-pack-name>3/0/ETH-PLUG</circuit-pack-name>
+      <circuit-pack-type>port</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>VENDORA</vendor>
+      <model>GIGAETHMGT</model>
+      <manufacture-date>2017-08-08T10:47:04.698808+00:00</manufacture-date>
+      <clei>ETHW</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>3</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+         <parent-circuit-pack>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <cp-slot-name>ETH-PLUG</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>ETH-PLUG</port-name>
+        <port-type>1GEX</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>4/0</circuit-pack-name>
+      <circuit-pack-type>ADDDROP</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>16CX4D</model>
+      <clei>cccccccc</clei>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>4</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <ports>
+        <port-name>C1</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP1</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C10</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP10</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C11</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP11</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C12</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP12</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C13</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP13</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C14</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP14</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C15</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP15</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C16</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP16</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C2</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP2</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C3</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP3</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C4</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP4</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C5</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP5</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C6</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP6</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C7</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP7</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C8</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP8</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>C9</port-name>
+        <port-type>Client</port-type>
+        <port-qual>roadm-external</port-qual>
+        <port-wavelength-type>wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-PP9</logical-connection-point>
+        <roadm-port>
+          <port-power-capability-min-rx>-15.0</port-power-capability-min-rx>
+          <port-power-capability-min-tx>-28.0</port-power-capability-min-tx>
+          <port-power-capability-max-rx>10.0</port-power-capability-max-rx>
+          <port-power-capability-max-tx>15.0</port-power-capability-max-tx>
+        </roadm-port>
+      </ports>
+      <ports>
+        <port-name>AD-DEG1</port-name>
+        <port-type>Edge</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-CP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>AD-DEG2</port-name>
+        <port-type>Edge</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-CP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>AD-DEG3</port-name>
+        <port-type>Edge</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-CP-TXRX</logical-connection-point>
+      </ports>
+      <ports>
+        <port-name>AD-DEG4</port-name>
+        <port-type>Edge</port-type>
+        <port-qual>roadm-internal</port-qual>
+        <port-wavelength-type>multi-wavelength</port-wavelength-type>
+        <port-direction>bidirectional</port-direction>
+        <administrative-state>inService</administrative-state>
+        <operational-state>inService</operational-state>
+        <logical-connection-point>SRG1-CP-TXRX</logical-connection-point>
+      </ports>
+    </circuit-packs>
+    <interface>
+      <name>oms-2/0/0/L1</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:openROADMOpticalMultiplex</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-interface>ots-2/0/0/L1</supporting-interface>
+      <supporting-circuit-pack-name>2/0</supporting-circuit-pack-name>
+      <supporting-port>L1</supporting-port>
+    </interface>
+    <interface>
+      <name>oms-3/0/0/L1</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:openROADMOpticalMultiplex</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <circuit-id>Link-1</circuit-id>
+      <supporting-interface>ots-3/0/0/L1</supporting-interface>
+      <supporting-circuit-pack-name>3/0</supporting-circuit-pack-name>
+      <supporting-port>L1</supporting-port>
+    </interface>
+    <interface>
+      <name>ots-2/0/0/L1</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:opticalTransport</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-circuit-pack-name>2/0</supporting-circuit-pack-name>
+      <supporting-port>L1</supporting-port>
+      <ots xmlns="http://org/openroadm/optical-transport-interfaces">
+        <fiber-type>smf</fiber-type>
+        <span-loss-receive>25</span-loss-receive>
+        <span-loss-transmit>25</span-loss-transmit>
+      </ots>
+    </interface>
+    <interface>
+      <name>ots-3/0/0/L1</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:opticalTransport</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-circuit-pack-name>3/0</supporting-circuit-pack-name>
+      <supporting-port>L1</supporting-port>
+      <ots xmlns="http://org/openroadm/optical-transport-interfaces">
+        <fiber-type>smf</fiber-type>
+        <span-loss-receive>15.0</span-loss-receive>
+        <span-loss-transmit>15.0</span-loss-transmit>
+      </ots>
+    </interface>
+       <interface>
+      <name>eth-2/0/ETH-PLUG</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:ethernetCsmacd</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-circuit-pack-name>2/0/ETH-PLUG</supporting-circuit-pack-name>
+      <supporting-port>ETH-PLUG</supporting-port>
+      <ethernet xmlns="http://org/openroadm/ethernet-interfaces">
+        <speed>1000</speed>
+        <duplex>full</duplex>
+        <mtu>1800</mtu>
+        <auto-negotiation>enabled</auto-negotiation>
+        <curr-speed>1000</curr-speed>
+        <curr-duplex>FULL</curr-duplex>
+      </ethernet>
+    </interface>
+    <interface>
+      <name>eth-3/0/ETH-PLUG</name>
+      <type xmlns:openROADM-if="http://org/openroadm/interfaces">openROADM-if:ethernetCsmacd</type>
+      <administrative-state>inService</administrative-state>
+      <operational-state>inService</operational-state>
+      <supporting-circuit-pack-name>3/0/ETH-PLUG</supporting-circuit-pack-name>
+      <supporting-port>ETH-PLUG</supporting-port>
+      <ethernet xmlns="http://org/openroadm/ethernet-interfaces">
+        <speed>1000</speed>
+        <duplex>full</duplex>
+        <mtu>1800</mtu>
+        <auto-negotiation>enabled</auto-negotiation>
+        <curr-speed>1000</curr-speed>
+        <curr-duplex>FULL</curr-duplex>
+      </ethernet>
+    </interface>
+       <protocols>
+      <lldp xmlns="http://org/openroadm/lldp">
+        <global-config>
+          <adminStatus>enable</adminStatus>
+          <msgTxInterval>20</msgTxInterval>
+          <msgTxHoldMultiplier>4</msgTxHoldMultiplier>
+        </global-config>
+        <port-config>
+          <ifName>eth-2/0/ETH-PLUG</ifName>
+          <adminStatus>txandrx</adminStatus>
+        </port-config>
+               <port-config>
+          <ifName>eth-3/0/ETH-PLUG</ifName>
+          <adminStatus>txandrx</adminStatus>
+        </port-config>
+        <nbr-list>
+          <if-name>
+            <ifName>eth-3/0/ETH-PLUG</ifName>
+            <remoteSysName>ROADMA</remoteSysName>
+            <remoteMgmtAddressSubType>ipV4</remoteMgmtAddressSubType>
+            <remoteMgmtAddress>1.1.1.1</remoteMgmtAddress>
+            <remotePortIdSubType>ifalias</remotePortIdSubType>
+            <remotePortId>eth-2/0/ETH-PLUG</remotePortId>
+            <remoteChassisIdSubType>chassiscomponent</remoteChassisIdSubType>
+            <remoteChassisId>1?</remoteChassisId>
+          </if-name>
+          <if-name>
+            <ifName>eth-2/0/ETH-PLUG</ifName>
+            <remoteSysName>ROADMB</remoteSysName>
+            <remoteMgmtAddressSubType>ipV4</remoteMgmtAddressSubType>
+            <remoteMgmtAddress>1.1.1.1</remoteMgmtAddress>
+            <remotePortIdSubType>ifalias</remotePortIdSubType>
+            <remotePortId>eth-3/0/ETH-PLUG</remotePortId>
+            <remoteChassisIdSubType>chassiscomponent</remoteChassisIdSubType>
+            <remoteChassisId>1?</remoteChassisId>
+          </if-name>
+        </nbr-list>
+      </lldp>
+    </protocols>
+    <wavelength-map>
+      <wavelengths>
+        <wavelength-number>1</wavelength-number>
+        <center-frequency>196.1</center-frequency>
+        <wavelength>1528.77</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>2</wavelength-number>
+        <center-frequency>196.05</center-frequency>
+        <wavelength>1529.16</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>3</wavelength-number>
+        <center-frequency>196.0</center-frequency>
+        <wavelength>1529.55</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>4</wavelength-number>
+        <center-frequency>195.95</center-frequency>
+        <wavelength>1529.94</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>5</wavelength-number>
+        <center-frequency>195.9</center-frequency>
+        <wavelength>1530.33</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>6</wavelength-number>
+        <center-frequency>195.85</center-frequency>
+        <wavelength>1530.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>7</wavelength-number>
+        <center-frequency>195.8</center-frequency>
+        <wavelength>1531.11</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>8</wavelength-number>
+        <center-frequency>195.75</center-frequency>
+        <wavelength>1531.5</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>9</wavelength-number>
+        <center-frequency>195.7</center-frequency>
+        <wavelength>1531.89</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>10</wavelength-number>
+        <center-frequency>195.65</center-frequency>
+        <wavelength>1532.28</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>11</wavelength-number>
+        <center-frequency>195.6</center-frequency>
+        <wavelength>1532.67</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>12</wavelength-number>
+        <center-frequency>195.55</center-frequency>
+        <wavelength>1533.06</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>13</wavelength-number>
+        <center-frequency>195.5</center-frequency>
+        <wavelength>1533.45</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>14</wavelength-number>
+        <center-frequency>195.45</center-frequency>
+        <wavelength>1533.84</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>15</wavelength-number>
+        <center-frequency>195.4</center-frequency>
+        <wavelength>1534.23</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>16</wavelength-number>
+        <center-frequency>195.35</center-frequency>
+        <wavelength>1534.62</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>17</wavelength-number>
+        <center-frequency>195.3</center-frequency>
+        <wavelength>1535.01</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>18</wavelength-number>
+        <center-frequency>195.25</center-frequency>
+        <wavelength>1535.4</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>19</wavelength-number>
+        <center-frequency>195.2</center-frequency>
+        <wavelength>1535.79</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>20</wavelength-number>
+        <center-frequency>195.15</center-frequency>
+        <wavelength>1536.18</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>21</wavelength-number>
+        <center-frequency>195.1</center-frequency>
+        <wavelength>1536.57</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>22</wavelength-number>
+        <center-frequency>195.05</center-frequency>
+        <wavelength>1536.96</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>23</wavelength-number>
+        <center-frequency>195.0</center-frequency>
+        <wavelength>1537.35</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>24</wavelength-number>
+        <center-frequency>194.95</center-frequency>
+        <wavelength>1537.74</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>25</wavelength-number>
+        <center-frequency>194.9</center-frequency>
+        <wavelength>1538.13</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>26</wavelength-number>
+        <center-frequency>194.85</center-frequency>
+        <wavelength>1538.52</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>27</wavelength-number>
+        <center-frequency>194.8</center-frequency>
+        <wavelength>1538.91</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>28</wavelength-number>
+        <center-frequency>194.75</center-frequency>
+        <wavelength>1539.3</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>29</wavelength-number>
+        <center-frequency>194.7</center-frequency>
+        <wavelength>1539.69</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>30</wavelength-number>
+        <center-frequency>194.65</center-frequency>
+        <wavelength>1540.08</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>31</wavelength-number>
+        <center-frequency>194.6</center-frequency>
+        <wavelength>1540.47</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>32</wavelength-number>
+        <center-frequency>194.55</center-frequency>
+        <wavelength>1540.86</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>33</wavelength-number>
+        <center-frequency>194.5</center-frequency>
+        <wavelength>1541.25</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>34</wavelength-number>
+        <center-frequency>194.45</center-frequency>
+        <wavelength>1541.64</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>35</wavelength-number>
+        <center-frequency>194.4</center-frequency>
+        <wavelength>1542.03</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>36</wavelength-number>
+        <center-frequency>194.35</center-frequency>
+        <wavelength>1542.42</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>37</wavelength-number>
+        <center-frequency>194.3</center-frequency>
+        <wavelength>1542.81</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>38</wavelength-number>
+        <center-frequency>194.25</center-frequency>
+        <wavelength>1543.2</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>39</wavelength-number>
+        <center-frequency>194.2</center-frequency>
+        <wavelength>1543.59</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>40</wavelength-number>
+        <center-frequency>194.15</center-frequency>
+        <wavelength>1543.98</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>41</wavelength-number>
+        <center-frequency>194.1</center-frequency>
+        <wavelength>1544.37</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>42</wavelength-number>
+        <center-frequency>194.05</center-frequency>
+        <wavelength>1544.76</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>43</wavelength-number>
+        <center-frequency>194.0</center-frequency>
+        <wavelength>1545.15</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>44</wavelength-number>
+        <center-frequency>193.95</center-frequency>
+        <wavelength>1545.54</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>45</wavelength-number>
+        <center-frequency>193.9</center-frequency>
+        <wavelength>1545.93</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>46</wavelength-number>
+        <center-frequency>193.85</center-frequency>
+        <wavelength>1546.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>47</wavelength-number>
+        <center-frequency>193.8</center-frequency>
+        <wavelength>1546.71</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>48</wavelength-number>
+        <center-frequency>193.75</center-frequency>
+        <wavelength>1547.1</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>49</wavelength-number>
+        <center-frequency>193.7</center-frequency>
+        <wavelength>1547.49</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>50</wavelength-number>
+        <center-frequency>193.65</center-frequency>
+        <wavelength>1547.88</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>51</wavelength-number>
+        <center-frequency>193.6</center-frequency>
+        <wavelength>1548.27</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>52</wavelength-number>
+        <center-frequency>193.55</center-frequency>
+        <wavelength>1548.66</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>53</wavelength-number>
+        <center-frequency>193.5</center-frequency>
+        <wavelength>1549.05</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>54</wavelength-number>
+        <center-frequency>193.45</center-frequency>
+        <wavelength>1549.44</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>55</wavelength-number>
+        <center-frequency>193.4</center-frequency>
+        <wavelength>1549.83</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>56</wavelength-number>
+        <center-frequency>193.35</center-frequency>
+        <wavelength>1550.22</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>57</wavelength-number>
+        <center-frequency>193.3</center-frequency>
+        <wavelength>1550.61</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>58</wavelength-number>
+        <center-frequency>193.25</center-frequency>
+        <wavelength>1551.0</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>59</wavelength-number>
+        <center-frequency>193.2</center-frequency>
+        <wavelength>1551.39</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>60</wavelength-number>
+        <center-frequency>193.15</center-frequency>
+        <wavelength>1551.78</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>61</wavelength-number>
+        <center-frequency>193.1</center-frequency>
+        <wavelength>1552.17</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>62</wavelength-number>
+        <center-frequency>193.05</center-frequency>
+        <wavelength>1552.56</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>63</wavelength-number>
+        <center-frequency>193.0</center-frequency>
+        <wavelength>1552.95</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>64</wavelength-number>
+        <center-frequency>192.95</center-frequency>
+        <wavelength>1553.34</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>65</wavelength-number>
+        <center-frequency>192.9</center-frequency>
+        <wavelength>1553.73</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>66</wavelength-number>
+        <center-frequency>192.85</center-frequency>
+        <wavelength>1554.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>67</wavelength-number>
+        <center-frequency>192.8</center-frequency>
+        <wavelength>1554.51</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>68</wavelength-number>
+        <center-frequency>192.75</center-frequency>
+        <wavelength>1554.9</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>69</wavelength-number>
+        <center-frequency>192.7</center-frequency>
+        <wavelength>1555.29</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>70</wavelength-number>
+        <center-frequency>192.65</center-frequency>
+        <wavelength>1555.68</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>71</wavelength-number>
+        <center-frequency>192.6</center-frequency>
+        <wavelength>1556.07</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>72</wavelength-number>
+        <center-frequency>192.55</center-frequency>
+        <wavelength>1556.46</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>73</wavelength-number>
+        <center-frequency>192.5</center-frequency>
+        <wavelength>1556.85</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>74</wavelength-number>
+        <center-frequency>192.45</center-frequency>
+        <wavelength>1557.24</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>75</wavelength-number>
+        <center-frequency>192.4</center-frequency>
+        <wavelength>1557.63</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>76</wavelength-number>
+        <center-frequency>192.35</center-frequency>
+        <wavelength>1558.02</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>77</wavelength-number>
+        <center-frequency>192.3</center-frequency>
+        <wavelength>1558.41</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>78</wavelength-number>
+        <center-frequency>192.25</center-frequency>
+        <wavelength>1558.8</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>79</wavelength-number>
+        <center-frequency>192.2</center-frequency>
+        <wavelength>1559.19</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>80</wavelength-number>
+        <center-frequency>192.15</center-frequency>
+        <wavelength>1559.58</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>81</wavelength-number>
+        <center-frequency>192.1</center-frequency>
+        <wavelength>1559.97</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>82</wavelength-number>
+        <center-frequency>192.05</center-frequency>
+        <wavelength>1560.36</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>83</wavelength-number>
+        <center-frequency>192.0</center-frequency>
+        <wavelength>1560.75</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>84</wavelength-number>
+        <center-frequency>191.95</center-frequency>
+        <wavelength>1561.14</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>85</wavelength-number>
+        <center-frequency>191.9</center-frequency>
+        <wavelength>1561.53</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>86</wavelength-number>
+        <center-frequency>191.85</center-frequency>
+        <wavelength>1561.92</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>87</wavelength-number>
+        <center-frequency>191.8</center-frequency>
+        <wavelength>1562.31</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>88</wavelength-number>
+        <center-frequency>191.75</center-frequency>
+        <wavelength>1562.7</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>89</wavelength-number>
+        <center-frequency>191.7</center-frequency>
+        <wavelength>1563.09</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>90</wavelength-number>
+        <center-frequency>191.65</center-frequency>
+        <wavelength>1563.48</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>91</wavelength-number>
+        <center-frequency>191.6</center-frequency>
+        <wavelength>1563.87</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>92</wavelength-number>
+        <center-frequency>191.55</center-frequency>
+        <wavelength>1564.26</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>93</wavelength-number>
+        <center-frequency>191.5</center-frequency>
+        <wavelength>1564.65</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>94</wavelength-number>
+        <center-frequency>191.45</center-frequency>
+        <wavelength>1565.04</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>95</wavelength-number>
+        <center-frequency>191.4</center-frequency>
+        <wavelength>1565.43</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>96</wavelength-number>
+        <center-frequency>191.35</center-frequency>
+        <wavelength>1565.82</wavelength>
+      </wavelengths>
+    </wavelength-map>
+    <internal-link>
+      <internal-link-name>2/0/C1-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C2-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C3-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C4-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C5-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C6-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C7-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C8-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/C9-to-2/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>2/0/L1-to-2/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C1-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C2-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C3-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C4-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C5-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C6-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C7-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C8-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/C9-to-3/0/L1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>3/0/L1-to-3/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C1-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C1-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C1-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C1-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C2-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C2-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C2-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C2-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C3-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C3-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C3-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C3-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C4-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C4-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C4-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C4-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C5-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C5-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C5-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C5-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C6-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C6-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C6-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C6-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C7-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C7-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C7-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C7-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C8-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C8-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C8-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C8-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C9-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C9-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C9-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C9-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C10-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C10-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C10-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C10-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C11-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C11-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C11-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C11-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C12-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C12-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C12-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C12-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C13-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C13-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C13-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C13-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C14-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C14-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C14-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C14-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C15-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C15-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C15-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C15-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C16-to-4/0/ADD-DEG1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C16-to-4/0/ADD-DEG2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C16-to-4/0/ADD-DEG3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/C16-to-4/0/ADD-DEG4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C10</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C11</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C12</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C13</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C14</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C15</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG1-to-4/0/C16</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C10</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C11</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C12</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C13</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C14</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C15</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG2-to-4/0/C16</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C10</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C11</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C12</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C13</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C14</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C15</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG3-to-4/0/C16</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C1</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C2</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C3</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C4</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C5</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C6</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C7</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C8</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C9</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C10</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C11</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C12</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C13</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C14</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C15</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+    </internal-link>
+    <internal-link>
+      <internal-link-name>4/0/ADD-DEG4-to-4/0/C16</internal-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </internal-link>
+    <physical-link>
+      <physical-link-name>phylink-1</physical-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-2</physical-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-3</physical-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-4</physical-link-name>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>ADD-DEG2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-5</physical-link-name>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </physical-link>
+    <physical-link>
+      <physical-link-name>phylink-6</physical-link-name>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+    </physical-link>
+    <degree>
+      <degree-number>1</degree-number>
+      <max-wavelengths>96</max-wavelengths>
+      <circuit-packs>
+        <index>1</index>
+        <circuit-pack-name>2/0</circuit-pack-name>
+      </circuit-packs>
+         <circuit-packs>
+        <index>2</index>
+        <circuit-pack-name>2/0/OSC-PLUG</circuit-pack-name>
+      </circuit-packs>
+         <circuit-packs>
+        <index>3</index>
+        <circuit-pack-name>2/0/ETH-PLUG</circuit-pack-name>
+      </circuit-packs>
+      <connection-ports>
+        <index>1</index>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </connection-ports>
+    </degree>
+    <degree>
+      <degree-number>2</degree-number>
+      <max-wavelengths>96</max-wavelengths>
+      <circuit-packs>
+        <index>1</index>
+        <circuit-pack-name>3/0</circuit-pack-name>
+      </circuit-packs>
+         <circuit-packs>
+        <index>2</index>
+        <circuit-pack-name>3/0/OSC-PLUG</circuit-pack-name>
+      </circuit-packs>
+         <circuit-packs>
+        <index>3</index>
+        <circuit-pack-name>3/0/ETH-PLUG</circuit-pack-name>
+      </circuit-packs>
+      <connection-ports>
+        <index>1</index>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </connection-ports>
+    </degree>
+    <shared-risk-group>
+      <srg-number>1</srg-number>
+      <max-add-drop-ports>16</max-add-drop-ports>
+      <wavelengthDuplication>onePerSRG</wavelengthDuplication>
+      <circuit-packs>
+        <index>1</index>
+        <circuit-pack-name>4/0</circuit-pack-name>
+      </circuit-packs>
+    </shared-risk-group>
+    <connection-map>
+      <connection-map-number>1</connection-map-number>
+      <source>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>2</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>3</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>4</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>5</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>6</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>7</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>8</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>9</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>10</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>11</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>12</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>13</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>14</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>15</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>16</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>17</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>2/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>18</connection-map-number>
+      <source>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>L1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </destination>
+      <destination>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>19</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>20</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C2</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>21</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C3</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>22</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C4</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>23</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C5</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>24</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C6</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>25</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C7</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>26</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C8</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>27</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C9</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>28</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C10</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>29</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C11</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>30</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C12</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>31</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C13</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>32</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C14</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>33</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C15</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+    <connection-map>
+      <connection-map-number>34</connection-map-number>
+      <source>
+        <circuit-pack-name>4/0</circuit-pack-name>
+        <port-name>C16</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>3/0</circuit-pack-name>
+        <port-name>E1</port-name>
+      </destination>
+    </connection-map>
+  </org-openroadm-device>
+</data>
diff --git a/tests/sample_configs/ord_2.1/oper-XPDRA.xml b/tests/sample_configs/ord_2.1/oper-XPDRA.xml
new file mode 100644 (file)
index 0000000..ac31d67
--- /dev/null
@@ -0,0 +1,673 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <org-openroadm-device xmlns="http://org/openroadm/device">
+    <info>
+      <node-id>XPDRA</node-id>
+      <node-number>1</node-number>
+      <node-type>xpdr</node-type>
+      <clli>NodeA</clli>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>00001</serial-id>
+      <ipAddress>127.0.0.10</ipAddress>
+      <prefix-length>28</prefix-length>
+      <defaultGateway>127.0.0.20</defaultGateway>
+      <source>static</source>
+      <current-ipAddress>127.0.0.10</current-ipAddress>
+      <current-prefix-length>28</current-prefix-length>
+      <macAddress>aa:aa:aa:aa:aa:aa</macAddress>
+      <softwareVersion>1.0</softwareVersion>
+      <template>TPCE-XPDR001</template>
+      <current-datetime>2017-08-29T15:58:01+00:00</current-datetime>
+      <geoLocation>
+        <latitude>33</latitude>
+        <longitude>-96</longitude>
+      </geoLocation>
+    </info>
+    <users>
+      <user>
+        <name>openroadm</name>
+        <password>openroadm</password>
+        <group>sudo</group>
+      </user>
+    </users>
+    <shelves>
+      <shelf-name>1</shelf-name>
+      <shelf-type>pizza</shelf-type>
+      <rack>XYZ</rack>
+      <shelf-position>1</shelf-position>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>0001</serial-id>
+      <type>pizza</type>
+      <product-code>zzz</product-code>
+      <manufacture-date>2017-04-01T00:00:00+00:00</manufacture-date>
+      <clei>www</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <due-date>2017-02-24T15:56:10+00:00</due-date>
+      <slots>
+        <slot-name>0</slot-name>
+        <label>0</label>
+        <provisioned-circuit-pack>1/0</provisioned-circuit-pack>
+      </slots>
+    </shelves>
+    <circuit-packs>
+      <circuit-pack-name>1/0</circuit-pack-name>
+      <circuit-pack-type>TSP100G</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>VendorA</vendor>
+      <model>WDM80</model>
+      <serial-id>aaaaa</serial-id>
+      <type>TSP</type>
+      <product-code>TSP100G1</product-code>
+      <manufacture-date>2017-04-01T00:00:00+00:00</manufacture-date>
+      <clei>xxx</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <circuit-pack-category>
+        <type>circuitPack</type>
+      </circuit-pack-category>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>1</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <due-date>2017-04-12T15:56:10+00:00</due-date>
+      <cp-slots>
+        <slot-name>1</slot-name>
+        <label>1</label>
+        <provisioned-circuit-pack>1/0/1-PLUG-NET
+        </provisioned-circuit-pack>
+      </cp-slots>
+      <cp-slots>
+        <slot-name>2</slot-name>
+        <label>2</label>
+        <provisioned-circuit-pack>1/0/2-PLUG-CLIENT
+        </provisioned-circuit-pack>
+      </cp-slots>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>1/0/1-PLUG-NET</circuit-pack-name>
+      <circuit-pack-type>pluggable</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>CFP2</model>
+      <serial-id>ssss</serial-id>
+      <type>Coherent</type>
+      <product-code>T100N</product-code>
+      <manufacture-date>2017-04-01T00:00:00+00:00</manufacture-date>
+      <clei>tttt</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <circuit-pack-category>
+        <type>other</type>
+      </circuit-pack-category>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>1</shelf>
+      <slot>0</slot>
+      <subSlot>1</subSlot>
+      <due-date>2017-04-14T15:56:10+00:00</due-date>
+      <parent-circuit-pack>
+        <circuit-pack-name>1/0</circuit-pack-name>
+        <cp-slot-name>1</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>1</port-name>
+        <port-type>CFP2</port-type>
+        <port-qual>xpdr-network</port-qual>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>XPDRA-NETWORK</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <logical-connection-point>NETWORK1</logical-connection-point>
+        <transponder-port>
+        </transponder-port>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>1/0/2-PLUG-CLIENT</circuit-pack-name>
+      <circuit-pack-type>pluggable</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>QSFP28</model>
+      <serial-id>xxxx</serial-id>
+      <type>QSFP28</type>
+      <product-code>100GELR4</product-code>
+      <manufacture-date>2017-03-01T00:00:00+00:00</manufacture-date>
+      <clei>ccccc</clei>
+      <hardware-version>01</hardware-version>
+      <circuit-pack-category>
+        <type>other</type>
+      </circuit-pack-category>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>1</shelf>
+      <slot>0</slot>
+      <subSlot>2</subSlot>
+      <due-date>2017-04-14T15:56:10+00:00</due-date>
+      <parent-circuit-pack>
+        <circuit-pack-name>1/0</circuit-pack-name>
+        <cp-slot-name>2</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>1</port-name>
+        <port-type>QSFP28</port-type>
+        <port-qual>xpdr-client</port-qual>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>XPDRA-CLIENT</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <logical-connection-point>CLIENT1</logical-connection-point>
+        <transponder-port>
+        </transponder-port>
+      </ports>
+    </circuit-packs>
+    <wavelength-map>
+      <wavelengths>
+        <wavelength-number>1</wavelength-number>
+        <center-frequency>196.1</center-frequency>
+        <wavelength>1528.77</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>2</wavelength-number>
+        <center-frequency>196.05</center-frequency>
+        <wavelength>1529.16</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>3</wavelength-number>
+        <center-frequency>196.0</center-frequency>
+        <wavelength>1529.55</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>4</wavelength-number>
+        <center-frequency>195.95</center-frequency>
+        <wavelength>1529.94</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>5</wavelength-number>
+        <center-frequency>195.9</center-frequency>
+        <wavelength>1530.33</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>6</wavelength-number>
+        <center-frequency>195.85</center-frequency>
+        <wavelength>1530.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>7</wavelength-number>
+        <center-frequency>195.8</center-frequency>
+        <wavelength>1531.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>8</wavelength-number>
+        <center-frequency>195.75</center-frequency>
+        <wavelength>1531.51</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>9</wavelength-number>
+        <center-frequency>195.7</center-frequency>
+        <wavelength>1531.9</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>10</wavelength-number>
+        <center-frequency>195.65</center-frequency>
+        <wavelength>1532.29</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>11</wavelength-number>
+        <center-frequency>195.6</center-frequency>
+        <wavelength>1532.68</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>12</wavelength-number>
+        <center-frequency>195.55</center-frequency>
+        <wavelength>1533.07</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>13</wavelength-number>
+        <center-frequency>195.5</center-frequency>
+        <wavelength>1533.47</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>14</wavelength-number>
+        <center-frequency>195.45</center-frequency>
+        <wavelength>1533.86</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>15</wavelength-number>
+        <center-frequency>195.4</center-frequency>
+        <wavelength>1534.25</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>16</wavelength-number>
+        <center-frequency>195.35</center-frequency>
+        <wavelength>1534.64</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>17</wavelength-number>
+        <center-frequency>195.3</center-frequency>
+        <wavelength>1535.04</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>18</wavelength-number>
+        <center-frequency>195.25</center-frequency>
+        <wavelength>1535.43</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>19</wavelength-number>
+        <center-frequency>195.2</center-frequency>
+        <wavelength>1535.82</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>20</wavelength-number>
+        <center-frequency>195.15</center-frequency>
+        <wavelength>1536.22</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>21</wavelength-number>
+        <center-frequency>195.1</center-frequency>
+        <wavelength>1536.61</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>22</wavelength-number>
+        <center-frequency>195.05</center-frequency>
+        <wavelength>1537.0</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>23</wavelength-number>
+        <center-frequency>195.0</center-frequency>
+        <wavelength>1537.4</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>24</wavelength-number>
+        <center-frequency>194.95</center-frequency>
+        <wavelength>1537.79</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>25</wavelength-number>
+        <center-frequency>194.9</center-frequency>
+        <wavelength>1538.19</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>26</wavelength-number>
+        <center-frequency>194.85</center-frequency>
+        <wavelength>1538.58</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>27</wavelength-number>
+        <center-frequency>194.8</center-frequency>
+        <wavelength>1538.98</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>28</wavelength-number>
+        <center-frequency>194.75</center-frequency>
+        <wavelength>1539.37</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>29</wavelength-number>
+        <center-frequency>194.7</center-frequency>
+        <wavelength>1539.77</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>30</wavelength-number>
+        <center-frequency>194.65</center-frequency>
+        <wavelength>1540.16</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>31</wavelength-number>
+        <center-frequency>194.6</center-frequency>
+        <wavelength>1540.56</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>32</wavelength-number>
+        <center-frequency>194.55</center-frequency>
+        <wavelength>1540.95</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>33</wavelength-number>
+        <center-frequency>194.5</center-frequency>
+        <wavelength>1541.35</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>34</wavelength-number>
+        <center-frequency>194.45</center-frequency>
+        <wavelength>1541.75</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>35</wavelength-number>
+        <center-frequency>194.4</center-frequency>
+        <wavelength>1542.14</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>36</wavelength-number>
+        <center-frequency>194.35</center-frequency>
+        <wavelength>1542.54</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>37</wavelength-number>
+        <center-frequency>194.3</center-frequency>
+        <wavelength>1542.94</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>38</wavelength-number>
+        <center-frequency>194.25</center-frequency>
+        <wavelength>1543.33</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>39</wavelength-number>
+        <center-frequency>194.2</center-frequency>
+        <wavelength>1543.73</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>40</wavelength-number>
+        <center-frequency>194.15</center-frequency>
+        <wavelength>1544.13</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>41</wavelength-number>
+        <center-frequency>194.1</center-frequency>
+        <wavelength>1544.53</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>42</wavelength-number>
+        <center-frequency>194.05</center-frequency>
+        <wavelength>1544.92</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>43</wavelength-number>
+        <center-frequency>194.0</center-frequency>
+        <wavelength>1545.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>44</wavelength-number>
+        <center-frequency>193.95</center-frequency>
+        <wavelength>1545.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>45</wavelength-number>
+        <center-frequency>193.9</center-frequency>
+        <wavelength>1546.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>46</wavelength-number>
+        <center-frequency>193.85</center-frequency>
+        <wavelength>1546.52</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>47</wavelength-number>
+        <center-frequency>193.8</center-frequency>
+        <wavelength>1546.92</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>48</wavelength-number>
+        <center-frequency>193.75</center-frequency>
+        <wavelength>1547.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>49</wavelength-number>
+        <center-frequency>193.7</center-frequency>
+        <wavelength>1547.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>50</wavelength-number>
+        <center-frequency>193.65</center-frequency>
+        <wavelength>1548.11</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>51</wavelength-number>
+        <center-frequency>193.6</center-frequency>
+        <wavelength>1548.51</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>52</wavelength-number>
+        <center-frequency>193.55</center-frequency>
+        <wavelength>1548.91</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>53</wavelength-number>
+        <center-frequency>193.5</center-frequency>
+        <wavelength>1549.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>54</wavelength-number>
+        <center-frequency>193.45</center-frequency>
+        <wavelength>1549.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>55</wavelength-number>
+        <center-frequency>193.4</center-frequency>
+        <wavelength>1550.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>56</wavelength-number>
+        <center-frequency>193.35</center-frequency>
+        <wavelength>1550.52</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>57</wavelength-number>
+        <center-frequency>193.3</center-frequency>
+        <wavelength>1550.92</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>58</wavelength-number>
+        <center-frequency>193.25</center-frequency>
+        <wavelength>1551.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>59</wavelength-number>
+        <center-frequency>193.2</center-frequency>
+        <wavelength>1551.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>60</wavelength-number>
+        <center-frequency>193.15</center-frequency>
+        <wavelength>1552.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>61</wavelength-number>
+        <center-frequency>193.1</center-frequency>
+        <wavelength>1552.52</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>62</wavelength-number>
+        <center-frequency>193.05</center-frequency>
+        <wavelength>1552.93</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>63</wavelength-number>
+        <center-frequency>193.0</center-frequency>
+        <wavelength>1553.33</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>64</wavelength-number>
+        <center-frequency>192.95</center-frequency>
+        <wavelength>1553.73</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>65</wavelength-number>
+        <center-frequency>192.9</center-frequency>
+        <wavelength>1554.13</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>66</wavelength-number>
+        <center-frequency>192.85</center-frequency>
+        <wavelength>1554.54</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>67</wavelength-number>
+        <center-frequency>192.8</center-frequency>
+        <wavelength>1554.94</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>68</wavelength-number>
+        <center-frequency>192.75</center-frequency>
+        <wavelength>1555.34</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>69</wavelength-number>
+        <center-frequency>192.7</center-frequency>
+        <wavelength>1555.75</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>70</wavelength-number>
+        <center-frequency>192.65</center-frequency>
+        <wavelength>1556.15</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>71</wavelength-number>
+        <center-frequency>192.6</center-frequency>
+        <wavelength>1556.55</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>72</wavelength-number>
+        <center-frequency>192.55</center-frequency>
+        <wavelength>1556.96</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>73</wavelength-number>
+        <center-frequency>192.5</center-frequency>
+        <wavelength>1557.36</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>74</wavelength-number>
+        <center-frequency>192.45</center-frequency>
+        <wavelength>1557.77</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>75</wavelength-number>
+        <center-frequency>192.4</center-frequency>
+        <wavelength>1558.17</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>76</wavelength-number>
+        <center-frequency>192.35</center-frequency>
+        <wavelength>1558.58</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>77</wavelength-number>
+        <center-frequency>192.3</center-frequency>
+        <wavelength>1558.98</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>78</wavelength-number>
+        <center-frequency>192.25</center-frequency>
+        <wavelength>1559.39</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>79</wavelength-number>
+        <center-frequency>192.2</center-frequency>
+        <wavelength>1559.79</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>80</wavelength-number>
+        <center-frequency>192.15</center-frequency>
+        <wavelength>1560.2</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>81</wavelength-number>
+        <center-frequency>192.1</center-frequency>
+        <wavelength>1560.61</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>82</wavelength-number>
+        <center-frequency>192.05</center-frequency>
+        <wavelength>1561.01</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>83</wavelength-number>
+        <center-frequency>192.0</center-frequency>
+        <wavelength>1561.42</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>84</wavelength-number>
+        <center-frequency>191.95</center-frequency>
+        <wavelength>1561.83</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>85</wavelength-number>
+        <center-frequency>191.9</center-frequency>
+        <wavelength>1562.23</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>86</wavelength-number>
+        <center-frequency>191.85</center-frequency>
+        <wavelength>1562.64</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>87</wavelength-number>
+        <center-frequency>191.8</center-frequency>
+        <wavelength>1563.05</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>88</wavelength-number>
+        <center-frequency>191.75</center-frequency>
+        <wavelength>1563.45</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>89</wavelength-number>
+        <center-frequency>191.7</center-frequency>
+        <wavelength>1563.86</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>90</wavelength-number>
+        <center-frequency>191.65</center-frequency>
+        <wavelength>1564.27</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>91</wavelength-number>
+        <center-frequency>191.6</center-frequency>
+        <wavelength>1564.68</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>92</wavelength-number>
+        <center-frequency>191.55</center-frequency>
+        <wavelength>1565.09</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>93</wavelength-number>
+        <center-frequency>191.5</center-frequency>
+        <wavelength>1565.5</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>94</wavelength-number>
+        <center-frequency>191.45</center-frequency>
+        <wavelength>1565.9</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>95</wavelength-number>
+        <center-frequency>191.4</center-frequency>
+        <wavelength>1566.31</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>96</wavelength-number>
+        <center-frequency>191.35</center-frequency>
+        <wavelength>1566.72</wavelength>
+      </wavelengths>
+    </wavelength-map>
+    <internal-link>
+      <internal-link-name>1/0/2-PLUG-CLIENT-to-1/0/1-PLUG-NET
+      </internal-link-name>
+      <source>
+        <circuit-pack-name>1/0/2-PLUG-CLIENT</circuit-pack-name>
+        <port-name>1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>1/0/1-PLUG-NET</circuit-pack-name>
+        <port-name>1</port-name>
+      </destination>
+    </internal-link>
+    <connection-map>
+      <connection-map-number>1</connection-map-number>
+      <source>
+        <circuit-pack-name>1/0/2-PLUG-CLIENT</circuit-pack-name>
+        <port-name>1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>1/0/1-PLUG-NET</circuit-pack-name>
+        <port-name>1</port-name>
+      </destination>
+    </connection-map>
+  </org-openroadm-device>
+</data>
diff --git a/tests/sample_configs/ord_2.1/oper-XPDRC.xml b/tests/sample_configs/ord_2.1/oper-XPDRC.xml
new file mode 100644 (file)
index 0000000..080954b
--- /dev/null
@@ -0,0 +1,673 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <org-openroadm-device xmlns="http://org/openroadm/device">
+    <info>
+      <node-id>XPDRC</node-id>
+      <node-number>1</node-number>
+      <node-type>xpdr</node-type>
+      <clli>NodeC</clli>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>00001</serial-id>
+      <ipAddress>127.0.0.12</ipAddress>
+      <prefix-length>28</prefix-length>
+      <defaultGateway>127.0.0.20</defaultGateway>
+      <source>static</source>
+      <current-ipAddress>127.0.0.11</current-ipAddress>
+      <current-prefix-length>28</current-prefix-length>
+      <macAddress>aa:aa:aa:aa:aa:aa</macAddress>
+      <softwareVersion>1.0</softwareVersion>
+      <template>TPCE-XPDR001</template>
+      <current-datetime>2017-08-29T15:58:01+00:00</current-datetime>
+      <geoLocation>
+        <latitude>33</latitude>
+        <longitude>-96</longitude>
+      </geoLocation>
+    </info>
+    <users>
+      <user>
+        <name>openroadm</name>
+        <password>openroadm</password>
+        <group>sudo</group>
+      </user>
+    </users>
+    <shelves>
+      <shelf-name>1</shelf-name>
+      <shelf-type>pizza</shelf-type>
+      <rack>XYZ</rack>
+      <shelf-position>1</shelf-position>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>1</model>
+      <serial-id>0001</serial-id>
+      <type>pizza</type>
+      <product-code>zzz</product-code>
+      <manufacture-date>2017-04-01T00:00:00+00:00</manufacture-date>
+      <clei>www</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <equipment-state>not-reserved-available</equipment-state>
+      <due-date>2017-02-24T15:56:10+00:00</due-date>
+      <slots>
+        <slot-name>0</slot-name>
+        <label>0</label>
+        <provisioned-circuit-pack>1/0</provisioned-circuit-pack>
+      </slots>
+    </shelves>
+    <circuit-packs>
+      <circuit-pack-name>1/0</circuit-pack-name>
+      <circuit-pack-type>TSP100G</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>VendorA</vendor>
+      <model>WDM80</model>
+      <serial-id>aaaaa</serial-id>
+      <type>TSP</type>
+      <product-code>TSP100G1</product-code>
+      <manufacture-date>2017-04-01T00:00:00+00:00</manufacture-date>
+      <clei>xxx</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <circuit-pack-category>
+        <type>circuitPack</type>
+      </circuit-pack-category>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>1</shelf>
+      <slot>0</slot>
+      <subSlot>0</subSlot>
+      <due-date>2017-04-12T15:56:10+00:00</due-date>
+      <cp-slots>
+        <slot-name>1</slot-name>
+        <label>1</label>
+        <provisioned-circuit-pack>1/0/1-PLUG-NET
+        </provisioned-circuit-pack>
+      </cp-slots>
+      <cp-slots>
+        <slot-name>2</slot-name>
+        <label>2</label>
+        <provisioned-circuit-pack>1/0/2-PLUG-CLIENT
+        </provisioned-circuit-pack>
+      </cp-slots>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>1/0/1-PLUG-NET</circuit-pack-name>
+      <circuit-pack-type>pluggable</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>CFP2</model>
+      <serial-id>ssss</serial-id>
+      <type>Coherent</type>
+      <product-code>T100N</product-code>
+      <manufacture-date>2017-04-01T00:00:00+00:00</manufacture-date>
+      <clei>tttt</clei>
+      <hardware-version>01</hardware-version>
+      <operational-state>inService</operational-state>
+      <circuit-pack-category>
+        <type>other</type>
+      </circuit-pack-category>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>1</shelf>
+      <slot>0</slot>
+      <subSlot>1</subSlot>
+      <due-date>2017-04-14T15:56:10+00:00</due-date>
+      <parent-circuit-pack>
+        <circuit-pack-name>1/0</circuit-pack-name>
+        <cp-slot-name>1</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>1</port-name>
+        <port-type>CFP2</port-type>
+        <port-qual>xpdr-network</port-qual>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>XPDRC-NETWORK</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <logical-connection-point>NETWORK1</logical-connection-point>
+        <transponder-port>
+        </transponder-port>
+      </ports>
+    </circuit-packs>
+    <circuit-packs>
+      <circuit-pack-name>1/0/2-PLUG-CLIENT</circuit-pack-name>
+      <circuit-pack-type>pluggable</circuit-pack-type>
+      <administrative-state>inService</administrative-state>
+      <vendor>vendorA</vendor>
+      <model>QSFP28</model>
+      <serial-id>xxxx</serial-id>
+      <type>QSFP28</type>
+      <product-code>100GELR4</product-code>
+      <manufacture-date>2017-03-01T00:00:00+00:00</manufacture-date>
+      <clei>ccccc</clei>
+      <hardware-version>01</hardware-version>
+      <circuit-pack-category>
+        <type>other</type>
+      </circuit-pack-category>
+      <equipment-state>not-reserved-available</equipment-state>
+      <circuit-pack-mode>NORMAL</circuit-pack-mode>
+      <shelf>1</shelf>
+      <slot>0</slot>
+      <subSlot>2</subSlot>
+      <due-date>2017-04-14T15:56:10+00:00</due-date>
+      <parent-circuit-pack>
+        <circuit-pack-name>1/0</circuit-pack-name>
+        <cp-slot-name>2</cp-slot-name>
+      </parent-circuit-pack>
+      <ports>
+        <port-name>1</port-name>
+        <port-type>QSFP28</port-type>
+        <port-qual>xpdr-client</port-qual>
+        <port-direction>bidirectional</port-direction>
+        <circuit-id>XPDRC-CLIENT</circuit-id>
+        <administrative-state>inService</administrative-state>
+        <logical-connection-point>CLIENT1</logical-connection-point>
+        <transponder-port>
+        </transponder-port>
+      </ports>
+    </circuit-packs>
+    <wavelength-map>
+      <wavelengths>
+        <wavelength-number>1</wavelength-number>
+        <center-frequency>196.1</center-frequency>
+        <wavelength>1528.77</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>2</wavelength-number>
+        <center-frequency>196.05</center-frequency>
+        <wavelength>1529.16</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>3</wavelength-number>
+        <center-frequency>196.0</center-frequency>
+        <wavelength>1529.55</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>4</wavelength-number>
+        <center-frequency>195.95</center-frequency>
+        <wavelength>1529.94</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>5</wavelength-number>
+        <center-frequency>195.9</center-frequency>
+        <wavelength>1530.33</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>6</wavelength-number>
+        <center-frequency>195.85</center-frequency>
+        <wavelength>1530.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>7</wavelength-number>
+        <center-frequency>195.8</center-frequency>
+        <wavelength>1531.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>8</wavelength-number>
+        <center-frequency>195.75</center-frequency>
+        <wavelength>1531.51</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>9</wavelength-number>
+        <center-frequency>195.7</center-frequency>
+        <wavelength>1531.9</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>10</wavelength-number>
+        <center-frequency>195.65</center-frequency>
+        <wavelength>1532.29</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>11</wavelength-number>
+        <center-frequency>195.6</center-frequency>
+        <wavelength>1532.68</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>12</wavelength-number>
+        <center-frequency>195.55</center-frequency>
+        <wavelength>1533.07</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>13</wavelength-number>
+        <center-frequency>195.5</center-frequency>
+        <wavelength>1533.47</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>14</wavelength-number>
+        <center-frequency>195.45</center-frequency>
+        <wavelength>1533.86</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>15</wavelength-number>
+        <center-frequency>195.4</center-frequency>
+        <wavelength>1534.25</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>16</wavelength-number>
+        <center-frequency>195.35</center-frequency>
+        <wavelength>1534.64</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>17</wavelength-number>
+        <center-frequency>195.3</center-frequency>
+        <wavelength>1535.04</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>18</wavelength-number>
+        <center-frequency>195.25</center-frequency>
+        <wavelength>1535.43</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>19</wavelength-number>
+        <center-frequency>195.2</center-frequency>
+        <wavelength>1535.82</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>20</wavelength-number>
+        <center-frequency>195.15</center-frequency>
+        <wavelength>1536.22</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>21</wavelength-number>
+        <center-frequency>195.1</center-frequency>
+        <wavelength>1536.61</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>22</wavelength-number>
+        <center-frequency>195.05</center-frequency>
+        <wavelength>1537.0</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>23</wavelength-number>
+        <center-frequency>195.0</center-frequency>
+        <wavelength>1537.4</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>24</wavelength-number>
+        <center-frequency>194.95</center-frequency>
+        <wavelength>1537.79</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>25</wavelength-number>
+        <center-frequency>194.9</center-frequency>
+        <wavelength>1538.19</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>26</wavelength-number>
+        <center-frequency>194.85</center-frequency>
+        <wavelength>1538.58</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>27</wavelength-number>
+        <center-frequency>194.8</center-frequency>
+        <wavelength>1538.98</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>28</wavelength-number>
+        <center-frequency>194.75</center-frequency>
+        <wavelength>1539.37</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>29</wavelength-number>
+        <center-frequency>194.7</center-frequency>
+        <wavelength>1539.77</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>30</wavelength-number>
+        <center-frequency>194.65</center-frequency>
+        <wavelength>1540.16</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>31</wavelength-number>
+        <center-frequency>194.6</center-frequency>
+        <wavelength>1540.56</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>32</wavelength-number>
+        <center-frequency>194.55</center-frequency>
+        <wavelength>1540.95</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>33</wavelength-number>
+        <center-frequency>194.5</center-frequency>
+        <wavelength>1541.35</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>34</wavelength-number>
+        <center-frequency>194.45</center-frequency>
+        <wavelength>1541.75</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>35</wavelength-number>
+        <center-frequency>194.4</center-frequency>
+        <wavelength>1542.14</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>36</wavelength-number>
+        <center-frequency>194.35</center-frequency>
+        <wavelength>1542.54</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>37</wavelength-number>
+        <center-frequency>194.3</center-frequency>
+        <wavelength>1542.94</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>38</wavelength-number>
+        <center-frequency>194.25</center-frequency>
+        <wavelength>1543.33</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>39</wavelength-number>
+        <center-frequency>194.2</center-frequency>
+        <wavelength>1543.73</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>40</wavelength-number>
+        <center-frequency>194.15</center-frequency>
+        <wavelength>1544.13</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>41</wavelength-number>
+        <center-frequency>194.1</center-frequency>
+        <wavelength>1544.53</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>42</wavelength-number>
+        <center-frequency>194.05</center-frequency>
+        <wavelength>1544.92</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>43</wavelength-number>
+        <center-frequency>194.0</center-frequency>
+        <wavelength>1545.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>44</wavelength-number>
+        <center-frequency>193.95</center-frequency>
+        <wavelength>1545.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>45</wavelength-number>
+        <center-frequency>193.9</center-frequency>
+        <wavelength>1546.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>46</wavelength-number>
+        <center-frequency>193.85</center-frequency>
+        <wavelength>1546.52</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>47</wavelength-number>
+        <center-frequency>193.8</center-frequency>
+        <wavelength>1546.92</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>48</wavelength-number>
+        <center-frequency>193.75</center-frequency>
+        <wavelength>1547.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>49</wavelength-number>
+        <center-frequency>193.7</center-frequency>
+        <wavelength>1547.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>50</wavelength-number>
+        <center-frequency>193.65</center-frequency>
+        <wavelength>1548.11</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>51</wavelength-number>
+        <center-frequency>193.6</center-frequency>
+        <wavelength>1548.51</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>52</wavelength-number>
+        <center-frequency>193.55</center-frequency>
+        <wavelength>1548.91</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>53</wavelength-number>
+        <center-frequency>193.5</center-frequency>
+        <wavelength>1549.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>54</wavelength-number>
+        <center-frequency>193.45</center-frequency>
+        <wavelength>1549.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>55</wavelength-number>
+        <center-frequency>193.4</center-frequency>
+        <wavelength>1550.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>56</wavelength-number>
+        <center-frequency>193.35</center-frequency>
+        <wavelength>1550.52</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>57</wavelength-number>
+        <center-frequency>193.3</center-frequency>
+        <wavelength>1550.92</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>58</wavelength-number>
+        <center-frequency>193.25</center-frequency>
+        <wavelength>1551.32</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>59</wavelength-number>
+        <center-frequency>193.2</center-frequency>
+        <wavelength>1551.72</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>60</wavelength-number>
+        <center-frequency>193.15</center-frequency>
+        <wavelength>1552.12</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>61</wavelength-number>
+        <center-frequency>193.1</center-frequency>
+        <wavelength>1552.52</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>62</wavelength-number>
+        <center-frequency>193.05</center-frequency>
+        <wavelength>1552.93</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>63</wavelength-number>
+        <center-frequency>193.0</center-frequency>
+        <wavelength>1553.33</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>64</wavelength-number>
+        <center-frequency>192.95</center-frequency>
+        <wavelength>1553.73</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>65</wavelength-number>
+        <center-frequency>192.9</center-frequency>
+        <wavelength>1554.13</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>66</wavelength-number>
+        <center-frequency>192.85</center-frequency>
+        <wavelength>1554.54</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>67</wavelength-number>
+        <center-frequency>192.8</center-frequency>
+        <wavelength>1554.94</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>68</wavelength-number>
+        <center-frequency>192.75</center-frequency>
+        <wavelength>1555.34</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>69</wavelength-number>
+        <center-frequency>192.7</center-frequency>
+        <wavelength>1555.75</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>70</wavelength-number>
+        <center-frequency>192.65</center-frequency>
+        <wavelength>1556.15</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>71</wavelength-number>
+        <center-frequency>192.6</center-frequency>
+        <wavelength>1556.55</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>72</wavelength-number>
+        <center-frequency>192.55</center-frequency>
+        <wavelength>1556.96</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>73</wavelength-number>
+        <center-frequency>192.5</center-frequency>
+        <wavelength>1557.36</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>74</wavelength-number>
+        <center-frequency>192.45</center-frequency>
+        <wavelength>1557.77</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>75</wavelength-number>
+        <center-frequency>192.4</center-frequency>
+        <wavelength>1558.17</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>76</wavelength-number>
+        <center-frequency>192.35</center-frequency>
+        <wavelength>1558.58</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>77</wavelength-number>
+        <center-frequency>192.3</center-frequency>
+        <wavelength>1558.98</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>78</wavelength-number>
+        <center-frequency>192.25</center-frequency>
+        <wavelength>1559.39</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>79</wavelength-number>
+        <center-frequency>192.2</center-frequency>
+        <wavelength>1559.79</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>80</wavelength-number>
+        <center-frequency>192.15</center-frequency>
+        <wavelength>1560.2</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>81</wavelength-number>
+        <center-frequency>192.1</center-frequency>
+        <wavelength>1560.61</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>82</wavelength-number>
+        <center-frequency>192.05</center-frequency>
+        <wavelength>1561.01</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>83</wavelength-number>
+        <center-frequency>192.0</center-frequency>
+        <wavelength>1561.42</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>84</wavelength-number>
+        <center-frequency>191.95</center-frequency>
+        <wavelength>1561.83</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>85</wavelength-number>
+        <center-frequency>191.9</center-frequency>
+        <wavelength>1562.23</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>86</wavelength-number>
+        <center-frequency>191.85</center-frequency>
+        <wavelength>1562.64</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>87</wavelength-number>
+        <center-frequency>191.8</center-frequency>
+        <wavelength>1563.05</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>88</wavelength-number>
+        <center-frequency>191.75</center-frequency>
+        <wavelength>1563.45</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>89</wavelength-number>
+        <center-frequency>191.7</center-frequency>
+        <wavelength>1563.86</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>90</wavelength-number>
+        <center-frequency>191.65</center-frequency>
+        <wavelength>1564.27</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>91</wavelength-number>
+        <center-frequency>191.6</center-frequency>
+        <wavelength>1564.68</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>92</wavelength-number>
+        <center-frequency>191.55</center-frequency>
+        <wavelength>1565.09</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>93</wavelength-number>
+        <center-frequency>191.5</center-frequency>
+        <wavelength>1565.5</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>94</wavelength-number>
+        <center-frequency>191.45</center-frequency>
+        <wavelength>1565.9</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>95</wavelength-number>
+        <center-frequency>191.4</center-frequency>
+        <wavelength>1566.31</wavelength>
+      </wavelengths>
+      <wavelengths>
+        <wavelength-number>96</wavelength-number>
+        <center-frequency>191.35</center-frequency>
+        <wavelength>1566.72</wavelength>
+      </wavelengths>
+    </wavelength-map>
+    <internal-link>
+      <internal-link-name>1/0/2-PLUG-CLIENT-to-1/0/1-PLUG-NET
+      </internal-link-name>
+      <source>
+        <circuit-pack-name>1/0/2-PLUG-CLIENT</circuit-pack-name>
+        <port-name>1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>1/0/1-PLUG-NET</circuit-pack-name>
+        <port-name>1</port-name>
+      </destination>
+    </internal-link>
+    <connection-map>
+      <connection-map-number>1</connection-map-number>
+      <source>
+        <circuit-pack-name>1/0/2-PLUG-CLIENT</circuit-pack-name>
+        <port-name>1</port-name>
+      </source>
+      <destination>
+        <circuit-pack-name>1/0/1-PLUG-NET</circuit-pack-name>
+        <port-name>1</port-name>
+      </destination>
+    </connection-map>
+  </org-openroadm-device>
+</data>