Merge "Add sal-netconf-connector unit tests"
authorTomas Cere <tcere@cisco.com>
Mon, 24 Oct 2016 10:17:44 +0000 (10:17 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 24 Oct 2016 10:17:44 +0000 (10:17 +0000)
207 files changed:
features/netconf-connector/pom.xml
features/netconf-connector/src/main/features/features.xml
features/netconf/pom.xml
features/netconf/src/main/features/features.xml
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/InitialStateProvider.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeListener.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeManager.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeManagerCallback.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RemoteNodeListener.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RoleChangeListener.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RoleChangeStrategy.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/StateAggregator.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/TopologyManager.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/TopologyManagerCallback.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleNodeManagerCallback.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleSingleStateAggregator.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleTopology.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleTopologyManagerCallback.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/LoggingSalNodeWriter.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseNodeManager.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseTopologyManager.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NodeRoleChangeStrategy.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NodeWriter.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NoopRoleChangeStrategy.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/SalNodeWriter.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyRoleChangeStrategy.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/CustomIdentifyMessage.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/CustomIdentifyMessageReply.java [deleted file]
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/NormalizedNodeMessage.java [deleted file]
netconf/messagebus-netconf/src/main/java/org/opendaylight/netconf/messagebus/eventsources/netconf/NetconfEventSourceRegistration.java
netconf/messagebus-netconf/src/test/java/org/opendaylight/netconf/messagebus/eventsources/netconf/NetconfTestUtils.java
netconf/netconf-artifacts/pom.xml
netconf/netconf-console/pom.xml
netconf/netconf-console/src/main/java/org/opendaylight/netconf/console/commands/NetconfCommandUtils.java
netconf/netconf-console/src/main/java/org/opendaylight/netconf/console/commands/NetconfConnectDeviceCommand.java
netconf/netconf-console/src/main/java/org/opendaylight/netconf/console/commands/NetconfDisconnectDeviceCommand.java
netconf/netconf-console/src/main/java/org/opendaylight/netconf/console/commands/NetconfShowDeviceCommand.java
netconf/netconf-console/src/main/java/org/opendaylight/netconf/console/commands/NetconfUpdateDeviceCommand.java
netconf/netconf-console/src/main/java/org/opendaylight/netconf/console/impl/NetconfCommandsImpl.java
netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/commands/NetconfCommandUtilsTest.java [new file with mode: 0644]
netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/commands/NetconfCommandsImplCallsTest.java [new file with mode: 0644]
netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/impl/NetconfCommandsImplTest.java [new file with mode: 0644]
netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/impl/NetconfConsoleProviderTest.java [new file with mode: 0644]
netconf/netconf-console/src/test/resources/schemas/ietf-inet-types@2013-07-15.yang [new file with mode: 0644]
netconf/netconf-console/src/test/resources/schemas/netconf-node-topology.yang [new file with mode: 0644]
netconf/netconf-console/src/test/resources/schemas/network-topology@2013-10-21.yang [new file with mode: 0644]
netconf/netconf-console/src/test/resources/schemas/yang-ext.yang [new file with mode: 0644]
netconf/netconf-notifications-api/src/test/java/org/opendaylight/netconf/notifications/NetconfNotificationTest.java [new file with mode: 0644]
netconf/netconf-ssh/pom.xml
netconf/netconf-ssh/src/main/java/org/opendaylight/netconf/ssh/osgi/NetconfSSHActivator.java
netconf/netconf-tcp/pom.xml
netconf/netconf-tcp/src/main/java/org/opendaylight/netconf/tcp/osgi/NetconfTCPActivator.java
netconf/netconf-topology-config/pom.xml
netconf/netconf-topology-config/src/main/resources/initial/02-clustered-netconf-topology.xml [deleted file]
netconf/netconf-topology-singleton/pom.xml [moved from netconf/abstract-topology/pom.xml with 64% similarity]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/NetconfDOMTransaction.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/NetconfTopologySingletonService.java [moved from netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/NetconfDeviceDataBrokerProxy.java with 50% similarity]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/RemoteDeviceConnector.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/RemoteOperationTxProcessor.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfDOMDataBroker.java [moved from netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBroker.java with 68% similarity]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfNodeManager.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyContext.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManager.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/ProxyDOMRpcService.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/ProxyYangTextSourceProvider.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImpl.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteOperationTxProcessorImpl.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/SlaveSalFacade.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/actors/NetconfNodeActor.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfMasterDOMTransaction.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfProxyDOMTransaction.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfReadOnlyTransaction.java [moved from netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransaction.java with 64% similarity]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfWriteOnlyTransaction.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfConnectorDTO.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologySetup.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologyUtils.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/AskForMasterMountPoint.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/CreateInitialMasterActorData.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/MasterActorDataInitialized.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/NormalizedNodeMessage.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/RefreshSetupMasterActorData.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/RegisterMountPoint.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/UnregisterSlaveMountPoint.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/YangTextSchemaSourceRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/CancelRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/DeleteRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/EmptyReadResponse.java [moved from netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/AnnounceMasterMountPoint.java with 55% similarity]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/ExistsRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/MergeRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/PutRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/ReadRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/SubmitFailedReply.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/SubmitReply.java [moved from netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/AnnounceMasterMountPointDown.java with 53% similarity]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/SubmitRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/TransactionRequest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/main/resources/org/opendaylight/blueprint/netconf-topology-singleton.xml [new file with mode: 0644]
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfNodeActorTest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManagerTest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImplTest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/TestingRemoteDeviceConnectorImpl.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/tx/ReadOnlyTransactionTest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/tx/WriteOnlyTransactionTest.java [new file with mode: 0644]
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologyUtilTest.java [new file with mode: 0644]
netconf/netconf-topology/pom.xml
netconf/netconf-topology/src/main/java/org/opendaylight/controller/config/yang/clustered/netconf/topology/ClusteredNetconfTopologyModule.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/controller/config/yang/clustered/netconf/topology/ClusteredNetconfTopologyModuleFactory.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/NetconfTopology.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfNodeManagerCallback.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfNodeOperationalDataAggregator.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyManagerCallback.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriter.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyUtil.java [moved from netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyUtil.java with 84% similarity]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredDeviceSourcesResolver.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredDeviceSourcesResolverImpl.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDevice.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceCommunicator.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceMountInstanceProxy.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProvider.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProviderImpl.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProviderOnSameNodeException.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceMasterDataBroker.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ProxyNetconfDeviceDataBroker.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacade.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceClusteredDeviceSourcesResolverUp.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceMasterOnSameNodeUp.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceMasterSourceProviderUp.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyWriteOnlyTransaction.java [deleted file]
netconf/netconf-topology/src/main/yang/clustered-netconf-topology.yang [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/ActorTest.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/TestingEntityOwnershipService.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/TestingTopologyDispatcher.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfNodeOperationalDataAggregatorTest.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriterTest.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceCommunicatorTest.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBrokerTest.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacadeTest.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransactionTest.java [deleted file]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyWriteOnlyTransactionTest.java [deleted file]
netconf/netconf-topology/src/test/resources/netconf-node1.conf [deleted file]
netconf/netconf-topology/src/test/resources/netconf-node2.conf [deleted file]
netconf/netconf-topology/src/test/resources/netconf-node3.conf [deleted file]
netconf/netconf-topology/src/test/resources/test.conf [deleted file]
netconf/netconf-util/pom.xml
netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfigUtil.java
netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfiguration.java [new file with mode: 0644]
netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfigurationActivator.java [new file with mode: 0644]
netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfigurationHolder.java [new file with mode: 0644]
netconf/netconf-util/src/main/resources/netconf.cfg [new file with mode: 0644]
netconf/netconf-util/src/test/resources/netconfMessages/copy-config.xml [new file with mode: 0644]
netconf/netconf-util/src/test/resources/netconfMessages/edit-config-test-module-running.xml [new file with mode: 0644]
netconf/netconf-util/src/test/resources/netconfMessages/edit-config-test-module.xml [new file with mode: 0644]
netconf/netconf-util/src/test/resources/netconfMessages/getConfig_candidate-filter.xml [new file with mode: 0644]
netconf/netconf-util/src/test/resources/netconfMessages/lock-running.xml [new file with mode: 0644]
netconf/netconf-util/src/test/resources/netconfMessages/rpc-reply_get.xml [new file with mode: 0644]
netconf/netconf-util/src/test/resources/netconfMessages/unlock-running.xml [new file with mode: 0644]
netconf/netconf-util/src/test/resources/netconfMessages/validate-running.xml [new file with mode: 0644]
netconf/pom.xml
netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfDeviceCapabilities.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfSessionPreferences.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceTopologyAdapter.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java
netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDeviceTest.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadWriteTxTest.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/TxTestUtils.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTxTest.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTxTest.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTxTest.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/util/NetconfBaseOpsTest.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/util/NodeContainerProxyTest.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/test/resources/schemas/netconf-node-topology.yang
netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/TesttoolParameters.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/common/wrapper/services/ServicesWrapperImpl.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/AbstractIdentifierAwareJaxRsProvider.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/ModuleImpl.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/RestconfModulesServiceImpl.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/RestconfOperationsServiceImpl.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/parser/ParserIdentifier.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/AbstractBodyReaderTest.java [moved from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17AbstractBodyReaderTest.java with 78% similarity]
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/JsonBodyReaderTest.java [moved from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17JsonBodyReaderTest.java with 92% similarity]
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/JsonPATCHBodyReaderMountPointTest.java [new file with mode: 0644]
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/JsonPATCHBodyReaderTest.java [moved from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft17JsonPATCHBodyReader.java with 92% similarity]
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/XmlBodyReaderTest.java [moved from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17XmlBodyReaderTest.java with 92% similarity]
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/XmlPATCHBodyReaderMountPointTest.java [new file with mode: 0644]
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/XmlPATCHBodyReaderTest.java [moved from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft17XmlPATCHBodyReader.java with 92% similarity]
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/rest/services/impl/RestconfModulesServiceTest.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImplTest.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtilTest.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/utils/parser/ParserIdentifierTest.java
restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/BaseYangSwaggerGenerator.java
restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/ModelGenerator.java
restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/model/builder/OperationBuilder.java
restconf/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java

index cf4131026bb253e2e3b452019b1adb97074261c5..9600b0ba5aa50cd7c8c73458da2c8ed50c608af4 100644 (file)
       <classifier>config</classifier>
       <type>xml</type>
     </dependency>
-    <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>abstract-topology</artifactId>
-    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-topology</artifactId>
       <classifier>config</classifier>
       <type>xml</type>
     </dependency>
-    <dependency>
-       <groupId>${project.groupId}</groupId>
-       <artifactId>netconf-topology-config</artifactId>
-       <classifier>clustered-config</classifier>
-       <type>xml</type>
-    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-tcp</artifactId>
       <groupId>org.bouncycastle</groupId>
       <artifactId>bcprov-jdk15on</artifactId>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-topology-singleton</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>${project.groupId}</groupId>
index fe3e66dba3ced96accabdbc0f98c5b10115d1d8a..27c883f2211198353299047f1fa5da04474a23d3 100644 (file)
@@ -38,7 +38,6 @@
         <bundle>mvn:org.opendaylight.netconf/sal-netconf-connector/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.controller.model/model-inventory/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.netconf/netconf-topology/{{VERSION}}</bundle>
-        <bundle>mvn:org.opendaylight.netconf/abstract-topology/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.netconf/sal-netconf-connector/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.netconf/netconf-config-dispatcher/{{VERSION}}</bundle>
         <configfile finalname='${config.configfile.directory}/${config.netconf.client.configfile}'>mvn:org.opendaylight.netconf/netconf-config/{{VERSION}}/xml/config</configfile>
         <configfile finalname='${config.configfile.directory}/${config.netconf.topology.configfile}'>mvn:org.opendaylight.netconf/netconf-topology-config/{{VERSION}}/xml/config</configfile>
     </feature>
 
-    <feature name='odl-netconf-clustered-topology' version='${project.version}' description="OpenDaylight :: Clustered Netconf Topology :: Netconf Connector + Netconf SSH Server + Clustered Netconf configuration via config topology datastore">
-        <feature version='${netconf.version}'>odl-netconf-ssh</feature>
+    <feature name='odl-netconf-clustered-topology' version='${project.version}' description="OpenDaylight :: Clustered Netconf Topology :: Netconf Connector + Netconf SSH Server">
+        <feature version='${project.version}'>odl-netconf-ssh</feature>
         <feature version='${project.version}'>odl-netconf-connector</feature>
-        <configfile finalname='${config.configfile.directory}/${config.netconf.topology.configfile}'>mvn:org.opendaylight.netconf/netconf-topology-config/{{VERSION}}/xml/clustered-config</configfile>
+        <bundle>mvn:org.opendaylight.netconf/netconf-topology-singleton/{{VERSION}}</bundle>
     </feature>
 
     <feature name='odl-netconf-console' version='${project.version}' description="OpenDaylight :: Netconf Console + Karaf CLI for netconf CRUD operations">
index 4862a9523ad60c767841dde63a4283fa7b4762ad..b413f6b838d807eb4f1cc2fd2eb1e545b8db83e6 100644 (file)
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-util</artifactId>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-util</artifactId>
+      <type>cfg</type>
+      <classifier>config</classifier>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-impl</artifactId>
index 645f9852823bfc3e6e72f3992ecaf812f654b02a..b43653d2a05fd2c75bfdc294fe6b2d32c9dac2cf 100644 (file)
@@ -44,6 +44,7 @@
     <feature version='${project.version}'>odl-netconf-mapping-api</feature>
     <feature version='${yangtools.version}'>odl-yangtools-yang-data</feature>
     <bundle>mvn:org.opendaylight.netconf/netconf-util/{{VERSION}}</bundle>
+    <configfile finalname="etc/netconf.cfg">mvn:org.opendaylight.netconf/netconf-util/{{VERSION}}/cfg/config</configfile>
   </feature>
 
   <feature name='odl-netconf-impl' version='${project.version}' description="OpenDaylight :: Netconf :: Impl">
   </feature>
 
   <feature name='odl-netconf-ssh' version='${project.version}' description="OpenDaylight :: Netconf Connector :: SSH">
+    <feature version='${project.version}'>odl-netconf-util</feature>
     <feature version='${project.version}'>odl-netconf-tcp</feature>
     <feature version='${project.version}'>odl-aaa-netconf-plugin</feature>
     <bundle>mvn:org.opendaylight.netconf/netconf-ssh/{{VERSION}}</bundle>
   </feature>
 
   <feature name='odl-netconf-tcp' version='${project.version}' description="OpenDaylight :: Netconf Connector :: TCP">
+    <feature version='${project.version}'>odl-netconf-util</feature>
     <feature version='${project.version}'>odl-netconf-impl</feature>
     <feature version='${config.version}'>odl-config-netty</feature>
     <bundle>mvn:org.opendaylight.netconf/netconf-tcp/{{VERSION}}</bundle>
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/InitialStateProvider.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/InitialStateProvider.java
deleted file mode 100644 (file)
index ae53a9d..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import com.google.common.annotations.Beta;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-
-/**
- * Provides initial and failed state for NodeManagers
- */
-@Beta
-public interface InitialStateProvider {
-    @Nonnull
-    Node getInitialState(@Nonnull final NodeId nodeId, @Nonnull final Node configNode);
-
-    @Nonnull
-    Node getFailedState(@Nonnull final NodeId nodeId, @Nullable final Node configNode);
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeListener.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeListener.java
deleted file mode 100644 (file)
index b49d3bb..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import com.google.common.annotations.Beta;
-import com.google.common.util.concurrent.ListenableFuture;
-import javax.annotation.Nonnull;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-
-/**
- * Node events that happen on a single node on cluster, for a method to notify remote nodes of these events look into RemoteNodeListener
- */
-@Beta
-public interface NodeListener extends RoleChangeListener {
-
-    @Nonnull ListenableFuture<Node> onNodeCreated(@Nonnull NodeId nodeId, @Nonnull Node configNode);
-
-    @Nonnull ListenableFuture<Node> onNodeUpdated(@Nonnull NodeId nodeId, @Nonnull Node configNode);
-
-    @Nonnull ListenableFuture<Void> onNodeDeleted(@Nonnull NodeId nodeId);
-
-    @Nonnull ListenableFuture<Node> getCurrentStatusForNode(@Nonnull NodeId nodeId);
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeManager.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeManager.java
deleted file mode 100644 (file)
index c8ca14d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import akka.actor.TypedActor.Receiver;
-import com.google.common.annotations.Beta;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-
-/**
- * Node manager that handles communication between node managers and delegates calls to the customizable NodeManagerCallback
- */
-@Beta
-public interface NodeManager extends InitialStateProvider, NodeListener, Receiver, RemoteNodeListener, RemoteDeviceHandler<NetconfSessionPreferences> {
-
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeManagerCallback.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/NodeManagerCallback.java
deleted file mode 100644 (file)
index 670bb81..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor.Receiver;
-import com.google.common.annotations.Beta;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-
-/**
- * Customizable layer that handles communication with your application.
- */
-@Beta
-public interface NodeManagerCallback extends InitialStateProvider, NodeListener, Receiver, RemoteDeviceHandler<NetconfSessionPreferences> {
-
-    interface NodeManagerCallbackFactory<M> {
-        NodeManagerCallback create(String nodeId, String topologyId, ActorSystem actorSystem);
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RemoteNodeListener.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RemoteNodeListener.java
deleted file mode 100644 (file)
index 7a8dc59..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import com.google.common.annotations.Beta;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import scala.concurrent.Future;
-
-/**
- * Interface that provides methods of calling node events on a remote actor.
- * Use these when you want to call node events asynchronously similar to akka ask()
- */
-@Beta
-public interface RemoteNodeListener {
-
-    /**
-     * This is called when a remote node is informing you that a new configuration was recieved.
-     * @param message - serializable message to send
-     * @return response from the remote node
-     */
-    Future<NormalizedNodeMessage> onRemoteNodeCreated(NormalizedNodeMessage message);
-
-    /**
-     * This is called when a remote node is informing you that a configuration was updated.
-     * @param message - serializable message to send
-     * @return response from the remote node
-     */
-    Future<NormalizedNodeMessage> onRemoteNodeUpdated(NormalizedNodeMessage message);
-
-    /**
-     * This is called when a remote node is informing you that a new configuration was deleted.
-     * @param nodeId - id of the node which was deleted
-     * @return void future success if delete succeed, failure otherwise
-     */
-    Future<Void> onRemoteNodeDeleted(NodeId nodeId);
-
-    /**
-     * Called when a remote node is requesting a node's status, after a status change notification(f.ex sessionUp, sessionDown)
-     * on lower level
-     * @param nodeId - id of the node which status we want to retrieve
-     * @return status for the node requested
-     */
-    Future<NormalizedNodeMessage> remoteGetCurrentStatusForNode(NodeId nodeId);
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RoleChangeListener.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RoleChangeListener.java
deleted file mode 100644 (file)
index 5cf4250..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import com.google.common.annotations.Beta;
-
-/**
- * A listener that recieves {@link #onRoleChanged(RoleChangeDTO)} callbacks when a role change occurs
- */
-@Beta
-public interface RoleChangeListener {
-
-    /**
-     * Called when a role change occurs
-     * @param roleChangeDTO a DTO that wraps the current ownership status
-     */
-    void onRoleChanged(RoleChangeDTO roleChangeDTO);
-
-    /**
-     * A DTO that wraps an ownership change status
-     */
-    class RoleChangeDTO {
-
-        private final boolean wasOwner;
-        private final boolean isOwner;
-        private final boolean hasOwner;
-
-        public RoleChangeDTO(boolean wasOwner, boolean isOwner, boolean hasOwner) {
-            this.wasOwner = wasOwner;
-            this.isOwner = isOwner;
-            this.hasOwner = hasOwner;
-        }
-
-        public boolean wasOwner() {
-            return wasOwner;
-        }
-
-        public boolean isOwner() {
-            return isOwner;
-        }
-
-        public boolean hasOwner() {
-            return hasOwner;
-        }
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RoleChangeStrategy.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/RoleChangeStrategy.java
deleted file mode 100644 (file)
index f4f3013..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import com.google.common.annotations.Beta;
-
-/**
- * A customizable strategy that gets executed when a BaseTopologyManager|BaseNodeManager is created.
- * If the election should be executed at another moment, you need to pass the NoopRoleChangeStrategy into the Manager
- * and the role candidate registration needs to happen in your implemented Node/Topology callback
- */
-@Beta
-public interface RoleChangeStrategy extends RoleChangeListener {
-
-    /**
-     * Your pre-election and election logic goes here, e.g you should register your candidate into the ElectionService
-     * @param electionCandidate NodeListener that should receive the subsequent onRoleChanged callback
-     *                          when a role change occurs.
-     */
-    void registerRoleCandidate(NodeListener electionCandidate);
-
-    /**
-     * Invoke whenever you want to stop candidate from partaking in election.
-     */
-    void unregisterRoleCandidate();
-
-    /**
-     *
-     * @return True/False based on if this candidate is already registered into ownership service
-     */
-    boolean isCandidateRegistered();
-
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/StateAggregator.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/StateAggregator.java
deleted file mode 100644 (file)
index d72d280..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import com.google.common.annotations.Beta;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.List;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-
-/**
- * Aggregate different node states into a single state
- */
-@Beta
-public interface StateAggregator {
-
-    ListenableFuture<Node> combineCreateAttempts(final List<ListenableFuture<Node>> stateFutures);
-
-    ListenableFuture<Node> combineUpdateAttempts(final List<ListenableFuture<Node>> stateFutures);
-
-    ListenableFuture<Void> combineDeleteAttempts(final List<ListenableFuture<Void>> stateFutures);
-
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/TopologyManager.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/TopologyManager.java
deleted file mode 100644 (file)
index 3de1677..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import akka.actor.TypedActor.PostStop;
-import akka.actor.TypedActor.PreStart;
-import akka.actor.TypedActor.Receiver;
-import com.google.common.annotations.Beta;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import scala.concurrent.Future;
-
-/**
- * Top level topology manager that handles comunication between nodes, aggregates results, and handles writes into the datastore
- */
-@Beta
-public interface TopologyManager extends NodeListener, Receiver, RemoteNodeListener, PreStart, PostStop{
-
-    /**
-     * ask if this manager is master
-     * @return true/false based on ownership status
-     */
-    Future<Boolean> isMaster();
-
-    /**
-     *
-     * @param nodeId - id of the node that sessionUp/Down happened on
-     */
-    void notifyNodeStatusChange(NodeId nodeId);
-
-    boolean hasAllPeersUp();
-
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/TopologyManagerCallback.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/TopologyManagerCallback.java
deleted file mode 100644 (file)
index 8eee06a..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor.Receiver;
-import com.google.common.annotations.Beta;
-
-/**
- * Customizable extension layer between the top level TopologyManager and NodeManager
- */
-@Beta
-public interface TopologyManagerCallback extends InitialStateProvider, NodeListener, Receiver, RoleChangeListener {
-
-    interface TopologyManagerCallbackFactory {
-        TopologyManagerCallback create(ActorSystem actorSystem, String topologyId);
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleNodeManagerCallback.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleNodeManagerCallback.java
deleted file mode 100644 (file)
index 823c44b..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.example;
-
-import akka.actor.ActorRef;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.topology.NodeManagerCallback;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeFields;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class ExampleNodeManagerCallback implements NodeManagerCallback {
-
-    public ExampleNodeManagerCallback() {
-    }
-
-    @Nonnull
-    @Override public Node getInitialState(@Nonnull final NodeId nodeId,
-                                          @Nonnull final Node configNode) {
-        return new NodeBuilder().addAugmentation(NetconfNode.class,
-                new NetconfNodeBuilder().setConnectionStatus(NetconfNodeFields.ConnectionStatus.Connecting).build()).build();
-    }
-
-    @Nonnull @Override public Node getFailedState(@Nonnull final NodeId nodeId,
-                                                  @Nonnull final Node configNode) {
-        return new NodeBuilder().addAugmentation(NetconfNode.class,
-                new NetconfNodeBuilder().setConnectionStatus(NetconfNodeFields.ConnectionStatus.UnableToConnect).build()).build();
-    }
-
-    @Nonnull @Override public ListenableFuture<Node> onNodeCreated(@Nonnull final NodeId nodeId,
-                                                                   @Nonnull final Node configNode) {
-        return Futures.immediateFuture(new NodeBuilder().addAugmentation(NetconfNode.class,
-                new NetconfNodeBuilder().setConnectionStatus(NetconfNodeFields.ConnectionStatus.Connected).build()).build());
-    }
-
-    @Nonnull @Override public ListenableFuture<Node> onNodeUpdated(@Nonnull final NodeId nodeId,
-                                                                   @Nonnull final Node configNode) {
-        // update magic
-        return Futures.immediateFuture(new NodeBuilder().addAugmentation(NetconfNode.class,
-                new NetconfNodeBuilder().setConnectionStatus(NetconfNodeFields.ConnectionStatus.Connected).build()).build());
-    }
-
-    @Nonnull @Override public ListenableFuture<Void> onNodeDeleted(@Nonnull final NodeId nodeId) {
-        return Futures.immediateFuture(null);
-    }
-
-    @Nonnull
-    @Override
-    public ListenableFuture<Node> getCurrentStatusForNode(@Nonnull NodeId nodeId) {
-        return null;
-    }
-
-    @Override
-    public void onReceive(Object message, ActorRef sender) {
-
-    }
-
-    @Override
-    public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-
-    }
-
-    @Override
-    public void onDeviceConnected(SchemaContext remoteSchemaContext, NetconfSessionPreferences netconfSessionPreferences, DOMRpcService deviceRpc) {
-
-    }
-
-    @Override
-    public void onDeviceDisconnected() {
-
-    }
-
-    @Override
-    public void onDeviceFailed(Throwable throwable) {
-
-    }
-
-    @Override
-    public void onNotification(DOMNotification domNotification) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleSingleStateAggregator.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleSingleStateAggregator.java
deleted file mode 100644 (file)
index 6d27c26..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.example;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.List;
-import org.opendaylight.netconf.topology.StateAggregator;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-
-/**
- * Aggregator implementation expecting just a single state
- */
-public final class ExampleSingleStateAggregator implements StateAggregator {
-
-    @Override public ListenableFuture<Node> combineCreateAttempts(final List<ListenableFuture<Node>> stateFutures) {
-        return getSingleFuture(stateFutures);
-    }
-
-    private <T> ListenableFuture<T> getSingleFuture(final List<ListenableFuture<T>> stateFutures) {
-        Preconditions.checkArgument(stateFutures.size() == 1, "Recieved multiple results, Single result is enforced here");
-        return stateFutures.get(0);
-    }
-
-    @Override public ListenableFuture<Node> combineUpdateAttempts(final List<ListenableFuture<Node>> stateFutures) {
-        return getSingleFuture(stateFutures);
-    }
-
-    @Override public ListenableFuture<Void> combineDeleteAttempts(final List<ListenableFuture<Void>> stateFutures) {
-        return getSingleFuture(stateFutures);
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleTopology.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleTopology.java
deleted file mode 100644 (file)
index c31e18e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.example;
-
-import akka.actor.ActorSystem;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.netconf.topology.NodeManagerCallback;
-import org.opendaylight.netconf.topology.NodeManagerCallback.NodeManagerCallbackFactory;
-import org.opendaylight.netconf.topology.TopologyManagerCallback;
-import org.opendaylight.netconf.topology.TopologyManagerCallback.TopologyManagerCallbackFactory;
-import org.opendaylight.netconf.topology.util.BaseTopologyManager;
-
-public class ExampleTopology {
-
-    private static final String TOPOLOGY_NETCONF = "topology-netconf";
-    private BaseTopologyManager netconfNodeBaseTopologyManager;
-    private final DataBroker dataBroker;
-
-    public ExampleTopology(final EntityOwnershipService entityOwnershipService, final DataBroker dataBroker) {
-        final ActorSystem actorSystem = ActorSystem.create("netconf-cluster");
-
-        this.dataBroker = dataBroker;
-
-        final NodeManagerCallbackFactory nodeManagerCallbackFactory = new NodeManagerCallbackFactory() {
-            @Override
-            public NodeManagerCallback create(String nodeId, String topologyId, ActorSystem actorSystem) {
-                return new ExampleNodeManagerCallback();
-            }
-        };
-
-        final TopologyManagerCallbackFactory topologyManagerCallbackFactory = new TopologyManagerCallbackFactory() {
-            @Override
-            public TopologyManagerCallback create(ActorSystem actorSystem, String topologyId) {
-                return new ExampleTopologyManagerCallback(actorSystem, dataBroker, topologyId, nodeManagerCallbackFactory);
-            }
-        };
-
-//        netconfNodeBaseTopologyManager = new BaseTopologyManager<>(dataBroker, TOPOLOGY_NETCONF,
-//                topologyManagerCallbackFactory,
-//                new SingleStateAggregator(),
-//                new SalNodeWriter(dataBroker, TOPOLOGY_NETCONF),
-//                new TopologyRoleChangeStrategy(dataBroker, entityOwnershipService, "netconf", TOPOLOGY_NETCONF));
-
-    }
-
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleTopologyManagerCallback.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/ExampleTopologyManagerCallback.java
deleted file mode 100644 (file)
index a2eed6a..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.example;
-
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netconf.topology.NodeManager;
-import org.opendaylight.netconf.topology.NodeManagerCallback.NodeManagerCallbackFactory;
-import org.opendaylight.netconf.topology.TopologyManagerCallback;
-import org.opendaylight.netconf.topology.util.BaseNodeManager.BaseNodeManagerBuilder;
-import org.opendaylight.netconf.topology.util.NodeWriter;
-import org.opendaylight.netconf.topology.util.NoopRoleChangeStrategy;
-import org.opendaylight.netconf.topology.util.SalNodeWriter;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ExampleTopologyManagerCallback implements TopologyManagerCallback {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ExampleTopologyManagerCallback.class);
-
-    private final DataBroker dataBroker;
-    private final ActorSystem actorSystem;
-    private boolean isMaster;
-
-    private final String topologyId;
-    private final NodeWriter naSalNodeWriter;
-    private final Map<NodeId, NodeManager> nodes = new HashMap<>();
-    private final NodeManagerCallbackFactory nodeHandlerFactory;
-
-    public ExampleTopologyManagerCallback(final ActorSystem actorSystem,
-                                          final DataBroker dataBroker,
-                                          final String topologyId,
-                                          final NodeManagerCallbackFactory nodeHandlerFactory) {
-        this(actorSystem, dataBroker, topologyId, nodeHandlerFactory, new SalNodeWriter(dataBroker, topologyId));
-    }
-
-    public ExampleTopologyManagerCallback(final ActorSystem actorSystem,
-                                          final DataBroker dataBroker,
-                                          final String topologyId,
-                                          final NodeManagerCallbackFactory nodeHandlerFactory,
-                                          final NodeWriter naSalNodeWriter) {
-        this(actorSystem, dataBroker, topologyId, nodeHandlerFactory, naSalNodeWriter, false);
-
-    }
-
-    public ExampleTopologyManagerCallback(final ActorSystem actorSystem,
-                                          final DataBroker dataBroker,
-                                          final String topologyId,
-                                          final NodeManagerCallbackFactory nodeHandlerFactory,
-                                          final NodeWriter naSalNodeWriter,
-                                          boolean isMaster) {
-        this.dataBroker = dataBroker;
-        this.actorSystem = actorSystem;
-        this.topologyId = topologyId;
-        this.nodeHandlerFactory = nodeHandlerFactory;
-        this.naSalNodeWriter = naSalNodeWriter;
-
-        this.isMaster = isMaster;
-    }
-
-    @Override
-    public ListenableFuture<Node> onNodeCreated(NodeId nodeId, Node node) {
-        // Init node admin and a writer for it
-
-        // TODO let end user code notify the baseNodeManager about state changes and handle them here on topology level
-        final NodeManager naBaseNodeManager =
-                createNodeManager(nodeId);
-
-        nodes.put(nodeId, naBaseNodeManager);
-
-        // Set initial state ? in every peer or just master ? TODO
-        if (isMaster) {
-            naSalNodeWriter.init(nodeId, naBaseNodeManager.getInitialState(nodeId, node));
-        }
-
-        // trigger connect on this node
-        return naBaseNodeManager.onNodeCreated(nodeId, node);
-    }
-
-    @Override
-    public ListenableFuture<Node> onNodeUpdated(final NodeId nodeId, final Node node) {
-        // Set initial state
-        naSalNodeWriter.init(nodeId, nodes.get(nodeId).getInitialState(nodeId, node));
-
-        // Trigger onNodeUpdated only on this node
-        return nodes.get(nodeId).onNodeUpdated(nodeId, node);
-    }
-
-    @Override
-    public ListenableFuture<Void> onNodeDeleted(final NodeId nodeId) {
-        // Trigger delete only on this node
-        final ListenableFuture<Void> future = nodes.get(nodeId).onNodeDeleted(nodeId);
-        Futures.addCallback(future, new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-                // remove proxy from node list and stop the actor
-                final NodeManager remove = nodes.remove(nodeId);
-                TypedActor.get(actorSystem).stop(remove);
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                // NOOP will be handled on higher level
-            }
-        });
-        return future;
-    }
-
-    @Nonnull
-    @Override
-    public ListenableFuture<Node> getCurrentStatusForNode(@Nonnull NodeId nodeId) {
-        return nodes.get(nodeId).getCurrentStatusForNode(nodeId);
-    }
-
-    @Override
-    public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-        isMaster = roleChangeDTO.isOwner();
-        // our post-election logic
-    }
-
-    private NodeManager createNodeManager(NodeId nodeId) {
-        return new BaseNodeManagerBuilder().setNodeId(nodeId.getValue())
-                .setActorContext(TypedActor.context())
-                .setDelegateFactory(nodeHandlerFactory)
-                .setRoleChangeStrategy(new NoopRoleChangeStrategy())
-                .setTopologyId(topologyId)
-                .build();
-    }
-
-    @Override
-    public void onReceive(Object o, ActorRef actorRef) {
-
-    }
-
-    @Nonnull
-    @Override
-    public Node getInitialState(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-        return nodes.get(nodeId).getInitialState(nodeId, configNode);
-    }
-
-    @Nonnull
-    @Override
-    public Node getFailedState(@Nonnull NodeId nodeId, @Nullable Node configNode) {
-        return nodes.get(nodeId).getFailedState(nodeId, configNode);
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/LoggingSalNodeWriter.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/example/LoggingSalNodeWriter.java
deleted file mode 100644 (file)
index e4ead18..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.example;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import javax.annotation.Nonnull;
-import org.opendaylight.netconf.topology.util.NodeWriter;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class LoggingSalNodeWriter implements NodeWriter{
-
-    private static final Logger LOG = LoggerFactory.getLogger(LoggingSalNodeWriter.class);
-
-    private final ArrayList<NodeWriter> delegates;
-
-    public LoggingSalNodeWriter(final NodeWriter... delegates) {
-        this.delegates = new ArrayList<>(Arrays.asList(delegates));
-    }
-
-    @Override
-    public void init(@Nonnull NodeId id, @Nonnull Node operationalDataNode) {
-        LOG.warn("Init recieved");
-        LOG.warn("NodeId: {}", id.getValue());
-        LOG.warn("Node: {}", operationalDataNode);
-        for (final NodeWriter delegate : delegates) {
-            delegate.init(id, operationalDataNode);
-        }
-    }
-
-    @Override
-    public void update(@Nonnull NodeId id, @Nonnull Node operationalDataNode) {
-        LOG.warn("Update recieved");
-        LOG.warn("NodeId: {}", id.getValue());
-        LOG.warn("Node: {}", operationalDataNode);
-        for (final NodeWriter delegate : delegates) {
-            delegate.update(id, operationalDataNode);
-        }
-    }
-
-    @Override
-    public void delete(@Nonnull NodeId id) {
-        LOG.warn("Delete recieved");
-        LOG.warn("NodeId: {}", id.getValue());
-        for (final NodeWriter delegate : delegates) {
-            delegate.delete(id);
-        }
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseNodeManager.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseNodeManager.java
deleted file mode 100644 (file)
index f48f0c4..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util;
-
-import akka.actor.ActorContext;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import akka.actor.TypedProps;
-import akka.japi.Creator;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ListenableFuture;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.topology.NodeManager;
-import org.opendaylight.netconf.topology.NodeManagerCallback;
-import org.opendaylight.netconf.topology.NodeManagerCallback.NodeManagerCallbackFactory;
-import org.opendaylight.netconf.topology.RoleChangeStrategy;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import scala.concurrent.Future;
-
-public final class BaseNodeManager implements NodeManager {
-
-    private static final Logger LOG = LoggerFactory.getLogger(BaseNodeManager.class);
-
-    private final String nodeId;
-    private final NodeManagerCallback delegate;
-
-    private BaseNodeManager(final String nodeId,
-                            final String topologyId,
-                            final ActorSystem actorSystem,
-                            final NodeManagerCallbackFactory delegateFactory,
-                            final RoleChangeStrategy roleChangeStrategy) {
-        LOG.debug("Creating BaseNodeManager, id: {}, {}", topologyId, nodeId );
-        this.nodeId = nodeId;
-        this.delegate = delegateFactory.create(nodeId, topologyId, actorSystem);
-        // if we want to override the place election happens,
-        // we need to override this with noop election strategy and implement election in callback
-        // cannot leak "this" here! have to use TypedActor.self()
-        roleChangeStrategy.registerRoleCandidate((NodeManager) TypedActor.self());
-    }
-
-    @Nonnull @Override public Node getInitialState(@Nonnull final NodeId nodeId, @Nonnull final Node configNode) {
-        LOG.trace("Retrieving Node {} initial state", nodeId);
-        return delegate.getInitialState(nodeId, configNode);
-    }
-
-    @Nonnull @Override public Node getFailedState(@Nonnull final NodeId nodeId, @Nonnull final Node configNode) {
-        LOG.trace("Retrieving Node {} failed state", nodeId);
-        return delegate.getFailedState(nodeId, configNode);
-    }
-
-    @Nonnull @Override public ListenableFuture<Node> onNodeCreated(@Nonnull final NodeId nodeId, @Nonnull final Node configNode) {
-        LOG.debug("Creating Node {}, with configuration: {}", nodeId.getValue(), configNode);
-        return delegate.onNodeCreated(nodeId, configNode);
-    }
-
-    @Nonnull @Override public ListenableFuture<Node> onNodeUpdated(@Nonnull final NodeId nodeId, @Nonnull final Node configNode) {
-        LOG.debug("Updating Node {}, with configuration: {}", nodeId.getValue(), configNode);
-        return delegate.onNodeUpdated(nodeId, configNode);
-    }
-
-    @Nonnull @Override public ListenableFuture<Void> onNodeDeleted(@Nonnull final NodeId nodeId) {
-        LOG.debug("Deleting Node {}", nodeId.getValue());
-        return delegate.onNodeDeleted(nodeId);
-    }
-
-    @Nonnull
-    @Override
-    public ListenableFuture<Node> getCurrentStatusForNode(@Nonnull NodeId nodeId) {
-        LOG.debug("Getting current status for node: {}", nodeId.getValue());
-        return delegate.getCurrentStatusForNode(nodeId);
-    }
-
-    @Override
-    public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-        LOG.debug("Node {} role has changed from: {} to {}", nodeId,
-                (roleChangeDTO.wasOwner() ? "master" : "slave"),
-                (roleChangeDTO.isOwner() ? "master" : "slave"));
-
-        delegate.onRoleChanged(roleChangeDTO);
-    }
-
-    @Override
-    public void onReceive(Object o, ActorRef actorRef) {
-        delegate.onReceive(o, actorRef);
-    }
-
-    @Override
-    public Future<NormalizedNodeMessage> onRemoteNodeCreated(final NormalizedNodeMessage message) {
-        return null;
-    }
-
-    @Override
-    public Future<NormalizedNodeMessage> onRemoteNodeUpdated(final NormalizedNodeMessage message) {
-        return null;
-    }
-
-    @Override
-    public Future<Void> onRemoteNodeDeleted(final NodeId nodeId) {
-        return null;
-    }
-
-    @Override
-    public Future<NormalizedNodeMessage> remoteGetCurrentStatusForNode(final NodeId nodeId) {
-        return null;
-    }
-
-    @Override
-    public void onDeviceConnected(SchemaContext remoteSchemaContext, NetconfSessionPreferences netconfSessionPreferences, DOMRpcService deviceRpc) {
-        delegate.onDeviceConnected(remoteSchemaContext, netconfSessionPreferences, deviceRpc);
-    }
-
-    @Override
-    public void onDeviceDisconnected() {
-        delegate.onDeviceDisconnected();
-    }
-
-    @Override
-    public void onDeviceFailed(Throwable throwable) {
-        delegate.onDeviceFailed(throwable);
-    }
-
-    @Override
-    public void onNotification(DOMNotification domNotification) {
-        delegate.onNotification(domNotification);
-    }
-
-    @Override
-    public void close() {
-        // NOOP
-    }
-
-    /**
-     * Builder of BaseNodeManager instances that are proxied as TypedActors
-     */
-    public static class BaseNodeManagerBuilder {
-        private String nodeId;
-        private String topologyId;
-        private NodeManagerCallbackFactory delegateFactory;
-        private RoleChangeStrategy roleChangeStrategy;
-        private ActorContext actorContext;
-
-
-        public BaseNodeManagerBuilder setNodeId(final String nodeId) {
-            this.nodeId = nodeId;
-            return this;
-        }
-
-        public BaseNodeManagerBuilder setTopologyId(final String topologyId) {
-            this.topologyId = topologyId;
-            return this;
-        }
-
-        public BaseNodeManagerBuilder setDelegateFactory(final NodeManagerCallbackFactory delegateFactory) {
-            this.delegateFactory = delegateFactory;
-            return this;
-        }
-
-        public BaseNodeManagerBuilder setRoleChangeStrategy(final RoleChangeStrategy roleChangeStrategy) {
-            this.roleChangeStrategy = roleChangeStrategy;
-            return this;
-        }
-
-        public BaseNodeManagerBuilder setActorContext(final ActorContext actorContext) {
-            this.actorContext = actorContext;
-            return this;
-        }
-
-        public NodeManager build() {
-            Preconditions.checkNotNull(nodeId);
-            Preconditions.checkNotNull(topologyId);
-            Preconditions.checkNotNull(delegateFactory);
-            Preconditions.checkNotNull(roleChangeStrategy);
-            Preconditions.checkNotNull(actorContext);
-            LOG.debug("Creating typed actor with id: {}", nodeId);
-
-            return TypedActor.get(actorContext).typedActorOf(new TypedProps<>(NodeManager.class, new Creator<BaseNodeManager>() {
-                @Override
-                public BaseNodeManager create() throws Exception {
-                    return new BaseNodeManager(nodeId, topologyId, actorContext.system(), delegateFactory, roleChangeStrategy);
-                }
-            }), nodeId);
-        }
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseTopologyManager.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseTopologyManager.java
deleted file mode 100644 (file)
index 133aa46..0000000
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util;
-
-import akka.actor.ActorContext;
-import akka.actor.ActorIdentity;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.Address;
-import akka.actor.Identify;
-import akka.actor.TypedActor;
-import akka.actor.TypedActorExtension;
-import akka.actor.TypedProps;
-import akka.cluster.Cluster;
-import akka.cluster.ClusterEvent;
-import akka.cluster.ClusterEvent.MemberEvent;
-import akka.cluster.ClusterEvent.MemberExited;
-import akka.cluster.ClusterEvent.MemberRemoved;
-import akka.cluster.ClusterEvent.MemberUp;
-import akka.cluster.ClusterEvent.ReachableMember;
-import akka.cluster.ClusterEvent.UnreachableMember;
-import akka.cluster.Member;
-import akka.dispatch.OnComplete;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.netconf.topology.RoleChangeStrategy;
-import org.opendaylight.netconf.topology.StateAggregator;
-import org.opendaylight.netconf.topology.TopologyManager;
-import org.opendaylight.netconf.topology.TopologyManagerCallback;
-import org.opendaylight.netconf.topology.TopologyManagerCallback.TopologyManagerCallbackFactory;
-import org.opendaylight.netconf.topology.util.messages.CustomIdentifyMessage;
-import org.opendaylight.netconf.topology.util.messages.CustomIdentifyMessageReply;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
-import org.opendaylight.netconf.util.NetconfTopologyPathCreator;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import scala.concurrent.Future;
-import scala.concurrent.duration.FiniteDuration;
-import scala.concurrent.impl.Promise.DefaultPromise;
-
-public final class BaseTopologyManager
-        implements TopologyManager {
-
-    private static final Logger LOG = LoggerFactory.getLogger(BaseTopologyManager.class);
-
-    private final KeyedInstanceIdentifier<Topology, TopologyKey> topologyListPath;
-
-    private final ActorSystem system;
-    private final TypedActorExtension typedExtension;
-    private final Cluster clusterExtension;
-
-    private final BindingNormalizedNodeCodecRegistry codecRegistry;
-
-    private static final String PATH = "/user/";
-
-    private final DataBroker dataBroker;
-    private final RoleChangeStrategy roleChangeStrategy;
-    private final StateAggregator aggregator;
-
-    private final NodeWriter naSalNodeWriter;
-    private final String topologyId;
-    private final TopologyManagerCallback delegateTopologyHandler;
-    private final Set<NodeId> created = new HashSet<>();
-
-    private final Map<Address, TopologyManager> peers = new HashMap<>();
-    private final int id = new Random().nextInt();
-
-    private boolean isMaster;
-
-    public BaseTopologyManager(final ActorSystem system,
-                               final BindingNormalizedNodeCodecRegistry codecRegistry,
-                               final DataBroker dataBroker,
-                               final String topologyId,
-                               final TopologyManagerCallbackFactory topologyManagerCallbackFactory,
-                               final StateAggregator aggregator,
-                               final NodeWriter naSalNodeWriter,
-                               final RoleChangeStrategy roleChangeStrategy) {
-        this(system, codecRegistry, dataBroker, topologyId, topologyManagerCallbackFactory, aggregator, naSalNodeWriter, roleChangeStrategy, false);
-    }
-
-    public BaseTopologyManager(final ActorSystem system,
-                               final BindingNormalizedNodeCodecRegistry codecRegistry,
-                               final DataBroker dataBroker,
-                               final String topologyId,
-                               final TopologyManagerCallbackFactory topologyManagerCallbackFactory,
-                               final StateAggregator aggregator,
-                               final NodeWriter naSalNodeWriter,
-                               final RoleChangeStrategy roleChangeStrategy,
-                               final boolean isMaster) {
-
-        this.system = system;
-        this.typedExtension = TypedActor.get(system);
-        this.clusterExtension = Cluster.get(system);
-        this.dataBroker = dataBroker;
-        this.topologyId = topologyId;
-        this.delegateTopologyHandler = topologyManagerCallbackFactory.create(system, topologyId);
-        this.aggregator = aggregator;
-        this.naSalNodeWriter = naSalNodeWriter;
-        this.roleChangeStrategy = roleChangeStrategy;
-        this.codecRegistry = codecRegistry;
-
-        // election has not yet happened
-        this.isMaster = isMaster;
-
-        this.topologyListPath = TopologyUtil.createTopologyListPath(topologyId);
-
-        LOG.debug("Base manager started ", +id);
-    }
-
-    @Override
-    public void preStart() {
-        LOG.debug("preStart called");
-        // TODO change to enum, master/slave active/standby
-        roleChangeStrategy.registerRoleCandidate(TypedActor.<BaseTopologyManager>self());
-        LOG.debug("candidate registered");
-        clusterExtension.subscribe(TypedActor.context().self(), ClusterEvent.initialStateAsEvents(), MemberEvent.class, UnreachableMember.class);
-    }
-
-    @Override
-    public void postStop() {
-        LOG.debug("postStop called");
-        clusterExtension.leave(clusterExtension.selfAddress());
-        clusterExtension.unsubscribe(TypedActor.context().self());
-    }
-
-    @Override
-    public ListenableFuture<Node> onNodeCreated(final NodeId nodeId, final Node node) {
-        LOG.debug("TopologyManager({}) onNodeCreated received, nodeid: {} , isMaster: {}", id, nodeId.getValue(), isMaster);
-
-        if (created.contains(nodeId)) {
-            LOG.warn("Node{} already exists, triggering update..", nodeId);
-            return onNodeUpdated(nodeId, node);
-        }
-        created.add(nodeId);
-        final ArrayList<ListenableFuture<Node>> futures = new ArrayList<>();
-
-        if (isMaster) {
-
-            futures.add(delegateTopologyHandler.onNodeCreated(nodeId, node));
-            // only master should call connect on peers and aggregate futures
-            for (TopologyManager topologyManager : peers.values()) {
-                // convert binding into NormalizedNode for transfer
-                final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = codecRegistry.toNormalizedNode(TopologyUtil.createTopologyNodePath(topologyId), node);
-
-                LOG.debug("YangInstanceIdentifier {}", normalizedNodeEntry.getKey());
-                LOG.debug("Value {}", normalizedNodeEntry.getValue());
-
-                // add a future into our futures that gets its completion status from the converted scala future
-                final SettableFuture<Node> settableFuture = SettableFuture.create();
-                futures.add(settableFuture);
-                final Future<NormalizedNodeMessage> scalaFuture = topologyManager.onRemoteNodeCreated(new NormalizedNodeMessage(normalizedNodeEntry.getKey(), normalizedNodeEntry.getValue()));
-                scalaFuture.onComplete(new OnComplete<NormalizedNodeMessage>() {
-                    @Override
-                    public void onComplete(Throwable failure, NormalizedNodeMessage success) throws Throwable {
-                        if (failure != null) {
-                            settableFuture.setException(failure);
-                            return;
-                        }
-                        final Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode =
-                                codecRegistry.fromNormalizedNode(success.getIdentifier(), success.getNode());
-                        final Node value = (Node) fromNormalizedNode.getValue();
-
-                        settableFuture.set(value);
-                    }
-                }, TypedActor.context().dispatcher());
-            }
-
-            final ListenableFuture<Node> aggregatedFuture = aggregator.combineCreateAttempts(futures);
-            Futures.addCallback(aggregatedFuture, new FutureCallback<Node>() {
-                @Override
-                public void onSuccess(final Node result) {
-                    LOG.debug("Futures aggregated succesfully");
-                    naSalNodeWriter.init(nodeId, result);
-                }
-
-                @Override
-                public void onFailure(final Throwable t) {
-                    // If the combined connection attempt failed, set the node to connection failed
-                    LOG.debug("Futures aggregation failed");
-                    naSalNodeWriter.update(nodeId, delegateTopologyHandler.getFailedState(nodeId, node));
-                }
-            }, TypedActor.context().dispatcher());
-
-            //combine peer futures
-            return aggregatedFuture;
-        }
-
-        // trigger create on this slave
-        return delegateTopologyHandler.onNodeCreated(nodeId, node);
-    }
-
-    @Override
-    public ListenableFuture<Node> onNodeUpdated(final NodeId nodeId, final Node node) {
-        LOG.debug("TopologyManager({}) onNodeUpdated received, nodeid: {}", id, nodeId.getValue());
-
-        // Master needs to trigger onNodeUpdated on peers and combine results
-        if (isMaster) {
-            // first cleanup old node
-            final ListenableFuture<Void> deleteFuture = onNodeDeleted(nodeId);
-            final SettableFuture<Node> createFuture = SettableFuture.create();
-            final TopologyManager selfProxy = TypedActor.self();
-            final ActorContext context = TypedActor.context();
-            Futures.addCallback(deleteFuture, new FutureCallback<Void>() {
-                @Override
-                public void onSuccess(Void result) {
-                    LOG.warn("Delete part of update succesfull, triggering create");
-                    // trigger create on all nodes
-                    Futures.addCallback(selfProxy.onNodeCreated(nodeId, node), new FutureCallback<Node>() {
-                        @Override
-                        public void onSuccess(Node result) {
-                            createFuture.set(result);
-                        }
-
-                        @Override
-                        public void onFailure(Throwable t) {
-                            createFuture.setException(t);
-                        }
-                    }, context.dispatcher());
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.warn("Delete part of update failed, {}", t);
-                }
-            }, context.dispatcher());
-            return createFuture;
-        }
-
-        // Trigger update on this slave
-        return delegateTopologyHandler.onNodeUpdated(nodeId, node);
-    }
-
-    @Override
-    public ListenableFuture<Void> onNodeDeleted(final NodeId nodeId) {
-        final ArrayList<ListenableFuture<Void>> futures = new ArrayList<>();
-        created.remove(nodeId);
-
-        // Master needs to trigger delete on peers and combine results
-        if (isMaster) {
-            futures.add(delegateTopologyHandler.onNodeDeleted(nodeId));
-            for (TopologyManager topologyManager : peers.values()) {
-                // add a future into our futures that gets its completion status from the converted scala future
-                final SettableFuture<Void> settableFuture = SettableFuture.create();
-                futures.add(settableFuture);
-                final Future<Void> scalaFuture = topologyManager.onRemoteNodeDeleted(nodeId);
-                scalaFuture.onComplete(new OnComplete<Void>() {
-                    @Override
-                    public void onComplete(Throwable failure, Void success) throws Throwable {
-                        if (failure != null) {
-                            settableFuture.setException(failure);
-                            return;
-                        }
-
-                        settableFuture.set(success);
-                    }
-                }, TypedActor.context().dispatcher());
-            }
-
-            final ListenableFuture<Void> aggregatedFuture = aggregator.combineDeleteAttempts(futures);
-            Futures.addCallback(aggregatedFuture, new FutureCallback<Void>() {
-                @Override
-                public void onSuccess(final Void result) {
-                    naSalNodeWriter.delete(nodeId);
-                }
-
-                @Override
-                public void onFailure(final Throwable t) {
-
-                }
-            });
-
-            return aggregatedFuture;
-        }
-
-        // Trigger delete
-        return delegateTopologyHandler.onNodeDeleted(nodeId);
-    }
-
-    @Nonnull
-    @Override
-    public ListenableFuture<Node> getCurrentStatusForNode(@Nonnull final NodeId nodeId) {
-        return delegateTopologyHandler.getCurrentStatusForNode(nodeId);
-    }
-
-    @Override
-    public void onRoleChanged(final RoleChangeDTO roleChangeDTO) {
-        isMaster = roleChangeDTO.isOwner();
-        delegateTopologyHandler.onRoleChanged(roleChangeDTO);
-        if (isMaster) {
-            LOG.debug("Node {} is master now", clusterExtension.selfAddress());
-            clusterExtension.join(clusterExtension.selfAddress());
-        }
-    }
-
-    @Override
-    public Future<Boolean> isMaster() {
-        return new DefaultPromise<Boolean>().success(isMaster).future();
-    }
-
-    @Override
-    public void notifyNodeStatusChange(final NodeId nodeId) {
-        LOG.debug("Connection status has changed on node {}", nodeId.getValue());
-        if (isMaster) {
-            // grab status from all peers and aggregate
-            final ArrayList<ListenableFuture<Node>> futures = new ArrayList<>();
-            futures.add(delegateTopologyHandler.getCurrentStatusForNode(nodeId));
-            // only master should call connect on peers and aggregate futures
-            for (TopologyManager topologyManager : peers.values()) {
-                // add a future into our futures that gets its completion status from the converted scala future
-                final SettableFuture<Node> settableFuture = SettableFuture.create();
-                futures.add(settableFuture);
-                final Future<NormalizedNodeMessage> scalaFuture = topologyManager.remoteGetCurrentStatusForNode(nodeId);
-                scalaFuture.onComplete(new OnComplete<NormalizedNodeMessage>() {
-                    @Override
-                    public void onComplete(Throwable failure, NormalizedNodeMessage success) throws Throwable {
-                        if (failure != null) {
-                            settableFuture.setException(failure);
-                            return;
-                        }
-                        final Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode =
-                                codecRegistry.fromNormalizedNode(success.getIdentifier(), success.getNode());
-                        final Node value = (Node) fromNormalizedNode.getValue();
-
-                        settableFuture.set(value);
-                    }
-                }, TypedActor.context().dispatcher());
-            }
-
-            final ListenableFuture<Node> aggregatedFuture = aggregator.combineUpdateAttempts(futures);
-            Futures.addCallback(aggregatedFuture, new FutureCallback<Node>() {
-                @Override
-                public void onSuccess(final Node result) {
-                    LOG.debug("Futures aggregated succesfully");
-                    naSalNodeWriter.update(nodeId, result);
-                }
-
-                @Override
-                public void onFailure(final Throwable t) {
-                    // If the combined connection attempt failed, set the node to connection failed
-                    LOG.debug("Futures aggregation failed");
-                    naSalNodeWriter.update(nodeId, delegateTopologyHandler.getFailedState(nodeId, null));
-                }
-            });
-            return;
-        }
-        LOG.debug("Not master, forwarding..");
-        for (final TopologyManager manager : peers.values()) {
-            // asynchronously find out which peer is master
-            final Future<Boolean> future = manager.isMaster();
-            future.onComplete(new OnComplete<Boolean>() {
-                @Override
-                public void onComplete(Throwable failure, Boolean success) throws Throwable {
-                    if (failure == null && success) {
-                        LOG.debug("Found master peer");
-                        // forward to master
-                        manager.notifyNodeStatusChange(nodeId);
-                        return;
-                    }
-                    if (failure != null) {
-                        LOG.debug("Retrieving master peer failed, {}", failure);
-                    }
-                }
-            }, TypedActor.context().dispatcher());
-        }
-    }
-
-    @Override
-    public boolean hasAllPeersUp() {
-        LOG.debug("Peers needed: {} Peers up: {}", 2, peers.size());
-        LOG.warn(clusterExtension.state().toString());
-        LOG.warn(peers.toString());
-        return peers.size() == 2;
-    }
-
-    @Override
-    public Future<NormalizedNodeMessage> onRemoteNodeCreated(final NormalizedNodeMessage message) {
-        final Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode =
-                codecRegistry.fromNormalizedNode(message.getIdentifier(), message.getNode());
-        final InstanceIdentifier<Node> iid = (InstanceIdentifier<Node>) fromNormalizedNode.getKey();
-        final Node value = (Node) fromNormalizedNode.getValue();
-
-        LOG.debug("TopologyManager({}) onRemoteNodeCreated received, nodeid: {}", value.getNodeId(), value);
-        final ListenableFuture<Node> nodeListenableFuture = onNodeCreated(value.getNodeId(), value);
-        final DefaultPromise<NormalizedNodeMessage> promise = new DefaultPromise<>();
-        Futures.addCallback(nodeListenableFuture, new FutureCallback<Node>() {
-            @Override
-            public void onSuccess(Node result) {
-                final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = codecRegistry.toNormalizedNode(iid, result);
-                promise.success(new NormalizedNodeMessage(entry.getKey(), entry.getValue()));
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                promise.failure(t);
-            }
-        });
-
-        return promise.future();
-    }
-
-    @Override
-    public Future<NormalizedNodeMessage> onRemoteNodeUpdated(final NormalizedNodeMessage message) {
-        final Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode =
-                codecRegistry.fromNormalizedNode(message.getIdentifier(), message.getNode());
-        final InstanceIdentifier<Node> iid = (InstanceIdentifier<Node>) fromNormalizedNode.getKey();
-        final Node value = (Node) fromNormalizedNode.getValue();
-
-        LOG.debug("TopologyManager({}) onRemoteNodeUpdated received, nodeid: {}", id, value.getNodeId());
-
-        final ListenableFuture<Node> nodeListenableFuture = onNodeUpdated(value.getNodeId(), value);
-        final DefaultPromise<NormalizedNodeMessage> promise = new DefaultPromise<>();
-        Futures.addCallback(nodeListenableFuture, new FutureCallback<Node>() {
-            @Override
-            public void onSuccess(Node result) {
-                final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = codecRegistry.toNormalizedNode(iid, result);
-                promise.success(new NormalizedNodeMessage(entry.getKey(), entry.getValue()));
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                promise.failure(t);
-            }
-        });
-        return promise.future();
-    }
-
-    @Override
-    public Future<Void> onRemoteNodeDeleted(final NodeId nodeId) {
-        LOG.debug("TopologyManager({}) onRemoteNodeDeleted received, nodeid: {}", id, nodeId.getValue());
-
-        final ListenableFuture<Void> listenableFuture = onNodeDeleted(nodeId);
-        final DefaultPromise<Void> promise = new DefaultPromise<>();
-        Futures.addCallback(listenableFuture, new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-                promise.success(null);
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                promise.failure(t);
-            }
-        });
-
-        return promise.future();
-    }
-
-    public Future<NormalizedNodeMessage> remoteGetCurrentStatusForNode(final NodeId nodeId) {
-        LOG.debug("TopologyManager({}) remoteGetCurrentStatusForNode received, nodeid: {}", id, nodeId.getValue());
-
-        final ListenableFuture<Node> listenableFuture = getCurrentStatusForNode(nodeId);
-        final DefaultPromise<NormalizedNodeMessage> promise = new DefaultPromise<>();
-        Futures.addCallback(listenableFuture, new FutureCallback<Node>() {
-            @Override
-            public void onSuccess(Node result) {
-                final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = codecRegistry.toNormalizedNode(TopologyUtil.createTopologyNodePath(topologyId), result);
-                promise.success(new NormalizedNodeMessage(entry.getKey(), entry.getValue()));
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                promise.failure(t);
-            }
-        });
-        return promise.future();
-    }
-
-    @Override
-    public void onReceive(final Object message, final ActorRef actorRef) {
-        LOG.debug("message received {}", message);
-        if (message instanceof MemberUp) {
-            final Member member = ((MemberUp) message).member();
-            LOG.info("Member is Up: {}", member);
-            if (member.address().equals(clusterExtension.selfAddress())) {
-                return;
-            }
-
-            final NetconfTopologyPathCreator pathCreator = new NetconfTopologyPathCreator(member.address().toString(), topologyId);
-            final String path = pathCreator.build();
-            LOG.debug("Actor at :{} is resolving topology actor for path {}", clusterExtension.selfAddress(), path);
-
-            // first send basic identify message in case our messages have not been loaded through osgi yet to prevent crashing akka.
-            clusterExtension.system().actorSelection(path).tell(new Identify(member.address()), TypedActor.context().self());
-        } else if (message instanceof MemberExited) {
-            // remove peer
-            final Member member = ((MemberExited) message).member();
-            LOG.info("Member exited cluster: {}", member);
-            peers.remove(member.address());
-        } else if (message instanceof MemberRemoved) {
-            // remove peer
-            final Member member = ((MemberRemoved) message).member();
-            LOG.info("Member was removed from cluster: {}", member);
-            peers.remove(member.address());
-        } else if (message instanceof UnreachableMember) {
-            // remove peer
-            final Member member = ((UnreachableMember) message).member();
-            LOG.info("Member is unreachable: {}", member);
-            peers.remove(member.address());
-        } else if (message instanceof ReachableMember) {
-            // resync peer
-            final Member member = ((ReachableMember) message).member();
-            LOG.info("Member is reachable again: {}", member);
-
-            if (member.address().equals(clusterExtension.selfAddress())) {
-                return;
-            }
-            final NetconfTopologyPathCreator pathCreator = new NetconfTopologyPathCreator(member.address().toString(), topologyId);
-            final String path = pathCreator.build();
-            LOG.debug("Actor at :{} is resolving topology actor for path {}", clusterExtension.selfAddress(), path);
-
-            clusterExtension.system().actorSelection(path).tell(new Identify(member.address()), TypedActor.context().self());
-        } else if (message instanceof ActorIdentity) {
-            LOG.debug("Received ActorIdentity message", message);
-            final NetconfTopologyPathCreator pathCreator = new NetconfTopologyPathCreator(((ActorIdentity) message).correlationId().toString(), topologyId);
-            final String path = pathCreator.build();
-            if (((ActorIdentity) message).getRef() == null) {
-                LOG.debug("ActorIdentity has null actor ref, retrying..", message);
-                final ActorRef self = TypedActor.context().self();
-                final ActorContext context = TypedActor.context();
-                system.scheduler().scheduleOnce(new FiniteDuration(5, TimeUnit.SECONDS), new Runnable() {
-                    @Override
-                    public void run() {
-                        LOG.debug("Retrying identify message from master to node {} , full path {}", ((ActorIdentity) message).correlationId(), path);
-                        context.system().actorSelection(path).tell(new Identify(((ActorIdentity) message).correlationId()), self);
-
-                    }
-                }, system.dispatcher());
-                return;
-            }
-            LOG.debug("Actor at :{} is resolving topology actor for path {}, with a custom message", clusterExtension.selfAddress(), path);
-
-            clusterExtension.system().actorSelection(path).tell(new CustomIdentifyMessage(clusterExtension.selfAddress()), TypedActor.context().self());
-        } else if (message instanceof CustomIdentifyMessageReply) {
-
-            LOG.warn("Received a custom identify reply message from: {}", ((CustomIdentifyMessageReply) message).getAddress());
-            if (!peers.containsKey(((CustomIdentifyMessage) message).getAddress())) {
-                final TopologyManager peer = typedExtension.typedActorOf(new TypedProps<>(TopologyManager.class, BaseTopologyManager.class), actorRef);
-                peers.put(((CustomIdentifyMessageReply) message).getAddress(), peer);
-                if (isMaster) {
-                    resyncPeer(peer);
-                }
-            }
-        } else if (message instanceof CustomIdentifyMessage) {
-            LOG.warn("Received a custom identify message from: {}", ((CustomIdentifyMessage) message).getAddress());
-            if (!peers.containsKey(((CustomIdentifyMessage) message).getAddress())) {
-                final TopologyManager peer = typedExtension.typedActorOf(new TypedProps<>(TopologyManager.class, BaseTopologyManager.class), actorRef);
-                peers.put(((CustomIdentifyMessage) message).getAddress(), peer);
-                if (isMaster) {
-                    resyncPeer(peer);
-                }
-            }
-            actorRef.tell(new CustomIdentifyMessageReply(clusterExtension.selfAddress()), TypedActor.context().self());
-        }
-    }
-
-    private void resyncPeer(final TopologyManager peer) {
-        final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
-        final CheckedFuture<Optional<Topology>, ReadFailedException> read = rTx.read(LogicalDatastoreType.CONFIGURATION, topologyListPath);
-
-        Futures.addCallback(read, new FutureCallback<Optional<Topology>>() {
-            @Override
-            public void onSuccess(Optional<Topology> result) {
-                if (result.isPresent() && result.get().getNode() != null) {
-                    for (final Node node : result.get().getNode()) {
-                        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = codecRegistry.toNormalizedNode(TopologyUtil.createTopologyNodePath(topologyId), node);
-                        peer.onRemoteNodeCreated(new NormalizedNodeMessage(entry.getKey(), entry.getValue()));
-                        // we dont care about the future from now on since we will be notified by the onConnected event
-                    }
-                }
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                LOG.error("Unable to read from datastore");
-            }
-        });
-
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NodeRoleChangeStrategy.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NodeRoleChangeStrategy.java
deleted file mode 100644 (file)
index 4783404..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util;
-
-import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
-import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.netconf.topology.RoleChangeStrategy;
-import org.opendaylight.netconf.topology.NodeListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NodeRoleChangeStrategy implements RoleChangeStrategy, EntityOwnershipListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(NodeRoleChangeStrategy.class);
-
-    private final EntityOwnershipService entityOwnershipService;
-    private final String entityType;
-    private final String entityName;
-    private final Entity entity;
-    private NodeListener ownershipCandidate;
-
-    private EntityOwnershipCandidateRegistration candidateRegistration = null;
-    private EntityOwnershipListenerRegistration ownershipListenerRegistration = null;
-
-    public NodeRoleChangeStrategy(final EntityOwnershipService entityOwnershipService,
-                                  final String entityType,
-                                  final String entityName) {
-        this.entityOwnershipService = entityOwnershipService;
-        this.entityType = entityType + "/" + entityName;
-        this.entityName = entityName;
-        this.entity = new Entity(this.entityType, entityName);
-    }
-
-    @Override
-    public void registerRoleCandidate(NodeListener electionCandidate) {
-        LOG.debug("Registering role candidate type: {} , name: {}", entityType, entityName);
-        this.ownershipCandidate = electionCandidate;
-        try {
-            if (candidateRegistration != null) {
-                unregisterRoleCandidate();
-            }
-            candidateRegistration = entityOwnershipService.registerCandidate(entity);
-            ownershipListenerRegistration = entityOwnershipService.registerListener(entityType, this);
-        } catch (CandidateAlreadyRegisteredException e) {
-            LOG.error("Candidate already registered for election", e);
-            throw new IllegalStateException("Candidate already registered for election", e);
-        }
-    }
-
-    @Override
-    public void unregisterRoleCandidate() {
-        LOG.debug("Unregistering role candidate");
-        if (candidateRegistration != null) {
-            candidateRegistration.close();
-            candidateRegistration = null;
-        }
-        if (ownershipListenerRegistration != null) {
-            ownershipListenerRegistration.close();
-            ownershipListenerRegistration = null;
-        }
-    }
-
-    @Override
-    public boolean isCandidateRegistered() {
-        return entityOwnershipService.isCandidateRegistered(entity);
-    }
-
-    @Override
-    public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-        LOG.debug("Role was changed {}", roleChangeDTO);
-        ownershipCandidate.onRoleChanged(roleChangeDTO);
-    }
-
-    @Override
-    public void ownershipChanged(EntityOwnershipChange ownershipChange) {
-        LOG.debug("Ownership has changed {}", ownershipChange);
-        ownershipCandidate.onRoleChanged(new RoleChangeDTO(ownershipChange.wasOwner(), ownershipChange.isOwner(), ownershipChange.hasOwner()));
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NodeWriter.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NodeWriter.java
deleted file mode 100644 (file)
index 0b0d7b8..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util;
-
-import com.google.common.annotations.Beta;
-import javax.annotation.Nonnull;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-
-/**
- * Customizable code that gets executed after result aggregation, meant for custom writes
- * into the datastore, but any user code can be run here if desired.
- */
-@Beta
-public interface NodeWriter {
-
-    void init(@Nonnull final NodeId id, @Nonnull final Node operationalDataNode);
-
-    void update(@Nonnull final NodeId id, @Nonnull final Node operationalDataNode);
-
-    void delete(@Nonnull final NodeId id);
-
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NoopRoleChangeStrategy.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/NoopRoleChangeStrategy.java
deleted file mode 100644 (file)
index ea6e5d5..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util;
-
-import org.opendaylight.netconf.topology.NodeListener;
-import org.opendaylight.netconf.topology.RoleChangeStrategy;
-
-/**
- * Use this strategy to override the default roleChange registration's in BaseTopologyManager|BaseNodeManager
- * If you use this, you will need to execute your own election in your implemented callbacks.
- */
-public class NoopRoleChangeStrategy implements RoleChangeStrategy {
-
-    @Override
-    public void registerRoleCandidate(NodeListener electionCandidate) {
-
-    }
-
-    @Override
-    public void unregisterRoleCandidate() {
-
-    }
-
-    @Override
-    public boolean isCandidateRegistered() {
-        return false;
-    }
-
-    @Override
-    public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/SalNodeWriter.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/SalNodeWriter.java
deleted file mode 100644 (file)
index 4f0a53a..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
-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.AsyncTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public final class SalNodeWriter implements NodeWriter {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SalNodeWriter.class);
-
-    private final String topologyId;
-
-    private final BindingTransactionChain transactionChain;
-    public SalNodeWriter(final DataBroker dataBroker, final String topologyId) {
-        this.topologyId = topologyId;
-        this.transactionChain = Preconditions.checkNotNull(dataBroker).createTransactionChain(new TransactionChainListener() {
-            @Override
-            public void onTransactionChainFailed(TransactionChain<?, ?> transactionChain, AsyncTransaction<?, ?> transaction, Throwable cause) {
-                LOG.error("{}: TransactionChain({}) {} FAILED!", transactionChain,
-                        transaction.getIdentifier(), cause);
-                throw new IllegalStateException("Abstract topology writer TransactionChain(" + transactionChain + ") not committed correctly", cause);
-            }
-
-            @Override
-            public void onTransactionChainSuccessful(TransactionChain<?, ?> transactionChain) {
-                LOG.trace("Abstract topology writer TransactionChain({}) SUCCESSFUL", transactionChain);
-            }
-        });
-    }
-
-    @Override public void init(@Nonnull final NodeId id, @Nonnull final Node operationalDataNode) {
-        // put into Datastore
-        final WriteTransaction wTx = transactionChain.newWriteOnlyTransaction();
-        wTx.put(LogicalDatastoreType.OPERATIONAL, TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId), operationalDataNode);
-        commitTransaction(wTx, id, "init");
-    }
-
-    @Override public void update(@Nonnull final NodeId id, @Nonnull final Node operationalDataNode) {
-        // merge
-        final WriteTransaction wTx = transactionChain.newWriteOnlyTransaction();
-        wTx.put(LogicalDatastoreType.OPERATIONAL, TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId), operationalDataNode);
-        commitTransaction(wTx, id, "update");
-    }
-
-    @Override public void delete(@Nonnull final NodeId id) {
-        // delete
-        final WriteTransaction wTx = transactionChain.newWriteOnlyTransaction();
-        wTx.delete(LogicalDatastoreType.OPERATIONAL, TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId));
-        commitTransaction(wTx, id, "delete");
-    }
-
-    private void commitTransaction(final WriteTransaction transaction, final NodeId id, final String txType) {
-        LOG.debug("{}: Committing Transaction {}:{}", id.getValue(), txType,
-                transaction.getIdentifier());
-        final CheckedFuture<Void, TransactionCommitFailedException> result = transaction.submit();
-
-        Futures.addCallback(result, new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(final Void result) {
-                LOG.debug("{}: Transaction({}) {} SUCCESSFUL", id.getValue(), txType,
-                        transaction.getIdentifier());
-            }
-
-            @Override
-            public void onFailure(final Throwable t) {
-                LOG.error("{}: Transaction({}) {} FAILED!", id.getValue(), txType,
-                        transaction.getIdentifier(), t);
-                throw new IllegalStateException(id + "  Transaction(" + txType + ") not committed correctly", t);
-            }
-        });
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyRoleChangeStrategy.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyRoleChangeStrategy.java
deleted file mode 100644 (file)
index a7fc412..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util;
-
-import java.util.Collection;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
-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.DataTreeIdentifier;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
-import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netconf.topology.NodeListener;
-import org.opendaylight.netconf.topology.RoleChangeStrategy;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TopologyRoleChangeStrategy implements RoleChangeStrategy, ClusteredDataTreeChangeListener<Node>, EntityOwnershipListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(TopologyRoleChangeStrategy.class);
-
-    private final DataBroker dataBroker;
-
-    private final EntityOwnershipService entityOwnershipService;
-    private NodeListener ownershipCandidate;
-    private final String entityType;
-    // use topologyId as entityName
-    private final Entity entity;
-
-    private EntityOwnershipCandidateRegistration candidateRegistration = null;
-    private EntityOwnershipListenerRegistration ownershipListenerRegistration = null;
-
-    private ListenerRegistration<TopologyRoleChangeStrategy> datastoreListenerRegistration;
-
-    public TopologyRoleChangeStrategy(final DataBroker dataBroker,
-                                      final EntityOwnershipService entityOwnershipService,
-                                      final String entityType,
-                                      final String entityName) {
-        this.dataBroker = dataBroker;
-        this.entityOwnershipService = entityOwnershipService;
-        this.entityType = entityType;
-        this.entity = new Entity(entityType, entityName);
-
-        datastoreListenerRegistration = null;
-    }
-
-    @Override
-    public void registerRoleCandidate(NodeListener electionCandidate) {
-        LOG.warn("Registering candidate");
-        ownershipCandidate = electionCandidate;
-        try {
-            if (candidateRegistration != null) {
-                unregisterRoleCandidate();
-            }
-            candidateRegistration = entityOwnershipService.registerCandidate(entity);
-            ownershipListenerRegistration = entityOwnershipService.registerListener(entityType, this);
-        } catch (CandidateAlreadyRegisteredException e) {
-            LOG.error("Candidate already registered for election", e);
-            throw new IllegalStateException("Candidate already registered for election", e);
-        }
-    }
-
-    @Override
-    public void unregisterRoleCandidate() {
-        candidateRegistration.close();
-        candidateRegistration = null;
-        ownershipListenerRegistration.close();
-        ownershipListenerRegistration = null;
-    }
-
-    @Override
-    public boolean isCandidateRegistered() {
-        return entityOwnershipService.isCandidateRegistered(entity);
-    }
-
-    @Override
-    public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-        if (roleChangeDTO.isOwner()) {
-            LOG.warn("Gained ownership of entity, registering datastore listener");
-
-            if (datastoreListenerRegistration == null) {
-                LOG.debug("Listener on path {}", TopologyUtil.createTopologyListPath(entityType).child(Node.class).getPathArguments());
-                datastoreListenerRegistration = dataBroker.registerDataTreeChangeListener(
-                        new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, TopologyUtil.createTopologyListPath(entityType).child(Node.class)), this);
-            }
-        } else if (datastoreListenerRegistration != null) {
-            LOG.warn("No longer owner of entity, unregistering datastore listener");
-            datastoreListenerRegistration.close();
-            datastoreListenerRegistration = null;
-        }
-        ownershipCandidate.onRoleChanged(roleChangeDTO);
-    }
-
-    @Override
-    public void ownershipChanged(final EntityOwnershipChange ownershipChange) {
-        onRoleChanged(new RoleChangeDTO(ownershipChange.wasOwner(), ownershipChange.isOwner(), ownershipChange.hasOwner()));
-    }
-
-    @Override
-    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> changes) {
-        for (DataTreeModification<Node> change : changes) {
-            final DataObjectModification<Node> rootNode = change.getRootNode();
-            switch (rootNode.getModificationType()) {
-                case WRITE:
-                    LOG.debug("Data was Created {}, {}", rootNode.getIdentifier(), rootNode.getDataAfter());
-                    ownershipCandidate.onNodeCreated(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
-                    break;
-                case SUBTREE_MODIFIED:
-                    LOG.debug("Data was Updated {}, {}", rootNode.getIdentifier(), rootNode.getDataAfter());
-                    ownershipCandidate.onNodeUpdated(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
-                    break;
-                case DELETE:
-                    LOG.debug("Data was Deleted {}", rootNode.getIdentifier());
-                    ownershipCandidate.onNodeDeleted(TopologyUtil.getNodeId(rootNode.getIdentifier()));
-            }
-        }
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/CustomIdentifyMessage.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/CustomIdentifyMessage.java
deleted file mode 100644 (file)
index 721dcf6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util.messages;
-
-import akka.actor.Address;
-import java.io.Serializable;
-
-public class CustomIdentifyMessage implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private final Address address;
-
-    public CustomIdentifyMessage(final Address addressFrom) {
-        address = addressFrom;
-    }
-
-    public Address getAddress() {
-        return address;
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/CustomIdentifyMessageReply.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/CustomIdentifyMessageReply.java
deleted file mode 100644 (file)
index 62a5b43..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util.messages;
-
-import akka.actor.Address;
-
-// Marker message, that signals that actor should not reply to this one
-public class CustomIdentifyMessageReply extends CustomIdentifyMessage {
-    private static final long serialVersionUID = 1L;
-
-    public CustomIdentifyMessageReply(final Address addressFrom) {
-        super(addressFrom);
-    }
-}
diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/NormalizedNodeMessage.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/messages/NormalizedNodeMessage.java
deleted file mode 100644 (file)
index 9d12735..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util.messages;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataInput;
-import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput;
-import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputOutput;
-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;
-
-public class NormalizedNodeMessage implements Externalizable{
-    private static final long serialVersionUID = 1L;
-
-    private YangInstanceIdentifier identifier = null;
-    private NormalizedNode<?, ?> node = null;
-
-    public NormalizedNodeMessage() {
-
-    }
-
-    public NormalizedNodeMessage(YangInstanceIdentifier identifier, NormalizedNode<?, ?> node) {
-        this.identifier = identifier;
-        this.node = node;
-    }
-
-    public YangInstanceIdentifier getIdentifier() {
-        return identifier;
-    }
-
-    public NormalizedNode<?, ?> getNode() {
-        return node;
-    }
-
-    @Override
-    public void writeExternal(final ObjectOutput out) throws IOException {
-        final NormalizedNodeDataOutput dataOutput = NormalizedNodeInputOutput.newDataOutput(out);
-        final NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter((NormalizedNodeStreamWriter) dataOutput);
-
-        dataOutput.writeYangInstanceIdentifier(identifier);
-        normalizedNodeWriter.write(node);
-    }
-
-    @Override
-    public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
-        final NormalizedNodeDataInput dataInput = NormalizedNodeInputOutput.newDataInput(in);
-
-        identifier = dataInput.readYangInstanceIdentifier();
-        node = dataInput.readNormalizedNode();
-    }
-}
index 52b8a6a0859b0ca4cb618280912cc1472dca6125..8fcb44cfc120ff6f29fcfc4c1c5a3c6f6a809feb 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.messagebus.spi.EventSourceRegistration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
@@ -66,12 +67,12 @@ public class NetconfEventSourceRegistration implements AutoCloseable {
         if (netconfNode.getAvailableCapabilities() == null) {
             return false;
         }
-        final List<String> capabilities = netconfNode.getAvailableCapabilities().getAvailableCapability();
+        final List<AvailableCapability> capabilities = netconfNode.getAvailableCapabilities().getAvailableCapability();
         if (capabilities == null || capabilities.isEmpty()) {
             return false;
         }
-        for (final String capability : netconfNode.getAvailableCapabilities().getAvailableCapability()) {
-            if (capability.startsWith(NotificationCapabilityPrefix)) {
+        for (final AvailableCapability capability : netconfNode.getAvailableCapabilities().getAvailableCapability()) {
+            if (capability.getCapability().startsWith(NotificationCapabilityPrefix)) {
                 return true;
             }
         }
index a403681b7624703483e1240f62c627af171300c1..3124d6b1f064071f0dafa3a859b8300e44f1d675 100644 (file)
@@ -24,6 +24,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev15
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
@@ -55,8 +57,8 @@ public final class NetconfTestUtils {
         DomainName dn = new DomainName(hostName);
         Host host = new Host(dn);
 
-        List<String> avCapList = new ArrayList<>();
-        avCapList.add(notificationCapabilityPrefix + "_availableCapabilityString1");
+        List<AvailableCapability> avCapList = new ArrayList<>();
+        avCapList.add(new AvailableCapabilityBuilder().setCapability(notificationCapabilityPrefix + "_availableCapabilityString1").build());
         AvailableCapabilities avCaps = new AvailableCapabilitiesBuilder().setAvailableCapability(avCapList).build();
         NetconfNode nn = new NetconfNodeBuilder().setConnectionStatus(cs).setHost(host).setAvailableCapabilities(avCaps)
             .build();
index 4a8b22096a563dbb874e7c592797bbe75d17c58c..7102db1cb25db4a9b25fc1c357d57b50a4153631 100644 (file)
                 <artifactId>aaa-authn-odl-plugin</artifactId>
                 <version>${project.version}</version>
             </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>abstract-topology</artifactId>
-                <version>${project.version}</version>
-            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>netconf-config-dispatcher</artifactId>
                 <artifactId>netconf-util</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>netconf-util</artifactId>
+                <version>${project.version}</version>
+                <classifier>config</classifier>
+                <type>cfg</type>
+            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>netconf-mdsal-config</artifactId>
                 <classifier>config</classifier>
                 <type>xml</type>
             </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>netconf-topology-config</artifactId>
-                <version>${project.version}</version>
-                <classifier>clustered-config</classifier>
-                <type>xml</type>
-            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>yanglib-config</artifactId>
                 <version>${project.version}</version>
                 <type>test-jar</type>
             </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>netconf-topology-singleton</artifactId>
+                <version>${project.version}</version>
+            </dependency>
 
             <dependency>
                 <groupId>${project.groupId}</groupId>
index 8e4e05f93c1a1e701ac9596320f153c71ef14591..b4c260009a615fa554bed8cd1dbc160583ee25be 100644 (file)
@@ -40,5 +40,29 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <artifactId>sal-netconf-connector</artifactId>
       <version>${mdsal.version}</version>
     </dependency>
+      <dependency>
+          <groupId>org.mockito</groupId>
+          <artifactId>mockito-all</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-distributed-datastore</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.powermock</groupId>
+          <artifactId>powermock-module-junit4</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.powermock</groupId>
+          <artifactId>powermock-api-mockito</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.powermock</groupId>
+          <artifactId>powermock-core</artifactId>
+      </dependency>
   </dependencies>
 </project>
\ No newline at end of file
index 67024f910b005a9c8d4c28742c87761a4516c454..40ac48f17c633613afc9a1dd9be39db3ae5d86d0 100644 (file)
@@ -25,11 +25,13 @@ public class NetconfCommandUtils {
         if (Strings.isNullOrEmpty(devicePort)) {
             return false;
         }
-        Integer port = Integer.parseInt(devicePort);
-        if (port != null && port >= 0 && port <= 65535) {
-            return true;
+        Integer port;
+        try {
+            port = Integer.parseInt(devicePort);
+        } catch (NumberFormatException e) {
+          return false;
         }
-        return false;
+        return port >= 0 && port <= 65535;
     }
 
     public static boolean isIpValid(final String deviceIp) {
index 322f3d2cbe79340fa283d1705494db4929dd7dc5..a41839789c4ad1a5ed3f3d53e403bbe713ba3e19 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.netconf.console.commands;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.console.AbstractAction;
@@ -30,6 +31,13 @@ public class NetconfConnectDeviceCommand extends AbstractAction {
         this.service = service;
     }
 
+    @VisibleForTesting
+    NetconfConnectDeviceCommand(final NetconfCommands service, final String deviceIp, final String devicePort) {
+        this.service = service;
+        this.deviceIp = deviceIp;
+        this.devicePort = devicePort;
+    }
+
     @Option(name = "-i",
             aliases = { "--ipaddress" },
             description = "IP address of the netconf device",
index 94361901fdd123b96189cca32598f678d2658a06..b1abf2fa254d7a9f2bac9009245a99f1e0f48211 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.netconf.console.commands;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.console.AbstractAction;
@@ -24,6 +25,15 @@ public class NetconfDisconnectDeviceCommand extends AbstractAction {
         this.service = service;
     }
 
+    @VisibleForTesting
+    NetconfDisconnectDeviceCommand(final NetconfCommands service, final String deviceId, final String deviceIp,
+                                   final String devicePort) {
+        this.service = service;
+        this.deviceId = deviceId;
+        this.deviceIp = deviceIp;
+        this.devicePort = devicePort;
+    }
+
     @Option(name = "-i",
             aliases = { "--ipaddress" },
             description = "IP address of the netconf device",
index b50ea715493a732c47853f03131e889b96a6e90e..46d36dceb53e39a5d078bacafd8aa3a60f7f1caf 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.netconf.console.commands;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Strings;
 import java.util.List;
 import java.util.Map;
@@ -28,6 +29,15 @@ public class NetconfShowDeviceCommand extends AbstractAction {
         this.service = service;
     }
 
+    @VisibleForTesting
+    NetconfShowDeviceCommand(final NetconfCommands service, final String deviceId, final String deviceIp,
+                             final String devicePort) {
+        this.service = service;
+        this.deviceId = deviceId;
+        this.deviceIp = deviceIp;
+        this.devicePort = devicePort;
+    }
+
     @Option(name = "-id",
             aliases = { "--identifier" },
             description = "Node Identifier of the netconf device",
index b03556948e3e29b45469fad02ab99a19c8566898..79b6bb498e4d0b6e00f596749fa5264ce9164323 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.netconf.console.commands;
 
+import com.google.common.annotations.VisibleForTesting;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -26,6 +27,12 @@ public class NetconfUpdateDeviceCommand extends AbstractAction {
         this.service = service;
     }
 
+    @VisibleForTesting
+    NetconfUpdateDeviceCommand(final NetconfCommands service, final String newIp) {
+        this.service = service;
+        this.newIp = newIp;
+    }
+
     @Option(name = "-id",
             aliases = { "--nodeId" },
             description = "NETCONF node ID of the netconf device",
index baf98f06d677705b5668998e40382eab055cb63f..d830e9d097b0f14a6a94a2ea20b7fd5a2a026ae0 100644 (file)
@@ -17,8 +17,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import java.util.stream.Collectors;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.MountPoint;
 import org.opendaylight.controller.md.sal.binding.api.MountPointService;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -33,20 +33,15 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.ModuleType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.Modules;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.connector.netconf.rev150803.SalNetconfConnector;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -97,7 +92,8 @@ public class NetconfCommandsImpl implements NetconfCommands {
                     attributes.put(NetconfConsoleConstants.NETCONF_IP, ImmutableList.of(netconfNode.getHost().getIpAddress().getIpv4Address().getValue()));
                     attributes.put(NetconfConsoleConstants.NETCONF_PORT, ImmutableList.of(netconfNode.getPort().getValue().toString()));
                     attributes.put(NetconfConsoleConstants.STATUS, ImmutableList.of(netconfNode.getConnectionStatus().name()));
-                    attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES, netconfNode.getAvailableCapabilities().getAvailableCapability());
+                    attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES,
+                            netconfNode.getAvailableCapabilities().getAvailableCapability().stream().map(AvailableCapability::getCapability).collect(Collectors.toList()));
                     device.put(node.getNodeId().getValue(), attributes);
                 }
             }
@@ -117,7 +113,8 @@ public class NetconfCommandsImpl implements NetconfCommands {
                 attributes.put(NetconfConsoleConstants.NETCONF_IP, ImmutableList.of(netconfNode.getHost().getIpAddress().getIpv4Address().getValue()));
                 attributes.put(NetconfConsoleConstants.NETCONF_PORT, ImmutableList.of(netconfNode.getPort().getValue().toString()));
                 attributes.put(NetconfConsoleConstants.STATUS, ImmutableList.of(netconfNode.getConnectionStatus().name()));
-                attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES, netconfNode.getAvailableCapabilities().getAvailableCapability());
+                attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES,
+                        netconfNode.getAvailableCapabilities().getAvailableCapability().stream().map(AvailableCapability::getCapability).collect(Collectors.toList()));
                 device.put(node.getNodeId().getValue(), attributes);
             }
         }
diff --git a/netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/commands/NetconfCommandUtilsTest.java b/netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/commands/NetconfCommandUtilsTest.java
new file mode 100644 (file)
index 0000000..0c19ce2
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.console.commands;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+import org.junit.Test;
+
+public class NetconfCommandUtilsTest {
+
+    @Test
+    public void testIsPortValid() {
+        final boolean portTrue = NetconfCommandUtils.isPortValid("65535");
+        final boolean portTrue2 = NetconfCommandUtils.isPortValid("0");
+
+        final boolean portFalse = NetconfCommandUtils.isPortValid("123x");
+        final boolean portFalse2 = NetconfCommandUtils.isPortValid("65536");
+        final boolean portFalse3 = NetconfCommandUtils.isPortValid("");
+
+        assertTrue(portTrue);
+        assertTrue(portTrue2);
+        assertFalse(portFalse);
+        assertFalse(portFalse2);
+        assertFalse(portFalse3);
+
+    }
+
+    @Test
+    public void testIsIpValid() {
+        final boolean ipTrue = NetconfCommandUtils.isIpValid("0.0.0.0");
+        final boolean ipTrue2 = NetconfCommandUtils.isIpValid("255.255.255.255");
+
+        final boolean ipFalse = NetconfCommandUtils.isIpValid("256.1.1.1");
+        final boolean ipFalse2 = NetconfCommandUtils.isIpValid("123.145.12.x");
+        final boolean ipFalse3 = NetconfCommandUtils.isIpValid("");
+
+        assertTrue(ipTrue);
+        assertTrue(ipTrue2);
+        assertFalse(ipFalse);
+        assertFalse(ipFalse2);
+        assertFalse(ipFalse3);
+    }
+}
diff --git a/netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/commands/NetconfCommandsImplCallsTest.java b/netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/commands/NetconfCommandsImplCallsTest.java
new file mode 100644 (file)
index 0000000..0b52925
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.console.commands;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.common.collect.Lists;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.opendaylight.netconf.console.api.NetconfCommands;
+import org.opendaylight.netconf.console.utils.NetconfConsoleConstants;
+
+public class NetconfCommandsImplCallsTest {
+
+    @Mock
+    private NetconfCommands netconfCommands;
+
+    @Before
+    public void setUp(){
+        initMocks(this);
+    }
+
+    @Test
+    public void testConnectDeviceCommand() throws Exception {
+        NetconfConnectDeviceCommand netconfConnectDeviceCommand =
+                new NetconfConnectDeviceCommand(netconfCommands);
+        netconfConnectDeviceCommand.doExecute();
+        verify(netconfCommands, times(0)).connectDevice(any(), any());
+
+        netconfConnectDeviceCommand = new NetconfConnectDeviceCommand(netconfCommands, "192.168.1.1", "7777");
+
+        netconfConnectDeviceCommand.doExecute();
+        doNothing().when(netconfCommands).connectDevice(any(), any());
+        verify(netconfCommands, times(1)).connectDevice(any(), any());
+    }
+
+    @Test
+    public void testDisconnectDeviceCommand() throws Exception {
+        NetconfDisconnectDeviceCommand netconfDisconnectDeviceCommand = new NetconfDisconnectDeviceCommand(netconfCommands);
+        netconfDisconnectDeviceCommand.doExecute();
+
+        verify(netconfCommands, times(0)).connectDevice(any(), any());
+
+        netconfDisconnectDeviceCommand = new NetconfDisconnectDeviceCommand(netconfCommands, "deviceId", null, null);
+
+        doReturn(true).when(netconfCommands).disconnectDevice(any());
+        netconfDisconnectDeviceCommand.doExecute();
+
+        verify(netconfCommands, times(1)).disconnectDevice(any());
+
+        netconfDisconnectDeviceCommand =
+                new NetconfDisconnectDeviceCommand(netconfCommands, null, "192.168.1.1", "7777");
+
+        doReturn(true).when(netconfCommands).disconnectDevice(any(), any());
+        netconfDisconnectDeviceCommand.doExecute();
+
+        verify(netconfCommands, times(1)).disconnectDevice(any(), any());
+    }
+
+    @Test
+    public void testListDeviceCommand() throws Exception {
+        final NetconfListDevicesCommand netconfListDeviceCommand = new NetconfListDevicesCommand(netconfCommands);
+        doReturn(getDeviceHashMap()).when(netconfCommands).listDevices();
+
+        netconfListDeviceCommand.doExecute();
+
+        verify(netconfCommands, times(1)).listDevices();
+    }
+
+    @Test
+    public void testShowDeviceCommand() throws Exception {
+        NetconfShowDeviceCommand netconfShowDeviceCommand = new NetconfShowDeviceCommand(netconfCommands);
+        netconfShowDeviceCommand.doExecute();
+
+        verify(netconfCommands, times(0)).showDevice(any());
+
+        netconfShowDeviceCommand = new NetconfShowDeviceCommand(netconfCommands, "deviceId", null, null);
+
+        doReturn(getDeviceHashMap()).when(netconfCommands).showDevice(any());
+        netconfShowDeviceCommand.doExecute();
+
+        verify(netconfCommands, times(1)).showDevice(any());
+
+        netconfShowDeviceCommand = new NetconfShowDeviceCommand(netconfCommands, null, "192.168.1.1", "7777");
+
+        doReturn(getDeviceHashMap()).when(netconfCommands).showDevice(any(), any());
+        netconfShowDeviceCommand.doExecute();
+
+        verify(netconfCommands, times(1)).showDevice(any(), any());
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testUpdateDeviceCommand() throws Exception {
+        final NetconfUpdateDeviceCommand netconfUpdateDeviceCommand =
+                new NetconfUpdateDeviceCommand(netconfCommands, "192.168.1.1");
+
+        final ArgumentCaptor<HashMap> hashMapArgumentCaptor = ArgumentCaptor.forClass(HashMap.class);
+
+        doReturn("").when(netconfCommands).updateDevice(anyString(), anyString(), anyString(), any());
+
+        netconfUpdateDeviceCommand.doExecute();
+
+        verify(netconfCommands, times(1)).updateDevice(anyString(), anyString(), anyString(), hashMapArgumentCaptor.capture());
+
+        assertTrue(hashMapArgumentCaptor.getValue().containsKey(NetconfConsoleConstants.NETCONF_IP));
+        assertEquals("192.168.1.1", hashMapArgumentCaptor.getValue().get(NetconfConsoleConstants.NETCONF_IP));
+    }
+
+    private HashMap getDeviceHashMap() {
+        final HashMap<String, Map<String, List<String>>> devices = new HashMap<>();
+        final HashMap<String, List<String>> deviceMap = new HashMap<>();
+        deviceMap.put(NetconfConsoleConstants.NETCONF_IP, Lists.newArrayList("192.168.1.1"));
+        deviceMap.put(NetconfConsoleConstants.NETCONF_PORT, Lists.newArrayList("7777"));
+        deviceMap.put(NetconfConsoleConstants.STATUS, Lists.newArrayList("connecting"));
+        deviceMap.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES, Lists.newArrayList("cap1", "cap2", "cap3"));
+        devices.put("device", deviceMap);
+        return devices;
+    }
+
+}
diff --git a/netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/impl/NetconfCommandsImplTest.java b/netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/impl/NetconfCommandsImplTest.java
new file mode 100644 (file)
index 0000000..1ccd575
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.console.impl;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.collect.ImmutableList;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.databroker.ConcurrentDOMDataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.netconf.console.utils.NetconfConsoleConstants;
+import org.opendaylight.netconf.console.utils.NetconfConsoleUtils;
+import org.opendaylight.netconf.console.utils.NetconfIidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.HostBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
+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.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+
+public class NetconfCommandsImplTest {
+
+    private static final String NODE_ID = "NodeID";
+    private static final String IP = "192.168.1.1";
+    private static final int PORT = 1234;
+    private static final NetconfNodeConnectionStatus.ConnectionStatus CONN_STATUS =
+            NetconfNodeConnectionStatus.ConnectionStatus.Connected;
+    private static final String CAP_PREFIX = "prefix";
+
+    private DataBroker dataBroker;
+    private SchemaContext schemaContext;
+    private NetconfCommandsImpl netconfCommands;
+
+    @Before
+    public void setUp() throws TransactionCommitFailedException, TimeoutException, InterruptedException {
+        schemaContext = parseYangStreams(getYangSchemas());
+        schemaContext.getModules();
+        final SchemaService schemaService = createSchemaService();
+
+        final DOMStore operStore = InMemoryDOMDataStoreFactory.create("DOM-OPER", schemaService);
+        final DOMStore configStore = InMemoryDOMDataStoreFactory.create("DOM-CFG", schemaService);
+
+        final EnumMap<LogicalDatastoreType, DOMStore> datastores = new EnumMap<>(LogicalDatastoreType.class);
+        datastores.put(LogicalDatastoreType.CONFIGURATION, configStore);
+        datastores.put(LogicalDatastoreType.OPERATIONAL, operStore);
+
+        final ExecutorService listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(
+                16, 16, "CommitFutures");
+
+        final ConcurrentDOMDataBroker cDOMDataBroker = new ConcurrentDOMDataBroker(datastores, listenableFutureExecutor);
+
+        final ClassPool pool = ClassPool.getDefault();
+        final DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(pool));
+        final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
+        final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
+        codecRegistry.onBindingRuntimeContextUpdated(BindingRuntimeContext.create(moduleInfoBackedContext, schemaContext));
+
+        final GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
+        final BindingToNormalizedNodeCodec bindingToNormalized = new BindingToNormalizedNodeCodec(loading, codecRegistry);
+        bindingToNormalized.onGlobalContextUpdated(schemaContext);
+        dataBroker = new BindingDOMDataBrokerAdapter(cDOMDataBroker, bindingToNormalized);
+
+        final MountPointService mountPointService = mock(MountPointService.class);
+        netconfCommands = new NetconfCommandsImpl(dataBroker, mountPointService);
+    }
+
+    @Test
+    public void testListDevice() throws TimeoutException, TransactionCommitFailedException {
+        createTopology(LogicalDatastoreType.OPERATIONAL);
+
+        final Map map = netconfCommands.listDevices();
+        map.containsKey(NetconfConsoleConstants.NETCONF_ID);
+        assertTrue(map.containsKey(NODE_ID));
+
+        final Map mapNode = (Map) map.get(NODE_ID);
+        assertBaseNodeAttributes(mapNode);
+    }
+
+    @Test
+    public void testShowDevice() throws TimeoutException, TransactionCommitFailedException {
+        createTopology(LogicalDatastoreType.OPERATIONAL);
+
+        final Map mapCorrect = netconfCommands.showDevice(IP, String.valueOf(PORT));
+        mapCorrect.containsKey(NetconfConsoleConstants.NETCONF_ID);
+        assertTrue(mapCorrect.containsKey(NODE_ID));
+
+        assertBaseNodeAttributesImmutableList((Map) mapCorrect.get(NODE_ID));
+
+        final Map mapWrongPort = netconfCommands.showDevice(IP, "1");
+        assertFalse(mapWrongPort.containsKey(NODE_ID));
+
+        final Map mapWrongIP = netconfCommands.showDevice("1.1.1.1", String.valueOf(PORT));
+        assertFalse(mapWrongIP.containsKey(NODE_ID));
+
+        final Map mapId = netconfCommands.showDevice(NODE_ID);
+        assertTrue(mapId.containsKey(NODE_ID));
+        assertBaseNodeAttributesImmutableList((Map) mapId.get(NODE_ID));
+    }
+
+    @Test
+    public void testConnectDisconnectDevice() throws InterruptedException, TimeoutException, TransactionCommitFailedException {
+        final NetconfNode netconfNode = new NetconfNodeBuilder().setPort(new PortNumber(7777)).
+                setHost(HostBuilder.getDefaultInstance("10.10.1.1")).build();
+
+        createTopology(LogicalDatastoreType.CONFIGURATION);
+        netconfCommands.connectDevice(netconfNode, "netconf-ID");
+        NetconfConsoleUtils.waitForUpdate("10.10.1.1");
+
+        final Topology topology = NetconfConsoleUtils.read(LogicalDatastoreType.CONFIGURATION,
+                NetconfIidFactory.NETCONF_TOPOLOGY_IID, dataBroker);
+        final List<Node> nodes = topology.getNode();
+        assertEquals(2, nodes.size());
+
+        final Optional<Node> storedNode = nodes.stream().filter(node ->
+                node.getKey().getNodeId().getValue().equals("netconf-ID")).findFirst();
+
+        assertTrue(storedNode.isPresent());
+
+        NetconfNode storedNetconfNode = storedNode.get().getAugmentation(NetconfNode.class);
+        assertEquals(7777, storedNetconfNode.getPort().getValue().longValue());
+        assertEquals("10.10.1.1", storedNetconfNode.getHost().getIpAddress().getIpv4Address().getValue());
+
+        netconfCommands.disconnectDevice("netconf-ID");
+
+        final Topology topologyDeleted = NetconfConsoleUtils.read(LogicalDatastoreType.CONFIGURATION,
+                NetconfIidFactory.NETCONF_TOPOLOGY_IID, dataBroker);
+        final List<Node> nodesDeleted = topologyDeleted.getNode();
+        assertEquals(1, nodesDeleted.size());
+
+        final Optional<Node> storedNodeDeleted = nodesDeleted.stream().filter(node ->
+                node.getKey().getNodeId().getValue().equals("netconf-ID")).findFirst();
+
+        assertFalse(storedNodeDeleted.isPresent());
+    }
+
+    @Test
+    public void testUpdateDevice() throws TimeoutException, TransactionCommitFailedException {
+        //We need both, read data from OPERATIONAL DS and update data in CONFIGURATIONAL DS
+        createTopology(LogicalDatastoreType.OPERATIONAL);
+        createTopology(LogicalDatastoreType.CONFIGURATION);
+
+        final Map<String, String> update = new HashMap<>();
+        update.put(NetconfConsoleConstants.NETCONF_IP, "7.7.7.7");
+        update.put(NetconfConsoleConstants.TCP_ONLY, "true");
+
+        netconfCommands.updateDevice(NODE_ID, "admin", "admin", update);
+        NetconfConsoleUtils.waitForUpdate("7.7.7.7");
+
+        final Topology topology = NetconfConsoleUtils.read(LogicalDatastoreType.CONFIGURATION,
+                NetconfIidFactory.NETCONF_TOPOLOGY_IID, dataBroker);
+        final List<Node> nodes = topology.getNode();
+        assertEquals(1, nodes.size());
+
+        final Optional<Node> storedNode = nodes.stream().filter(node ->
+                node.getKey().getNodeId().getValue().equals(NODE_ID)).findFirst();
+        assertTrue(storedNode.isPresent());
+
+        NetconfNode storedNetconfNode = storedNode.get().getAugmentation(NetconfNode.class);
+        assertEquals("7.7.7.7", storedNetconfNode.getHost().getIpAddress().getIpv4Address().getValue());
+    }
+
+    @Test
+    public void testNetconfNodeFromIp() throws TimeoutException, TransactionCommitFailedException {
+        final List<Node> nodesNotExist = NetconfConsoleUtils.getNetconfNodeFromIp(IP, dataBroker);
+        assertNull(nodesNotExist);
+        createTopology(LogicalDatastoreType.OPERATIONAL);
+        final List<Node> nodes = NetconfConsoleUtils.getNetconfNodeFromIp(IP, dataBroker);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+    }
+
+    private void createTopology(LogicalDatastoreType dataStoreType) throws TransactionCommitFailedException, TimeoutException {
+        final List<Node> nodes = new ArrayList<>();
+        final Node node = getNetconfNode(NODE_ID, IP, PORT, CONN_STATUS, CAP_PREFIX);
+        nodes.add(node);
+
+        final Topology topology = new TopologyBuilder().
+                setKey(new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))).
+                setTopologyId(new TopologyId(TopologyNetconf.QNAME.getLocalName())).setNode(nodes).build();
+
+        final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+        writeTransaction.put(dataStoreType, NetconfIidFactory.NETCONF_TOPOLOGY_IID, topology);
+        writeTransaction.submit().checkedGet(2, TimeUnit.SECONDS);
+    }
+
+    private Node getNetconfNode(String nodeIdent, String ip, int portNumber, NetconfNodeConnectionStatus.ConnectionStatus cs,
+                                String notificationCapabilityPrefix) {
+
+        final Host host = HostBuilder.getDefaultInstance(ip);
+        final PortNumber port = new PortNumber(portNumber);
+
+        final List<AvailableCapability> avCapList = new ArrayList<>();
+        avCapList.add(new AvailableCapabilityBuilder()
+                .setCapabilityOrigin(AvailableCapability.CapabilityOrigin.UserDefined)
+                .setCapability(notificationCapabilityPrefix + "_availableCapabilityString1").build());
+        final AvailableCapabilities avCaps = new AvailableCapabilitiesBuilder().setAvailableCapability(avCapList).build();
+
+        final NetconfNode nn = new NetconfNodeBuilder().setConnectionStatus(cs).setHost(host).setPort(port).
+                setAvailableCapabilities(avCaps).build();
+        final NodeId nodeId = new NodeId(nodeIdent);
+        final NodeKey nk = new NodeKey(nodeId);
+        final NodeBuilder nb = new NodeBuilder();
+        nb.setKey(nk);
+        nb.setNodeId(nodeId);
+        nb.addAugmentation(NetconfNode.class, nn);
+        return nb.build();
+    }
+
+    private void assertBaseNodeAttributes(Map mapNode) {
+
+        assertTrue(mapNode.containsKey(NetconfConsoleConstants.NETCONF_ID));
+        assertTrue(mapNode.containsKey(NetconfConsoleConstants.NETCONF_IP));
+        assertTrue(mapNode.containsKey(NetconfConsoleConstants.NETCONF_PORT));
+        assertTrue(mapNode.containsKey(NetconfConsoleConstants.STATUS));
+
+        assertEquals(NODE_ID, mapNode.get(NetconfConsoleConstants.NETCONF_ID));
+        assertEquals(IP, mapNode.get(NetconfConsoleConstants.NETCONF_IP));
+        assertEquals(String.valueOf(PORT), mapNode.get(NetconfConsoleConstants.NETCONF_PORT));
+        assertEquals(CONN_STATUS.name().toLowerCase(), mapNode.get(NetconfConsoleConstants.STATUS));
+    }
+
+    private void assertBaseNodeAttributesImmutableList(Map mapNode) {
+        assertTrue(mapNode.containsKey(NetconfConsoleConstants.NETCONF_ID));
+        assertTrue(mapNode.containsKey(NetconfConsoleConstants.NETCONF_IP));
+        assertTrue(mapNode.containsKey(NetconfConsoleConstants.NETCONF_PORT));
+        assertTrue(mapNode.containsKey(NetconfConsoleConstants.STATUS));
+
+        assertEquals(ImmutableList.of(NODE_ID), mapNode.get(NetconfConsoleConstants.NETCONF_ID));
+        assertEquals(ImmutableList.of(IP), mapNode.get(NetconfConsoleConstants.NETCONF_IP));
+        assertEquals(ImmutableList.of(String.valueOf(PORT)), mapNode.get(NetconfConsoleConstants.NETCONF_PORT));
+        assertEquals(ImmutableList.of(CONN_STATUS.name()), mapNode.get(NetconfConsoleConstants.STATUS));
+    }
+
+    private List<InputStream> getYangSchemas() {
+        final List<String> schemaPaths = Arrays.asList("/schemas/network-topology@2013-10-21.yang",
+                "/schemas/ietf-inet-types@2013-07-15.yang", "/schemas/yang-ext.yang",
+                "/schemas/netconf-node-topology.yang");
+
+        final List<InputStream> schemas = new ArrayList<>();
+        for (String schemaPath : schemaPaths) {
+            final InputStream resourceAsStream = getClass().getResourceAsStream(schemaPath);
+            schemas.add(resourceAsStream);
+        }
+        return schemas;
+    }
+
+    private static SchemaContext parseYangStreams(final List<InputStream> streams) {
+        CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR
+                .newBuild();
+        final SchemaContext schemaContext;
+        try {
+            schemaContext = reactor.buildEffective(streams);
+        } catch (ReactorException e) {
+            throw new RuntimeException("Unable to build schema context from " + streams, e);
+        }
+        return schemaContext;
+    }
+
+    private SchemaService createSchemaService() {
+        return new SchemaService() {
+
+            @Override
+            public void addModule(Module module) {
+            }
+
+            @Override
+            public void removeModule(Module module) {
+
+            }
+
+            @Override
+            public SchemaContext getSessionContext() {
+                return schemaContext;
+            }
+
+            @Override
+            public SchemaContext getGlobalContext() {
+                return schemaContext;
+            }
+
+            @Override
+            public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(final SchemaContextListener listener) {
+                listener.onGlobalContextUpdated(getGlobalContext());
+                return new ListenerRegistration<SchemaContextListener>() {
+                    @Override
+                    public void close() {
+
+                    }
+
+                    @Override
+                    public SchemaContextListener getInstance() {
+                        return listener;
+                    }
+                };
+            }
+        };
+    }
+}
diff --git a/netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/impl/NetconfConsoleProviderTest.java b/netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/impl/NetconfConsoleProviderTest.java
new file mode 100644 (file)
index 0000000..ef20f81
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.console.impl;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.BDDMockito;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.netconf.console.api.NetconfCommands;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(FrameworkUtil.class)
+public class NetconfConsoleProviderTest {
+
+    @Test
+    public void testProvider() throws Exception {
+        final NetconfConsoleProvider netconfConsoleProvider = new NetconfConsoleProvider();
+
+        PowerMockito.mockStatic(FrameworkUtil.class);
+
+        final BindingAwareBroker.ProviderContext session = mock(BindingAwareBroker.ProviderContext.class);
+        final MountPointService mountPointService = mock(MountPointService.class);
+        final BundleContext bundleContext = mock(BundleContext.class);
+        final DataBroker dataBroker = mock(DataBroker.class);
+        final Bundle bundle = mock(Bundle.class);
+
+        doReturn(dataBroker).when(session).getSALService(DataBroker.class);
+        doReturn(mountPointService).when(session).getSALService(MountPointService.class);
+        BDDMockito.given(FrameworkUtil.getBundle(any())).willReturn(bundle);
+        when(bundle.getBundleContext()).thenReturn(bundleContext);
+
+        netconfConsoleProvider.onSessionInitiated(session);
+
+        verify(bundleContext, times(1)).registerService(eq(NetconfCommands.class), any(NetconfCommandsImpl.class), eq(null));
+
+    }
+}
diff --git a/netconf/netconf-console/src/test/resources/schemas/ietf-inet-types@2013-07-15.yang b/netconf/netconf-console/src/test/resources/schemas/ietf-inet-types@2013-07-15.yang
new file mode 100644 (file)
index 0000000..5c6f139
--- /dev/null
@@ -0,0 +1,457 @@
+module ietf-inet-types {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+  prefix "inet";
+
+  organization
+   "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+  contact
+   "WG Web:   <http://tools.ietf.org/wg/netmod/>
+    WG List:  <mailto:netmod@ietf.org>
+
+    WG Chair: David Kessens
+              <mailto:david.kessens@nsn.com>
+
+    WG Chair: Juergen Schoenwaelder
+              <mailto:j.schoenwaelder@jacobs-university.de>
+
+    Editor:   Juergen Schoenwaelder
+              <mailto:j.schoenwaelder@jacobs-university.de>";
+
+  description
+   "This module contains a collection of generally useful derived
+    YANG data types for Internet addresses and related things.
+
+    Copyright (c) 2013 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 6991; see
+    the RFC itself for full legal notices.";
+
+  revision 2013-07-15 {
+    description
+     "This revision adds the following new data types:
+      - ip-address-no-zone
+      - ipv4-address-no-zone
+      - ipv6-address-no-zone";
+    reference
+     "RFC 6991: Common YANG Data Types";
+  }
+
+  revision 2010-09-24 {
+    description
+     "Initial revision.";
+    reference
+     "RFC 6021: Common YANG Data Types";
+  }
+
+  /*** collection of types related to protocol fields ***/
+
+  typedef ip-version {
+    type enumeration {
+      enum unknown {
+        value "0";
+        description
+         "An unknown or unspecified version of the Internet
+          protocol.";
+      }
+      enum ipv4 {
+        value "1";
+        description
+         "The IPv4 protocol as defined in RFC 791.";
+      }
+      enum ipv6 {
+        value "2";
+        description
+         "The IPv6 protocol as defined in RFC 2460.";
+      }
+    }
+    description
+     "This value represents the version of the IP protocol.
+
+      In the value set and its semantics, this type is equivalent
+      to the InetVersion textual convention of the SMIv2.";
+    reference
+     "RFC  791: Internet Protocol
+      RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+      RFC 4001: Textual Conventions for Internet Network Addresses";
+  }
+
+  typedef dscp {
+    type uint8 {
+      range "0..63";
+    }
+    description
+     "The dscp type represents a Differentiated Services Code Point
+      that may be used for marking packets in a traffic stream.
+      In the value set and its semantics, this type is equivalent
+      to the Dscp textual convention of the SMIv2.";
+    reference
+     "RFC 3289: Management Information Base for the Differentiated
+                Services Architecture
+      RFC 2474: Definition of the Differentiated Services Field
+                (DS Field) in the IPv4 and IPv6 Headers
+      RFC 2780: IANA Allocation Guidelines For Values In
+                the Internet Protocol and Related Headers";
+  }
+
+  typedef ipv6-flow-label {
+    type uint32 {
+      range "0..1048575";
+    }
+    description
+     "The ipv6-flow-label type represents the flow identifier or Flow
+      Label in an IPv6 packet header that may be used to
+      discriminate traffic flows.
+
+      In the value set and its semantics, this type is equivalent
+      to the IPv6FlowLabel textual convention of the SMIv2.";
+    reference
+     "RFC 3595: Textual Conventions for IPv6 Flow Label
+      RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+  }
+
+  typedef port-number {
+    type uint16 {
+      range "0..65535";
+    }
+    description
+     "The port-number type represents a 16-bit port number of an
+      Internet transport-layer protocol such as UDP, TCP, DCCP, or
+      SCTP.  Port numbers are assigned by IANA.  A current list of
+      all assignments is available from <http://www.iana.org/>.
+
+      Note that the port number value zero is reserved by IANA.  In
+      situations where the value zero does not make sense, it can
+      be excluded by subtyping the port-number type.
+      In the value set and its semantics, this type is equivalent
+      to the InetPortNumber textual convention of the SMIv2.";
+    reference
+     "RFC  768: User Datagram Protocol
+      RFC  793: Transmission Control Protocol
+      RFC 4960: Stream Control Transmission Protocol
+      RFC 4340: Datagram Congestion Control Protocol (DCCP)
+      RFC 4001: Textual Conventions for Internet Network Addresses";
+  }
+
+  /*** collection of types related to autonomous systems ***/
+
+  typedef as-number {
+    type uint32;
+    description
+     "The as-number type represents autonomous system numbers
+      which identify an Autonomous System (AS).  An AS is a set
+      of routers under a single technical administration, using
+      an interior gateway protocol and common metrics to route
+      packets within the AS, and using an exterior gateway
+      protocol to route packets to other ASes.  IANA maintains
+      the AS number space and has delegated large parts to the
+      regional registries.
+
+      Autonomous system numbers were originally limited to 16
+      bits.  BGP extensions have enlarged the autonomous system
+      number space to 32 bits.  This type therefore uses an uint32
+      base type without a range restriction in order to support
+      a larger autonomous system number space.
+
+      In the value set and its semantics, this type is equivalent
+      to the InetAutonomousSystemNumber textual convention of
+      the SMIv2.";
+    reference
+     "RFC 1930: Guidelines for creation, selection, and registration
+                of an Autonomous System (AS)
+      RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+      RFC 4001: Textual Conventions for Internet Network Addresses
+      RFC 6793: BGP Support for Four-Octet Autonomous System (AS)
+                Number Space";
+  }
+
+  /*** collection of types related to IP addresses and hostnames ***/
+
+  typedef ip-address {
+    type union {
+      type inet:ipv4-address;
+      type inet:ipv6-address;
+    }
+    description
+     "The ip-address type represents an IP address and is IP
+      version neutral.  The format of the textual representation
+      implies the IP version.  This type supports scoped addresses
+      by allowing zone identifiers in the address format.";
+    reference
+     "RFC 4007: IPv6 Scoped Address Architecture";
+  }
+
+  typedef ipv4-address {
+    type string {
+      pattern
+        '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+      +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+      + '(%[\p{N}\p{L}]+)?';
+    }
+    description
+      "The ipv4-address type represents an IPv4 address in
+       dotted-quad notation.  The IPv4 address may include a zone
+       index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format for the zone index is the numerical
+       format";
+  }
+
+  typedef ipv6-address {
+    type string {
+      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+            + '(%[\p{N}\p{L}]+)?';
+      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+            + '(%.+)?';
+    }
+    description
+     "The ipv6-address type represents an IPv6 address in full,
+      mixed, shortened, and shortened-mixed notation.  The IPv6
+      address may include a zone index, separated by a % sign.
+
+      The zone index is used to disambiguate identical address
+      values.  For link-local addresses, the zone index will
+      typically be the interface index number or the name of an
+      interface.  If the zone index is not present, the default
+      zone of the device will be used.
+
+      The canonical format of IPv6 addresses uses the textual
+      representation defined in Section 4 of RFC 5952.  The
+      canonical format for the zone index is the numerical
+      format as described in Section 11.2 of RFC 4007.";
+    reference
+     "RFC 4291: IP Version 6 Addressing Architecture
+      RFC 4007: IPv6 Scoped Address Architecture
+      RFC 5952: A Recommendation for IPv6 Address Text
+                Representation";
+  }
+
+  typedef ip-address-no-zone {
+    type union {
+      type inet:ipv4-address-no-zone;
+      type inet:ipv6-address-no-zone;
+    }
+    description
+     "The ip-address-no-zone type represents an IP address and is
+      IP version neutral.  The format of the textual representation
+      implies the IP version.  This type does not support scoped
+      addresses since it does not allow zone identifiers in the
+      address format.";
+    reference
+     "RFC 4007: IPv6 Scoped Address Architecture";
+  }
+
+  typedef ipv4-address-no-zone {
+    type inet:ipv4-address {
+      pattern '[0-9\.]*';
+    }
+    description
+      "An IPv4 address without a zone index.  This type, derived from
+       ipv4-address, may be used in situations where the zone is
+       known from the context and hence no zone index is needed.";
+  }
+
+  typedef ipv6-address-no-zone {
+    type inet:ipv6-address {
+      pattern '[0-9a-fA-F:\.]*';
+    }
+    description
+      "An IPv6 address without a zone index.  This type, derived from
+       ipv6-address, may be used in situations where the zone is
+       known from the context and hence no zone index is needed.";
+    reference
+     "RFC 4291: IP Version 6 Addressing Architecture
+      RFC 4007: IPv6 Scoped Address Architecture
+      RFC 5952: A Recommendation for IPv6 Address Text
+                Representation";
+  }
+
+  typedef ip-prefix {
+    type union {
+      type inet:ipv4-prefix;
+      type inet:ipv6-prefix;
+    }
+    description
+     "The ip-prefix type represents an IP prefix and is IP
+      version neutral.  The format of the textual representations
+      implies the IP version.";
+  }
+
+  typedef ipv4-prefix {
+    type string {
+      pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+    }
+    description
+     "The ipv4-prefix type represents an IPv4 address prefix.
+      The prefix length is given by the number following the
+      slash character and must be less than or equal to 32.
+
+      A prefix length value of n corresponds to an IP address
+      mask that has n contiguous 1-bits from the most
+      significant bit (MSB) and all other bits set to 0.
+
+      The canonical format of an IPv4 prefix has all bits of
+      the IPv4 address set to zero that are not part of the
+      IPv4 prefix.";
+  }
+
+  typedef ipv6-prefix {
+    type string {
+      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+            + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+            + '(/.+)';
+    }
+    description
+     "The ipv6-prefix type represents an IPv6 address prefix.
+      The prefix length is given by the number following the
+      slash character and must be less than or equal to 128.
+
+      A prefix length value of n corresponds to an IP address
+      mask that has n contiguous 1-bits from the most
+      significant bit (MSB) and all other bits set to 0.
+
+      The IPv6 address should have all bits that do not belong
+      to the prefix set to zero.
+
+      The canonical format of an IPv6 prefix has all bits of
+      the IPv6 address set to zero that are not part of the
+      IPv6 prefix.  Furthermore, the IPv6 address is represented
+      as defined in Section 4 of RFC 5952.";
+    reference
+     "RFC 5952: A Recommendation for IPv6 Address Text
+                Representation";
+  }
+
+  /*** collection of domain name and URI types ***/
+
+  typedef domain-name {
+    type string {
+      pattern
+        '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+      + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+      + '|\.';
+      length "1..253";
+    }
+    description
+     "The domain-name type represents a DNS domain name.  The
+      name SHOULD be fully qualified whenever possible.
+
+      Internet domain names are only loosely specified.  Section
+      3.5 of RFC 1034 recommends a syntax (modified in Section
+      2.1 of RFC 1123).  The pattern above is intended to allow
+      for current practice in domain name use, and some possible
+      future expansion.  It is designed to hold various types of
+      domain names, including names used for A or AAAA records
+      (host names) and other records, such as SRV records.  Note
+      that Internet host names have a stricter syntax (described
+      in RFC 952) than the DNS recommendations in RFCs 1034 and
+      1123, and that systems that want to store host names in
+      schema nodes using the domain-name type are recommended to
+      adhere to this stricter standard to ensure interoperability.
+
+      The encoding of DNS names in the DNS protocol is limited
+      to 255 characters.  Since the encoding consists of labels
+      prefixed by a length bytes and there is a trailing NULL
+      byte, only 253 characters can appear in the textual dotted
+      notation.
+
+      The description clause of schema nodes using the domain-name
+      type MUST describe when and how these names are resolved to
+      IP addresses.  Note that the resolution of a domain-name value
+      may require to query multiple DNS records (e.g., A for IPv4
+      and AAAA for IPv6).  The order of the resolution process and
+      which DNS record takes precedence can either be defined
+      explicitly or may depend on the configuration of the
+      resolver.
+
+      Domain-name values use the US-ASCII encoding.  Their canonical
+      format uses lowercase US-ASCII characters.  Internationalized
+      domain names MUST be A-labels as per RFC 5890.";
+    reference
+     "RFC  952: DoD Internet Host Table Specification
+      RFC 1034: Domain Names - Concepts and Facilities
+      RFC 1123: Requirements for Internet Hosts -- Application
+                and Support
+      RFC 2782: A DNS RR for specifying the location of services
+                (DNS SRV)
+      RFC 5890: Internationalized Domain Names in Applications
+                (IDNA): Definitions and Document Framework";
+  }
+
+  typedef host {
+    type union {
+      type inet:ip-address;
+      type inet:domain-name;
+    }
+    description
+     "The host type represents either an IP address or a DNS
+      domain name.";
+  }
+
+  typedef uri {
+    type string;
+    description
+     "The uri type represents a Uniform Resource Identifier
+      (URI) as defined by STD 66.
+
+      Objects using the uri type MUST be in US-ASCII encoding,
+      and MUST be normalized as described by RFC 3986 Sections
+      6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+      percent-encoding is removed, and all case-insensitive
+      characters are set to lowercase except for hexadecimal
+      digits, which are normalized to uppercase as described in
+      Section 6.2.2.1.
+
+      The purpose of this normalization is to help provide
+      unique URIs.  Note that this normalization is not
+      sufficient to provide uniqueness.  Two URIs that are
+      textually distinct after this normalization may still be
+      equivalent.
+
+      Objects using the uri type may restrict the schemes that
+      they permit.  For example, 'data:' and 'urn:' schemes
+      might not be appropriate.
+
+      A zero-length URI is not a valid URI.  This can be used to
+      express 'URI absent' where required.
+
+      In the value set and its semantics, this type is equivalent
+      to the Uri SMIv2 textual convention defined in RFC 5017.";
+    reference
+     "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+      RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                Group: Uniform Resource Identifiers (URIs), URLs,
+                and Uniform Resource Names (URNs): Clarifications
+                and Recommendations
+      RFC 5017: MIB Textual Conventions for Uniform Resource
+                Identifiers (URIs)";
+  }
+
+}
diff --git a/netconf/netconf-console/src/test/resources/schemas/netconf-node-topology.yang b/netconf/netconf-console/src/test/resources/schemas/netconf-node-topology.yang
new file mode 100644 (file)
index 0000000..07461d4
--- /dev/null
@@ -0,0 +1,251 @@
+module netconf-node-topology {
+    namespace "urn:opendaylight:netconf-node-topology";
+    prefix "nettop";
+
+    import network-topology { prefix nt; revision-date 2013-10-21; }
+    import yang-ext { prefix ext; revision-date "2013-07-09";}
+    import ietf-inet-types { prefix inet; revision-date "2013-07-15"; }
+
+    revision "2015-01-14" {
+        description "Initial revision of Topology model";
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:topology-types" {
+        container topology-netconf {
+        }
+    }
+
+    grouping netconf-node-credentials {
+
+        choice credentials {
+            config true;
+            case login-password {
+                leaf username {
+                    type string;
+                }
+
+                leaf password {
+                    type string;
+                }
+            }
+        }
+    }
+
+    grouping netconf-node-connection-parameters {
+
+        leaf host {
+            type inet:host;
+        }
+
+        leaf port {
+            type inet:port-number;
+        }
+
+        leaf tcp-only {
+            config true;
+            type boolean;
+        }
+
+        leaf schemaless {
+            type boolean;
+            default false;
+        }
+
+        container yang-module-capabilities {
+            config true;
+            leaf override {
+                type boolean;
+                default false;
+                description "Whether to override or merge this list of capabilities with capabilities from device";
+            }
+
+            leaf-list capability {
+                type string;
+                description "Set a list of capabilities to override capabilities provided in device's hello message.
+                             Can be used for devices that do not report any yang modules in their hello message";
+            }
+        }
+
+        leaf reconnect-on-changed-schema {
+            config true;
+            type boolean;
+            default false;
+            description "If true, the connector would auto disconnect/reconnect when schemas are changed in the remote device.
+                         The connector subscribes (right after connect) to base netconf notifications and listens for netconf-capability-change notification";
+        }
+
+        leaf connection-timeout-millis {
+            description "Specifies timeout in milliseconds after which connection must be established.";
+            config true;
+            type uint32;
+            default 20000;
+        }
+
+        leaf default-request-timeout-millis {
+            description "Timeout for blocking operations within transactions.";
+            config true;
+            type uint32;
+            default 60000;
+        }
+
+        leaf max-connection-attempts {
+            description "Maximum number of connection retries. Non positive value or null is interpreted as infinity.";
+            config true;
+            type uint32;
+            default 0; // retry forever
+        }
+
+        leaf between-attempts-timeout-millis {
+            description "Initial timeout in milliseconds to wait between connection attempts. Will be multiplied by sleep-factor with every additional attempt";
+            config true;
+            type uint16;
+            default 2000;
+        }
+
+        leaf sleep-factor {
+            config true;
+            type decimal64 {
+                fraction-digits 1;
+            }
+            default 1.5;
+        }
+
+        // Keepalive configuration
+        leaf keepalive-delay {
+            config true;
+            type uint32;
+            default 120;
+            description "Netconf connector sends keepalive RPCs while the session is idle, this delay specifies the delay between keepalive RPC in seconds
+                         If a value <1 is provided, no keepalives will be sent";
+        }
+
+        leaf concurrent-rpc-limit {
+            config true;
+            type uint16;
+            default 0;
+            description "Limit of concurrent messages that can be send before reply messages are received.
+                         If value <1 is provided, no limit will be enforced";
+        }
+    }
+
+    grouping netconf-node-connection-status {
+
+        leaf connection-status {
+            config false;
+            type enumeration {
+                enum connecting;
+                enum connected;
+                enum unable-to-connect;
+            }
+        }
+
+        container clustered-connection-status {
+            config false;
+            list node-status {
+                leaf node {
+                    type string;
+                }
+                leaf status {
+                    type enumeration {
+                        enum connected;
+                        enum unavailable;
+                        enum failed;
+                    }
+                }
+            }
+        }
+
+        leaf connected-message {
+            config false;
+            type string;
+        }
+
+        container available-capabilities {
+            config false;
+            list available-capability {
+                leaf capability {
+                    type string;
+                }
+                leaf capability-origin {
+                    type enumeration {
+                        enum user-defined;
+                        enum device-advertised;
+                    }
+                }
+            }
+        }
+
+        container unavailable-capabilities {
+            config false;
+            list unavailable-capability {
+                leaf capability {
+                    type string;
+                }
+
+                leaf failure-reason {
+                    type enumeration {
+                        enum missing-source;
+                        enum unable-to-resolve;
+                    }
+                }
+            }
+        }
+
+        container pass-through {
+            when "../connection-status = connected";
+            description
+                "When the underlying node is connected, its NETCONF context
+                is available verbatim under this container through the
+                mount extension.";
+        }
+
+    }
+
+    grouping netconf-schema-storage {
+        leaf schema-cache-directory {
+            config true;
+            type string;
+            default "schema";
+            description "The destination schema repository for yang files relative to the cache directory.  This may be specified per netconf mount
+                         so that the loaded yang files are stored to a distinct directory to avoid potential conflict.";
+        }
+
+        container yang-library {
+            leaf yang-library-url {
+                config true;
+                type inet:uri;
+                description "Yang library to be plugged as additional source provider into the shared schema repository";
+            }
+
+            // credentials for basic http authentication
+            leaf username {
+                config true;
+                type string;
+            }
+
+            leaf password {
+                config true;
+                type string;
+            }
+        }
+    }
+
+    grouping netconf-node-fields {
+
+        uses netconf-node-credentials;
+
+        uses netconf-node-connection-parameters;
+
+        uses netconf-node-connection-status;
+
+        uses netconf-schema-storage;
+
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node" {
+        when "../../nt:topology-types/topology-netconf";
+        ext:augment-identifier "netconf-node";
+
+        uses netconf-node-fields;
+    }
+}
diff --git a/netconf/netconf-console/src/test/resources/schemas/network-topology@2013-10-21.yang b/netconf/netconf-console/src/test/resources/schemas/network-topology@2013-10-21.yang
new file mode 100644 (file)
index 0000000..dc5dcad
--- /dev/null
@@ -0,0 +1,339 @@
+module network-topology  {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:network-topology";
+    // replace with IANA namespace when assigned
+    prefix "nt";
+
+    import ietf-inet-types { prefix "inet"; revision-date 2013-07-15; }
+
+    organization "TBD";
+
+    contact "WILL-BE-DEFINED-LATER";
+
+    description
+        "This module defines a model for the topology of a network.
+        Key design decisions are as follows:
+        A topology consists of a set of nodes and links.
+        Links are point-to-point and unidirectional.
+        Bidirectional connections need to be represented through
+        two separate links.
+        Multipoint connections, broadcast domains etc can be represented
+        through a hierarchy of nodes, then connecting nodes at
+        upper layers of the hierarchy.";
+
+    revision 2013-10-21 {
+        description
+            "Initial revision.";
+    }
+
+    typedef topology-id {
+        type inet:uri;
+        description
+            "An identifier for a topology.";
+    }
+
+    typedef node-id {
+        type inet:uri;
+        description
+            "An identifier for a node in a topology.
+            The identifier may be opaque.
+            The identifier SHOULD be chosen such that the same node in a
+            real network topology will always be identified through the
+            same identifier, even if the model is instantiated in separate
+            datastores. An implementation MAY choose to capture semantics
+            in the identifier, for example to indicate the type of node
+            and/or the type of topology that the node is a part of.";
+    }
+
+
+    typedef link-id {
+        type inet:uri;
+        description
+            "An identifier for a link in a topology.
+            The identifier may be opaque.
+            The identifier SHOULD be chosen such that the same link in a
+            real network topology will always be identified through the
+            same identifier, even if the model is instantiated in separate
+            datastores. An implementation MAY choose to capture semantics
+            in the identifier, for example to indicate the type of link
+            and/or the type of topology that the link is a part of.";
+    }
+
+    typedef tp-id {
+        type inet:uri;
+        description
+            "An identifier for termination points on a node.
+            The identifier may be opaque.
+            The identifier SHOULD be chosen such that the same TP in a
+            real network topology will always be identified through the
+            same identifier, even if the model is instantiated in separate
+            datastores. An implementation MAY choose to capture semantics
+            in the identifier, for example to indicate the type of TP
+            and/or the type of node and topology that the TP is a part of.";
+    }
+
+    typedef tp-ref {
+        type leafref {
+            path "/network-topology/topology/node/termination-point/tp-id";
+        }
+        description
+            "A type for an absolute reference to a termination point.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+    typedef topology-ref {
+        type leafref {
+            path "/network-topology/topology/topology-id";
+        }
+        description
+            "A type for an absolute reference a topology instance.";
+    }
+
+    typedef node-ref {
+        type leafref {
+            path "/network-topology/topology/node/node-id";
+        }
+        description
+
+            "A type for an absolute reference to a node instance.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+
+    typedef link-ref {
+        type leafref {
+            path "/network-topology/topology/link/link-id";
+        }
+        description
+            "A type for an absolute reference a link instance.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+
+    grouping tp-attributes {
+        description
+            "The data objects needed to define a termination point.
+            (This only includes a single leaf at this point, used
+            to identify the termination point.)
+            Provided in a grouping so that in addition to the datastore,
+            the data can also be included in notifications.";
+        leaf tp-id {
+            type tp-id;
+        }
+        leaf-list tp-ref {
+            type tp-ref;
+            config false;
+            description
+                "The leaf list identifies any termination points that the
+                termination point is dependent on, or maps onto.
+                Those termination points will themselves be contained
+                in a supporting node.
+                This dependency information can be inferred from
+                the dependencies between links.  For this reason,
+                this item is not separately configurable.  Hence no
+                corresponding constraint needs to be articulated.
+                The corresponding information is simply provided by the
+                implementing system.";
+        }
+    }
+
+    grouping node-attributes {
+        description
+            "The data objects needed to define a node.
+            The objects are provided in a grouping so that in addition to
+            the datastore, the data can also be included in notifications
+            as needed.";
+
+        leaf node-id {
+            type node-id;
+            description
+                "The identifier of a node in the topology.
+                A node is specific to a topology to which it belongs.";
+        }
+        list supporting-node {
+            description
+                "This list defines vertical layering information for nodes.
+                It allows to capture for any given node, which node (or nodes)
+                in the corresponding underlay topology it maps onto.
+                A node can map to zero, one, or more nodes below it;
+                accordingly there can be zero, one, or more elements in the list.
+                If there are specific layering requirements, for example
+                specific to a particular type of topology that only allows
+                for certain layering relationships, the choice
+                below can be augmented with additional cases.
+                A list has been chosen rather than a leaf-list in order
+                to provide room for augmentations, e.g. for
+                statistics or priorization information associated with
+                supporting nodes.";
+            // This is not what was published in the initial draft,
+            // added topology-ref leaf and added it to the key
+            key "topology-ref node-ref";
+            leaf topology-ref {
+                type topology-ref;
+            }
+            leaf node-ref {
+                type node-ref;
+            }
+        }
+    }
+
+    grouping link-attributes {
+        // This is a grouping, not defined inline with the link definition itself,
+        // so it can be included in a notification, if needed
+        leaf link-id {
+            type link-id;
+            description
+                "The identifier of a link in the topology.
+                A link is specific to a topology to which it belongs.";
+        }
+        container source {
+            leaf source-node {
+                mandatory true;
+                type node-ref;
+                description
+                    "Source node identifier, must be in same topology.";
+            }
+            leaf source-tp {
+                type tp-ref;
+                description
+                    "Termination point within source node that terminates the link.";
+
+            }
+        }
+        container destination {
+            leaf dest-node {
+                mandatory true;
+                type node-ref;
+                description
+                    "Destination node identifier, must be in same topology.";
+            }
+            leaf dest-tp {
+                type tp-ref;
+                description
+                    "Termination point within destination node that terminates the link.";
+            }
+        }
+        list supporting-link {
+            key "link-ref";
+            leaf link-ref {
+                type link-ref;
+            }
+        }
+    }
+
+
+    container network-topology {
+        list topology {
+            description "
+                This is the model of an abstract topology.
+                A topology contains nodes and links.
+                Each topology MUST be identified by
+                unique topology-id for reason that a network could contain many
+                topologies.
+            ";
+            key "topology-id";
+            leaf topology-id {
+                type topology-id;
+                description "
+                    It is presumed that a datastore will contain many topologies. To
+                    distinguish between topologies it is vital to have UNIQUE
+                    topology identifiers.
+                ";
+            }
+            leaf server-provided {
+                type boolean;
+                config false;
+                description "
+                    Indicates whether the topology is configurable by clients,
+                    or whether it is provided by the server.  This leaf is
+
+                    populated by the server implementing the model.
+                    It is set to false for topologies that are created by a client;
+                    it is set to true otherwise.  If it is set to true, any
+                    attempt to edit the topology MUST be rejected.
+                ";
+            }
+            container topology-types {
+                description
+                    "This container is used to identify the type, or types
+                    (as a topology can support several types simultaneously),
+                    of the topology.
+                    Topology types are the subject of several integrity constraints
+                    that an implementing server can validate in order to
+                    maintain integrity of the datastore.
+                    Topology types are indicated through separate data nodes;
+                    the set of topology types is expected to increase over time.
+                    To add support for a new topology, an augmenting module
+                    needs to augment this container with a new empty optional
+                    container to indicate the new topology type.
+                    The use of a container allows to indicate a subcategorization
+                    of topology types.
+                    The container SHALL NOT be augmented with any data nodes
+                    that serve a purpose other than identifying a particular
+                    topology type.
+                ";
+            }
+            list underlay-topology {
+                key "topology-ref";
+                leaf topology-ref {
+                    type topology-ref;
+                }
+                // a list, not a leaf-list, to allow for potential augmentation
+                // with properties specific to the underlay topology,
+                // such as statistics, preferences, or cost.
+                description
+                    "Identifies the topology, or topologies, that this topology
+                    is dependent on.";
+            }
+
+            list node {
+                description "The list of network nodes defined for the topology.";
+                key "node-id";
+                uses node-attributes;
+                must "boolean(../underlay-topology[*]/node[./supporting-nodes/node-ref])";
+                    // This constraint is meant to ensure that a referenced node is in fact
+                    // a node in an underlay topology.
+                list termination-point {
+                    description
+
+                        "A termination point can terminate a link.
+                        Depending on the type of topology, a termination point could,
+                        for example, refer to a port or an interface.";
+                    key "tp-id";
+                    uses tp-attributes;
+                }
+            }
+
+            list link {
+                description "
+                    A Network Link connects a by Local (Source) node and
+                    a Remote (Destination) Network Nodes via a set of the
+                    nodes' termination points.
+                    As it is possible to have several links between the same
+                    source and destination nodes, and as a link could potentially
+                    be re-homed between termination points, to ensure that we
+                    would always know to distinguish between links, every link
+                    is identified by a dedicated link identifier.
+                    Note that a link models a point-to-point link, not a multipoint
+                    link.
+                    Layering dependencies on links in underlay topologies are
+                    not represented as the layering information of nodes and of
+                    termination points is sufficient.
+                ";
+                key "link-id";
+                uses link-attributes;
+                must "boolean(../underlay-topology/link[./supporting-link])";
+                    // Constraint: any supporting link must be part of an underlay topology
+                must "boolean(../node[./source/source-node])";
+                    // Constraint: A link must have as source a node of the same topology
+                must "boolean(../node[./destination/dest-node])";
+                    // Constraint: A link must have as source a destination of the same topology
+                must "boolean(../node/termination-point[./source/source-tp])";
+                    // Constraint: The source termination point must be contained in the source node
+                must "boolean(../node/termination-point[./destination/dest-tp])";
+                    // Constraint: The destination termination point must be contained
+                    // in the destination node
+            }
+        }
+    }
+}
diff --git a/netconf/netconf-console/src/test/resources/schemas/yang-ext.yang b/netconf/netconf-console/src/test/resources/schemas/yang-ext.yang
new file mode 100644 (file)
index 0000000..0fbe94d
--- /dev/null
@@ -0,0 +1,79 @@
+module yang-ext {
+    yang-version 1;
+    namespace "urn:opendaylight:yang:extension:yang-ext";
+    prefix "ext";
+    
+    contact "Anton Tkacik <ttkacik@cisco.com>";
+
+    description 
+            "Copyright (c) 2013 Cisco Systems, Inc. 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";
+
+    revision "2013-07-09" {
+        description "";
+    }
+
+    // Augmentation name
+
+    extension "augment-identifier" {
+        description 
+           "YANG language extension which assigns an identifier to 
+            augmentation. Augment identifier is used to identify
+            specific augment statement by name. 
+
+            The identifier syntax is defined formally defined by the rule
+            'identifier' in Section 12 of RFC 6020.
+
+            All augment identifiers defined in a namespace MUST be unique.
+            The namespace of augment identifiers is shared by module and
+            its submodules.";
+
+            /*
+                Discussion:
+                This extension allows for ease of development / debug
+                of YANG modules and it is suitable for code generation,
+                where each augment statement is nicely identified by
+                unique name instead of combination of augment target
+                and when condition. 
+            */
+        argument "identifier";
+    }
+
+
+    // Context-aware RPCs
+
+    grouping rpc-context-ref {
+        description 
+           "A reference to RPC context.";
+        leaf context-instance {
+            type instance-identifier;
+            description "Pointer to the context. ";
+        }
+    }
+
+    extension "rpc-context-instance" {
+        description
+           "YANG language extension which defines enclosing (parent) 
+            schema node as referencable context for RPCs.
+
+            The argument is identity which is used to identify RPC context
+            type.";
+
+        argument "context-type";
+    }
+
+    extension "context-reference" {
+        argument "context-type";
+    }
+
+    extension "context-instance" {
+        argument "context-type";
+    }
+    
+    extension "instance-target" {
+       argument "path";
+    }
+}
diff --git a/netconf/netconf-notifications-api/src/test/java/org/opendaylight/netconf/notifications/NetconfNotificationTest.java b/netconf/netconf-notifications-api/src/test/java/org/opendaylight/netconf/notifications/NetconfNotificationTest.java
new file mode 100644 (file)
index 0000000..345b37a
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.notifications;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class NetconfNotificationTest {
+
+    @Test
+    public void testWrapNotification() throws Exception {
+        final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+        final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+        final Document document = docBuilder.newDocument();
+
+        final Element rootElement = document.createElement("test-root");
+        document.appendChild(rootElement);
+
+        final Date eventTime = new Date();
+        eventTime.setTime(10000000);
+
+        final NetconfNotification netconfNotification = new NetconfNotification(document, eventTime);
+        final Document resultDoc = netconfNotification.getDocument();
+        final NodeList nodeList = resultDoc.getElementsByTagNameNS(NetconfNotification.NOTIFICATION_NAMESPACE,
+                NetconfNotification.NOTIFICATION);
+
+        assertNotNull(nodeList);
+        // expected only the one NOTIFICATION tag
+        assertEquals(1, nodeList.getLength());
+
+        final Element entireNotification = (Element) nodeList.item(0);
+        final NodeList childNodes = entireNotification.getElementsByTagNameNS(
+                NetconfNotification.NOTIFICATION_NAMESPACE, NetconfNotification.EVENT_TIME);
+
+        assertNotNull(childNodes);
+        // expected only the one EVENT_TIME tag
+        assertEquals(1, childNodes.getLength());
+
+        final Element eventTimeElement = (Element) childNodes.item(0);
+
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+        assertEquals(eventTime.getTime(), sdf.parse(eventTimeElement.getTextContent()).getTime());
+
+        assertEquals(eventTime, netconfNotification.getEventTime());
+
+    }
+}
index fe563f4883f8b96ab078415ed4c99c2f12f5b5f5..0225bdbf6f9f075ac302e473f994f2a380aade71 100644 (file)
       <artifactId>netconf-client</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+        <groupId>org.osgi</groupId>
+        <artifactId>org.osgi.compendium</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
           </execution>
         </executions>
       </plugin>
-        <plugin>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-maven-plugin</artifactId>
-        </plugin>
+      <plugin>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>yang-maven-plugin</artifactId>
+      </plugin>
     </plugins>
   </build>
 
index 9cbfac1580a3a22a0c3285129f6cee526f300e8b..14cbae81e1891edb357717c5f0dfc88e88dcd545 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.netconf.ssh.osgi;
 
-import com.google.common.base.Optional;
 import io.netty.channel.local.LocalAddress;
 import io.netty.channel.nio.NioEventLoopGroup;
 import java.io.IOException;
@@ -21,7 +20,7 @@ import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
 import org.opendaylight.netconf.ssh.SshProxyServer;
 import org.opendaylight.netconf.ssh.SshProxyServerConfigurationBuilder;
 import org.opendaylight.netconf.util.osgi.NetconfConfigUtil;
-import org.opendaylight.netconf.util.osgi.NetconfConfigUtil.InfixProp;
+import org.opendaylight.netconf.util.osgi.NetconfConfiguration;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
@@ -79,25 +78,17 @@ public class NetconfSSHActivator implements BundleActivator {
     }
 
     private SshProxyServer startSSHServer(final BundleContext bundleContext) throws IOException {
-        final Optional<InetSocketAddress> maybeSshSocketAddress = NetconfConfigUtil.extractNetconfServerAddress(bundleContext, InfixProp.ssh);
-        if (!maybeSshSocketAddress.isPresent()) {
-            LOG.warn("SSH bridge not configured. Using default value {}", NetconfConfigUtil.DEFAULT_SSH_SERVER_ADRESS);
-        }
-        final InetSocketAddress sshSocketAddress = maybeSshSocketAddress
-                .or(NetconfConfigUtil.DEFAULT_SSH_SERVER_ADRESS);
-        LOG.info("Starting netconf SSH bridge at {}", sshSocketAddress);
+        final NetconfConfiguration netconfConfiguration = NetconfConfigUtil.getNetconfConfigurationService(bundleContext).
+                        orElseThrow(() -> new IllegalStateException("Configuration for SSH not found."));
 
-        final LocalAddress localAddress = NetconfConfigUtil.getNetconfLocalAddress();
+        final InetSocketAddress sshSocketAddress = netconfConfiguration.getSshServerAddress();
+        LOG.info("Starting netconf SSH server at {}", sshSocketAddress);
 
+        final LocalAddress localAddress = NetconfConfigUtil.getNetconfLocalAddress();
         authProviderTracker = new AuthProviderTracker(bundleContext);
 
-        final Optional<String> maybePath = NetconfConfigUtil.getPrivateKeyPath(bundleContext);
-        if(!maybePath.isPresent()) {
-            LOG.warn("Private key path not configured. Using default value {}",
-                    NetconfConfigUtil.DEFAULT_PRIVATE_KEY_PATH);
-        }
-        final String path = maybePath.or(NetconfConfigUtil.DEFAULT_PRIVATE_KEY_PATH);
-        LOG.trace("Starting netconf SSH bridge with path to ssh private key {}", path);
+        final String path = netconfConfiguration.getPrivateKeyPath();
+        LOG.trace("Starting netconf SSH server with path to ssh private key {}", path);
 
         final SshProxyServer sshProxyServer = new SshProxyServer(minaTimerExecutor, clientGroup, nioExecutor);
         sshProxyServer.bind(
@@ -110,5 +101,4 @@ public class NetconfSSHActivator implements BundleActivator {
                         .createSshProxyServerConfiguration());
         return sshProxyServer;
     }
-
 }
index f6c8c05f0539260883847f988c463b6b87b301ed..0e45504a588c639ff716e6810064cd9eb74d736e 100644 (file)
       <artifactId>mockito-configuration</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
index 1f4188d827103fbbd5a2562d615ace2536de7e38..d972a32ba70c9ede29a146cdc572bd610f979862 100644 (file)
@@ -8,11 +8,11 @@
 
 package org.opendaylight.netconf.tcp.osgi;
 
-import com.google.common.base.Optional;
 import java.net.InetSocketAddress;
 import org.opendaylight.netconf.tcp.netty.ProxyServer;
 import org.opendaylight.netconf.util.osgi.NetconfConfigUtil;
 import org.opendaylight.netconf.util.osgi.NetconfConfigUtil.InfixProp;
+import org.opendaylight.netconf.util.osgi.NetconfConfiguration;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
@@ -27,13 +27,10 @@ public class NetconfTCPActivator implements BundleActivator {
 
     @Override
     public void start(BundleContext context) {
-        final Optional<InetSocketAddress> maybeAddress = NetconfConfigUtil.extractNetconfServerAddress(context, InfixProp.tcp);
-        if (maybeAddress.isPresent() == false) {
-            LOG.warn("Netconf tcp server is not configured. Using default value {}",
-                    NetconfConfigUtil.DEFAULT_TCP_SERVER_ADRESS);
-        }
+        final NetconfConfiguration netconfConfiguration = NetconfConfigUtil.getNetconfConfigurationService(context).
+                        orElseThrow(() -> new IllegalStateException("Configuration for TCP not found."));
 
-        InetSocketAddress address = maybeAddress.or(NetconfConfigUtil.DEFAULT_TCP_SERVER_ADRESS);
+        final InetSocketAddress address = netconfConfiguration.getTcpServerAddress();
 
         if (address.getAddress().isAnyLocalAddress()) {
             LOG.warn("Unprotected netconf TCP address is configured to ANY local address. This is a security risk. Consider changing {} to 127.0.0.1",
index 65135c0f81e0a95669a7129ab1a097237489040e..75113816f39a41908befb264f29907ade9f2b074 100644 (file)
                                     <type>xml</type>
                                     <classifier>config</classifier>
                                 </artifact>
-                                <artifact>
-                                    <file>${project.build.directory}/classes/initial/02-clustered-netconf-topology.xml</file>
-                                    <type>xml</type>
-                                    <classifier>clustered-config</classifier>
-                                </artifact>
                             </artifacts>
                         </configuration>
                     </execution>
diff --git a/netconf/netconf-topology-config/src/main/resources/initial/02-clustered-netconf-topology.xml b/netconf/netconf-topology-config/src/main/resources/initial/02-clustered-netconf-topology.xml
deleted file mode 100644 (file)
index ded67f5..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- Copyright (c) 2015 Cisco Systems, Inc. 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
--->
-<snapshot>
-    <configuration>
-        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                <module>
-                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">prefix:clustered-netconf-topology-impl</type>
-                    <name>clustered-netconf-topology</name>
-                    <topology-id xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">topology-netconf</topology-id>
-                    <event-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>
-                        <name>global-event-executor</name>
-                    </event-executor>
-                    <binding-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>
-                        <name>binding-osgi-broker</name>
-                    </binding-registry>
-                    <dom-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
-                        <name>dom-broker</name>
-                    </dom-registry>
-                    <client-dispatcher xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">prefix:netconf-client-dispatcher</type>
-                        <name>global-netconf-dispatcher</name>
-                    </client-dispatcher>
-                    <processing-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>
-                        <name>global-netconf-processing-executor</name>
-                    </processing-executor>
-                    <keepalive-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:scheduled-threadpool</type>
-                        <name>global-netconf-ssh-scheduled-executor</name>
-                    </keepalive-executor>
-                    <shared-schema-repository xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:topology:shared:schema:repository">prefix:shared-schema-repository</type>
-                        <name>default-shared-schema-repository</name>
-                    </shared-schema-repository>
-                    <entity-ownership-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">prefix:entity-ownership-service</type>
-                        <name>entity-ownership-service</name>
-                    </entity-ownership-service>
-                    <actor-system-provider-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology">
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:actor-system-provider:service">prefix:actor-system-provider-service</type>
-                        <name>actor-system-provider</name>
-                    </actor-system-provider-service>
-                </module>
-            </modules>
-
-            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                <service>
-                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:topology">prefix:netconf-topology</type>
-                    <instance>
-                        <name>clustered-netconf-topology</name>
-                        <provider>/modules/module[type='clustered-netconf-topology-impl'][name='clustered-netconf-topology']</provider>
-                    </instance>
-                </service>
-            </services>
-        </data>
-    </configuration>
-    <required-capabilities>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:netconf:topology?module=netconf-topology&amp;revision=2015-07-27</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology?module=clustered-netconf-topology&amp;revision=2015-11-04</capability>
-        <capability>
-            urn:opendaylight:params:xml:ns:yang:controller:config:legacy-entity-ownership-service-provider?module=opendaylight-legacy-entity-ownership-service-provider&amp;revision=2016-02-26
-        </capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:actor-system-provider:service?module=actor-system-provider-service&amp;revision=2015-10-05</capability>
-    </required-capabilities>
-</snapshot>
\ No newline at end of file
similarity index 64%
rename from netconf/abstract-topology/pom.xml
rename to netconf/netconf-topology-singleton/pom.xml
index bf17207321dfecd69e25b887cf77c4a4e4750e68..e247fb5071c1a62541c62a932c60493b8990919c 100644 (file)
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <groupId>org.opendaylight.odlparent</groupId>
-        <artifactId>bundle-parent</artifactId>
-        <version>1.8.0-SNAPSHOT</version>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-parent</artifactId>
+        <version>0.6.0-SNAPSHOT</version>
         <relativePath/>
     </parent>
 
     <groupId>org.opendaylight.netconf</groupId>
-    <artifactId>abstract-topology</artifactId>
+    <artifactId>netconf-topology-singleton</artifactId>
     <version>1.2.0-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
     <packaging>bundle</packaging>
 
     <dependencyManagement>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.controller</groupId>
+                <artifactId>mdsal-artifacts</artifactId>
+                <version>1.5.0-SNAPSHOT</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
-    <properties>
-    </properties>
-
     <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>mdsal-netconf-notification</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.mdsal.model</groupId>
             <artifactId>ietf-topology</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-api</artifactId>
+            <groupId>com.typesafe.akka</groupId>
+            <artifactId>akka-actor_2.11</artifactId>
         </dependency>
         <dependency>
-            <groupId>${project.groupId}</groupId>
+            <groupId>org.opendaylight.netconf</groupId>
             <artifactId>sal-netconf-connector</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-api</artifactId>
+            <groupId>com.typesafe.akka</groupId>
+            <artifactId>akka-cluster_2.11</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-clustering-commons</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.scala-lang</groupId>
-            <artifactId>scala-library</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.typesafe.akka</groupId>
-            <artifactId>akka-actor_${scala.version}</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.typesafe.akka</groupId>
-            <artifactId>akka-remote_${scala.version}</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.typesafe.akka</groupId>
-            <artifactId>akka-cluster_${scala.version}</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.typesafe.akka</groupId>
-            <artifactId>akka-osgi_${scala.version}</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.typesafe</groupId>
-            <artifactId>config</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-all</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>com.jayway.awaitility</groupId>
-            <artifactId>awaitility</artifactId>
-            <version>1.6.5</version>
+            <groupId>com.typesafe.akka</groupId>
+            <artifactId>akka-testkit_2.11</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-distributed-datastore</artifactId>
+        </dependency>
     </dependencies>
-</project>
+
+</project>
\ No newline at end of file
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/NetconfDOMTransaction.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/NetconfDOMTransaction.java
new file mode 100644 (file)
index 0000000..ec9c717
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.api;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import scala.concurrent.Future;
+
+/**
+ * Provides API for all operations of read and write transactions
+ */
+public interface NetconfDOMTransaction {
+
+    /**
+     * Read data from particular data-store
+     * @param store data-store type
+     * @param path unique identifier of a particular node instance in the data tree
+     * @return result as future
+     */
+    Future<Optional<NormalizedNodeMessage>> read(LogicalDatastoreType store, YangInstanceIdentifier path);
+
+    /**
+     * Test existence of node in certain data-store
+     * @param store data-store type
+     * @param path unique identifier of a particular node instance in the data tree
+     * @return result as future
+     */
+    Future<Boolean> exists(LogicalDatastoreType store, YangInstanceIdentifier path);
+
+    /**
+     * Put data to particular data-store
+     * @param store data-store type
+     * @param data data for inserting included in NormalizedNodeMessage object
+     */
+    void put(LogicalDatastoreType store, NormalizedNodeMessage data);
+
+    /**
+     * Merge data with existing node in particular data-store
+     * @param store data-store type
+     * @param data data for merging included in NormalizedNodeMessage object
+     */
+    void merge(LogicalDatastoreType store, NormalizedNodeMessage data);
+
+    /**
+     * Delete node in particular data-store in path
+     * @param store data-store type
+     * @param path unique identifier of a particular node instance in the data tree
+     */
+    void delete(LogicalDatastoreType store, YangInstanceIdentifier path);
+
+    /**
+     * Cancel operation
+     * @return success or not
+     */
+    boolean cancel();
+
+    /**
+     * Commit opened transaction.
+     * @return void or raised exception
+     */
+    Future<Void> submit();
+}
@@ -1,12 +1,15 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline.tx;
+package org.opendaylight.netconf.topology.singleton.api;
 
-public interface NetconfDeviceDataBrokerProxy {
+/**
+ * Provides API for advertising services for blue print service
+ */
+public interface NetconfTopologySingletonService {
 }
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/RemoteDeviceConnector.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/RemoteDeviceConnector.java
new file mode 100644 (file)
index 0000000..bb74b75
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.api;
+
+import akka.actor.ActorRef;
+
+/**
+ * Provides API for connection odl (master) with device
+ */
+public interface RemoteDeviceConnector {
+
+    /**
+     * Create device communicator and open device connection
+     * @param masterActorRef master actor reference
+     */
+    void startRemoteDeviceConnection(ActorRef masterActorRef);
+
+    /**
+     * Stop device communicator
+     */
+    void stopRemoteDeviceConnection();
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/RemoteOperationTxProcessor.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/api/RemoteOperationTxProcessor.java
new file mode 100644 (file)
index 0000000..9023847
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.api;
+
+import akka.actor.ActorRef;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * Provides API for remote calling operations of transactions. Slave sends message of particular
+ * operation to master and master performs it.
+ */
+public interface RemoteOperationTxProcessor {
+
+    /**
+     * Delete node in particular data-store in path
+     * @param store data-store type
+     * @param path unique identifier of a particular node instance in the data tree
+     */
+    void doDelete(LogicalDatastoreType store, YangInstanceIdentifier path);
+
+    /**
+     * Commit opened transaction.
+     * @param recipient recipient of submit result
+     * @param sender sender of submit result
+     */
+    void doSubmit(ActorRef recipient, ActorRef sender);
+
+    /**
+     * Cancel operation
+     * @param recipient recipient of cancel result
+     * @param sender sender of cancel result
+     */
+    void doCancel(ActorRef recipient, ActorRef sender);
+
+    /**
+     * Put data to particular data-store
+     * @param store data-store type
+     * @param data data for inserting included in NormalizedNodeMessage object
+     */
+    void doPut(LogicalDatastoreType store, NormalizedNodeMessage data);
+
+    /**
+     * Merge data with existing node in particular data-store
+     * @param store data-store type
+     * @param data data for merging included in NormalizedNodeMessage object
+     */
+    void doMerge(LogicalDatastoreType store, NormalizedNodeMessage data);
+
+    /**
+     * Read data from particular data-store
+     * @param store data-store type
+     * @param path unique identifier of a particular node instance in the data tree
+     * @param recipient recipient of read result
+     * @param sender sender of read result
+     */
+    void doRead(LogicalDatastoreType store, YangInstanceIdentifier path, ActorRef recipient, ActorRef sender);
+
+    /**
+     * Test existence of node in certain data-store
+     * @param store data-store type
+     * @param path unique identifier of a particular node instance in the data tree
+     * @param recipient recipient of exists result
+     * @param sender sender of exists result
+     */
+    void doExists(LogicalDatastoreType store, YangInstanceIdentifier path, ActorRef recipient, ActorRef sender);
+
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java
new file mode 100644 (file)
index 0000000..8e45cbc
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.cluster.Cluster;
+import akka.dispatch.OnComplete;
+import akka.pattern.Patterns;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceNotificationService;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalProvider;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.impl.tx.NetconfMasterDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.netconf.topology.singleton.messages.CreateInitialMasterActorData;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.Future;
+
+class MasterSalFacade implements AutoCloseable, RemoteDeviceHandler<NetconfSessionPreferences> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MasterSalFacade.class);
+
+    private final RemoteDeviceId id;
+
+    private SchemaContext remoteSchemaContext = null;
+    private NetconfSessionPreferences netconfSessionPreferences = null;
+    private DOMRpcService deviceRpc = null;
+    private final NetconfDeviceSalProvider salProvider;
+
+    private final ActorRef masterActorRef;
+    private final ActorSystem actorSystem;
+    private DOMDataBroker deviceDataBroker = null;
+
+    MasterSalFacade(final RemoteDeviceId id,
+                           final Broker domBroker,
+                           final BindingAwareBroker bindingBroker,
+                           final ActorSystem actorSystem,
+                           final ActorRef masterActorRef) {
+        this.id = id;
+        this.salProvider = new NetconfDeviceSalProvider(id);
+        this.actorSystem = actorSystem;
+        this.masterActorRef = masterActorRef;
+
+        registerToSal(domBroker, bindingBroker);
+    }
+
+    private void registerToSal(final Broker domRegistryDependency, final BindingAwareBroker bindingBroker) {
+        // TODO: remove use of provider, there is possible directly create mount instance and
+        // TODO: NetconfDeviceTopologyAdapter in constructor = less complexity
+
+        domRegistryDependency.registerProvider(salProvider);
+        bindingBroker.registerProvider(salProvider);
+    }
+
+    @Override
+    public void onDeviceConnected(final SchemaContext remoteSchemaContext,
+                                  final NetconfSessionPreferences netconfSessionPreferences,
+                                  final DOMRpcService deviceRpc) {
+        this.remoteSchemaContext = remoteSchemaContext;
+        this.netconfSessionPreferences = netconfSessionPreferences;
+        this.deviceRpc = deviceRpc;
+
+        registerMasterMountPoint();
+
+        sendInitialDataToActor().onComplete(new OnComplete<Object>() {
+            @Override
+            public void onComplete(final Throwable failure, final Object success) throws Throwable {
+                if (failure == null) {
+                    updateDeviceData();
+                    return;
+                }
+                throw failure;
+            }
+        }, actorSystem.dispatcher());
+
+    }
+
+    @Override
+    public void onDeviceDisconnected() {
+        salProvider.getTopologyDatastoreAdapter().updateDeviceData(false, new NetconfDeviceCapabilities());
+        unregisterMasterMountPoint();
+    }
+
+    @Override
+    public void onDeviceFailed(final Throwable throwable) {
+        salProvider.getTopologyDatastoreAdapter().setDeviceAsFailed(throwable);
+        unregisterMasterMountPoint();
+    }
+
+    @Override
+    public void onNotification(final DOMNotification domNotification) {
+        salProvider.getMountInstance().publish(domNotification);
+    }
+
+    @Override
+    public void close() {
+        unregisterMasterMountPoint();
+        closeGracefully(salProvider);
+    }
+
+    private void registerMasterMountPoint() {
+        Preconditions.checkNotNull(id);
+        Preconditions.checkNotNull(remoteSchemaContext,
+                "Device has no remote schema context yet. Probably not fully connected.");
+        Preconditions.checkNotNull(netconfSessionPreferences,
+                "Device has no capabilities yet. Probably not fully connected.");
+
+        final NetconfDeviceNotificationService notificationService = new NetconfDeviceNotificationService();
+
+        LOG.info("{}: Creating master data broker for device", id);
+
+        final NetconfDOMTransaction masterDOMTransactions =
+                new NetconfMasterDOMTransaction(id, remoteSchemaContext, deviceRpc, netconfSessionPreferences);
+        deviceDataBroker =
+                new NetconfDOMDataBroker(actorSystem, id, masterDOMTransactions);
+        salProvider.getMountInstance()
+                .onTopologyDeviceConnected(remoteSchemaContext, deviceDataBroker, deviceRpc, notificationService);
+    }
+
+    private Future<Object> sendInitialDataToActor() {
+        final List<SourceIdentifier> sourceIdentifiers =
+                remoteSchemaContext.getAllModuleIdentifiers().stream().map(mi ->
+                        RevisionSourceIdentifier.create(mi.getName(),
+                            (SimpleDateFormatUtil.DEFAULT_DATE_REV == mi.getRevision() ? Optional.<String>absent() :
+                                    Optional.of(SimpleDateFormatUtil.getRevisionFormat().format(mi.getRevision())))))
+                        .collect(Collectors.toList());
+
+        // send initial data to master actor and create actor for providing it
+        return Patterns.ask(masterActorRef, new CreateInitialMasterActorData(deviceDataBroker, sourceIdentifiers),
+                NetconfTopologyUtils.TIMEOUT);
+    }
+
+    private void updateDeviceData() {
+        Cluster cluster = Cluster.get(actorSystem);
+        salProvider.getTopologyDatastoreAdapter().updateClusteredDeviceData(true, cluster.selfAddress().toString(),
+                netconfSessionPreferences.getNetconfDeviceCapabilities());
+    }
+
+    private void unregisterMasterMountPoint() {
+        salProvider.getMountInstance().onTopologyDeviceDisconnected();
+    }
+
+    private void closeGracefully(final AutoCloseable resource) {
+        if (resource != null) {
+            try {
+                resource.close();
+            } catch (final Exception e) {
+                LOG.error("{}: Ignoring exception while closing {}", id, resource, e);
+            }
+        }
+    }
+
+}
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.netconf.topology.pipeline;
+package org.opendaylight.netconf.topology.singleton.impl;
 
 import akka.actor.ActorSystem;
 import java.util.Collections;
@@ -23,18 +23,20 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.netconf.sal.connect.netconf.sal.tx.ReadWriteTx;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.pipeline.tx.ProxyReadOnlyTransaction;
-import org.opendaylight.netconf.topology.pipeline.tx.ProxyWriteOnlyTransaction;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.impl.tx.NetconfReadOnlyTransaction;
+import org.opendaylight.netconf.topology.singleton.impl.tx.NetconfWriteOnlyTransaction;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
-public class NetconfDeviceSlaveDataBroker implements DOMDataBroker{
+public class NetconfDOMDataBroker implements DOMDataBroker {
 
     private final RemoteDeviceId id;
-    private final ProxyNetconfDeviceDataBroker masterDataBroker;
+    private final NetconfDOMTransaction masterDataBroker;
     private final ActorSystem actorSystem;
 
-    public NetconfDeviceSlaveDataBroker(final ActorSystem actorSystem, final RemoteDeviceId id, final ProxyNetconfDeviceDataBroker masterDataBroker) {
+    public NetconfDOMDataBroker(final ActorSystem actorSystem, final RemoteDeviceId id,
+                         final NetconfDOMTransaction masterDataBroker) {
         this.id = id;
         this.masterDataBroker = masterDataBroker;
         this.actorSystem = actorSystem;
@@ -42,21 +44,24 @@ public class NetconfDeviceSlaveDataBroker implements DOMDataBroker{
 
     @Override
     public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
-        return new ProxyReadOnlyTransaction(actorSystem, id, masterDataBroker);
+        return new NetconfReadOnlyTransaction(id, actorSystem, masterDataBroker);
     }
 
     @Override
     public DOMDataReadWriteTransaction newReadWriteTransaction() {
-        return new ReadWriteTx(new ProxyReadOnlyTransaction(actorSystem, id, masterDataBroker), new ProxyWriteOnlyTransaction(actorSystem, masterDataBroker));
+        return new ReadWriteTx(new NetconfReadOnlyTransaction(id, actorSystem, masterDataBroker),
+                new NetconfWriteOnlyTransaction(id, actorSystem, masterDataBroker));
     }
 
     @Override
     public DOMDataWriteTransaction newWriteOnlyTransaction() {
-        return new ProxyWriteOnlyTransaction(actorSystem, masterDataBroker);
+        return new NetconfWriteOnlyTransaction(id, actorSystem, masterDataBroker);
     }
 
     @Override
-    public ListenerRegistration<DOMDataChangeListener> registerDataChangeListener(LogicalDatastoreType store, YangInstanceIdentifier path, DOMDataChangeListener listener, DataChangeScope triggeringScope) {
+    public ListenerRegistration<DOMDataChangeListener> registerDataChangeListener(
+            LogicalDatastoreType store, YangInstanceIdentifier path, DOMDataChangeListener listener,
+            DataChangeScope triggeringScope) {
         throw new UnsupportedOperationException(id + ": Data change listeners not supported for netconf mount point");
     }
 
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfNodeManager.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfNodeManager.java
new file mode 100644 (file)
index 0000000..7cc3d29
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import java.util.Collection;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService;
+import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.netconf.topology.singleton.messages.AskForMasterMountPoint;
+import org.opendaylight.netconf.topology.singleton.messages.UnregisterSlaveMountPoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Managing and reacting on data tree changes in specific netconf node when master writes status to the operational
+ * data store (e.g. handling lifecycle of slave mount point).
+ */
+class NetconfNodeManager
+        implements ClusteredDataTreeChangeListener<Node>, NetconfTopologySingletonService, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfNodeManager.class);
+
+    private NetconfTopologySetup setup;
+    private ListenerRegistration<NetconfNodeManager> dataChangeListenerRegistration;
+    private RemoteDeviceId id;
+    private final SchemaSourceRegistry schemaRegistry;
+    private final SchemaRepository schemaRepository;
+    private ActorRef slaveActorRef;
+
+    NetconfNodeManager(final NetconfTopologySetup setup,
+                       final RemoteDeviceId id, final SchemaSourceRegistry schemaRegistry,
+                       final SchemaRepository schemaRepository) {
+        this.setup = setup;
+        this.id = id;
+        this.schemaRegistry = schemaRegistry;
+        this.schemaRepository = schemaRepository;
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<Node>> changes) {
+        for (final DataTreeModification<Node> change : changes) {
+            final DataObjectModification<Node> rootNode = change.getRootNode();
+            final NodeId nodeId = NetconfTopologyUtils.getNodeId(rootNode.getIdentifier());
+            switch (rootNode.getModificationType()) {
+                case SUBTREE_MODIFIED:
+                    LOG.debug("{}: Operational for node {} updated. Trying to register slave mount point", id, nodeId);
+                    handleSlaveMountPoint(rootNode);
+                    break;
+                case WRITE:
+                    if (rootNode.getDataBefore() != null) {
+                        LOG.debug("{}: Operational for node {} rewrited. Trying to register slave mount point", id, nodeId);
+                    } else {
+                        LOG.debug("{}: Operational for node {} created. Trying to register slave mount point", id, nodeId);
+                    }
+                    handleSlaveMountPoint(rootNode);
+                    break;
+                case DELETE:
+                    LOG.debug("{}: Operational for node {} deleted. Trying to remove slave mount point", id, nodeId);
+                    closeActor();
+                    break;
+                default:
+                    LOG.debug("{}: Uknown operation for node: {}", id, nodeId);
+            }
+        }
+    }
+
+    @Override
+    public void close() {
+        closeActor();
+
+        if (dataChangeListenerRegistration != null) {
+            dataChangeListenerRegistration.close();
+            dataChangeListenerRegistration = null;
+        }
+    }
+
+    private void closeActor() {
+        if (slaveActorRef != null) {
+            slaveActorRef.tell(new UnregisterSlaveMountPoint(), ActorRef.noSender());
+            slaveActorRef.tell(PoisonPill.getInstance(), ActorRef.noSender());
+            slaveActorRef = null;
+        }
+    }
+
+    void registerDataTreeChangeListener(final String topologyId, final NodeKey key) {
+        LOG.debug("{}: Registering data tree change listener on node {}", id, key);
+        dataChangeListenerRegistration = setup.getDataBroker().registerDataTreeChangeListener(
+                new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                        NetconfTopologyUtils.createTopologyNodeListPath(key, topologyId)), this);
+    }
+
+    private void handleSlaveMountPoint(final DataObjectModification<Node> rootNode) {
+        @SuppressWarnings("ConstantConditions")
+        final NetconfNode netconfNodeAfter = rootNode.getDataAfter().getAugmentation(NetconfNode.class);
+
+        if (NetconfNodeConnectionStatus.ConnectionStatus.Connected.equals(netconfNodeAfter.getConnectionStatus())) {
+            createActorRef();
+            final String masterAddress = netconfNodeAfter.getClusteredConnectionStatus().getNetconfMasterNode();
+            final String path = NetconfTopologyUtils.createActorPath(masterAddress,
+                    NetconfTopologyUtils.createMasterActorName(id.getName(),
+                            netconfNodeAfter.getClusteredConnectionStatus().getNetconfMasterNode()));
+            setup.getActorSystem().actorSelection(path).tell(new AskForMasterMountPoint(), slaveActorRef);
+        } else {            ;
+            closeActor();
+        }
+    }
+
+    private void createActorRef() {
+        if (slaveActorRef == null) {
+            slaveActorRef = setup.getActorSystem().actorOf(NetconfNodeActor.props(setup, id, schemaRegistry,
+                    schemaRepository), id.getName());
+        }
+    }
+
+    void refreshDevice(final NetconfTopologySetup netconfTopologyDeviceSetup, final RemoteDeviceId remoteDeviceId) {
+        setup = netconfTopologyDeviceSetup;
+        id = remoteDeviceId;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyContext.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyContext.java
new file mode 100644 (file)
index 0000000..0f8255c
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import static org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY;
+
+import akka.actor.ActorRef;
+import akka.cluster.Cluster;
+import akka.dispatch.OnComplete;
+import akka.pattern.Patterns;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
+import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.RemoteDeviceConnector;
+import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.Future;
+
+class NetconfTopologyContext implements ClusterSingletonService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyContext.class);
+
+    private final ServiceGroupIdentifier serviceGroupIdent;
+    private NetconfTopologySetup netconfTopologyDeviceSetup;
+    private RemoteDeviceId remoteDeviceId;
+    private RemoteDeviceConnector remoteDeviceConnector;
+    private NetconfNodeManager netconfNodeManager;
+    private boolean finalClose = false;
+    private boolean isMaster;
+
+    private ActorRef masterActorRef;
+
+    NetconfTopologyContext(final NetconfTopologySetup netconfTopologyDeviceSetup,
+                           final ServiceGroupIdentifier serviceGroupIdent) {
+        this.netconfTopologyDeviceSetup = Preconditions.checkNotNull(netconfTopologyDeviceSetup);
+        this.serviceGroupIdent = serviceGroupIdent;
+
+        remoteDeviceId = NetconfTopologyUtils.createRemoteDeviceId(netconfTopologyDeviceSetup.getNode().getNodeId(),
+                netconfTopologyDeviceSetup.getNode().getAugmentation(NetconfNode.class));
+
+        remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId);
+
+        netconfNodeManager = createNodeDeviceManager();
+
+    }
+
+    @Override
+    public void instantiateServiceInstance() {
+        LOG.info("Master was selected: {}", remoteDeviceId.getHost().getIpAddress());
+
+        isMaster = true;
+
+        // master should not listen on netconf-node operational datastore
+        if (netconfNodeManager != null) {
+            netconfNodeManager.close();
+            netconfNodeManager = null;
+        }
+
+        if (!finalClose) {
+            final String masterAddress = Cluster.get(netconfTopologyDeviceSetup.getActorSystem()).selfAddress().toString();
+            masterActorRef = netconfTopologyDeviceSetup.getActorSystem().actorOf(NetconfNodeActor.props(
+                    netconfTopologyDeviceSetup, remoteDeviceId, DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY),
+                    NetconfTopologyUtils.createMasterActorName(remoteDeviceId.getName(), masterAddress));
+
+            remoteDeviceConnector.startRemoteDeviceConnection(masterActorRef);
+        }
+
+    }
+
+    // called when master is down/changed to slave
+    @Override
+    public ListenableFuture<Void> closeServiceInstance() {
+
+        if (!finalClose) {
+            // in case that master changes role to slave, new NodeDeviceManager must be created and listener registered
+            netconfNodeManager = createNodeDeviceManager();
+        }
+        if (masterActorRef != null) {
+            netconfTopologyDeviceSetup.getActorSystem().stop(masterActorRef);
+            masterActorRef = null;
+        }
+        if (remoteDeviceConnector != null) {
+            remoteDeviceConnector.stopRemoteDeviceConnection();
+        }
+
+        return Futures.immediateCheckedFuture(null);
+    }
+
+    @Override
+    public ServiceGroupIdentifier getIdentifier() {
+        return serviceGroupIdent;
+    }
+
+    private NetconfNodeManager createNodeDeviceManager() {
+        final NetconfNodeManager ndm =
+                new NetconfNodeManager(netconfTopologyDeviceSetup, remoteDeviceId, DEFAULT_SCHEMA_REPOSITORY,
+                        DEFAULT_SCHEMA_REPOSITORY);
+        ndm.registerDataTreeChangeListener(netconfTopologyDeviceSetup.getTopologyId(),
+                netconfTopologyDeviceSetup.getNode().getKey());
+
+        return ndm;
+    }
+
+    void closeFinal() throws Exception {
+        finalClose = true;
+
+        if (netconfNodeManager != null) {
+            netconfNodeManager.close();
+        }
+
+        if (remoteDeviceConnector != null) {
+            remoteDeviceConnector.stopRemoteDeviceConnection();
+        }
+
+        if (masterActorRef != null) {
+            netconfTopologyDeviceSetup.getActorSystem().stop(masterActorRef);
+            masterActorRef = null;
+        }
+    }
+
+    /**
+     * If configuration data was changed
+     * @param setup new setup
+     */
+    void refresh(@Nonnull final NetconfTopologySetup setup) {
+        netconfTopologyDeviceSetup = Preconditions.checkNotNull(setup);
+        remoteDeviceId = NetconfTopologyUtils.createRemoteDeviceId(netconfTopologyDeviceSetup.getNode().getNodeId(),
+                netconfTopologyDeviceSetup.getNode().getAugmentation(NetconfNode.class));
+
+        if (isMaster) {
+            remoteDeviceConnector.stopRemoteDeviceConnection();
+        }
+        if (!isMaster) {
+            netconfNodeManager.refreshDevice(netconfTopologyDeviceSetup, remoteDeviceId);
+        }
+        remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId);
+
+        if (isMaster) {
+            final Future<Object> future = Patterns.ask(masterActorRef, new RefreshSetupMasterActorData(
+                    netconfTopologyDeviceSetup, remoteDeviceId), NetconfTopologyUtils.TIMEOUT);
+
+            future.onComplete(new OnComplete<Object>() {
+                @Override
+                public void onComplete(final Throwable failure, final Object success) throws Throwable {
+                    if (failure != null) {
+                        LOG.error("Failed to refresh master actor data: {}", failure);
+                        return;
+                    }
+                    remoteDeviceConnector.startRemoteDeviceConnection(masterActorRef);
+                }
+            }, netconfTopologyDeviceSetup.getActorSystem().dispatcher());
+        }
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManager.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManager.java
new file mode 100644 (file)
index 0000000..cfd9dd8
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import akka.actor.ActorSystem;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import io.netty.util.concurrent.EventExecutor;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.cluster.ActorSystemProvider;
+import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
+import org.opendaylight.controller.config.threadpool.ThreadPool;
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+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.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.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
+import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
+import org.opendaylight.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup.NetconfTopologySetupBuilder;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfTopologyManager
+        implements ClusteredDataTreeChangeListener<Node>, NetconfTopologySingletonService, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyManager.class);
+
+    private final Map<InstanceIdentifier<Node>, NetconfTopologyContext> contexts = new HashMap<>();
+    private final Map<InstanceIdentifier<Node>, ClusterSingletonServiceRegistration>
+            clusterRegistrations = new HashMap<>();
+
+    private ListenerRegistration<NetconfTopologyManager> dataChangeListenerRegistration;
+
+    private final DataBroker dataBroker;
+    private final RpcProviderRegistry rpcProviderRegistry;
+    private final ClusterSingletonServiceProvider clusterSingletonServiceProvider;
+    private final BindingAwareBroker bindingAwareBroker;
+    private final ScheduledThreadPool keepaliveExecutor;
+    private final ThreadPool processingExecutor;
+    private final Broker domBroker;
+    private final ActorSystem actorSystem;
+    private final EventExecutor eventExecutor;
+    private final NetconfClientDispatcher clientDispatcher;
+    private final String topologyId;
+
+    public NetconfTopologyManager(final DataBroker dataBroker, final RpcProviderRegistry rpcProviderRegistry,
+                           final ClusterSingletonServiceProvider clusterSingletonServiceProvider,
+                           final BindingAwareBroker bindingAwareBroker,
+                           final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
+                           final Broker domBroker, final ActorSystemProvider actorSystemProvider, final EventExecutor eventExecutor,
+                           final NetconfClientDispatcher clientDispatcher, final String topologyId) {
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
+        this.rpcProviderRegistry = Preconditions.checkNotNull(rpcProviderRegistry);
+        this.clusterSingletonServiceProvider = Preconditions.checkNotNull(clusterSingletonServiceProvider);
+        this.bindingAwareBroker = Preconditions.checkNotNull(bindingAwareBroker);
+        this.keepaliveExecutor = Preconditions.checkNotNull(keepaliveExecutor);
+        this.processingExecutor = Preconditions.checkNotNull(processingExecutor);
+        this.domBroker = Preconditions.checkNotNull(domBroker);
+        this.actorSystem = Preconditions.checkNotNull(actorSystemProvider).getActorSystem();
+        this.eventExecutor = Preconditions.checkNotNull(eventExecutor);
+        this.clientDispatcher = Preconditions.checkNotNull(clientDispatcher);
+        this.topologyId = Preconditions.checkNotNull(topologyId);
+    }
+
+    // Blueprint init method
+    public void init() {
+        dataChangeListenerRegistration = registerDataTreeChangeListener(topologyId);
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<Node>> changes) {
+        for (DataTreeModification<Node> change : changes) {
+            final DataObjectModification<Node> rootNode = change.getRootNode();
+            final InstanceIdentifier<Node> dataModifIdent = change.getRootPath().getRootIdentifier();
+            final NodeId nodeId = NetconfTopologyUtils.getNodeId(rootNode.getIdentifier());
+            switch (rootNode.getModificationType()) {
+                case SUBTREE_MODIFIED:
+                    LOG.debug("Config for node {} updated", nodeId);
+                    refreshNetconfDeviceContext(dataModifIdent, rootNode.getDataAfter());
+                    break;
+                case WRITE:
+                    if (contexts.containsKey(dataModifIdent)) {
+                        LOG.debug("RemoteDevice{{}} was already configured, reconfiguring node...", nodeId);
+                        refreshNetconfDeviceContext(dataModifIdent, rootNode.getDataAfter());
+                    } else {
+                        LOG.debug("Config for node {} created", nodeId);
+                        startNetconfDeviceContext(dataModifIdent, rootNode.getDataAfter());
+                    }
+                    break;
+                case DELETE:
+                    LOG.debug("Config for node {} deleted", nodeId);
+                    stopNetconfDeviceContext(dataModifIdent);
+                    break;
+                default:
+                    LOG.warn("Unknown operation for {}.", nodeId);
+            }
+        }
+    }
+
+    private void refreshNetconfDeviceContext(InstanceIdentifier<Node> instanceIdentifier, Node node) {
+        final NetconfTopologyContext context = contexts.get(instanceIdentifier);
+        context.refresh(createSetup(instanceIdentifier, node));
+    }
+
+    private void startNetconfDeviceContext(final InstanceIdentifier<Node> instanceIdentifier, final Node node) {
+        final NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
+        Preconditions.checkNotNull(netconfNode);
+        Preconditions.checkNotNull(netconfNode.getHost());
+        Preconditions.checkNotNull(netconfNode.getHost().getIpAddress());
+
+        final ServiceGroupIdentifier serviceGroupIdent =
+                ServiceGroupIdentifier.create(instanceIdentifier.toString());
+
+        final NetconfTopologyContext newNetconfTopologyContext =
+                new NetconfTopologyContext(createSetup(instanceIdentifier, node), serviceGroupIdent);
+
+        final ClusterSingletonServiceRegistration clusterSingletonServiceRegistration  =
+                clusterSingletonServiceProvider.registerClusterSingletonService(newNetconfTopologyContext);
+
+        clusterRegistrations.put(instanceIdentifier, clusterSingletonServiceRegistration);
+        contexts.put(instanceIdentifier, newNetconfTopologyContext);
+    }
+
+    private void stopNetconfDeviceContext(final InstanceIdentifier<Node> instanceIdentifier) {
+        if (contexts.containsKey(instanceIdentifier)) {
+            try {
+                clusterRegistrations.get(instanceIdentifier).close();
+                contexts.get(instanceIdentifier).closeFinal();
+            } catch (Exception e) {
+                LOG.warn("Error at closing topology context. InstanceIdentifier: " + instanceIdentifier);
+            }
+            contexts.remove(instanceIdentifier);
+            clusterRegistrations.remove(instanceIdentifier);
+        }
+    }
+
+    @Override
+    public void close() {
+        if (dataChangeListenerRegistration != null) {
+            dataChangeListenerRegistration.close();
+            dataChangeListenerRegistration = null;
+        }
+        contexts.forEach((instanceIdentifier, netconfTopologyContext) -> {
+            try {
+                netconfTopologyContext.closeFinal();
+            } catch (Exception e) {
+                LOG.error("Error at closing topology context. InstanceIdentifier: " + instanceIdentifier, e);
+            }
+        });
+        clusterRegistrations.forEach((instanceIdentifier, clusterSingletonServiceRegistration) -> {
+            try {
+                clusterSingletonServiceRegistration.close();
+            } catch (Exception e) {
+                LOG.error("Error at unregistering from cluster. InstanceIdentifier: " + instanceIdentifier, e);
+            }
+        });
+        contexts.clear();
+        clusterRegistrations.clear();
+    }
+
+    private ListenerRegistration<NetconfTopologyManager> registerDataTreeChangeListener(String topologyId) {
+        final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        initTopology(wtx, LogicalDatastoreType.CONFIGURATION, topologyId);
+        initTopology(wtx, LogicalDatastoreType.OPERATIONAL, topologyId);
+        Futures.addCallback(wtx.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(Void result) {
+                LOG.debug("topology initialization successful");
+            }
+
+            @Override
+            public void onFailure(@Nonnull Throwable throwable) {
+                LOG.error("Unable to initialize netconf-topology, {}", throwable);
+            }
+        });
+
+        LOG.debug("Registering datastore listener");
+        return dataBroker.registerDataTreeChangeListener(
+                        new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                                NetconfTopologyUtils.createTopologyListPath(topologyId).child(Node.class)), this);
+    }
+
+    private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType, String topologyId) {
+        final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
+        final InstanceIdentifier<NetworkTopology> networkTopologyId =
+                InstanceIdentifier.builder(NetworkTopology.class).build();
+        wtx.merge(datastoreType, networkTopologyId, networkTopology);
+        final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
+        wtx.merge(datastoreType, networkTopologyId.child(Topology.class,
+                new TopologyKey(new TopologyId(topologyId))), topology);
+    }
+
+    private NetconfTopologySetup createSetup(final InstanceIdentifier<Node> instanceIdentifier, final Node node) {
+        final NetconfTopologySetupBuilder builder = NetconfTopologySetupBuilder.create()
+                .setClusterSingletonServiceProvider(clusterSingletonServiceProvider)
+                .setDataBroker(dataBroker)
+                .setInstanceIdentifier(instanceIdentifier)
+                .setRpcProviderRegistry(rpcProviderRegistry)
+                .setNode(node)
+                .setBindingAwareBroker(bindingAwareBroker)
+                .setActorSystem(actorSystem)
+                .setEventExecutor(eventExecutor)
+                .setDomBroker(domBroker)
+                .setKeepaliveExecutor(keepaliveExecutor)
+                .setProcessingExecutor(processingExecutor)
+                .setTopologyId(topologyId)
+                .setNetconfClientDispatcher(clientDispatcher);
+
+        return builder.build();
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/ProxyDOMRpcService.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/ProxyDOMRpcService.java
new file mode 100644 (file)
index 0000000..c1c8430
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class ProxyDOMRpcService implements DOMRpcService {
+
+    @Nonnull
+    @Override
+    public CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(@Nonnull final SchemaPath type,
+                                                                  @Nullable final NormalizedNode<?, ?> input) {
+        throw new UnsupportedOperationException("InvokeRpc: DOMRpc service not working in cluster.");
+    }
+
+    @Nonnull
+    @Override
+    public <T extends DOMRpcAvailabilityListener> ListenerRegistration<T> registerRpcListener(
+            @Nonnull final T listener) {
+        throw new UnsupportedOperationException("RegisterRpcListener: DOMRpc service not working in cluster.");
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/ProxyYangTextSourceProvider.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/ProxyYangTextSourceProvider.java
new file mode 100644 (file)
index 0000000..27514c7
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import akka.actor.ActorContext;
+import akka.actor.ActorRef;
+import akka.dispatch.Futures;
+import akka.dispatch.OnComplete;
+import akka.pattern.Patterns;
+import com.google.common.collect.Sets;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.cluster.schema.provider.RemoteYangTextSourceProvider;
+import org.opendaylight.controller.cluster.schema.provider.impl.YangTextSchemaSourceSerializationProxy;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.netconf.topology.singleton.messages.YangTextSchemaSourceRequest;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import scala.concurrent.Future;
+import scala.concurrent.impl.Promise;
+
+public class ProxyYangTextSourceProvider implements RemoteYangTextSourceProvider {
+
+    private final ActorRef masterRef;
+    private final ActorContext actorContext;
+
+    public ProxyYangTextSourceProvider(final ActorRef masterRef, final ActorContext actorContext) {
+        this.masterRef = masterRef;
+        this.actorContext = actorContext;
+    }
+
+    @Override
+    public Future<Set<SourceIdentifier>> getProvidedSources() {
+        // NOOP
+        return Futures.successful(Sets.newHashSet());
+    }
+
+    @Override
+    public Future<YangTextSchemaSourceSerializationProxy> getYangTextSchemaSource(
+            @Nonnull final SourceIdentifier sourceIdentifier) {
+
+        final Future<Object> scalaFuture = Patterns.ask(masterRef,
+                new YangTextSchemaSourceRequest(sourceIdentifier), NetconfTopologyUtils.TIMEOUT);
+
+        final Promise.DefaultPromise<YangTextSchemaSourceSerializationProxy> promise = new Promise.DefaultPromise<>();
+
+        scalaFuture.onComplete(new OnComplete<Object>() {
+            @Override
+            public void onComplete(final Throwable failure, final Object success) throws Throwable {
+                if (failure != null) {
+                    promise.failure(failure);
+                    return;
+                }
+                if (success instanceof Throwable) {
+                    promise.failure((Throwable) success);
+                    return;
+                }
+                promise.success((YangTextSchemaSourceSerializationProxy) success);
+            }
+        }, actorContext.dispatcher());
+
+        return promise.future();
+
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImpl.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImpl.java
new file mode 100644 (file)
index 0000000..0525789
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import akka.actor.ActorRef;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import io.netty.util.concurrent.EventExecutor;
+import java.io.File;
+import java.math.BigDecimal;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.opendaylight.netconf.api.NetconfMessage;
+import org.opendaylight.netconf.client.NetconfClientSessionListener;
+import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
+import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
+import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
+import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
+import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
+import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
+import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.RemoteDeviceConnector;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfConnectorDTO;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
+import org.opendaylight.protocol.framework.TimedReconnectStrategy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
+import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
+import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
+import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RemoteDeviceConnectorImpl implements RemoteDeviceConnector {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RemoteDeviceConnectorImpl.class);
+
+    /**
+     * Keeps track of initialized Schema resources.  A Map is maintained in which the key represents the name
+     * of the schema cache directory, and the value is a corresponding <code>SchemaResourcesDTO</code>.  The
+     * <code>SchemaResourcesDTO</code> is essentially a container that allows for the extraction of the
+     * <code>SchemaRegistry</code> and <code>SchemaContextFactory</code> which should be used for a particular
+     * Netconf mount.  Access to <code>schemaResourcesDTOs</code> should be surrounded by appropriate
+     * synchronization locks.
+     */
+    private static final Map<String, NetconfDevice.SchemaResourcesDTO> schemaResourcesDTOs = new HashMap<>();
+
+    private SchemaSourceRegistry schemaRegistry = NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY;
+    private SchemaRepository schemaRepository = NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY;
+
+    private final NetconfTopologySetup netconfTopologyDeviceSetup;
+    private final RemoteDeviceId remoteDeviceId;
+
+    private SchemaContextFactory schemaContextFactory = NetconfTopologyUtils.DEFAULT_SCHEMA_CONTEXT_FACTORY;
+    private NetconfConnectorDTO deviceCommunicatorDTO;
+
+    // Initializes default constant instances for the case when the default schema repository
+    // directory cache/schema is used.
+    static {
+        schemaResourcesDTOs.put(NetconfTopologyUtils.DEFAULT_CACHE_DIRECTORY,
+                new NetconfDevice.SchemaResourcesDTO(NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY,
+                        NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY,
+                        NetconfTopologyUtils.DEFAULT_SCHEMA_CONTEXT_FACTORY,
+                        new NetconfStateSchemasResolverImpl()));
+        NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(NetconfTopologyUtils.DEFAULT_CACHE);
+        NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
+                TextToASTTransformer.create(NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY,
+                        NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY));
+    }
+
+    public RemoteDeviceConnectorImpl(final NetconfTopologySetup netconfTopologyDeviceSetup,
+                                     final RemoteDeviceId remoteDeviceId) {
+
+        this.netconfTopologyDeviceSetup = Preconditions.checkNotNull(netconfTopologyDeviceSetup);
+        this.remoteDeviceId = remoteDeviceId;
+    }
+
+    @Override
+    public void startRemoteDeviceConnection(final ActorRef deviceContextActorRef) {
+
+        final NetconfNode netconfNode = netconfTopologyDeviceSetup.getNode().getAugmentation(NetconfNode.class);
+        final NodeId nodeId = netconfTopologyDeviceSetup.getNode().getNodeId();
+        Preconditions.checkNotNull(netconfNode.getHost());
+        Preconditions.checkNotNull(netconfNode.getPort());
+        Preconditions.checkNotNull(netconfNode.isTcpOnly());
+
+        this.deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode, deviceContextActorRef);
+        final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
+        final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
+        final NetconfReconnectingClientConfiguration clientConfig =
+                getClientConfig(netconfClientSessionListener, netconfNode);
+        final ListenableFuture<NetconfDeviceCapabilities> future = deviceCommunicator
+                .initializeRemoteConnection(netconfTopologyDeviceSetup.getNetconfClientDispatcher(), clientConfig);
+
+        Futures.addCallback(future, new FutureCallback<NetconfDeviceCapabilities>() {
+            @Override
+            public void onSuccess(NetconfDeviceCapabilities result) {
+                LOG.debug("{}: Connector started successfully", remoteDeviceId);
+            }
+
+            @Override
+            public void onFailure(@Nullable Throwable throwable) {
+                LOG.error("{}: Connector failed, {}", remoteDeviceId, throwable);
+            }
+        });
+    }
+
+    @Override
+    public void stopRemoteDeviceConnection() {
+        Preconditions.checkNotNull(deviceCommunicatorDTO, remoteDeviceId + ": Device communicator was not created.");
+        try {
+            deviceCommunicatorDTO.close();
+        } catch (Exception e) {
+            LOG.error("{}: Error at closing device communicator.", remoteDeviceId, e);
+        }
+    }
+
+    @VisibleForTesting
+    NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node,
+                                                         final ActorRef deviceContextActorRef) {
+        //setup default values since default value is not supported in mdsal
+        final Long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null
+                ? NetconfTopologyUtils.DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis();
+        final Long keepaliveDelay = node.getKeepaliveDelay() == null
+                ? NetconfTopologyUtils.DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay();
+        final Boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null
+                ? NetconfTopologyUtils.DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
+
+        RemoteDeviceHandler<NetconfSessionPreferences> salFacade =  new MasterSalFacade(remoteDeviceId,
+                netconfTopologyDeviceSetup.getDomBroker(), netconfTopologyDeviceSetup.getBindingAwareBroker(),
+                netconfTopologyDeviceSetup.getActorSystem(), deviceContextActorRef);
+        if (keepaliveDelay > 0) {
+            LOG.info("{}: Adding keepalive facade.", remoteDeviceId);
+            salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade,
+                    netconfTopologyDeviceSetup.getKeepaliveExecutor().getExecutor(), keepaliveDelay,
+                    defaultRequestTimeoutMillis);
+        }
+
+        // pre register yang library sources as fallback schemas to schema registry
+        List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources = Lists.newArrayList();
+        if (node.getYangLibrary() != null) {
+            final String yangLibURL = node.getYangLibrary().getYangLibraryUrl().getValue();
+            final String yangLibUsername = node.getYangLibrary().getUsername();
+            final String yangLigPassword = node.getYangLibrary().getPassword();
+
+            LibraryModulesSchemas libraryModulesSchemas;
+            if (yangLibURL != null) {
+                if (yangLibUsername != null && yangLigPassword != null) {
+                    libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
+                } else {
+                    libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
+                }
+
+                for (Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry :
+                        libraryModulesSchemas.getAvailableModels().entrySet()) {
+                    registeredYangLibSources
+                            .add(schemaRegistry.registerSchemaSource(
+                                    new YangLibrarySchemaYangSourceProvider(remoteDeviceId,
+                                            libraryModulesSchemas.getAvailableModels()),
+                                    PotentialSchemaSource
+                                            .create(sourceIdentifierURLEntry.getKey(), YangTextSchemaSource.class,
+                                                    PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
+                }
+            }
+        }
+
+        final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node);
+        final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
+        if (node.isSchemaless()) {
+            device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
+        } else {
+            device = new NetconfDeviceBuilder()
+                    .setReconnectOnSchemasChange(reconnectOnChangedSchema)
+                    .setSchemaResourcesDTO(schemaResourcesDTO)
+                    .setGlobalProcessingExecutor(netconfTopologyDeviceSetup.getProcessingExecutor().getExecutor())
+                    .setId(remoteDeviceId)
+                    .setSalFacade(salFacade)
+                    .build();
+        }
+
+        final Optional<NetconfSessionPreferences> userCapabilities = getUserCapabilities(node);
+        final int rpcMessageLimit =
+                node.getConcurrentRpcLimit() == null
+                        ? NetconfTopologyUtils.DEFAULT_CONCURRENT_RPC_LIMIT : node.getConcurrentRpcLimit();
+
+        if (rpcMessageLimit < 1) {
+            LOG.info("{}: Concurrent rpc limit is smaller than 1, no limit will be enforced.", remoteDeviceId);
+        }
+
+        return new NetconfConnectorDTO(
+                userCapabilities.isPresent()
+                        ? new NetconfDeviceCommunicator(
+                                remoteDeviceId, device, new UserPreferences(userCapabilities.get(),
+                                node.getYangModuleCapabilities().isOverride()), rpcMessageLimit) :
+                        new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit), salFacade);
+    }
+
+    private Optional<NetconfSessionPreferences> getUserCapabilities(final NetconfNode node) {
+        if (node.getYangModuleCapabilities() == null) {
+            return Optional.empty();
+        }
+
+        final List<String> capabilities = node.getYangModuleCapabilities().getCapability();
+        if (capabilities == null || capabilities.isEmpty()) {
+            return Optional.empty();
+        }
+
+        final NetconfSessionPreferences parsedOverrideCapabilities =
+                NetconfSessionPreferences.fromStrings(capabilities);
+        Preconditions.checkState(parsedOverrideCapabilities.getNonModuleCaps().isEmpty(), remoteDeviceId +
+                ": Capabilities to override can only contain module based capabilities, non-module capabilities "
+                        + "will be retrieved from the device, configured non-module capabilities: "
+                        + parsedOverrideCapabilities.getNonModuleCaps());
+
+        return Optional.of(parsedOverrideCapabilities);
+    }
+
+    private NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final NodeId nodeId, final NetconfNode node) {
+        // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc.
+        NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null;
+        final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory();
+        // Only checks to ensure the String is not empty or null;  further checks related to directory accessibility
+        // and file permissions are handled during the FilesystemSchemaSourceCache initialization.
+        if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) {
+            // If a custom schema cache directory is specified, create the backing DTO; otherwise, the SchemaRegistry
+            // and SchemaContextFactory remain the default values.
+            if (!moduleSchemaCacheDirectory.equals(NetconfTopologyUtils.DEFAULT_CACHE_DIRECTORY)) {
+                // Multiple modules may be created at once;  synchronize to avoid issues with data consistency among
+                // threads.
+                synchronized (schemaResourcesDTOs) {
+                    // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables if
+                    // they already exist
+                    schemaResourcesDTO = schemaResourcesDTOs.get(moduleSchemaCacheDirectory);
+                    if (schemaResourcesDTO == null) {
+                        schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory);
+                        schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener(
+                                TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(),
+                                        schemaResourcesDTO.getSchemaRegistry())
+                        );
+                        schemaResourcesDTOs.put(moduleSchemaCacheDirectory, schemaResourcesDTO);
+                    }
+                }
+                LOG.info("{} : netconf connector will use schema cache directory {} instead of {}",
+                        remoteDeviceId, moduleSchemaCacheDirectory, NetconfTopologyUtils.DEFAULT_CACHE_DIRECTORY);
+            }
+        } else {
+            LOG.info("{} : using the default directory {}",
+                    remoteDeviceId, NetconfTopologyUtils.QUALIFIED_DEFAULT_CACHE_DIRECTORY);
+        }
+
+        if (schemaResourcesDTO == null) {
+            schemaResourcesDTO =
+                    new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaContextFactory,
+                            new NetconfStateSchemasResolverImpl());
+        }
+
+        return schemaResourcesDTO;
+    }
+
+    /**
+     * Creates the backing Schema classes for a particular directory.
+     *
+     * @param moduleSchemaCacheDirectory The string directory relative to "cache"
+     * @return A DTO containing the Schema classes for the Netconf mount.
+     */
+    private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) {
+        final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory);
+        final SchemaContextFactory schemaContextFactory
+                = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
+        this.schemaRegistry = repository;
+        this.schemaContextFactory = schemaContextFactory;
+
+        final FilesystemSchemaSourceCache<YangTextSchemaSource> deviceCache =
+                createDeviceFilesystemCache(moduleSchemaCacheDirectory);
+        repository.registerSchemaSourceListener(deviceCache);
+        return new NetconfDevice.SchemaResourcesDTO(repository, repository, schemaContextFactory,
+                new NetconfStateSchemasResolverImpl());
+    }
+
+    /**
+     * Creates a <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory.
+     *
+     * @param schemaCacheDirectory The custom cache directory relative to "cache"
+     * @return A <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory
+     */
+    private FilesystemSchemaSourceCache<YangTextSchemaSource> createDeviceFilesystemCache(
+            final String schemaCacheDirectory) {
+        final String relativeSchemaCacheDirectory =
+                NetconfTopologyUtils.CACHE_DIRECTORY + File.separator + schemaCacheDirectory;
+        return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class,
+                new File(relativeSchemaCacheDirectory));
+    }
+
+    //TODO: duplicate code
+    private InetSocketAddress getSocketAddress(final Host host, int port) {
+        if (host.getDomainName() != null) {
+            return new InetSocketAddress(host.getDomainName().getValue(), port);
+        } else {
+            final IpAddress ipAddress = host.getIpAddress();
+            final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() :
+                    ipAddress.getIpv6Address().getValue();
+            return new InetSocketAddress(ip, port);
+        }
+    }
+
+    private static final class TimedReconnectStrategyFactory implements ReconnectStrategyFactory {
+        private final Long connectionAttempts;
+        private final EventExecutor executor;
+        private final double sleepFactor;
+        private final int minSleep;
+
+        TimedReconnectStrategyFactory(final EventExecutor executor, final Long maxConnectionAttempts,
+                                      final int minSleep, final BigDecimal sleepFactor) {
+            if (maxConnectionAttempts != null && maxConnectionAttempts > 0) {
+                connectionAttempts = maxConnectionAttempts;
+            } else {
+                connectionAttempts = null;
+            }
+
+            this.sleepFactor = sleepFactor.doubleValue();
+            this.executor = executor;
+            this.minSleep = minSleep;
+        }
+
+        @Override
+        public ReconnectStrategy createReconnectStrategy() {
+            final Long maxSleep = null;
+            final Long deadline = null;
+
+            return new TimedReconnectStrategy(executor, minSleep,
+                    minSleep, sleepFactor, maxSleep, connectionAttempts, deadline);
+        }
+    }
+
+    @VisibleForTesting
+    NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener,
+                                                                   final NetconfNode node) {
+
+        //setup default values since default value is not supported in mdsal
+        final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null
+                ? NetconfTopologyUtils.DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis();
+        final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null
+                ? NetconfTopologyUtils.DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts();
+        final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null
+                ? NetconfTopologyUtils.DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis();
+        final BigDecimal sleepFactor = node.getSleepFactor() == null
+                ? NetconfTopologyUtils.DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
+
+        final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue());
+
+        final ReconnectStrategyFactory sf =
+                new TimedReconnectStrategyFactory(netconfTopologyDeviceSetup.getEventExecutor(), maxConnectionAttempts,
+                        betweenAttemptsTimeoutMillis, sleepFactor);
+        final ReconnectStrategy strategy = sf.createReconnectStrategy();
+
+        final AuthenticationHandler authHandler;
+        final Credentials credentials = node.getCredentials();
+        if (credentials instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) {
+            authHandler = new LoginPassword(
+                    ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) credentials).getUsername(),
+                    ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) credentials).getPassword());
+        } else {
+            throw new IllegalStateException(remoteDeviceId + ": Only login/password authentication is supported");
+        }
+
+        return NetconfReconnectingClientConfigurationBuilder.create()
+                .withAddress(socketAddress)
+                .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
+                .withReconnectStrategy(strategy)
+                .withAuthHandler(authHandler)
+                .withProtocol(node.isTcpOnly()
+                        ? NetconfClientConfiguration.NetconfClientProtocol.TCP
+                        : NetconfClientConfiguration.NetconfClientProtocol.SSH)
+                .withConnectStrategyFactory(sf)
+                .withSessionListener(listener)
+                .build();
+    }
+
+    @VisibleForTesting
+    Map<String, NetconfDevice.SchemaResourcesDTO> getSchemaResourcesDTOs() {
+        return schemaResourcesDTOs;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteOperationTxProcessorImpl.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteOperationTxProcessorImpl.java
new file mode 100644 (file)
index 0000000..f107966
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import akka.actor.ActorRef;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.RemoteOperationTxProcessor;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitFailedReply;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyReadResponse;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitReply;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RemoteOperationTxProcessorImpl implements RemoteOperationTxProcessor, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RemoteOperationTxProcessorImpl.class);
+
+    private final DOMDataBroker dataBroker;
+    private final RemoteDeviceId id;
+    private DOMDataWriteTransaction writeTx;
+    private DOMDataReadOnlyTransaction readTx;
+
+    public RemoteOperationTxProcessorImpl(final DOMDataBroker dataBroker, final RemoteDeviceId id) {
+        this.dataBroker = dataBroker;
+        this.id = id;
+        this.readTx = dataBroker.newReadOnlyTransaction();
+    }
+
+    @Override
+    public void doDelete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        if (writeTx == null) {
+            writeTx = dataBroker.newWriteOnlyTransaction();
+        }
+        writeTx.delete(store, path);
+    }
+
+    @Override
+    public void doSubmit(final ActorRef recipient, final ActorRef sender) {
+        if (writeTx != null) {
+            CheckedFuture<Void, TransactionCommitFailedException> submitFuture = writeTx.submit();
+            Futures.addCallback(submitFuture, new FutureCallback<Void>() {
+                @Override
+                public void onSuccess(Void result) {
+                    recipient.tell(new SubmitReply(), sender);
+                }
+
+                @Override
+                public void onFailure(@Nonnull Throwable throwable) {
+                    recipient.tell(throwable, sender);
+                }
+            });
+        } else {
+            recipient.tell(new SubmitFailedReply(), sender);
+            LOG.warn("{}: Couldn't submit transaction because it was already closed.", id);
+        }
+    }
+
+    @Override
+    public void doCancel(final ActorRef recipient, final ActorRef sender) {
+        boolean cancel = false;
+        if (writeTx != null) {
+            cancel = writeTx.cancel();
+        }
+        recipient.tell(cancel, sender);
+    }
+
+    @Override
+    public void doPut(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
+        if (writeTx == null) {
+            writeTx = dataBroker.newWriteOnlyTransaction();
+        }
+        writeTx.put(store, data.getIdentifier(), data.getNode());
+    }
+
+    @Override
+    public void doMerge(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
+        if (writeTx == null) {
+            writeTx = dataBroker.newWriteOnlyTransaction();
+        }
+        writeTx.merge(store, data.getIdentifier(), data.getNode());
+    }
+
+    @Override
+    public void doRead(final LogicalDatastoreType store, final YangInstanceIdentifier path, final ActorRef recipient,
+                       final ActorRef sender) {
+        final CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> readFuture =
+                readTx.read(store, path);
+
+        Futures.addCallback(readFuture, new FutureCallback<Optional<NormalizedNode<?, ?>>>() {
+
+            @Override
+            public void onSuccess(final Optional<NormalizedNode<?, ?>> result) {
+                if (!result.isPresent()) {
+                    recipient.tell(new EmptyReadResponse(), sender);
+                    return;
+                }
+                recipient.tell(new NormalizedNodeMessage(path, result.get()), sender);
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable throwable) {
+                recipient.tell(throwable, sender);
+            }
+        });
+    }
+
+    @Override
+    public void doExists(final LogicalDatastoreType store, final YangInstanceIdentifier path, final ActorRef recipient,
+                         final ActorRef sender) {
+        final CheckedFuture<Boolean, ReadFailedException> readFuture =
+                readTx.exists(store, path);
+        Futures.addCallback(readFuture, new FutureCallback<Boolean>() {
+            @Override
+            public void onSuccess(final Boolean result) {
+                if (result == null) {
+                    recipient.tell(false, sender);
+                } else {
+                    recipient.tell(result, sender);
+                }
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable throwable) {
+                recipient.tell(throwable, sender);
+            }
+        });
+    }
+
+    @Override
+    public void close() throws Exception {
+        if (readTx != null) {
+            readTx.close();
+        }
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/SlaveSalFacade.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/SlaveSalFacade.java
new file mode 100644 (file)
index 0000000..877436d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceNotificationService;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalProvider;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.impl.tx.NetconfProxyDOMTransaction;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SlaveSalFacade {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SlaveSalFacade.class);
+
+    private final RemoteDeviceId id;
+    private final NetconfDeviceSalProvider salProvider;
+
+    private final ActorSystem actorSystem;
+
+    public SlaveSalFacade(final RemoteDeviceId id,
+                          final Broker domBroker,
+                          final ActorSystem actorSystem) {
+        this.id = id;
+        this.salProvider = new NetconfDeviceSalProvider(id);
+        this.actorSystem = actorSystem;
+
+        registerToSal(domBroker);
+    }
+
+    private void registerToSal(final Broker domRegistryDependency) {
+        domRegistryDependency.registerProvider(salProvider);
+
+    }
+
+    public void registerSlaveMountPoint(final SchemaContext remoteSchemaContext, final DOMRpcService deviceRpc,
+                                        final ActorRef masterActorRef) {
+        final NetconfDeviceNotificationService notificationService = new NetconfDeviceNotificationService();
+
+        final NetconfDOMTransaction proxyDOMTransactions =
+                new NetconfProxyDOMTransaction(id, actorSystem, masterActorRef);
+
+        final NetconfDOMDataBroker netconfDeviceDataBroker =
+                new NetconfDOMDataBroker(actorSystem, id, proxyDOMTransactions);
+
+        salProvider.getMountInstance().onTopologyDeviceConnected(remoteSchemaContext, netconfDeviceDataBroker,
+                deviceRpc, notificationService);
+
+        LOG.info("{}: Slave mount point registered.", id);
+    }
+
+    public void unregisterSlaveMountPoint() {
+        salProvider.getMountInstance().onTopologyDeviceDisconnected();
+    }
+
+    public void close() {
+        unregisterSlaveMountPoint();
+        try {
+            salProvider.getMountInstance().close();
+        } catch (Exception exception) {
+            LOG.warn("{}: Exception in closing slave sal facade: {}", id, exception);
+        }
+
+    }
+
+
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/actors/NetconfNodeActor.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/actors/NetconfNodeActor.java
new file mode 100644 (file)
index 0000000..75c7e62
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.actors;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import java.io.IOException;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.cluster.schema.provider.RemoteYangTextSourceProvider;
+import org.opendaylight.controller.cluster.schema.provider.impl.RemoteSchemaProvider;
+import org.opendaylight.controller.cluster.schema.provider.impl.YangTextSchemaSourceSerializationProxy;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.RemoteOperationTxProcessor;
+import org.opendaylight.netconf.topology.singleton.impl.ProxyDOMRpcService;
+import org.opendaylight.netconf.topology.singleton.impl.ProxyYangTextSourceProvider;
+import org.opendaylight.netconf.topology.singleton.impl.RemoteOperationTxProcessorImpl;
+import org.opendaylight.netconf.topology.singleton.impl.SlaveSalFacade;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.netconf.topology.singleton.messages.AskForMasterMountPoint;
+import org.opendaylight.netconf.topology.singleton.messages.CreateInitialMasterActorData;
+import org.opendaylight.netconf.topology.singleton.messages.MasterActorDataInitialized;
+import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
+import org.opendaylight.netconf.topology.singleton.messages.RegisterMountPoint;
+import org.opendaylight.netconf.topology.singleton.messages.UnregisterSlaveMountPoint;
+import org.opendaylight.netconf.topology.singleton.messages.YangTextSchemaSourceRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.CancelRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.DeleteRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.ExistsRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.MergeRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.PutRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.ReadRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.TransactionRequest;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfNodeActor extends UntypedActor {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfNodeActor.class);
+
+    private NetconfTopologySetup setup;
+    private RemoteDeviceId id;
+    private final SchemaSourceRegistry schemaRegistry;
+    private final SchemaRepository schemaRepository;
+
+    private RemoteOperationTxProcessor operationsProcessor;
+    private List<SourceIdentifier> sourceIdentifiers;
+    private SlaveSalFacade slaveSalManager;
+
+    public static Props props(final NetconfTopologySetup setup,
+                              final RemoteDeviceId id, final SchemaSourceRegistry schemaRegistry,
+                              final SchemaRepository schemaRepository) {
+        return Props.create(NetconfNodeActor.class, () ->
+                new NetconfNodeActor(setup, id, schemaRegistry, schemaRepository));
+    }
+
+    private NetconfNodeActor(final NetconfTopologySetup setup,
+                             final RemoteDeviceId id, SchemaSourceRegistry schemaRegistry,
+                             final SchemaRepository schemaRepository) {
+        this.setup = setup;
+        this.id = id;
+        this.schemaRegistry = schemaRegistry;
+        this.schemaRepository = schemaRepository;
+    }
+
+    @Override
+    public void onReceive(final Object message) throws Exception {
+        if (message instanceof CreateInitialMasterActorData) { // master
+
+            sourceIdentifiers = ((CreateInitialMasterActorData) message).getSourceIndentifiers();
+            operationsProcessor =
+                    new RemoteOperationTxProcessorImpl(((CreateInitialMasterActorData) message).getDeviceDataBroker(),
+                            id);
+            sender().tell(new MasterActorDataInitialized(), self());
+
+            LOG.debug("{}: Master is ready.", id);
+
+        } else if (message instanceof  RefreshSetupMasterActorData) {
+            setup = ((RefreshSetupMasterActorData) message).getNetconfTopologyDeviceSetup();
+            id = ((RefreshSetupMasterActorData) message).getRemoteDeviceId();
+            sender().tell(new MasterActorDataInitialized(), self());
+        } else if (message instanceof AskForMasterMountPoint) { // master
+            // only master contains reference to operations processor
+            if (operationsProcessor != null) {
+                getSender().tell(new RegisterMountPoint(sourceIdentifiers), getSelf());
+            }
+
+        } else if (message instanceof TransactionRequest) { // master
+
+            resolveProxyCalls(message, sender(), getSelf());
+
+        } else if (message instanceof YangTextSchemaSourceRequest) { // master
+
+            final YangTextSchemaSourceRequest yangTextSchemaSourceRequest = (YangTextSchemaSourceRequest) message;
+            sendYangTextSchemaSourceProxy(yangTextSchemaSourceRequest.getSourceIdentifier(), sender());
+
+        } else if (message instanceof RegisterMountPoint) { //slaves
+
+            sourceIdentifiers = ((RegisterMountPoint) message).getSourceIndentifiers();
+            registerSlaveMountPoint(getSender());
+
+        } else if (message instanceof UnregisterSlaveMountPoint) { //slaves
+            if (slaveSalManager != null) {
+                slaveSalManager.close();
+                slaveSalManager = null;
+            }
+
+        }
+    }
+
+    private void resolveProxyCalls(final Object message, final ActorRef recipient, final ActorRef futureSender) {
+        if (message instanceof ReadRequest) {
+
+            final ReadRequest readRequest = (ReadRequest) message;
+            operationsProcessor.doRead(readRequest.getStore(), readRequest.getPath(), recipient, futureSender);
+
+        } else if (message instanceof ExistsRequest) {
+
+            final ExistsRequest readRequest = (ExistsRequest) message;
+            operationsProcessor.doExists(readRequest.getStore(), readRequest.getPath(), recipient, futureSender);
+
+        } else if (message instanceof MergeRequest) {
+
+            final MergeRequest mergeRequest = (MergeRequest) message;
+            operationsProcessor.doMerge(mergeRequest.getStore(), mergeRequest.getNormalizedNodeMessage());
+
+        } else if (message instanceof PutRequest) {
+
+            final PutRequest putRequest = (PutRequest) message;
+            operationsProcessor.doPut(putRequest.getStore(), putRequest.getNormalizedNodeMessage());
+
+        } else if (message instanceof DeleteRequest) {
+
+            final DeleteRequest deleteRequest = (DeleteRequest) message;
+            operationsProcessor.doDelete(deleteRequest.getStore(), deleteRequest.getPath());
+
+        } else if (message instanceof CancelRequest) {
+
+            operationsProcessor.doCancel(recipient, futureSender);
+
+        } else if (message instanceof SubmitRequest) {
+
+            operationsProcessor.doSubmit(recipient, futureSender);
+        }
+    }
+
+    private void sendYangTextSchemaSourceProxy(final SourceIdentifier sourceIdentifier, final ActorRef sender) {
+        final CheckedFuture<YangTextSchemaSource, SchemaSourceException> yangTextSchemaSource =
+                schemaRepository.getSchemaSource(sourceIdentifier, YangTextSchemaSource.class);
+
+        Futures.addCallback(yangTextSchemaSource, new FutureCallback<YangTextSchemaSource>() {
+            @Override
+            public void onSuccess(final YangTextSchemaSource yangTextSchemaSource) {
+                try {
+                    sender.tell(new YangTextSchemaSourceSerializationProxy(yangTextSchemaSource), getSelf());
+                } catch (IOException exception) {
+                    sender.tell(exception.getCause(), getSelf());
+                }
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable throwable) {
+                sender.tell(throwable, getSelf());
+            }
+        });
+    }
+
+    private void registerSlaveMountPoint(final ActorRef masterReference) {
+        if (this.slaveSalManager != null) {
+            slaveSalManager.close();
+        }
+        slaveSalManager = new SlaveSalFacade(id, setup.getDomBroker(), setup.getActorSystem());
+
+        final CheckedFuture<SchemaContext, SchemaResolutionException> remoteSchemaContext =
+                getSchemaContext(masterReference);
+        final DOMRpcService deviceRpc = getDOMRpcService();
+
+        Futures.addCallback(remoteSchemaContext, new FutureCallback<SchemaContext>() {
+            @Override
+            public void onSuccess(final SchemaContext result) {
+                LOG.info("{}: Schema context resolved: {}", id, result.getModules());
+                slaveSalManager.registerSlaveMountPoint(result, deviceRpc, masterReference);
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable throwable) {
+                LOG.error("{}: Failed to register mount point: {}", id, throwable);
+            }
+        });
+    }
+
+    private DOMRpcService getDOMRpcService() {
+        return new ProxyDOMRpcService();
+    }
+
+    private CheckedFuture<SchemaContext, SchemaResolutionException> getSchemaContext(ActorRef masterReference) {
+
+        final RemoteYangTextSourceProvider remoteYangTextSourceProvider =
+                new ProxyYangTextSourceProvider(masterReference, getContext());
+        final RemoteSchemaProvider remoteProvider = new RemoteSchemaProvider(remoteYangTextSourceProvider,
+                getContext().dispatcher());
+
+        sourceIdentifiers.forEach(sourceId ->
+                schemaRegistry.registerSchemaSource(remoteProvider, PotentialSchemaSource.create(sourceId,
+                        YangTextSchemaSource.class, PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
+
+        final SchemaContextFactory schemaContextFactory
+                = schemaRepository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
+
+        return schemaContextFactory.createSchemaContext(sourceIdentifiers);
+    }
+
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfMasterDOMTransaction.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfMasterDOMTransaction.java
new file mode 100644 (file)
index 0000000..33680f2
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.tx;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceDataBroker;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.Future;
+import scala.concurrent.impl.Promise.DefaultPromise;
+
+public class NetconfMasterDOMTransaction implements NetconfDOMTransaction {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfMasterDOMTransaction.class);
+
+    private final RemoteDeviceId id;
+    private final DOMDataBroker delegateBroker;
+
+    private DOMDataReadOnlyTransaction readTx;
+    private DOMDataWriteTransaction writeTx;
+
+    public NetconfMasterDOMTransaction(final RemoteDeviceId id,
+                                       final SchemaContext schemaContext,
+                                       final DOMRpcService rpc,
+                                       final NetconfSessionPreferences netconfSessionPreferences) {
+        this(id, new NetconfDeviceDataBroker(id, schemaContext, rpc, netconfSessionPreferences));
+    }
+
+    public NetconfMasterDOMTransaction(final RemoteDeviceId id, final DOMDataBroker delegateBroker) {
+        this.id = id;
+        this.delegateBroker = delegateBroker;
+
+        // only ever need 1 readTx since it doesnt need to be closed
+        readTx = delegateBroker.newReadOnlyTransaction();
+    }
+
+    @Override
+    public Future<Optional<NormalizedNodeMessage>> read(final LogicalDatastoreType store,
+                                                        final YangInstanceIdentifier path) {
+        LOG.trace("{}: Read[{}] {} via NETCONF: {}", id, readTx.getIdentifier(), store, path);
+
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readFuture = readTx.read(store, path);
+
+        final DefaultPromise<Optional<NormalizedNodeMessage>> promise = new DefaultPromise<>();
+        Futures.addCallback(readFuture, new FutureCallback<Optional<NormalizedNode<?, ?>>>() {
+            @Override
+            public void onSuccess(final Optional<NormalizedNode<?, ?>> result) {
+                if (!result.isPresent()) {
+                    promise.success(Optional.absent());
+                } else {
+                    promise.success(Optional.of(new NormalizedNodeMessage(path, result.get())));
+                }
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable throwable) {
+                promise.failure(throwable);
+            }
+        });
+        return promise.future();
+    }
+
+    @Override
+    public Future<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        LOG.trace("{}: Exists[{}] {} via NETCONF: {}", id, readTx.getIdentifier(), store, path);
+
+        final CheckedFuture<Boolean, ReadFailedException> existsFuture = readTx.exists(store, path);
+
+        final DefaultPromise<Boolean> promise = new DefaultPromise<>();
+        Futures.addCallback(existsFuture, new FutureCallback<Boolean>() {
+            @Override
+            public void onSuccess(final Boolean result) {
+                promise.success(result);
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable throwable) {
+                promise.failure(throwable);
+            }
+        });
+        return promise.future();
+    }
+
+    @Override
+    public void put(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
+        if (writeTx == null) {
+            writeTx = delegateBroker.newWriteOnlyTransaction();
+        }
+
+        LOG.trace("{}: Write[{}] {} via NETCONF: {} with payload {}", id, writeTx.getIdentifier(), store,
+                data.getIdentifier(), data.getNode());
+
+        writeTx.put(store, data.getIdentifier(), data.getNode());
+    }
+
+    @Override
+    public void merge(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
+        if (writeTx == null) {
+            writeTx = delegateBroker.newWriteOnlyTransaction();
+        }
+
+        LOG.trace("{}: Merge[{}] {} via NETCONF: {} with payload {}", id, writeTx.getIdentifier(),store,
+                data.getIdentifier(), data.getNode());
+
+        writeTx.merge(store, data.getIdentifier(), data.getNode());
+    }
+
+    @Override
+    public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        if (writeTx == null) {
+            writeTx = delegateBroker.newWriteOnlyTransaction();
+        }
+
+        LOG.trace("{}: Delete[{}} {} via NETCONF: {}", id, writeTx.getIdentifier(), store, path);
+
+        writeTx.delete(store, path);
+    }
+
+    @Override
+    public boolean cancel() {
+        LOG.trace("{}: Cancel[{}} via NETCONF", id, writeTx.getIdentifier());
+
+        return writeTx.cancel();
+    }
+
+    @Override
+    public Future<Void> submit() {
+        LOG.trace("{}: Submit[{}} via NETCONF", id, writeTx.getIdentifier());
+
+        final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = writeTx.submit();
+        final DefaultPromise<Void> promise = new DefaultPromise<>();
+        Futures.addCallback(submitFuture, new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(final Void result) {
+                promise.success(result);
+                writeTx = null;
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable throwable) {
+                promise.failure(throwable);
+                writeTx = null;
+            }
+        });
+        return promise.future();
+    }
+
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfProxyDOMTransaction.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfProxyDOMTransaction.java
new file mode 100644 (file)
index 0000000..9a23a71
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.tx;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.dispatch.OnComplete;
+import akka.pattern.Patterns;
+import com.google.common.base.Optional;
+import org.opendaylight.controller.config.util.xml.DocumentedException;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitFailedReply;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.CancelRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.DeleteRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyReadResponse;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.ExistsRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.MergeRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.PutRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.ReadRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitRequest;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.impl.Promise.DefaultPromise;
+
+
+public class NetconfProxyDOMTransaction implements NetconfDOMTransaction {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfProxyDOMTransaction.class);
+
+    private final RemoteDeviceId id;
+    private final ActorSystem actorSystem;
+    private final ActorRef masterContextRef;
+
+    public NetconfProxyDOMTransaction(final RemoteDeviceId id,
+                                      final ActorSystem actorSystem,
+                                      final ActorRef masterContextRef) {
+        this.id = id;
+        this.actorSystem = actorSystem;
+        this.masterContextRef = masterContextRef;
+    }
+
+    @Override
+    public Future<Optional<NormalizedNodeMessage>> read(final LogicalDatastoreType store,
+                                                        final YangInstanceIdentifier path) {
+
+        final Future<Object> readScalaFuture =
+                Patterns.ask(masterContextRef, new ReadRequest(store, path), NetconfTopologyUtils.TIMEOUT);
+
+        LOG.trace("{}: Read {} via NETCONF: {}", id, store, path);
+
+        final DefaultPromise<Optional<NormalizedNodeMessage>> promise = new DefaultPromise<>();
+
+        readScalaFuture.onComplete(new OnComplete<Object>() {
+            @Override
+            public void onComplete(final Throwable failure, final Object success) throws Throwable {
+                if (failure != null) { // ask timeout
+                    Exception exception = new DocumentedException(id + ":Master is down. Please try again.",
+                            DocumentedException.ErrorType.APPLICATION, DocumentedException.ErrorTag.OPERATION_FAILED,
+                            DocumentedException.ErrorSeverity.WARNING);
+                    promise.failure(exception);
+                    return;
+                }
+                if (success instanceof Throwable) { // Error sended by master
+                    promise.failure((Throwable) success);
+                    return;
+                }
+                if (success instanceof EmptyReadResponse) {
+                    promise.success(Optional.absent());
+                    return;
+                }
+
+                promise.success(Optional.of((NormalizedNodeMessage) success));
+            }
+        }, actorSystem.dispatcher());
+
+        return promise.future();
+    }
+
+    @Override
+    public Future<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        final Future<Object> existsScalaFuture =
+                Patterns.ask(masterContextRef, new ExistsRequest(store, path), NetconfTopologyUtils.TIMEOUT);
+
+        LOG.trace("{}: Exists {} via NETCONF: {}", id, store, path);
+
+        final DefaultPromise<Boolean> promise = new DefaultPromise<>();
+        existsScalaFuture.onComplete(new OnComplete<Object>() {
+            @Override
+            public void onComplete(final Throwable failure, final Object success) throws Throwable {
+                if (failure != null) { // ask timeout
+                    Exception exception = new DocumentedException(id + ":Master is down. Please try again.",
+                            DocumentedException.ErrorType.APPLICATION, DocumentedException.ErrorTag.OPERATION_FAILED,
+                            DocumentedException.ErrorSeverity.WARNING);
+                    promise.failure(exception);
+                    return;
+                }
+                if (success instanceof Throwable) {
+                    promise.failure((Throwable) success);
+                    return;
+                }
+                promise.success((Boolean) success);
+            }
+        }, actorSystem.dispatcher());
+        return promise.future();
+    }
+
+    @Override
+    public void put(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
+        LOG.trace("{}: Write {} via NETCONF: {} with payload {}", id, store, data.getIdentifier(), data.getNode());
+
+        masterContextRef.tell(new PutRequest(store, data), ActorRef.noSender());
+
+    }
+
+    @Override
+    public void merge(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
+        LOG.trace("{}: Merge {} via NETCONF: {} with payload {}", id, store, data.getIdentifier(), data.getNode());
+
+        masterContextRef.tell(new MergeRequest(store, data), ActorRef.noSender());
+    }
+
+    @Override
+    public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        LOG.trace("{}: Delete {} via NETCONF: {}", id, store, path);
+
+        masterContextRef.tell(new DeleteRequest(store, path), ActorRef.noSender());
+    }
+
+    @Override
+    public boolean cancel() {
+        final Future<Object> cancelScalaFuture =
+                Patterns.ask(masterContextRef, new CancelRequest(), NetconfTopologyUtils.TIMEOUT);
+
+        LOG.trace("{}: Cancel {} via NETCONF", id);
+
+        try {
+            // here must be Await because AsyncWriteTransaction do not return future
+            return (boolean) Await.result(cancelScalaFuture, NetconfTopologyUtils.TIMEOUT.duration());
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    @Override
+    public Future<Void> submit() {
+        final Future<Object> submitScalaFuture =
+                Patterns.ask(masterContextRef, new SubmitRequest(), NetconfTopologyUtils.TIMEOUT);
+
+        LOG.trace("{}: Submit {} via NETCONF", id);
+
+        final DefaultPromise<Void> promise = new DefaultPromise<>();
+
+        submitScalaFuture.onComplete(new OnComplete<Object>() {
+            @Override
+            public void onComplete(final Throwable failure, final Object success) throws Throwable {
+                if (failure != null) { // ask timeout
+                    Exception exception = new DocumentedException(id + ":Master is down. Please try again.",
+                            DocumentedException.ErrorType.APPLICATION, DocumentedException.ErrorTag.OPERATION_FAILED,
+                            DocumentedException.ErrorSeverity.WARNING);
+                    promise.failure(exception);
+                    return;
+                }
+                if (success instanceof Throwable) {
+                    promise.failure((Throwable) success);
+                } else {
+                    if (success instanceof SubmitFailedReply) {
+                        LOG.error("{}: Transaction was not submitted because already closed.", id);
+                    }
+                    promise.success(null);
+                }
+            }
+        }, actorSystem.dispatcher());
+
+        return promise.future();
+    }
+
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline.tx;
+package org.opendaylight.netconf.topology.singleton.impl.tx;
 
 import akka.actor.ActorSystem;
 import akka.dispatch.OnComplete;
@@ -20,19 +20,25 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.pipeline.ProxyNetconfDeviceDataBroker;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import scala.concurrent.Future;
 
-public class ProxyReadOnlyTransaction implements DOMDataReadOnlyTransaction{
+public class NetconfReadOnlyTransaction implements DOMDataReadOnlyTransaction {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfReadOnlyTransaction.class);
 
     private final RemoteDeviceId id;
-    private final ProxyNetconfDeviceDataBroker delegate;
+    private final NetconfDOMTransaction delegate;
     private final ActorSystem actorSystem;
 
-    public ProxyReadOnlyTransaction(final ActorSystem actorSystem, final RemoteDeviceId id, final ProxyNetconfDeviceDataBroker delegate) {
+    public NetconfReadOnlyTransaction(final RemoteDeviceId id,
+                                      final ActorSystem actorSystem,
+                                      final NetconfDOMTransaction delegate) {
         this.id = id;
         this.delegate = delegate;
         this.actorSystem = actorSystem;
@@ -44,10 +50,15 @@ public class ProxyReadOnlyTransaction implements DOMDataReadOnlyTransaction{
     }
 
     @Override
-    public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+    public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(final LogicalDatastoreType store,
+                                                                                   final YangInstanceIdentifier path) {
+
+        LOG.trace("{}: Read {} via NETCONF: {}", id, store, path);
+
         final Future<Optional<NormalizedNodeMessage>> future = delegate.read(store, path);
         final SettableFuture<Optional<NormalizedNode<?, ?>>> settableFuture = SettableFuture.create();
-        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> checkedFuture = Futures.makeChecked(settableFuture, new Function<Exception, ReadFailedException>() {
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> checkedFuture;
+        checkedFuture = Futures.makeChecked(settableFuture, new Function<Exception, ReadFailedException>() {
             @Nullable
             @Override
             public ReadFailedException apply(Exception cause) {
@@ -56,13 +67,16 @@ public class ProxyReadOnlyTransaction implements DOMDataReadOnlyTransaction{
         });
         future.onComplete(new OnComplete<Optional<NormalizedNodeMessage>>() {
             @Override
-            public void onComplete(Throwable throwable, Optional<NormalizedNodeMessage> normalizedNodeMessage) throws Throwable {
+            public void onComplete(final Throwable throwable,
+                                   final Optional<NormalizedNodeMessage> normalizedNodeMessage) throws Throwable {
                 if (throwable == null) {
                     if (normalizedNodeMessage.isPresent()) {
-                        settableFuture.set(normalizedNodeMessage.transform(new Function<NormalizedNodeMessage, NormalizedNode<?, ?>>() {
+                        settableFuture.set(normalizedNodeMessage.transform(new Function<NormalizedNodeMessage,
+                                NormalizedNode<?, ?>>() {
+
                             @Nullable
                             @Override
-                            public NormalizedNode<?, ?> apply(NormalizedNodeMessage input) {
+                            public NormalizedNode<?, ?> apply(final NormalizedNodeMessage input) {
                                 return input.getNode();
                             }
                         }));
@@ -78,10 +92,15 @@ public class ProxyReadOnlyTransaction implements DOMDataReadOnlyTransaction{
     }
 
     @Override
-    public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+    public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
+                                                              final YangInstanceIdentifier path) {
+
+        LOG.trace("{}: Exists {} via NETCONF: {}", id, store, path);
+
         final Future<Boolean> existsFuture = delegate.exists(store, path);
         final SettableFuture<Boolean> settableFuture = SettableFuture.create();
-        final CheckedFuture<Boolean, ReadFailedException> checkedFuture = Futures.makeChecked(settableFuture, new Function<Exception, ReadFailedException>() {
+        final CheckedFuture<Boolean, ReadFailedException> checkedFuture;
+        checkedFuture = Futures.makeChecked(settableFuture, new Function<Exception, ReadFailedException>() {
             @Nullable
             @Override
             public ReadFailedException apply(Exception cause) {
@@ -90,7 +109,7 @@ public class ProxyReadOnlyTransaction implements DOMDataReadOnlyTransaction{
         });
         existsFuture.onComplete(new OnComplete<Boolean>() {
             @Override
-            public void onComplete(Throwable throwable, Boolean result) throws Throwable {
+            public void onComplete(final Throwable throwable, final Boolean result) throws Throwable {
                 if (throwable == null) {
                     settableFuture.set(result);
                 } else {
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfWriteOnlyTransaction.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/tx/NetconfWriteOnlyTransaction.java
new file mode 100644 (file)
index 0000000..f938748
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.tx;
+
+import akka.actor.ActorSystem;
+import akka.dispatch.OnComplete;
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.Future;
+
+public class NetconfWriteOnlyTransaction implements DOMDataWriteTransaction {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfWriteOnlyTransaction.class);
+
+    private final RemoteDeviceId id;
+    private final NetconfDOMTransaction delegate;
+    private final ActorSystem actorSystem;
+
+    public NetconfWriteOnlyTransaction(final RemoteDeviceId id,
+                                       final ActorSystem actorSystem,
+                                       final NetconfDOMTransaction delegate) {
+        this.id = id;
+        this.delegate = delegate;
+        this.actorSystem = actorSystem;
+    }
+
+    @Override
+    public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path,
+                    final NormalizedNode<?,?> data) {
+        LOG.trace("{}: Write {} via NETCONF: {} with payload {}", id, store, path, data);
+
+        delegate.put(store, new NormalizedNodeMessage(path, data));
+    }
+
+    @Override
+    public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path,
+                      final NormalizedNode<?,?> data) {
+        LOG.trace("{}: Merge {} via NETCONF: {} with payload {}", id, store, path, data);
+
+        delegate.merge(store, new NormalizedNodeMessage(path, data));
+    }
+
+    @Override
+    public boolean cancel() {
+        LOG.trace("{}: Cancel", id);
+
+        return delegate.cancel();
+    }
+
+    @Override
+    public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        LOG.trace("{}: Delete {} via NETCONF: {}", id, store, path);
+
+        delegate.delete(store, path);
+    }
+
+    @Override
+    public CheckedFuture<Void, TransactionCommitFailedException> submit() {
+        LOG.trace("{}: Submit", id);
+
+        final Future<Void> submit = delegate.submit();
+        final SettableFuture<Void> settFuture = SettableFuture.create();
+        final CheckedFuture<Void, TransactionCommitFailedException> checkedFuture;
+        checkedFuture = Futures.makeChecked(settFuture, new Function<Exception, TransactionCommitFailedException>() {
+            @Nullable
+            @Override
+            public TransactionCommitFailedException apply(Exception input) {
+                return new TransactionCommitFailedException("Transaction commit failed", input);
+            }
+        });
+        submit.onComplete(new OnComplete<Void>() {
+            @Override
+            public void onComplete(Throwable throwable, Void object) throws Throwable {
+                if (throwable == null) {
+                    settFuture.set(object);
+                } else {
+                    settFuture.setException(throwable);
+                }
+            }
+        }, actorSystem.dispatcher());
+        return checkedFuture;
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<TransactionStatus>> commit() {
+        LOG.trace("{}: Commit", id);
+
+        final Future<Void> commit = delegate.submit();
+        final SettableFuture<RpcResult<TransactionStatus>> settFuture = SettableFuture.create();
+        commit.onComplete(new OnComplete<Void>() {
+            @Override
+            public void onComplete(final Throwable throwable, final Void result) throws Throwable {
+                if (throwable == null) {
+                    TransactionStatus status = TransactionStatus.SUBMITED;
+                    RpcResult<TransactionStatus> rpcResult = RpcResultBuilder.success(status).build();
+                    settFuture.set(rpcResult);
+                } else {
+                    settFuture.setException(throwable);
+                }
+            }
+        }, actorSystem.dispatcher());
+        return settFuture;
+    }
+
+    @Override
+    public Object getIdentifier() {
+        return this;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfConnectorDTO.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfConnectorDTO.java
new file mode 100644 (file)
index 0000000..0657878
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.utils;
+
+import org.opendaylight.netconf.client.NetconfClientSessionListener;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+
+public class NetconfConnectorDTO implements AutoCloseable {
+
+    private final NetconfDeviceCommunicator communicator;
+    private final RemoteDeviceHandler<NetconfSessionPreferences> facade;
+
+    public NetconfConnectorDTO(final NetconfDeviceCommunicator communicator,
+                               final RemoteDeviceHandler<NetconfSessionPreferences> facade) {
+        this.communicator = communicator;
+        this.facade = facade;
+    }
+
+    public NetconfDeviceCommunicator getCommunicator() {
+        return communicator;
+    }
+
+    public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
+        return facade;
+    }
+
+    public NetconfClientSessionListener getSessionListener() {
+        return communicator;
+    }
+
+    @Override
+    public void close() throws Exception {
+        if (communicator != null) {
+            communicator.close();
+        }
+        if (facade != null) {
+            facade.close();
+        }
+    }
+}
\ No newline at end of file
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologySetup.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologySetup.java
new file mode 100644 (file)
index 0000000..d607f33
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.utils;
+
+import akka.actor.ActorSystem;
+import io.netty.util.concurrent.EventExecutor;
+import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
+import org.opendaylight.controller.config.threadpool.ThreadPool;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NetconfTopologySetup {
+
+    private final ClusterSingletonServiceProvider clusterSingletonServiceProvider;
+    private final RpcProviderRegistry rpcProviderRegistry;
+    private final DataBroker dataBroker;
+    private final InstanceIdentifier<Node> instanceIdentifier;
+    private final Node node;
+    private final BindingAwareBroker bindingAwareBroker;
+    private final ScheduledThreadPool keepaliveExecutor;
+    private final ThreadPool processingExecutor;
+    private final Broker domBroker;
+    private final ActorSystem actorSystem;
+    private final EventExecutor eventExecutor;
+    private final NetconfClientDispatcher netconfClientDispatcher;
+    private final String topologyId;
+    private NetconfTopologySetup(final NetconfTopologySetupBuilder builder) {
+        this.clusterSingletonServiceProvider = builder.getClusterSingletonServiceProvider();
+        this.rpcProviderRegistry = builder.getRpcProviderRegistry();
+        this.dataBroker = builder.getDataBroker();
+        this.instanceIdentifier = builder.getInstanceIdentifier();
+        this.node = builder.getNode();
+        this.bindingAwareBroker = builder.getBindingAwareBroker();
+        this.keepaliveExecutor = builder.getKeepaliveExecutor();
+        this.processingExecutor = builder.getProcessingExecutor();
+        this.domBroker = builder.getDomBroker();
+        this.actorSystem = builder.getActorSystem();
+        this.eventExecutor = builder.getEventExecutor();
+        this.netconfClientDispatcher = builder.getNetconfClientDispatcher();
+        this.topologyId = builder.getTopologyId();
+    }
+
+    public ClusterSingletonServiceProvider getClusterSingletonServiceProvider() {
+        return clusterSingletonServiceProvider;
+    }
+
+    public RpcProviderRegistry getRpcProviderRegistry() {
+        return rpcProviderRegistry;
+    }
+
+    public DataBroker getDataBroker() {
+        return dataBroker;
+    }
+
+    public InstanceIdentifier<Node> getInstanceIdentifier() {
+        return instanceIdentifier;
+    }
+
+    public Node getNode() {
+        return node;
+    }
+
+    public BindingAwareBroker getBindingAwareBroker() {
+        return bindingAwareBroker;
+    }
+
+    public ThreadPool getProcessingExecutor() {
+        return processingExecutor;
+    }
+
+    public ScheduledThreadPool getKeepaliveExecutor() {
+        return keepaliveExecutor;
+    }
+
+    public Broker getDomBroker() {
+        return domBroker;
+    }
+
+    public ActorSystem getActorSystem() {
+        return actorSystem;
+    }
+
+    public EventExecutor getEventExecutor() {
+        return eventExecutor;
+    }
+
+    public String getTopologyId() {
+        return topologyId;
+    }
+
+    public NetconfClientDispatcher getNetconfClientDispatcher() {
+        return netconfClientDispatcher;
+    }
+
+    public static class NetconfTopologySetupBuilder {
+
+        private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
+        private RpcProviderRegistry rpcProviderRegistry;
+        private DataBroker dataBroker;
+        private InstanceIdentifier<Node> instanceIdentifier;
+        private Node node;
+        private BindingAwareBroker bindingAwareBroker;
+        private ScheduledThreadPool keepaliveExecutor;
+        private ThreadPool processingExecutor;
+        private Broker domBroker;
+        private ActorSystem actorSystem;
+        private EventExecutor eventExecutor;
+        private String topologyId;
+        private NetconfClientDispatcher netconfClientDispatcher;
+
+        public NetconfTopologySetupBuilder(){
+        }
+
+        private ClusterSingletonServiceProvider getClusterSingletonServiceProvider() {
+            return clusterSingletonServiceProvider;
+        }
+
+        public NetconfTopologySetupBuilder setClusterSingletonServiceProvider(
+                final ClusterSingletonServiceProvider clusterSingletonServiceProvider) {
+            this.clusterSingletonServiceProvider = clusterSingletonServiceProvider;
+            return this;
+        }
+
+        private RpcProviderRegistry getRpcProviderRegistry() {
+            return rpcProviderRegistry;
+        }
+
+        public NetconfTopologySetupBuilder setRpcProviderRegistry(final RpcProviderRegistry rpcProviderRegistry) {
+            this.rpcProviderRegistry = rpcProviderRegistry;
+            return this;
+        }
+
+        private DataBroker getDataBroker() {
+            return dataBroker;
+        }
+
+        public NetconfTopologySetupBuilder setDataBroker(final DataBroker dataBroker) {
+            this.dataBroker = dataBroker;
+            return this;
+        }
+
+        private InstanceIdentifier<Node> getInstanceIdentifier() {
+            return instanceIdentifier;
+        }
+
+        public NetconfTopologySetupBuilder setInstanceIdentifier(final InstanceIdentifier<Node> instanceIdentifier) {
+            this.instanceIdentifier = instanceIdentifier;
+            return this;
+        }
+
+        public Node getNode() {
+            return node;
+        }
+
+        public NetconfTopologySetupBuilder setNode(final Node node) {
+            this.node = node;
+            return this;
+        }
+
+        public NetconfTopologySetup build() {
+            return new NetconfTopologySetup(this);
+        }
+
+        private BindingAwareBroker getBindingAwareBroker() {
+            return bindingAwareBroker;
+        }
+
+        public NetconfTopologySetupBuilder setBindingAwareBroker(BindingAwareBroker bindingAwareBroker) {
+            this.bindingAwareBroker = bindingAwareBroker;
+            return this;
+        }
+
+        private ScheduledThreadPool getKeepaliveExecutor() {
+            return keepaliveExecutor;
+        }
+
+        public NetconfTopologySetupBuilder setKeepaliveExecutor(ScheduledThreadPool keepaliveExecutor) {
+            this.keepaliveExecutor = keepaliveExecutor;
+            return this;
+        }
+
+        private ThreadPool getProcessingExecutor() {
+            return processingExecutor;
+        }
+
+        public NetconfTopologySetupBuilder setProcessingExecutor(ThreadPool processingExecutor) {
+            this.processingExecutor = processingExecutor;
+            return this;
+        }
+
+        private Broker getDomBroker() {
+            return domBroker;
+        }
+
+        public NetconfTopologySetupBuilder setDomBroker(Broker domBroker) {
+            this.domBroker = domBroker;
+            return this;
+        }
+
+        private ActorSystem getActorSystem() {
+            return actorSystem;
+        }
+
+        public NetconfTopologySetupBuilder setActorSystem(ActorSystem actorSystem) {
+            this.actorSystem = actorSystem;
+            return this;
+        }
+
+        private EventExecutor getEventExecutor() {
+            return eventExecutor;
+        }
+
+        public NetconfTopologySetupBuilder setEventExecutor(EventExecutor eventExecutor) {
+            this.eventExecutor = eventExecutor;
+            return this;
+        }
+
+        private String getTopologyId() {
+            return topologyId;
+        }
+
+        public NetconfTopologySetupBuilder setTopologyId(String topologyId) {
+            this.topologyId = topologyId;
+            return this;
+        }
+
+        private NetconfClientDispatcher getNetconfClientDispatcher() {
+            return netconfClientDispatcher;
+        }
+
+        public NetconfTopologySetupBuilder setNetconfClientDispatcher(NetconfClientDispatcher clientDispatcher) {
+            this.netconfClientDispatcher = clientDispatcher;
+            return this;
+        }
+
+        public static NetconfTopologySetupBuilder create() {
+            return new NetconfTopologySetupBuilder();
+        }
+    }
+
+
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologyUtils.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologyUtils.java
new file mode 100644 (file)
index 0000000..5114fae
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.utils;
+
+import akka.cluster.Member;
+import akka.util.Timeout;
+import java.io.File;
+import java.math.BigDecimal;
+import java.net.InetSocketAddress;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
+import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
+import scala.concurrent.duration.Duration;
+
+public class NetconfTopologyUtils {
+
+    private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector";
+
+    public static final Timeout TIMEOUT = new Timeout(Duration.create(10, "seconds"));
+
+    public static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
+    public static final int DEFAULT_KEEPALIVE_DELAY = 0;
+    public static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
+    public static final int DEFAULT_CONCURRENT_RPC_LIMIT = 0;
+    public static final int DEFAULT_MAX_CONNECTION_ATTEMPTS = 0;
+    public static final int DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS = 2000;
+    public static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
+    public static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
+
+
+    // The default cache directory relative to <code>CACHE_DIRECTORY</code>
+
+    public static final String DEFAULT_CACHE_DIRECTORY = "schema";
+
+    // Filesystem based caches are stored relative to the cache directory.
+    public static final String CACHE_DIRECTORY = "cache";
+
+    // The qualified schema cache directory <code>cache/schema</code>
+    public static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY =
+            CACHE_DIRECTORY + File.separator + DEFAULT_CACHE_DIRECTORY;
+
+    // The default schema repository in the case that one is not specified.
+    public static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY =
+            new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME);
+
+
+     // The default <code>FilesystemSchemaSourceCache</code>, which stores cached files in <code>cache/schema</code>.
+    public static final FilesystemSchemaSourceCache<YangTextSchemaSource> DEFAULT_CACHE =
+            new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class,
+                    new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY));
+
+    // The default factory for creating <code>SchemaContext</code> instances.
+    public static final SchemaContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY =
+            DEFAULT_SCHEMA_REPOSITORY.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
+
+    public static RemoteDeviceId createRemoteDeviceId(final NodeId nodeId, final NetconfNode node) {
+        IpAddress ipAddress = node.getHost().getIpAddress();
+        InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
+                ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
+                node.getPort().getValue());
+        return new RemoteDeviceId(nodeId.getValue(), address);
+    }
+
+    public static String createActorPath(String masterMember, String name) {
+        return  masterMember + "/user/" + name;
+    }
+
+    public static String createMasterActorName(String name, String masterAddress) {
+        return masterAddress.replaceAll("//", "") + "_" + name;
+    }
+
+    public static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
+        if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
+
+            final Identifier key = ((InstanceIdentifier.IdentifiableItem) pathArgument).getKey();
+            if (key instanceof NodeKey) {
+                return ((NodeKey) key).getNodeId();
+            }
+        }
+        throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
+    }
+
+    public static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
+        final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
+        return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
+    }
+
+    public static InstanceIdentifier<Node> createTopologyNodeListPath(final NodeKey key, final String topologyId) {
+        return createTopologyListPath(topologyId)
+                .child(Node.class, new NodeKey(new NodeId(key.getNodeId().getValue())));
+    }
+
+    public static InstanceIdentifier<Node> createTopologyNodePath(final String topologyId) {
+        return createTopologyListPath(topologyId).child(Node.class);
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/AskForMasterMountPoint.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/AskForMasterMountPoint.java
new file mode 100644 (file)
index 0000000..4d56e1f
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages;
+
+import java.io.Serializable;
+
+/**
+ * After master is connected, slaves send the message to master and master triggers registering slave mount point
+ * with reply 'RegisterMountPoint' which includes needed parameters.
+ */
+public class AskForMasterMountPoint implements Serializable {
+    private static final long serialVersionUID = 1L;
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/CreateInitialMasterActorData.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/CreateInitialMasterActorData.java
new file mode 100644 (file)
index 0000000..bab9056
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages;
+
+import java.io.Serializable;
+import java.util.List;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+
+/**
+ * Master sends this message to the own actor to set necessary parameters.
+ */
+public class CreateInitialMasterActorData implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private final DOMDataBroker deviceDataBroker;
+    private final List<SourceIdentifier> allSourceIdentifiers;
+
+    public CreateInitialMasterActorData(final DOMDataBroker deviceDataBroker,
+                                        final List<SourceIdentifier> allSourceIdentifiers) {
+        this.deviceDataBroker = deviceDataBroker;
+        this.allSourceIdentifiers = allSourceIdentifiers;
+    }
+
+    public DOMDataBroker getDeviceDataBroker() {
+        return deviceDataBroker;
+    }
+
+    public List<SourceIdentifier> getSourceIndentifiers() {
+        return allSourceIdentifiers;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/MasterActorDataInitialized.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/MasterActorDataInitialized.java
new file mode 100644 (file)
index 0000000..fa5482b
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages;
+
+import java.io.Serializable;
+
+/**
+ * Due to possibility of race condition (when data-store is updated before data are initialized in master actor), only
+ * when this message is received by master, operational data-store is changed.
+ */
+public class MasterActorDataInitialized implements Serializable {
+    private static final long serialVersionUID = 1L;
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/NormalizedNodeMessage.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/NormalizedNodeMessage.java
new file mode 100644 (file)
index 0000000..b4ede5b
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.opendaylight.controller.cluster.datastore.utils.SerializationUtils;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Message which holds node data, prepared to sending between remote hosts with serialization.
+ */
+public class NormalizedNodeMessage implements Externalizable {
+    private static final long serialVersionUID = 1L;
+
+    private YangInstanceIdentifier identifier = null;
+    private NormalizedNode<?, ?> node = null;
+
+    public NormalizedNodeMessage() {
+        // empty constructor needed for Externalizable
+    }
+
+    public NormalizedNodeMessage(final YangInstanceIdentifier identifier, final NormalizedNode<?, ?> node) {
+        this.identifier = identifier;
+        this.node = node;
+    }
+
+    public YangInstanceIdentifier getIdentifier() {
+        return identifier;
+    }
+
+    public NormalizedNode<?, ?> getNode() {
+        return node;
+    }
+
+    @Override
+    public void writeExternal(final ObjectOutput out) throws IOException {
+        SerializationUtils.serializePathAndNode(getIdentifier(), node, out);
+    }
+
+    @Override
+    public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+        SerializationUtils.deserializePathAndNode(in, this, APPLIER);
+    }
+
+    private static final SerializationUtils.Applier<NormalizedNodeMessage> APPLIER = (instance, path, node) -> {
+        instance.identifier = path;
+        instance.node = node;
+    };
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/RefreshSetupMasterActorData.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/RefreshSetupMasterActorData.java
new file mode 100644 (file)
index 0000000..fbc43f7
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages;
+
+import java.io.Serializable;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+
+/**
+ * Master sends this message to the own actor to refresh setup data
+ */
+public class RefreshSetupMasterActorData implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private final NetconfTopologySetup netconfTopologyDeviceSetup;
+    private final RemoteDeviceId remoteDeviceId;
+
+    public RefreshSetupMasterActorData(final NetconfTopologySetup netconfTopologyDeviceSetup,
+                                       final RemoteDeviceId remoteDeviceId) {
+        this.netconfTopologyDeviceSetup = netconfTopologyDeviceSetup;
+        this.remoteDeviceId = remoteDeviceId;
+    }
+
+    public NetconfTopologySetup getNetconfTopologyDeviceSetup() {
+        return netconfTopologyDeviceSetup;
+    }
+
+    public RemoteDeviceId getRemoteDeviceId() {
+        return remoteDeviceId;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/RegisterMountPoint.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/RegisterMountPoint.java
new file mode 100644 (file)
index 0000000..0023103
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages;
+
+import java.io.Serializable;
+import java.util.List;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+
+/**
+ * Master sends the message to slave with necessary parameters for creating slave mount point.
+ */
+public class RegisterMountPoint implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private final List<SourceIdentifier> allSourceIdentifiers;
+
+    public RegisterMountPoint(final List<SourceIdentifier> allSourceIdentifiers) {
+        this.allSourceIdentifiers = allSourceIdentifiers;
+    }
+
+    public List<SourceIdentifier> getSourceIndentifiers() {
+        return allSourceIdentifiers;
+    }
+
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/UnregisterSlaveMountPoint.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/UnregisterSlaveMountPoint.java
new file mode 100644 (file)
index 0000000..303f0b4
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages;
+
+import java.io.Serializable;
+
+/**
+ * Slave sends the message when unregisters slave mount point (in NetconfNodeManager
+ * close method). Message must be sended before slave actor is poisoned.
+ */
+public class UnregisterSlaveMountPoint implements Serializable {
+    private static final long serialVersionUID = 1L;
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/YangTextSchemaSourceRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/YangTextSchemaSourceRequest.java
new file mode 100644 (file)
index 0000000..ffc3d13
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages;
+
+import java.io.Serializable;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+
+/**
+ * Slave sends message to master when tries to resolve schema with particular sourceIdentifier (proxy call).
+ * Master responds with resolved schema source.
+ */
+public class YangTextSchemaSourceRequest implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private final SourceIdentifier sourceIdentifier;
+
+    public YangTextSchemaSourceRequest(final SourceIdentifier sourceIdentifier) {
+        this.sourceIdentifier = sourceIdentifier;
+    }
+
+    public SourceIdentifier getSourceIdentifier() {
+        return sourceIdentifier;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/CancelRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/CancelRequest.java
new file mode 100644 (file)
index 0000000..7a73fe2
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+public class CancelRequest implements TransactionRequest {
+    private static final long serialVersionUID = 1L;
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/DeleteRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/DeleteRequest.java
new file mode 100644 (file)
index 0000000..1548dc7
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class DeleteRequest implements TransactionRequest {
+    private static final long serialVersionUID = 1L;
+
+    private final LogicalDatastoreType store;
+    private final YangInstanceIdentifier path;
+
+    public DeleteRequest(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        this.store = store;
+        this.path = path;
+    }
+
+    public LogicalDatastoreType getStore() {
+        return store;
+    }
+
+    public YangInstanceIdentifier getPath() {
+        return path;
+    }
+}
@@ -1,17 +1,18 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util.messages;
+package org.opendaylight.netconf.topology.singleton.messages.transactions;
 
 import java.io.Serializable;
 
-public class AnnounceMasterMountPoint implements Serializable {
+/**
+ * Message is sended when read result do not present any value.
+ */
+public class EmptyReadResponse implements Serializable {
     private static final long serialVersionUID = 1L;
-
-    public AnnounceMasterMountPoint() {}
 }
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/ExistsRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/ExistsRequest.java
new file mode 100644 (file)
index 0000000..b5fae5f
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class ExistsRequest implements TransactionRequest {
+    private static final long serialVersionUID = 1L;
+
+    private final LogicalDatastoreType store;
+    private final YangInstanceIdentifier path;
+
+    public ExistsRequest(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        this.store = store;
+        this.path = path;
+    }
+
+    public LogicalDatastoreType getStore() {
+        return store;
+    }
+
+    public YangInstanceIdentifier getPath() {
+        return path;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/MergeRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/MergeRequest.java
new file mode 100644 (file)
index 0000000..8c03023
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
+
+public class MergeRequest implements TransactionRequest {
+    private static final long serialVersionUID = 1L;
+
+    private final NormalizedNodeMessage data;
+    private final LogicalDatastoreType store;
+
+    public MergeRequest(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
+        this.store = store;
+        this.data = data;
+    }
+
+    public NormalizedNodeMessage getNormalizedNodeMessage() {
+        return data;
+    }
+
+    public LogicalDatastoreType getStore() {
+        return store;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/PutRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/PutRequest.java
new file mode 100644 (file)
index 0000000..41de9c2
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
+
+public class PutRequest implements TransactionRequest {
+    private static final long serialVersionUID = 1L;
+
+    private final LogicalDatastoreType store;
+    private final NormalizedNodeMessage data;
+
+    public PutRequest(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
+        this.store = store;
+        this.data = data;
+    }
+
+    public NormalizedNodeMessage getNormalizedNodeMessage() {
+        return data;
+    }
+
+    public LogicalDatastoreType getStore() {
+        return store;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/ReadRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/ReadRequest.java
new file mode 100644 (file)
index 0000000..d950f28
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class ReadRequest implements TransactionRequest {
+    private static final long serialVersionUID = 1L;
+
+    private final LogicalDatastoreType store;
+    private final YangInstanceIdentifier path;
+
+    public ReadRequest(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        this.store = store;
+        this.path = path;
+    }
+
+    public LogicalDatastoreType getStore() {
+        return store;
+    }
+
+    public YangInstanceIdentifier getPath() {
+        return path;
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/SubmitFailedReply.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/SubmitFailedReply.java
new file mode 100644 (file)
index 0000000..fe077e2
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+import java.io.Serializable;
+
+/**
+ * Message sent from master back to the slave when submit is not performed, tx is closed
+ */
+public class SubmitFailedReply implements Serializable {
+    private static final long serialVersionUID = 1L;
+}
@@ -1,19 +1,18 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.util.messages;
+package org.opendaylight.netconf.topology.singleton.messages.transactions;
 
 import java.io.Serializable;
 
-public class AnnounceMasterMountPointDown implements Serializable {
+/**
+ * Message sent from master back to the slave when submit is successfully performed.
+ */
+public class SubmitReply implements Serializable {
     private static final long serialVersionUID = 1L;
-
-    public AnnounceMasterMountPointDown() {
-
-    }
 }
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/SubmitRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/SubmitRequest.java
new file mode 100644 (file)
index 0000000..6b6af7e
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+public class SubmitRequest implements TransactionRequest {
+    private static final long serialVersionUID = 1L;
+}
diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/TransactionRequest.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/messages/transactions/TransactionRequest.java
new file mode 100644 (file)
index 0000000..b5ef9f1
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.messages.transactions;
+
+import java.io.Serializable;
+
+/**
+ * API for transaction request messages, slave sends these message types to master for performing required operation.
+ * This interface helps better handle request messages in actor. All messages are send with operations defined in
+ * NetconfProxyDOMTransaction. Messages requiring response are send by ask otherwise with tell.
+ */
+public interface TransactionRequest extends Serializable {
+}
diff --git a/netconf/netconf-topology-singleton/src/main/resources/org/opendaylight/blueprint/netconf-topology-singleton.xml b/netconf/netconf-topology-singleton/src/main/resources/org/opendaylight/blueprint/netconf-topology-singleton.xml
new file mode 100644 (file)
index 0000000..8fced19
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright Â© 2016 Cisco Systems, Inc. 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
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+           odl:use-default-for-reference-types="true">
+
+    <reference id="dataBroker"
+               interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
+    <reference id="rpcRegistry"
+               interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"/>
+    <reference id="clusterSingletonService"
+               interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/>
+    <reference id="bindingAwareBroker"
+               interface="org.opendaylight.controller.sal.binding.api.BindingAwareBroker"/>
+    <reference id="keepAliveExecutor"
+               interface="org.opendaylight.controller.config.threadpool.ScheduledThreadPool"/>
+    <reference id="processingExecutor"
+               interface="org.opendaylight.controller.config.threadpool.ThreadPool"/>
+    <reference id="domBroker"
+               interface="org.opendaylight.controller.sal.core.api.Broker"/>
+    <reference id="actorSystemProvider"
+               interface="org.opendaylight.controller.cluster.ActorSystemProvider"/>
+    <reference id="eventExecutor"
+               interface="io.netty.util.concurrent.EventExecutor"
+               odl:type="global-event-executor"/>
+    <reference id="clientDispatcherDependency"
+               interface="org.opendaylight.netconf.client.NetconfClientDispatcher"/>
+
+    <bean id="netconfTopologyManager"
+          class="org.opendaylight.netconf.topology.singleton.impl.NetconfTopologyManager"
+          init-method="init" destroy-method="close">
+        <argument ref="dataBroker"/>
+        <argument ref="rpcRegistry"/>
+        <argument ref="clusterSingletonService"/>
+        <argument ref="bindingAwareBroker"/>
+        <argument ref="keepAliveExecutor"/>
+        <argument ref="processingExecutor"/>
+        <argument ref="domBroker"/>
+        <argument ref="actorSystemProvider"/>
+        <argument ref="eventExecutor"/>
+        <argument ref="clientDispatcherDependency"/>
+        <argument value="topology-netconf"/>
+    </bean>
+    <service ref="netconfTopologyManager"
+             interface="org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService"/>
+
+</blueprint>
diff --git a/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfNodeActorTest.java b/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfNodeActorTest.java
new file mode 100644 (file)
index 0000000..a77104e
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY;
+
+import akka.actor.ActorContext;
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.pattern.Patterns;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import akka.util.Timeout;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.controller.cluster.schema.provider.impl.YangTextSchemaSourceSerializationProxy;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.netconf.topology.singleton.messages.AskForMasterMountPoint;
+import org.opendaylight.netconf.topology.singleton.messages.CreateInitialMasterActorData;
+import org.opendaylight.netconf.topology.singleton.messages.MasterActorDataInitialized;
+import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
+import org.opendaylight.netconf.topology.singleton.messages.RegisterMountPoint;
+import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
+
+public class NetconfNodeActorTest {
+
+    private static final Timeout TIMEOUT = new Timeout(Duration.create(5, "seconds"));
+    private static ActorSystem system;
+
+    @Rule
+    public final ExpectedException exception = ExpectedException.none();
+
+    private ActorRef masterRef;
+    private RemoteDeviceId remoteDeviceId;
+
+    @Before
+    public void setup() throws UnknownHostException {
+
+        remoteDeviceId = new RemoteDeviceId("netconf-topology",
+                new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999));
+
+        final NetconfTopologySetup setup = mock(NetconfTopologySetup.class);
+
+        final Props props = NetconfNodeActor.props(setup, remoteDeviceId, DEFAULT_SCHEMA_REPOSITORY,
+                DEFAULT_SCHEMA_REPOSITORY);
+
+        system = ActorSystem.create();
+
+        masterRef = TestActorRef.create(system, props, "master_messages");
+    }
+
+    @After
+    public void teardown() {
+        JavaTestKit.shutdownActorSystem(system);
+        system = null;
+    }
+
+    @Test
+    public void testInitDataMessages() throws Exception {
+
+        final DOMDataBroker domDataBroker = mock(DOMDataBroker.class);
+        final List<SourceIdentifier> sourceIdentifiers = Lists.newArrayList();
+
+        /* Test init master data */
+
+        final Future<Object> initialDataToActor =
+                Patterns.ask(masterRef, new CreateInitialMasterActorData(domDataBroker, sourceIdentifiers),
+                        TIMEOUT);
+
+        final Object success = Await.result(initialDataToActor, TIMEOUT.duration());
+        assertTrue(success instanceof MasterActorDataInitialized);
+
+
+        /* Test refresh master data */
+
+        final RemoteDeviceId remoteDeviceId2 = new RemoteDeviceId("netconf-topology2",
+                new InetSocketAddress(InetAddress.getByName("127.0.0.2"), 9999));
+
+        final NetconfTopologySetup setup2 = mock(NetconfTopologySetup.class);
+
+        final Future<Object> refreshDataToActor =
+                Patterns.ask(masterRef, new RefreshSetupMasterActorData(setup2, remoteDeviceId2),
+                        TIMEOUT);
+
+        final Object success2 = Await.result(refreshDataToActor, TIMEOUT.duration());
+        assertTrue(success2 instanceof MasterActorDataInitialized);
+
+    }
+
+    @Test
+    public void testRegisterMountPointMessage() throws Exception {
+
+        final DOMDataBroker domDataBroker = mock(DOMDataBroker.class);
+        final List<SourceIdentifier> sourceIdentifiers =
+                Lists.newArrayList(SourceIdentifier.create("testID", Optional.absent()));
+
+        // init master data
+
+        final Future<Object> initialDataToActor =
+                Patterns.ask(masterRef, new CreateInitialMasterActorData(domDataBroker, sourceIdentifiers),
+                        TIMEOUT);
+
+        final Object successInit = Await.result(initialDataToActor, TIMEOUT.duration());
+
+        assertTrue(successInit instanceof MasterActorDataInitialized);
+
+        // test if slave get right identifiers from master
+
+        final Future<Object> registerMountPointFuture =
+                Patterns.ask(masterRef, new AskForMasterMountPoint(),
+                        TIMEOUT);
+
+        final RegisterMountPoint success =
+                (RegisterMountPoint) Await.result(registerMountPointFuture, TIMEOUT.duration());
+
+        assertEquals(sourceIdentifiers, success.getSourceIndentifiers());
+
+    }
+
+    @Test
+    public void testYangTextSchemaSourceRequestMessage() throws Exception {
+        final SchemaRepository schemaRepository = mock(SchemaRepository.class);
+        final SourceIdentifier sourceIdentifier = SourceIdentifier.create("testID", Optional.absent());
+        final Props props = NetconfNodeActor.props(mock(NetconfTopologySetup.class), remoteDeviceId,
+                DEFAULT_SCHEMA_REPOSITORY, schemaRepository);
+
+        final ActorRef actorRefSchemaRepo = TestActorRef.create(system, props, "master_mocked_schema_repository");
+        final ActorContext actorContext = mock(ActorContext.class);
+        doReturn(system.dispatcher()).when(actorContext).dispatcher();
+
+        final ProxyYangTextSourceProvider proxyYang =
+                new ProxyYangTextSourceProvider(actorRefSchemaRepo, actorContext);
+        // test if asking for source is resolved and sended back
+
+        final YangTextSchemaSource yangTextSchemaSource = new YangTextSchemaSource(sourceIdentifier) {
+            @Override
+            protected MoreObjects.ToStringHelper addToStringAttributes(MoreObjects.ToStringHelper toStringHelper) {
+                return null;
+            }
+
+            @Override
+            public InputStream openStream() throws IOException {
+                return new ByteArrayInputStream("YANG".getBytes());
+            }
+        };
+
+
+        final CheckedFuture<YangTextSchemaSource, SchemaSourceException> result =
+                Futures.immediateCheckedFuture(yangTextSchemaSource);
+
+        doReturn(result).when(schemaRepository).getSchemaSource(sourceIdentifier, YangTextSchemaSource.class);
+
+        final Future<YangTextSchemaSourceSerializationProxy> resolvedSchema =
+                proxyYang.getYangTextSchemaSource(sourceIdentifier);
+
+        final YangTextSchemaSourceSerializationProxy success = Await.result(resolvedSchema, TIMEOUT.duration());
+
+        assertEquals(sourceIdentifier, success.getRepresentation().getIdentifier());
+        assertEquals("YANG", convertStreamToString(success.getRepresentation().openStream()));
+
+
+        // test if asking for source is missing
+        exception.expect(MissingSchemaSourceException.class);
+
+        final SchemaSourceException schemaSourceException =
+                new MissingSchemaSourceException("Fail", sourceIdentifier);
+
+        final CheckedFuture<YangTextSchemaSource, SchemaSourceException> resultFail =
+                Futures.immediateFailedCheckedFuture(schemaSourceException);
+
+        doReturn(resultFail).when(schemaRepository).getSchemaSource(sourceIdentifier, YangTextSchemaSource.class);
+
+        final Future<YangTextSchemaSourceSerializationProxy> failedSchema =
+                proxyYang.getYangTextSchemaSource(sourceIdentifier);
+
+        Await.result(failedSchema, TIMEOUT.duration());
+
+    }
+
+    private String convertStreamToString(java.io.InputStream is) {
+        java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
+        return s.hasNext() ? s.next() : "";
+    }
+
+}
diff --git a/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManagerTest.java b/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManagerTest.java
new file mode 100644 (file)
index 0000000..9a3749c
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import static junit.framework.TestCase.assertFalse;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+import static org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType.DELETE;
+import static org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType.WRITE;
+
+import com.google.common.util.concurrent.Futures;
+import io.netty.util.concurrent.EventExecutor;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.cluster.ActorSystemProvider;
+import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
+import org.opendaylight.controller.config.threadpool.ThreadPool;
+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.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.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
+import org.opendaylight.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NetconfTopologyManagerTest {
+
+    private final String topologyId = "topologyID";
+    private NetconfTopologyManager netconfTopologyManager;
+
+    @Mock
+    private DataBroker dataBroker;
+
+    @Mock
+    private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+
+        final RpcProviderRegistry rpcProviderRegistry = mock(RpcProviderRegistry.class);
+        final BindingAwareBroker bindingAwareBroker = mock(BindingAwareBroker.class);
+        final ScheduledThreadPool keepaliveExecutor = mock(ScheduledThreadPool.class);
+        final ThreadPool processingExecutor = mock(ThreadPool.class);
+        final Broker domBroker = mock(Broker.class);
+        final ActorSystemProvider actorSystemProvider = mock(ActorSystemProvider.class);
+        final EventExecutor eventExecutor = mock(EventExecutor.class);
+        final NetconfClientDispatcher clientDispatcher = mock(NetconfClientDispatcher.class);
+
+        netconfTopologyManager = new NetconfTopologyManager(dataBroker, rpcProviderRegistry,
+                clusterSingletonServiceProvider, bindingAwareBroker, keepaliveExecutor, processingExecutor, domBroker,
+                actorSystemProvider, eventExecutor, clientDispatcher, topologyId);
+    }
+    @Test
+    public void testWriteConfiguration() throws Exception {
+
+        final ClusterSingletonServiceRegistration clusterRegistration = mock(ClusterSingletonServiceRegistration.class);
+
+        final Field fieldContexts = NetconfTopologyManager.class.getDeclaredField("contexts");
+        fieldContexts.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        final Map<InstanceIdentifier<Node>, NetconfTopologyContext> contexts =
+                (Map<InstanceIdentifier<Node>, NetconfTopologyContext>) fieldContexts.get(netconfTopologyManager);
+
+        final Field fieldClusterRegistrations = NetconfTopologyManager.class.getDeclaredField("clusterRegistrations");
+        fieldClusterRegistrations.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        final Map<InstanceIdentifier<Node>, ClusterSingletonServiceRegistration> clusterRegistrations =
+                (Map<InstanceIdentifier<Node>, ClusterSingletonServiceRegistration>)
+                        fieldClusterRegistrations.get(netconfTopologyManager);
+
+        final Collection<DataTreeModification<Node>> changes = new ArrayList<>();
+
+        final InstanceIdentifier<Node> instanceIdentifier = NetconfTopologyUtils.createTopologyNodeListPath(
+                new NodeKey(new NodeId("node-id-1")),"topology-1");
+
+        final InstanceIdentifier<Node> instanceIdentifierDiferent = NetconfTopologyUtils.createTopologyNodeListPath(
+                new NodeKey(new NodeId("node-id-2")),"topology-2");
+
+        final DataTreeIdentifier<Node> rootIdentifier =
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, instanceIdentifier);
+
+        final DataTreeIdentifier<Node> rootIdentifierDifferent =
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, instanceIdentifierDiferent);
+
+        @SuppressWarnings("unchecked")
+        final DataObjectModification<Node> objectModification = mock(DataObjectModification.class);
+
+        final NetconfNode netconfNode = new NetconfNodeBuilder()
+                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
+                .setPort(new PortNumber(9999))
+                .setReconnectOnChangedSchema(true)
+                .setDefaultRequestTimeoutMillis(1000L)
+                .setBetweenAttemptsTimeoutMillis(100)
+                .setSchemaless(false)
+                .setTcpOnly(false)
+                .build();
+        final Node node = new NodeBuilder().setNodeId(new NodeId("node-id"))
+                .addAugmentation(NetconfNode.class, netconfNode).build();
+
+        final Identifier key = new NodeKey(new NodeId("node-id"));
+
+        @SuppressWarnings("unchecked")
+        final InstanceIdentifier.IdentifiableItem<Node, NodeKey> pathArgument =
+                new InstanceIdentifier.IdentifiableItem(Node.class, key);
+
+
+        // testing WRITE on two identical rootIdentifiers and one different
+
+        changes.add(new CustomTreeModification(rootIdentifier, objectModification));
+        changes.add(new CustomTreeModification(rootIdentifier, objectModification));
+        changes.add(new CustomTreeModification(rootIdentifierDifferent, objectModification));
+
+        doReturn(WRITE).when(objectModification).getModificationType();
+        doReturn(node).when(objectModification).getDataAfter();
+        doReturn(pathArgument).when(objectModification).getIdentifier();
+        doReturn(clusterRegistration).when(clusterSingletonServiceProvider).registerClusterSingletonService(any());
+
+        netconfTopologyManager.onDataTreeChanged(changes);
+
+        verify(clusterSingletonServiceProvider, times(2)).registerClusterSingletonService(any());
+
+        // only two created contexts
+        assertEquals(2, contexts.size());
+        assertTrue(contexts.containsKey(rootIdentifier.getRootIdentifier()));
+        assertTrue(contexts.containsKey(rootIdentifierDifferent.getRootIdentifier()));
+
+        // only two created cluster registrations
+        assertEquals(2, contexts.size());
+        assertTrue(clusterRegistrations.containsKey(rootIdentifier.getRootIdentifier()));
+        assertTrue(clusterRegistrations.containsKey(rootIdentifierDifferent.getRootIdentifier()));
+
+        // after delete there should be no context and clustered registrations
+        doReturn(DELETE).when(objectModification).getModificationType();
+
+        doNothing().when(clusterRegistration).close();
+
+        netconfTopologyManager.onDataTreeChanged(changes);
+
+        verify(clusterRegistration, times(2)).close();
+
+        // empty map of contexts
+        assertTrue(contexts.isEmpty());
+        assertFalse(contexts.containsKey(rootIdentifier.getRootIdentifier()));
+        assertFalse(contexts.containsKey(rootIdentifierDifferent.getRootIdentifier()));
+
+        // empty map of clustered registrations
+        assertTrue(clusterRegistrations.isEmpty());
+        assertFalse(clusterRegistrations.containsKey(rootIdentifier.getRootIdentifier()));
+        assertFalse(clusterRegistrations.containsKey(rootIdentifierDifferent.getRootIdentifier()));
+
+    }
+
+    @Test
+    public void testRegisterDataTreeChangeListener() {
+
+        final WriteTransaction wtx = mock(WriteTransaction.class);
+
+        doReturn(wtx).when(dataBroker).newWriteOnlyTransaction();
+        doNothing().when(wtx).merge(any(), any(), any());
+        doReturn(Futures.immediateCheckedFuture(null)).when(wtx).submit();
+        doReturn(null).when(dataBroker).registerDataChangeListener(any(), any(), any(), any());
+
+        netconfTopologyManager.init();
+
+        // verify if listener is called with right parameters = registered on right path
+
+        verify(dataBroker, times(1)).registerDataTreeChangeListener(
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, NetconfTopologyUtils
+                        .createTopologyListPath(topologyId).child(Node.class)), netconfTopologyManager);
+
+    }
+
+    @Test
+    public void testClose() throws Exception {
+
+        final Field fieldContexts = NetconfTopologyManager.class.getDeclaredField("contexts");
+        fieldContexts.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        final Map<InstanceIdentifier<Node>, NetconfTopologyContext> contexts =
+                (Map<InstanceIdentifier<Node>, NetconfTopologyContext>) fieldContexts.get(netconfTopologyManager);
+
+        final Field fieldClusterRegistrations = NetconfTopologyManager.class.getDeclaredField("clusterRegistrations");
+        fieldClusterRegistrations.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        final Map<InstanceIdentifier<Node>, ClusterSingletonServiceRegistration> clusterRegistrations =
+                (Map<InstanceIdentifier<Node>, ClusterSingletonServiceRegistration>)
+                        fieldClusterRegistrations.get(netconfTopologyManager);
+
+        final InstanceIdentifier<Node> instanceIdentifier = NetconfTopologyUtils.createTopologyNodeListPath(
+                new NodeKey(new NodeId("node-id-1")),"topology-1");
+
+
+        final NetconfTopologyContext context = mock(NetconfTopologyContext.class);
+        final ClusterSingletonServiceRegistration clusterRegistration =
+                mock(ClusterSingletonServiceRegistration.class);
+        contexts.put(instanceIdentifier, context);
+        clusterRegistrations.put(instanceIdentifier, clusterRegistration);
+
+        doNothing().when(context).closeFinal();
+        doNothing().when(clusterRegistration).close();
+
+        netconfTopologyManager.close();
+        verify(context, times(1)).closeFinal();
+        verify(clusterRegistration, times(1)).close();
+
+        assertTrue(contexts.isEmpty());
+        assertTrue(clusterRegistrations.isEmpty());
+
+    }
+
+    private class CustomTreeModification  implements DataTreeModification<Node> {
+
+        private final DataTreeIdentifier<Node> rootPath;
+        private final DataObjectModification<Node> rootNode;
+
+        CustomTreeModification(DataTreeIdentifier<Node> rootPath, DataObjectModification<Node> rootNode) {
+            this.rootPath = rootPath;
+            this.rootNode = rootNode;
+        }
+
+        @Nonnull
+        @Override
+        public DataTreeIdentifier<Node> getRootPath() {
+            return rootPath;
+        }
+
+        @Nonnull
+        @Override
+        public DataObjectModification<Node> getRootNode() {
+            return rootNode;
+        }
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImplTest.java b/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImplTest.java
new file mode 100644 (file)
index 0000000..c1515ab
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import io.netty.util.concurrent.EventExecutor;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.concurrent.ExecutorService;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
+import org.opendaylight.controller.config.threadpool.ThreadPool;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.netconf.client.NetconfClientSessionListener;
+import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
+import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfConnectorDTO;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+
+public class RemoteDeviceConnectorImplTest {
+
+    private static final NodeId NODE_ID = new NodeId("testing-node");
+    private static final String TOPOLOGY_ID = "testing-topology";
+
+    @Mock
+    private DataBroker dataBroker;
+
+    @Mock
+    private RpcProviderRegistry rpcProviderRegistry;
+
+    @Mock
+    private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
+
+    @Mock
+    private BindingAwareBroker bindingAwareBroker;
+
+    @Mock
+    private ScheduledThreadPool keepaliveExecutor;
+
+    @Mock
+    private ThreadPool processingExecutor;
+
+    @Mock
+    private Broker domBroker;
+
+    @Mock
+    private ActorSystem actorSystem;
+
+    @Mock
+    private EventExecutor eventExecutor;
+
+    @Mock
+    private NetconfClientDispatcher clientDispatcher;
+
+    private NetconfTopologySetup.NetconfTopologySetupBuilder builder;
+    private RemoteDeviceId remoteDeviceId;
+
+    @Before
+    public void setUp() throws UnknownHostException {
+        initMocks(this);
+
+        remoteDeviceId = new RemoteDeviceId(TOPOLOGY_ID,
+                new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999));
+
+        builder = new NetconfTopologySetup.NetconfTopologySetupBuilder();
+        builder.setDataBroker(dataBroker);
+        builder.setRpcProviderRegistry(rpcProviderRegistry);
+        builder.setClusterSingletonServiceProvider(clusterSingletonServiceProvider);
+        builder.setBindingAwareBroker(bindingAwareBroker);
+        builder.setKeepaliveExecutor(keepaliveExecutor);
+        builder.setProcessingExecutor(processingExecutor);
+        builder.setDomBroker(domBroker);
+        builder.setActorSystem(actorSystem);
+        builder.setEventExecutor(eventExecutor);
+        builder.setNetconfClientDispatcher(clientDispatcher);
+        builder.setTopologyId(TOPOLOGY_ID);
+
+    }
+
+    @Test
+    public void testStopRemoteDeviceConnection() {
+        final Credentials credentials = new LoginPasswordBuilder().setPassword("admin").setUsername("admin").build();
+        final NetconfNode netconfNode = new NetconfNodeBuilder()
+                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
+                .setPort(new PortNumber(9999))
+                .setReconnectOnChangedSchema(true)
+                .setDefaultRequestTimeoutMillis(1000L)
+                .setBetweenAttemptsTimeoutMillis(100)
+                .setSchemaless(false)
+                .setTcpOnly(false)
+                .setCredentials(credentials)
+                .build();
+        final Node node = new NodeBuilder().setNodeId(NODE_ID).addAugmentation(NetconfNode.class, netconfNode).build();
+
+        builder.setNode(node);
+
+
+        final NetconfDeviceCommunicator communicator = mock (NetconfDeviceCommunicator.class);
+        final RemoteDeviceHandler salFacade = mock(RemoteDeviceHandler.class);
+
+        final TestingRemoteDeviceConnectorImpl remoteDeviceConnection =
+                new TestingRemoteDeviceConnectorImpl(builder.build(), remoteDeviceId, communicator, salFacade);
+
+        final ActorRef masterRef = mock(ActorRef.class);
+
+        remoteDeviceConnection.startRemoteDeviceConnection(masterRef);
+
+        remoteDeviceConnection.stopRemoteDeviceConnection();
+
+        verify(communicator, times(1)).close();
+        verify(salFacade, times(1)).close();
+
+    }
+
+    @Test
+    public void testMasterSalFacade() throws UnknownHostException {
+        final ExecutorService executorService = mock(ExecutorService.class);
+        doReturn(executorService).when(processingExecutor).getExecutor();
+
+        final Credentials credentials = new LoginPasswordBuilder().setPassword("admin").setUsername("admin").build();
+        final NetconfNode netconfNode = new NetconfNodeBuilder()
+                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
+                .setPort(new PortNumber(9999))
+                .setReconnectOnChangedSchema(true)
+                .setDefaultRequestTimeoutMillis(1000L)
+                .setBetweenAttemptsTimeoutMillis(100)
+                .setSchemaless(false)
+                .setTcpOnly(false)
+                .setCredentials(credentials)
+                .build();
+
+        final RemoteDeviceConnectorImpl remoteDeviceConnection =
+                new RemoteDeviceConnectorImpl(builder.build(), remoteDeviceId);
+
+        final ActorRef masterRef = mock(ActorRef.class);
+
+        final NetconfConnectorDTO connectorDTO =
+                remoteDeviceConnection.createDeviceCommunicator(NODE_ID, netconfNode, masterRef);
+
+        assertTrue(connectorDTO.getFacade() instanceof MasterSalFacade);
+    }
+
+    @Test
+    public void testKeapAliveFacade() throws UnknownHostException {
+        final ExecutorService executorService = mock(ExecutorService.class);
+        doReturn(executorService).when(processingExecutor).getExecutor();
+
+        final Credentials credentials = new LoginPasswordBuilder().setPassword("admin").setUsername("admin").build();
+        final NetconfNode netconfNode = new NetconfNodeBuilder()
+                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
+                .setPort(new PortNumber(9999))
+                .setReconnectOnChangedSchema(true)
+                .setDefaultRequestTimeoutMillis(1000L)
+                .setBetweenAttemptsTimeoutMillis(100)
+                .setSchemaless(false)
+                .setTcpOnly(false)
+                .setCredentials(credentials)
+                .setKeepaliveDelay(1L)
+                .build();
+
+        final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(TOPOLOGY_ID,
+                new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999));
+
+        final RemoteDeviceConnectorImpl remoteDeviceConnection =
+                new RemoteDeviceConnectorImpl(builder.build(), remoteDeviceId);
+
+        final ActorRef masterRef = mock(ActorRef.class);
+
+        final NetconfConnectorDTO connectorDTO =
+                remoteDeviceConnection.createDeviceCommunicator(NODE_ID, netconfNode, masterRef);
+
+        assertTrue(connectorDTO.getFacade() instanceof KeepaliveSalFacade);
+    }
+
+    @Test
+    public void testGetClientConfig() throws UnknownHostException {
+        final NetconfClientSessionListener listener = mock(NetconfClientSessionListener.class);
+        final Host host = new Host(new IpAddress(new Ipv4Address("127.0.0.1")));
+        final PortNumber portNumber = new PortNumber(9999);
+        final NetconfNode testingNode = new NetconfNodeBuilder()
+                .setConnectionTimeoutMillis(1000L)
+                .setDefaultRequestTimeoutMillis(2000L)
+                .setHost(host)
+                .setPort(portNumber)
+                .setCredentials(new LoginPasswordBuilder()
+                        .setUsername("testuser")
+                        .setPassword("testpassword").build())
+                .setTcpOnly(true)
+                .build();
+
+        final RemoteDeviceConnectorImpl remoteDeviceConnection =
+                new RemoteDeviceConnectorImpl(builder.build(), remoteDeviceId);
+
+        final NetconfReconnectingClientConfiguration defaultClientConfig =
+                remoteDeviceConnection.getClientConfig(listener, testingNode);
+
+        assertEquals(defaultClientConfig.getConnectionTimeoutMillis().longValue(), 1000L);
+        assertEquals(defaultClientConfig.getAddress(), new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999));
+        assertSame(defaultClientConfig.getSessionListener(), listener);
+        assertEquals(defaultClientConfig.getAuthHandler().getUsername(), "testuser");
+        assertEquals(defaultClientConfig.getProtocol(), NetconfClientConfiguration.NetconfClientProtocol.TCP);
+    }
+
+    @Test
+    public void testSchemaResourceDTO() throws UnknownHostException {
+        final ExecutorService executorService = mock(ExecutorService.class);
+        doReturn(executorService).when(processingExecutor).getExecutor();
+
+        final Credentials credentials = new LoginPasswordBuilder().setPassword("admin").setUsername("admin").build();
+        final NetconfNode netconfNode = new NetconfNodeBuilder()
+                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
+                .setPort(new PortNumber(9999))
+                .setReconnectOnChangedSchema(true)
+                .setDefaultRequestTimeoutMillis(1000L)
+                .setBetweenAttemptsTimeoutMillis(100)
+                .setSchemaless(false)
+                .setTcpOnly(false)
+                .setCredentials(credentials)
+                .setSchemaCacheDirectory("schemas-test")
+                .build();
+
+        final RemoteDeviceConnectorImpl remoteDeviceConnection =
+                new RemoteDeviceConnectorImpl(builder.build(), remoteDeviceId);
+
+        final ActorRef masterRef = mock(ActorRef.class);
+
+        remoteDeviceConnection.createDeviceCommunicator(NODE_ID, netconfNode, masterRef);
+
+        assertTrue(remoteDeviceConnection.getSchemaResourcesDTOs().containsKey("schemas-test"));
+    }
+
+}
diff --git a/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/TestingRemoteDeviceConnectorImpl.java b/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/TestingRemoteDeviceConnectorImpl.java
new file mode 100644 (file)
index 0000000..d4b4ec0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+
+import akka.actor.ActorRef;
+import com.google.common.util.concurrent.Futures;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfConnectorDTO;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+
+class TestingRemoteDeviceConnectorImpl extends RemoteDeviceConnectorImpl {
+
+    private final NetconfDeviceCommunicator communicator;
+    private final RemoteDeviceHandler salFacade;
+
+    TestingRemoteDeviceConnectorImpl(final NetconfTopologySetup netconfTopologyDeviceSetup,
+                                            final RemoteDeviceId remoteDeviceId,
+                                            final NetconfDeviceCommunicator communicator,
+                                            final RemoteDeviceHandler salFacade) {
+        super(netconfTopologyDeviceSetup, remoteDeviceId);
+        this.communicator = communicator;
+        this.salFacade = salFacade;
+    }
+
+    @Override
+    public NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node,
+                                                        final ActorRef deviceContextActorRef) {
+        final NetconfConnectorDTO connectorDTO = new NetconfConnectorDTO(communicator, salFacade);
+        doReturn(Futures.immediateCheckedFuture(null)).when(communicator).initializeRemoteConnection(any(), any());
+
+        return connectorDTO;
+    }
+
+}
diff --git a/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/tx/ReadOnlyTransactionTest.java b/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/tx/ReadOnlyTransactionTest.java
new file mode 100644 (file)
index 0000000..c491ee6
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.tx;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.MockitoAnnotations.initMocks;
+import static org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.pattern.Patterns;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import akka.util.Timeout;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.impl.NetconfDOMDataBroker;
+import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.netconf.topology.singleton.messages.CreateInitialMasterActorData;
+import org.opendaylight.netconf.topology.singleton.messages.MasterActorDataInitialized;
+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.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
+
+public class ReadOnlyTransactionTest {
+    private static final Timeout TIMEOUT = new Timeout(Duration.create(5, "seconds"));
+    private static final int TIMEOUT_SEC = 5;
+    private static ActorSystem system;
+
+    @Rule
+    public final ExpectedException exception = ExpectedException.none();
+
+    private ActorRef masterRef;
+    private NetconfDOMDataBroker slaveDataBroker;
+    private DOMDataBroker masterDataBroker;
+    private List<SourceIdentifier> sourceIdentifiers;
+
+    @Mock
+    private DOMDataReadOnlyTransaction readTx;
+
+    @Before
+    public void setup() throws UnknownHostException {
+        initMocks(this);
+
+        system = ActorSystem.create();
+
+        final RemoteDeviceId remoteDeviceId = new RemoteDeviceId("netconf-topology",
+                new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999));
+
+        final NetconfTopologySetup setup = mock(NetconfTopologySetup.class);
+        final Props props = NetconfNodeActor.props(setup, remoteDeviceId, DEFAULT_SCHEMA_REPOSITORY,
+                DEFAULT_SCHEMA_REPOSITORY);
+
+        masterRef = TestActorRef.create(system, props, "master_read");
+
+        sourceIdentifiers = Lists.newArrayList();
+
+        // Create master data broker
+
+        final DOMDataBroker delegateDataBroker = mock(DOMDataBroker.class);
+        readTx = mock(DOMDataReadOnlyTransaction.class);
+
+        doReturn(readTx).when(delegateDataBroker).newReadOnlyTransaction();
+
+        final NetconfDOMTransaction masterDOMTransactions =
+                new NetconfMasterDOMTransaction(remoteDeviceId, delegateDataBroker);
+
+        masterDataBroker =
+                new NetconfDOMDataBroker(system, remoteDeviceId, masterDOMTransactions);
+
+        // Create slave data broker for testing proxy
+
+        final NetconfDOMTransaction proxyDOMTransactions =
+                new NetconfProxyDOMTransaction(remoteDeviceId, system, masterRef);
+
+        slaveDataBroker = new NetconfDOMDataBroker(system, remoteDeviceId, proxyDOMTransactions);
+
+
+    }
+
+    @After
+    public void teardown() {
+        JavaTestKit.shutdownActorSystem(system);
+        system = null;
+    }
+
+    @Test
+    public void testRead() throws Exception {
+
+        /* Initialize data on master */
+
+        initializeDataTest();
+
+        final YangInstanceIdentifier instanceIdentifier = YangInstanceIdentifier.EMPTY;
+        final LogicalDatastoreType storeType = LogicalDatastoreType.CONFIGURATION;
+
+        // Message: EmptyReadResponse
+
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> resultEmpty =
+                Futures.immediateCheckedFuture(Optional.absent());
+
+        doReturn(resultEmpty).when(readTx).read(storeType, instanceIdentifier);
+
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> resultEmptyResponse =
+                slaveDataBroker.newReadOnlyTransaction().read(storeType,
+                        instanceIdentifier);
+
+        final Optional<NormalizedNode<?, ?>> resultEmptyMessage =
+                resultEmptyResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+        assertEquals(resultEmptyMessage, Optional.absent());
+
+        // Message: NormalizedNodeMessage
+
+        final NormalizedNode<?, ?> outputNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("TestQname")))
+                .withChild(ImmutableNodes.leafNode(QName.create("NodeQname"), "foo")).build();
+
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> resultNormalizedNodeMessage =
+                Futures.immediateCheckedFuture(Optional.of(outputNode));
+
+        doReturn(resultNormalizedNodeMessage).when(readTx).read(storeType, instanceIdentifier);
+
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> resultNodeMessageResponse =
+                slaveDataBroker.newReadOnlyTransaction().read(storeType, instanceIdentifier);
+
+        final Optional<NormalizedNode<?, ?>> resultNodeMessage =
+                resultNodeMessageResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+        assertTrue(resultNodeMessage.isPresent());
+        assertEquals(resultNodeMessage.get(), outputNode);
+
+        // Message: Throwable
+
+        final ReadFailedException readFailedException = new ReadFailedException("Fail", null);
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> resultThrowable =
+                Futures.immediateFailedCheckedFuture(readFailedException);
+
+        doReturn(resultThrowable).when(readTx).read(storeType, instanceIdentifier);
+
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> resultThrowableResponse =
+                slaveDataBroker.newReadOnlyTransaction().read(storeType, instanceIdentifier);
+
+        exception.expect(ReadFailedException.class);
+        resultThrowableResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+    }
+
+    @Test
+    public void testExist() throws Exception {
+
+        /* Initialize data on master */
+
+        initializeDataTest();
+
+        final YangInstanceIdentifier instanceIdentifier = YangInstanceIdentifier.EMPTY;
+        final LogicalDatastoreType storeType = LogicalDatastoreType.CONFIGURATION;
+
+        // Message: True
+
+        final CheckedFuture<Boolean, ReadFailedException> resultTrue =
+                Futures.immediateCheckedFuture(true);
+
+        doReturn(resultTrue).when(readTx).exists(storeType, instanceIdentifier);
+
+        final CheckedFuture<Boolean, ReadFailedException> trueResponse =
+                slaveDataBroker.newReadOnlyTransaction().exists(storeType, instanceIdentifier);
+
+        final Boolean trueMessage = trueResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+        assertEquals(true, trueMessage);
+
+        // Message: False
+
+        final CheckedFuture<Boolean, ReadFailedException> resultFalse = Futures.immediateCheckedFuture(false);
+
+        doReturn(resultFalse).when(readTx).exists(storeType, instanceIdentifier);
+
+        final CheckedFuture<Boolean, ReadFailedException> falseResponse =
+                slaveDataBroker.newReadOnlyTransaction().exists(storeType,
+                        instanceIdentifier);
+
+        final Boolean falseMessage = falseResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+        assertEquals(false, falseMessage);
+
+        // Message: False, result null
+
+        final CheckedFuture<Boolean, ReadFailedException> resultNull = Futures.immediateCheckedFuture(null);
+
+        doReturn(resultNull).when(readTx).exists(storeType, instanceIdentifier);
+
+        final CheckedFuture<Boolean, ReadFailedException> nullResponse =
+                slaveDataBroker.newReadOnlyTransaction().exists(storeType,
+                        instanceIdentifier);
+
+        final Boolean nullFalseMessage = nullResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+        assertEquals(false, nullFalseMessage);
+
+        // Message: Throwable
+
+        final ReadFailedException readFailedException = new ReadFailedException("Fail", null);
+        final CheckedFuture<Boolean, ReadFailedException> resultThrowable =
+                Futures.immediateFailedCheckedFuture(readFailedException);
+
+        doReturn(resultThrowable).when(readTx).exists(storeType, instanceIdentifier);
+
+        final CheckedFuture<Boolean, ReadFailedException> resultThrowableResponse =
+                slaveDataBroker.newReadOnlyTransaction().exists(storeType, instanceIdentifier);
+
+        exception.expect(ReadFailedException.class);
+        resultThrowableResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+    }
+
+    private void initializeDataTest() throws Exception {
+        final Future<Object> initialDataToActor =
+                Patterns.ask(masterRef, new CreateInitialMasterActorData(masterDataBroker, sourceIdentifiers),
+                        TIMEOUT);
+
+        final Object success = Await.result(initialDataToActor, TIMEOUT.duration());
+
+        assertTrue(success instanceof MasterActorDataInitialized);
+    }
+}
diff --git a/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/tx/WriteOnlyTransactionTest.java b/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/tx/WriteOnlyTransactionTest.java
new file mode 100644 (file)
index 0000000..c9fa38f
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.tx;
+
+import static junit.framework.TestCase.assertNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+import static org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.pattern.Patterns;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import akka.util.Timeout;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.api.NetconfDOMTransaction;
+import org.opendaylight.netconf.topology.singleton.impl.NetconfDOMDataBroker;
+import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
+import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
+import org.opendaylight.netconf.topology.singleton.messages.CreateInitialMasterActorData;
+import org.opendaylight.netconf.topology.singleton.messages.MasterActorDataInitialized;
+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.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
+
+public class WriteOnlyTransactionTest {
+    private static final Timeout TIMEOUT = new Timeout(Duration.create(5, "seconds"));
+    private static final int TIMEOUT_SEC = 5;
+    private static ActorSystem system;
+
+    @Rule
+    public final ExpectedException exception = ExpectedException.none();
+
+    private ActorRef masterRef;
+    private NetconfDOMDataBroker slaveDataBroker;
+    private DOMDataBroker masterDataBroker;
+    private List<SourceIdentifier> sourceIdentifiers;
+
+    @Mock
+    private DOMDataWriteTransaction writeTx;
+
+    @Before
+    public void setup() throws UnknownHostException {
+        initMocks(this);
+
+        system = ActorSystem.create();
+
+        final RemoteDeviceId remoteDeviceId = new RemoteDeviceId("netconf-topology",
+                new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999));
+
+        final NetconfTopologySetup setup = mock(NetconfTopologySetup.class);
+        final Props props = NetconfNodeActor.props(setup, remoteDeviceId, DEFAULT_SCHEMA_REPOSITORY,
+                DEFAULT_SCHEMA_REPOSITORY);
+
+        masterRef = TestActorRef.create(system, props, "master_read");
+
+        sourceIdentifiers = Lists.newArrayList();
+
+        // Create master data broker
+
+        final DOMDataBroker delegateDataBroker = mock(DOMDataBroker.class);
+        writeTx = mock(DOMDataWriteTransaction.class);
+        final DOMDataReadOnlyTransaction readTx = mock(DOMDataReadOnlyTransaction.class);
+
+        doReturn(writeTx).when(delegateDataBroker).newWriteOnlyTransaction();
+        doReturn(readTx).when(delegateDataBroker).newReadOnlyTransaction();
+
+        final NetconfDOMTransaction masterDOMTransactions =
+                new NetconfMasterDOMTransaction(remoteDeviceId, delegateDataBroker);
+
+        masterDataBroker =
+                new NetconfDOMDataBroker(system, remoteDeviceId, masterDOMTransactions);
+
+        // Create slave data broker for testing proxy
+
+        final NetconfDOMTransaction proxyDOMTransactions =
+                new NetconfProxyDOMTransaction(remoteDeviceId, system, masterRef);
+
+        slaveDataBroker = new NetconfDOMDataBroker(system, remoteDeviceId, proxyDOMTransactions);
+
+
+    }
+
+    @After
+    public void teardown() {
+        JavaTestKit.shutdownActorSystem(system);
+        system = null;
+    }
+
+    @Test
+    public void testPutMergeDeleteCalls() throws Exception {
+
+        /* Initialize data on master */
+
+        initializeDataTest();
+
+        final YangInstanceIdentifier instanceIdentifier = YangInstanceIdentifier.EMPTY;
+        final LogicalDatastoreType storeType = LogicalDatastoreType.CONFIGURATION;
+        final NormalizedNode<?, ?> testNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("TestQname")))
+                .withChild(ImmutableNodes.leafNode(QName.create("NodeQname"), "foo")).build();
+
+        // Test of invoking put on master through slave proxy
+
+        doNothing().when(writeTx).put(storeType, instanceIdentifier, testNode);
+        slaveDataBroker.newWriteOnlyTransaction().put(storeType, instanceIdentifier, testNode);
+
+        verify(writeTx, times(1)).put(storeType, instanceIdentifier, testNode);
+
+        // Test of invoking merge on master through slave proxy
+
+        doNothing().when(writeTx).merge(storeType, instanceIdentifier, testNode);
+        slaveDataBroker.newWriteOnlyTransaction().merge(storeType, instanceIdentifier, testNode);
+
+        verify(writeTx, times(1)).merge(storeType, instanceIdentifier, testNode);
+
+        // Test of invoking delete on master through slave proxy
+
+        doNothing().when(writeTx).delete(storeType, instanceIdentifier);
+        slaveDataBroker.newWriteOnlyTransaction().delete(storeType, instanceIdentifier);
+
+        verify(writeTx, times(1)).delete(storeType, instanceIdentifier);
+
+    }
+
+    @Test
+    public void testSubmit() throws Exception {
+
+        /* Initialize data on master */
+
+        initializeDataTest();
+
+        // Without Tx
+
+        final CheckedFuture<Void,TransactionCommitFailedException> resultSubmit = Futures.immediateCheckedFuture(null);
+        doReturn(resultSubmit).when(writeTx).submit();
+
+        final CheckedFuture<Void, TransactionCommitFailedException> resultSubmitResponse =
+                slaveDataBroker.newWriteOnlyTransaction().submit();
+
+        final Object result= resultSubmitResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+        assertNull(result);
+
+        // With Tx
+
+        doNothing().when(writeTx).delete(any(), any());
+        slaveDataBroker.newWriteOnlyTransaction().delete(LogicalDatastoreType.CONFIGURATION,
+                YangInstanceIdentifier.EMPTY);
+
+        final CheckedFuture<Void,TransactionCommitFailedException> resultSubmitTx = Futures.immediateCheckedFuture(null);
+        doReturn(resultSubmitTx).when(writeTx).submit();
+
+        final CheckedFuture<Void, TransactionCommitFailedException> resultSubmitTxResponse =
+                slaveDataBroker.newWriteOnlyTransaction().submit();
+
+        final Object resultTx = resultSubmitTxResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+        assertNull(resultTx);
+
+        slaveDataBroker.newWriteOnlyTransaction().delete(LogicalDatastoreType.CONFIGURATION,
+                YangInstanceIdentifier.EMPTY);
+
+        final TransactionCommitFailedException throwable = new TransactionCommitFailedException("Fail", null);
+        final CheckedFuture<Void,TransactionCommitFailedException> resultThrowable =
+                Futures.immediateFailedCheckedFuture(throwable);
+
+        doReturn(resultThrowable).when(writeTx).submit();
+
+        final CheckedFuture<Void, TransactionCommitFailedException> resultThrowableResponse =
+                slaveDataBroker.newWriteOnlyTransaction().submit();
+
+        exception.expect(TransactionCommitFailedException.class);
+        resultThrowableResponse.checkedGet(TIMEOUT_SEC, TimeUnit.SECONDS);
+    }
+
+    @Test
+    public void testCancel() throws Exception {
+
+        /* Initialize data on master */
+
+        initializeDataTest();
+
+        // Without Tx
+
+        final Boolean resultFalseNoTx = slaveDataBroker.newWriteOnlyTransaction().cancel();
+        assertEquals(false, resultFalseNoTx);
+
+        // With Tx, readWriteTx test
+
+        doNothing().when(writeTx).delete(any(), any());
+        slaveDataBroker.newReadWriteTransaction().delete(LogicalDatastoreType.CONFIGURATION,
+                YangInstanceIdentifier.EMPTY);
+
+        doReturn(true).when(writeTx).cancel();
+
+        final Boolean resultTrue = slaveDataBroker.newWriteOnlyTransaction().cancel();
+        assertEquals(true, resultTrue);
+
+        doReturn(false).when(writeTx).cancel();
+
+        final Boolean resultFalse = slaveDataBroker.newWriteOnlyTransaction().cancel();
+        assertEquals(false, resultFalse);
+
+    }
+
+    private void initializeDataTest() throws Exception {
+        final Future<Object> initialDataToActor =
+                Patterns.ask(masterRef, new CreateInitialMasterActorData(masterDataBroker, sourceIdentifiers),
+                        TIMEOUT);
+
+        final Object success = Await.result(initialDataToActor, TIMEOUT.duration());
+
+        assertTrue(success instanceof MasterActorDataInitialized);
+    }
+
+}
diff --git a/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologyUtilTest.java b/netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologyUtilTest.java
new file mode 100644 (file)
index 0000000..9f8d153
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.singleton.impl.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NetconfTopologyUtilTest {
+
+    @Test
+    public void testCreateRemoteDeviceId() {
+        final Host host = new Host(new IpAddress(new Ipv4Address("127.0.0.1")));
+        final NetconfNode netconfNode = new NetconfNodeBuilder().setHost(host).setPort(new PortNumber(9999)).build();
+        final NodeId nodeId = new NodeId("testing-node");
+        final RemoteDeviceId id = NetconfTopologyUtils.createRemoteDeviceId(nodeId, netconfNode);
+
+        assertEquals("testing-node", id.getName());
+        assertEquals(host, id.getHost());
+        assertEquals(9999, id.getAddress().getPort());
+    }
+
+    @Test
+    public void testCreateActorPath() {
+        final String actorPath = NetconfTopologyUtils.createActorPath("member", "name");
+        assertEquals("member/user/name", actorPath);
+    }
+
+    @Test
+    public void testCreateListPath() {
+        final InstanceIdentifier<Node> listPath =
+                NetconfTopologyUtils.createTopologyNodeListPath(new NodeKey(new NodeId("nodeId")), "topologyId");
+
+        assertEquals("nodeId", listPath.firstKeyOf(Node.class).getNodeId().getValue());
+        assertEquals("topologyId", listPath.firstKeyOf(Topology.class).getTopologyId().getValue());
+
+        assertEquals("topologyId",  NetconfTopologyUtils.createTopologyNodePath("topologyId").
+                firstKeyOf(Topology.class).getTopologyId().getValue());
+    }
+
+}
index b2488bd0ff36841e78ea55710aea7b62ad20025a..f0839ae945f914aabd912ff2b405decab5aec4f9 100644 (file)
             <groupId>org.opendaylight.netconf</groupId>
             <artifactId>sal-netconf-connector</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-clustering-commons</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-api</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.netconf</groupId>
-            <artifactId>abstract-topology</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.typesafe</groupId>
-            <artifactId>config</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-all</artifactId>
-            <version>1.9.5</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.jayway.awaitility</groupId>
-            <artifactId>awaitility</artifactId>
-            <version>1.6.5</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/controller/config/yang/clustered/netconf/topology/ClusteredNetconfTopologyModule.java b/netconf/netconf-topology/src/main/java/org/opendaylight/controller/config/yang/clustered/netconf/topology/ClusteredNetconfTopologyModule.java
deleted file mode 100644 (file)
index 54be237..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.controller.config.yang.clustered.netconf.topology;
-
-import org.opendaylight.netconf.topology.impl.ClusteredNetconfTopology;
-
-public class ClusteredNetconfTopologyModule extends org.opendaylight.controller.config.yang.clustered.netconf.topology.AbstractClusteredNetconfTopologyModule {
-    public ClusteredNetconfTopologyModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-        super(identifier, dependencyResolver);
-    }
-
-    public ClusteredNetconfTopologyModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.clustered.netconf.topology.ClusteredNetconfTopologyModule oldModule, java.lang.AutoCloseable oldInstance) {
-        super(identifier, dependencyResolver, oldModule, oldInstance);
-    }
-
-    @Override
-    public void customValidation() {
-        // add custom validation form module attributes here.
-    }
-
-    @Override
-    public java.lang.AutoCloseable createInstance() {
-        return new ClusteredNetconfTopology(getTopologyId(),
-                getClientDispatcherDependency(),
-                getBindingRegistryDependency(),
-                getDomRegistryDependency(),
-                getEventExecutorDependency(),
-                getKeepaliveExecutorDependency(),
-                getProcessingExecutorDependency(),
-                getSharedSchemaRepositoryDependency(),
-                getActorSystemProviderServiceDependency().getActorSystem(),
-                getEntityOwnershipServiceDependency());
-    }
-
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/controller/config/yang/clustered/netconf/topology/ClusteredNetconfTopologyModuleFactory.java b/netconf/netconf-topology/src/main/java/org/opendaylight/controller/config/yang/clustered/netconf/topology/ClusteredNetconfTopologyModuleFactory.java
deleted file mode 100644 (file)
index 0fb3a5b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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
- */
-
-/*
-* Generated file
-*
-* Generated from: yang module name: clustered-netconf-topology yang module local name: clustered-netconf-topology-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Nov 04 10:59:45 CET 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.controller.config.yang.clustered.netconf.topology;
-public class ClusteredNetconfTopologyModuleFactory extends org.opendaylight.controller.config.yang.clustered.netconf.topology.AbstractClusteredNetconfTopologyModuleFactory {
-
-}
index f0c56f3ca79301defcca62328ba63378083dbf84..7174c53be544c628a4d85eb510c870d7a18ea751 100644 (file)
@@ -57,13 +57,13 @@ import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
 import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade.ConnectionStatusListenerRegistration;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@@ -203,16 +203,6 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin
     @Override
     public abstract void onSessionInitiated(ProviderContext session);
 
-    @Override
-    public String getTopologyId() {
-        return topologyId;
-    }
-
-    @Override
-    public DataBroker getDataBroker() {
-        return dataBroker;
-    }
-
     @Override
     public ListenableFuture<NetconfDeviceCapabilities> connectNode(NodeId nodeId, Node configNode) {
         LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, configNode);
@@ -448,9 +438,6 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin
 
     protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker);
 
-    @Override
-    public abstract ConnectionStatusListenerRegistration registerConnectionStatusListener(NodeId node, RemoteDeviceHandler<NetconfSessionPreferences> listener);
-
     @Override
     public void onSessionInitiated(ProviderSession session) {
          mountPointService = session.getService(DOMMountPointService.class);
@@ -481,7 +468,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin
             return Optional.absent();
         }
 
-        final NetconfSessionPreferences parsedOverrideCapabilities = NetconfSessionPreferences.fromStrings(capabilities);
+        final NetconfSessionPreferences parsedOverrideCapabilities = NetconfSessionPreferences.fromStrings(capabilities, CapabilityOrigin.UserDefined);
         Preconditions.checkState(parsedOverrideCapabilities.getNonModuleCaps().isEmpty(), "Capabilities to override can " +
                 "only contain module based capabilities, non-module capabilities will be retrieved from the device," +
                 " configured non-module capabilities: " + parsedOverrideCapabilities.getNonModuleCaps());
index 7c3b83617b7ff2ef1e70210ea9f22428d63f22c4..b275c7584da82dd8db87cc986d64a15da00ca563 100644 (file)
@@ -8,43 +8,15 @@
 
 package org.opendaylight.netconf.topology;
 
-import akka.actor.ActorContext;
-import akka.actor.ActorRef;
 import com.google.common.util.concurrent.ListenableFuture;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade.ConnectionStatusListenerRegistration;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 
 public interface NetconfTopology {
 
-    String getTopologyId();
-
-    DataBroker getDataBroker();
-
     ListenableFuture<NetconfDeviceCapabilities> connectNode(NodeId nodeId, Node configNode);
 
     ListenableFuture<Void> disconnectNode(NodeId nodeId);
 
-    /**
-     * register master mount point
-     * @param context
-     * @param nodeId
-     */
-    void registerMountPoint(ActorContext context, NodeId nodeId);
-
-    /**
-     * register slave mountpoint with the provided ActorRef
-     * @param context
-     * @param nodeId
-     * @param masterRef
-     */
-    void registerMountPoint(ActorContext context, NodeId nodeId, ActorRef masterRef);
-
-    void unregisterMountPoint(NodeId nodeId);
-
-    ConnectionStatusListenerRegistration registerConnectionStatusListener(NodeId node, RemoteDeviceHandler<NetconfSessionPreferences> listener);
 }
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java
deleted file mode 100644 (file)
index 3822455..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.impl;
-
-import akka.actor.ActorContext;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import akka.actor.TypedActorExtension;
-import akka.actor.TypedProps;
-import akka.japi.Creator;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import io.netty.util.concurrent.EventExecutor;
-import java.net.InetSocketAddress;
-import java.util.Collection;
-import java.util.Collections;
-import javassist.ClassPool;
-import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
-import org.opendaylight.controller.config.threadpool.ThreadPool;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.netconf.client.NetconfClientDispatcher;
-import org.opendaylight.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.AbstractNetconfTopology;
-import org.opendaylight.netconf.topology.NetconfTopology;
-import org.opendaylight.netconf.topology.NodeManagerCallback;
-import org.opendaylight.netconf.topology.NodeManagerCallback.NodeManagerCallbackFactory;
-import org.opendaylight.netconf.topology.SchemaRepositoryProvider;
-import org.opendaylight.netconf.topology.TopologyManager;
-import org.opendaylight.netconf.topology.TopologyManagerCallback;
-import org.opendaylight.netconf.topology.TopologyManagerCallback.TopologyManagerCallbackFactory;
-import org.opendaylight.netconf.topology.example.LoggingSalNodeWriter;
-import org.opendaylight.netconf.topology.pipeline.ClusteredNetconfDevice;
-import org.opendaylight.netconf.topology.pipeline.ClusteredNetconfDeviceCommunicator;
-import org.opendaylight.netconf.topology.pipeline.ClusteredNetconfDeviceCommunicator.NetconfClientSessionListenerRegistration;
-import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade;
-import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade.ConnectionStatusListenerRegistration;
-import org.opendaylight.netconf.topology.util.BaseTopologyManager;
-import org.opendaylight.netconf.topology.util.NodeRoleChangeStrategy;
-import org.opendaylight.netconf.topology.util.NodeWriter;
-import org.opendaylight.netconf.topology.util.TopologyRoleChangeStrategy;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.$YangModuleInfoImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
-import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
-import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
-import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ClusteredNetconfTopology extends AbstractNetconfTopology implements AutoCloseable {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ClusteredNetconfTopology.class);
-
-    private final BindingNormalizedNodeCodecRegistry codecRegistry;
-
-    private final ActorSystem actorSystem;
-    private final EntityOwnershipService entityOwnershipService;
-    private TopologyManager topologyManager;
-
-    public ClusteredNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
-                               final BindingAwareBroker bindingAwareBroker, final Broker domBroker,
-                               final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
-                               final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
-                               final ActorSystem actorSystem, final EntityOwnershipService entityOwnershipService) {
-        super(topologyId, clientDispatcher,
-                bindingAwareBroker, domBroker, eventExecutor,
-                keepaliveExecutor, processingExecutor, schemaRepositoryProvider);
-
-        final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
-        moduleInfoBackedContext.addModuleInfos(Collections.singletonList($YangModuleInfoImpl.getInstance()));
-        final Optional<SchemaContext> schemaContextOptional = moduleInfoBackedContext.tryToCreateSchemaContext();
-        Preconditions.checkState(schemaContextOptional.isPresent());
-        final SchemaContext topologySchemaCtx = schemaContextOptional.get();
-
-        final JavassistUtils javassist = JavassistUtils.forClassPool(ClassPool.getDefault());
-        codecRegistry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(javassist));
-        codecRegistry.onBindingRuntimeContextUpdated(BindingRuntimeContext.create(moduleInfoBackedContext, topologySchemaCtx));
-
-        this.actorSystem = actorSystem;
-        this.entityOwnershipService = entityOwnershipService;
-        registerToSal(this, this);
-        LOG.warn("Clustered netconf topo started");
-    }
-
-
-
-    @Override
-    public void onSessionInitiated(final ProviderContext session) {
-        dataBroker = session.getSALService(DataBroker.class);
-        final NodeWriter writer = new TopologyNodeWriter(topologyId, dataBroker);
-        TypedActorExtension typedActorExtension = TypedActor.get(this.actorSystem);
-        LOG.warn("Registering actor on path {}", actorSystem.name() + "/user/" + topologyId);
-        topologyManager = typedActorExtension.typedActorOf(new TypedProps<>(TopologyManager.class, new Creator<BaseTopologyManager>() {
-            @Override
-            public BaseTopologyManager create() throws Exception {
-                return new BaseTopologyManager(actorSystem,
-                        codecRegistry,
-                        dataBroker,
-                        topologyId,
-                        new TopologyCallbackFactory(ClusteredNetconfTopology.this, entityOwnershipService, writer),
-                        new NetconfNodeOperationalDataAggregator(),
-                        new LoggingSalNodeWriter(writer),
-                        new TopologyRoleChangeStrategy(dataBroker, entityOwnershipService, "topology-netconf", "topology-manager"));
-            }
-        }), topologyId);
-    }
-
-    @Override
-    public void close() throws Exception {
-        // close all existing connectors, delete whole topology in datastore?
-        for (NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
-            connectorDTO.getCommunicator().close();
-        }
-        activeConnectors.clear();
-    }
-
-    @Override
-    protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId,
-                                                           final NetconfNode node) {
-        //setup default values since default value is not supported in mdsal
-        final Long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis();
-        final Long keepaliveDelay = node.getKeepaliveDelay() == null ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay();
-        final Boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
-
-        IpAddress ipAddress = node.getHost().getIpAddress();
-        InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null ?
-                ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
-                node.getPort().getValue());
-        RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
-
-        RemoteDeviceHandler<NetconfSessionPreferences> salFacade =
-                createSalFacade(remoteDeviceId, domBroker, bindingAwareBroker);
-
-        if (keepaliveDelay > 0) {
-            LOG.warn("Adding keepalive facade, for device {}", nodeId);
-            salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay, defaultRequestTimeoutMillis);
-        }
-
-        final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node);
-
-        final NetconfDevice device = new ClusteredNetconfDevice(schemaResourcesDTO, remoteDeviceId, salFacade,
-                processingExecutor.getExecutor(), actorSystem, topologyId, nodeId.getValue(), TypedActor.context(),
-                reconnectOnChangedSchema);
-
-        final int rpcMessageLimit =
-                node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT : node.getConcurrentRpcLimit();
-
-        if (rpcMessageLimit < 1) {
-            LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
-        }
-
-        return new NetconfConnectorDTO(new ClusteredNetconfDeviceCommunicator(remoteDeviceId, device, entityOwnershipService, rpcMessageLimit), salFacade);
-    }
-
-    @Override
-    protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker) {
-        return new TopologyMountPointFacade(topologyId, id, domBroker, bindingBroker);
-    }
-
-    @Override
-    public void registerMountPoint(final ActorContext context, final NodeId nodeId) {
-        ((TopologyMountPointFacade) activeConnectors.get(nodeId).getFacade()).registerMountPoint(actorSystem, context);
-    }
-
-    @Override
-    public void registerMountPoint(final ActorContext context, final NodeId nodeId, final ActorRef masterRef) {
-        ((TopologyMountPointFacade) activeConnectors.get(nodeId).getFacade()).registerMountPoint(actorSystem, context, masterRef);
-    }
-
-    @Override
-    public void unregisterMountPoint(final NodeId nodeId) {
-        Preconditions.checkState(activeConnectors.containsKey(nodeId), "Cannot unregister nonexistent mountpoint");
-        ((TopologyMountPointFacade) activeConnectors.get(nodeId).getFacade()).unregisterMountPoint();
-    }
-
-    @Override
-    public ConnectionStatusListenerRegistration registerConnectionStatusListener(final NodeId node, final RemoteDeviceHandler<NetconfSessionPreferences> listener) {
-        Preconditions.checkState(activeConnectors.containsKey(node), "Need to connect a node before a connection listener can be registered");
-        return ((TopologyMountPointFacade) activeConnectors.get(node).getFacade()).registerConnectionStatusListener(listener);
-    }
-
-    public Collection<ProviderFunctionality> getProviderFunctionality() {
-        return Collections.emptySet();
-    }
-
-    public NetconfClientSessionListenerRegistration registerNetconfClientSessionListener(final NodeId node, final NetconfClientSessionListener listener) {
-        Preconditions.checkState(activeConnectors.containsKey(node), "Need to connect a node before a session listener can be registered");
-        return ((ClusteredNetconfDeviceCommunicator) activeConnectors.get(node).getCommunicator()).registerNetconfClientSessionListener(listener);
-    }
-
-    static class TopologyCallbackFactory implements TopologyManagerCallbackFactory {
-
-        private final NetconfTopology netconfTopology;
-        private final EntityOwnershipService entityOwnershipService;
-        private final NodeWriter writer;
-
-        TopologyCallbackFactory(final NetconfTopology netconfTopology, final EntityOwnershipService entityOwnershipService, final NodeWriter writer) {
-            this.netconfTopology = netconfTopology;
-            this.entityOwnershipService = entityOwnershipService;
-            this.writer = writer;
-        }
-
-        @Override
-        public TopologyManagerCallback create(final ActorSystem actorSystem, final String topologyId) {
-            return new NetconfTopologyManagerCallback(actorSystem, topologyId, new NodeCallbackFactory(netconfTopology, entityOwnershipService), new LoggingSalNodeWriter(writer));
-        }
-    }
-
-    private static class NodeCallbackFactory implements NodeManagerCallbackFactory {
-
-        private final NetconfTopology netconfTopology;
-        private final EntityOwnershipService entityOwnershipService;
-
-        NodeCallbackFactory(final NetconfTopology netconfTopology, final EntityOwnershipService entityOwnershipService) {
-            this.netconfTopology = netconfTopology;
-            this.entityOwnershipService = entityOwnershipService;
-        }
-
-        @Override
-        public NodeManagerCallback create(final String nodeId, final String topologyId, final ActorSystem actorSystem) {
-            return new NetconfNodeManagerCallback(nodeId, topologyId, actorSystem, netconfTopology, new NodeRoleChangeStrategy(entityOwnershipService, "netconf-node", nodeId));
-        }
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfNodeManagerCallback.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfNodeManagerCallback.java
deleted file mode 100644 (file)
index 89e1dfa..0000000
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.impl;
-
-import akka.actor.ActorContext;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import akka.actor.TypedProps;
-import akka.cluster.Cluster;
-import akka.dispatch.OnComplete;
-import com.google.common.base.Function;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.concurrent.TimeUnit;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.api.NetconfMessage;
-import org.opendaylight.netconf.api.NetconfTerminationReason;
-import org.opendaylight.netconf.client.NetconfClientSession;
-import org.opendaylight.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.topology.NetconfTopology;
-import org.opendaylight.netconf.topology.NodeManager;
-import org.opendaylight.netconf.topology.NodeManagerCallback;
-import org.opendaylight.netconf.topology.RoleChangeStrategy;
-import org.opendaylight.netconf.topology.TopologyManager;
-import org.opendaylight.netconf.topology.pipeline.ClusteredNetconfDeviceCommunicator.NetconfClientSessionListenerRegistration;
-import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade.ConnectionStatusListenerRegistration;
-import org.opendaylight.netconf.topology.util.BaseNodeManager;
-import org.opendaylight.netconf.topology.util.BaseTopologyManager;
-import org.opendaylight.netconf.topology.util.messages.AnnounceMasterMountPoint;
-import org.opendaylight.netconf.topology.util.messages.AnnounceMasterMountPointDown;
-import org.opendaylight.netconf.util.NetconfTopologyPathCreator;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilities;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus.Status;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability.FailureReason;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapabilityBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import scala.concurrent.Future;
-import scala.concurrent.duration.FiniteDuration;
-
-public class NetconfNodeManagerCallback implements NodeManagerCallback, NetconfClientSessionListener{
-
-    private static final Logger LOG = LoggerFactory.getLogger(NetconfNodeManagerCallback.class);
-
-    public static final Function<Entry<QName, FailureReason>, UnavailableCapability> UNAVAILABLE_CAPABILITY_TRANSFORMER = new Function<Entry<QName, FailureReason>, UnavailableCapability>() {
-        @Override
-        public UnavailableCapability apply(final Entry<QName, FailureReason> input) {
-            return new UnavailableCapabilityBuilder()
-                    .setCapability(input.getKey().toString())
-                    .setFailureReason(input.getValue()).build();
-        }
-    };
-    public static final Function<QName, String> AVAILABLE_CAPABILITY_TRANSFORMER = new Function<QName, String>() {
-        @Override
-        public String apply(QName qName) {
-            // intern string representation of a capability to avoid duplicates
-            return qName.toString().intern();
-        }
-    };
-
-    private static final String UNKNOWN_REASON = "Unknown reason";
-
-    private boolean isMaster = false;
-    private ClusteredNetconfTopology topologyDispatcher;
-    private final ActorSystem actorSystem;
-    private final Cluster clusterExtension;
-
-    private final RoleChangeStrategy roleChangeStrategy;
-
-    private String nodeId;
-    private String topologyId;
-    private TopologyManager topologyManager;
-    private NodeManager nodeManager;
-    // cached context so that we can use it in callbacks from topology
-    private ActorContext cachedContext;
-
-    private Node currentConfig;
-    private Node currentOperationalNode;
-
-    private ConnectionStatusListenerRegistration connectionStatusregistration = null;
-    private NetconfClientSessionListenerRegistration sessionListener = null;
-
-    private ActorRef masterDataBrokerRef = null;
-    private boolean connected = false;
-
-    public NetconfNodeManagerCallback(final String nodeId,
-                                      final String topologyId,
-                                      final ActorSystem actorSystem,
-                                      final NetconfTopology topologyDispatcher,
-                                      final RoleChangeStrategy roleChangeStrategy) {
-        this.nodeId = nodeId;
-        this.topologyId = topologyId;
-        this.actorSystem = actorSystem;
-        this.clusterExtension = Cluster.get(actorSystem);
-        this.topologyDispatcher = (ClusteredNetconfTopology) topologyDispatcher;
-        this.roleChangeStrategy = roleChangeStrategy;
-
-        final NetconfTopologyPathCreator pathCreator = new NetconfTopologyPathCreator(topologyId);
-        final Future<ActorRef> topologyRefFuture = actorSystem.actorSelection(pathCreator.build()).resolveOne(FiniteDuration.create(10L, TimeUnit.SECONDS));
-        topologyRefFuture.onComplete(new OnComplete<ActorRef>() {
-            @Override
-            public void onComplete(Throwable throwable, ActorRef actorRef) throws Throwable {
-                if (throwable != null) {
-                    LOG.warn("Unable to resolve actor for path: {} ", "/user/" + topologyId, throwable);
-
-                }
-
-                LOG.debug("Actor ref for path {} resolved", "/user/" + topologyId);
-                topologyManager = TypedActor.get(actorSystem).typedActorOf(new TypedProps<>(TopologyManager.class, BaseTopologyManager.class), actorRef);
-            }
-        }, actorSystem.dispatcher());
-
-        final Future<ActorRef> nodeRefFuture = actorSystem.actorSelection(pathCreator.withSuffix(nodeId).build()).resolveOne(FiniteDuration.create(10L, TimeUnit.SECONDS));
-        nodeRefFuture.onComplete(new OnComplete<ActorRef>() {
-            @Override
-            public void onComplete(Throwable throwable, ActorRef actorRef) throws Throwable {
-                if (throwable != null) {
-                    LOG.warn("Unable to resolve actor for path: {} ", "/user/" + topologyId + "/" + nodeId, throwable);
-                }
-                LOG.debug("Actor ref for path {} resolved", "/user/" + topologyId);
-                nodeManager = TypedActor.get(actorSystem).typedActorOf(new TypedProps<>(NodeManager.class, BaseNodeManager.class), actorRef);
-            }
-        }, actorSystem.dispatcher());
-    }
-
-
-    @Nonnull
-    @Override public Node getInitialState(@Nonnull final NodeId nodeId,
-                                          @Nonnull final Node configNode) {
-        final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
-
-        final Node initialNode = new NodeBuilder()
-                .setNodeId(nodeId)
-                .addAugmentation(NetconfNode.class,
-                        new NetconfNodeBuilder()
-                                .setHost(netconfNode.getHost())
-                                .setPort(netconfNode.getPort())
-                                .setConnectionStatus(ConnectionStatus.Connecting)
-                                .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                .setClusteredConnectionStatus(
-                                        new ClusteredConnectionStatusBuilder()
-                                                .setNodeStatus(
-                                                        Lists.newArrayList(
-                                                                new NodeStatusBuilder()
-                                                                        .setNode(clusterExtension.selfAddress().toString())
-                                                                        .setStatus(Status.Unavailable)
-                                                                        .build()))
-                                                .build())
-                                .build())
-                .build();
-
-        if (currentOperationalNode == null) {
-            currentOperationalNode = initialNode;
-        }
-
-        return initialNode;
-    }
-
-    @Nonnull @Override public Node getFailedState(@Nonnull final NodeId nodeId,
-                                                  @Nullable final Node configNode) {
-        final NetconfNode netconfNode = configNode == null ? currentOperationalNode.getAugmentation(NetconfNode.class) : configNode.getAugmentation(NetconfNode.class);
-
-        final Node failedNode = new NodeBuilder()
-                .setNodeId(nodeId)
-                .addAugmentation(NetconfNode.class,
-                        new NetconfNodeBuilder()
-                                .setHost(netconfNode.getHost())
-                                .setPort(netconfNode.getPort())
-                                .setConnectionStatus(ConnectionStatus.UnableToConnect)
-                                .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                .setClusteredConnectionStatus(
-                                        new ClusteredConnectionStatusBuilder()
-                                                .setNodeStatus(
-                                                        Collections.singletonList(
-                                                                new NodeStatusBuilder()
-                                                                        .setNode(clusterExtension.selfAddress().toString())
-                                                                        .setStatus(Status.Failed)
-                                                                        .build()))
-                                                .build())
-                                .build())
-                .build();
-
-        if (currentOperationalNode == null) {
-            currentOperationalNode = failedNode;
-        }
-
-        return failedNode;
-    }
-
-    @Nonnull @Override public ListenableFuture<Node> onNodeCreated(@Nonnull final NodeId nodeId,
-                                                                   @Nonnull final Node configNode) {
-        cachedContext = TypedActor.context();
-        this.nodeId = nodeId.getValue();
-        this.currentConfig = configNode;
-        // set initial state before anything happens
-        this.currentOperationalNode = getInitialState(nodeId, configNode);
-
-        // connect magic, send config into the netconf pipeline through topo dispatcher
-        final ListenableFuture<NetconfDeviceCapabilities> connectionFuture = topologyDispatcher.connectNode(nodeId, configNode);
-
-        Futures.addCallback(connectionFuture, new FutureCallback<NetconfDeviceCapabilities>() {
-            @Override
-            public void onSuccess(@Nullable NetconfDeviceCapabilities result) {
-                connectionStatusregistration = topologyDispatcher.registerConnectionStatusListener(nodeId, nodeManager);
-                sessionListener = topologyDispatcher.registerNetconfClientSessionListener(nodeId, NetconfNodeManagerCallback.this);
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                LOG.error("Connection to device failed", t);
-            }
-        });
-
-        final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
-
-        // transform future result into state that gets written into datastore
-        return Futures.transform(connectionFuture, new Function<NetconfDeviceCapabilities, Node>() {
-            @Nullable
-            @Override
-            public Node apply(NetconfDeviceCapabilities input) {
-                // build state data
-                currentOperationalNode = new NodeBuilder().setNodeId(nodeId)
-                        .addAugmentation(NetconfNode.class,
-                                new NetconfNodeBuilder()
-                                        .setConnectionStatus(ConnectionStatus.Connected)
-                                        .setClusteredConnectionStatus(
-                                                new ClusteredConnectionStatusBuilder()
-                                                        .setNodeStatus(
-                                                                Collections.singletonList(
-                                                                        new NodeStatusBuilder()
-                                                                                .setNode(clusterExtension.selfAddress().toString())
-                                                                                .setStatus(Status.Connected)
-                                                                                .build()))
-                                                        .build())
-                                        .setHost(netconfNode.getHost())
-                                        .setPort(netconfNode.getPort())
-                                        .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                        .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                        .build()).build();
-                return currentOperationalNode;
-            }
-        });
-    }
-
-    @Nonnull
-    @Override
-    public ListenableFuture<Node> onNodeUpdated(@Nonnull final NodeId nodeId,
-                                                @Nonnull final Node configNode) {
-        // first disconnect this node
-        topologyDispatcher.unregisterMountPoint(nodeId);
-
-        if (connectionStatusregistration != null) {
-            connectionStatusregistration.close();
-        }
-        topologyDispatcher.disconnectNode(nodeId);
-
-        // now reinit this connection with new settings
-        final ListenableFuture<NetconfDeviceCapabilities> connectionFuture = topologyDispatcher.connectNode(nodeId, configNode);
-
-        Futures.addCallback(connectionFuture, new FutureCallback<NetconfDeviceCapabilities>() {
-            @Override
-            public void onSuccess(@Nullable NetconfDeviceCapabilities result) {
-                connectionStatusregistration = topologyDispatcher.registerConnectionStatusListener(nodeId, NetconfNodeManagerCallback.this);
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                LOG.error("Connection to device failed", t);
-            }
-        });
-
-        final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
-
-        return Futures.transform(connectionFuture, new Function<NetconfDeviceCapabilities, Node>() {
-            @Nullable
-            @Override
-            public Node apply(NetconfDeviceCapabilities input) {
-                // build state data
-                return new NodeBuilder()
-                        .setNodeId(nodeId)
-                        .addAugmentation(NetconfNode.class,
-                                new NetconfNodeBuilder()
-                                        .setConnectionStatus(ConnectionStatus.Connected)
-                                        .setClusteredConnectionStatus(
-                                                new ClusteredConnectionStatusBuilder()
-                                                        .setNodeStatus(
-                                                                Collections.singletonList(
-                                                                        new NodeStatusBuilder()
-                                                                                .setNode(clusterExtension.selfAddress().toString())
-                                                                                .setStatus(Status.Connected)
-                                                                                .build()))
-                                                        .build())
-                                        .setHost(netconfNode.getHost())
-                                        .setPort(netconfNode.getPort())
-                                        .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                        .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                        .build())
-                        .build();
-            }
-        });
-    }
-
-    @Nonnull @Override public ListenableFuture<Void> onNodeDeleted(@Nonnull final NodeId nodeId) {
-        // cleanup and disconnect
-        topologyDispatcher.unregisterMountPoint(nodeId);
-
-        if(connectionStatusregistration != null) {
-            connectionStatusregistration.close();
-        }
-        roleChangeStrategy.unregisterRoleCandidate();
-        return topologyDispatcher.disconnectNode(nodeId);
-    }
-
-    @Nonnull
-    @Override
-    public ListenableFuture<Node> getCurrentStatusForNode(@Nonnull NodeId nodeId) {
-        LOG.debug("Getting current status for node: {} status: {}", nodeId, currentOperationalNode);
-        return Futures.immediateFuture(currentOperationalNode);
-    }
-
-    @Override
-    public void onRoleChanged(final RoleChangeDTO roleChangeDTO) {
-        topologyDispatcher.unregisterMountPoint(new NodeId(nodeId));
-
-        isMaster = roleChangeDTO.isOwner();
-    }
-
-    @Override
-    public void onDeviceConnected(final SchemaContext remoteSchemaContext, final NetconfSessionPreferences netconfSessionPreferences, final DOMRpcService deviceRpc) {
-        // we need to notify the higher level that something happened, get a current status from all other nodes, and aggregate a new result
-        connected = true;
-        if (isMaster) {
-            LOG.debug("Master is done with schema resolution, registering mount point");
-            topologyDispatcher.registerMountPoint(TypedActor.context(), new NodeId(nodeId));
-        } else if (masterDataBrokerRef != null) {
-            LOG.warn("Device connected, master already present in topology, registering mount point");
-            topologyDispatcher.registerMountPoint(cachedContext, new NodeId(nodeId), masterDataBrokerRef);
-        }
-
-        List<String> capabilityList = new ArrayList<>();
-        capabilityList.addAll(netconfSessionPreferences.getNetconfDeviceCapabilities().getNonModuleBasedCapabilities());
-        capabilityList.addAll(FluentIterable.from(netconfSessionPreferences.getNetconfDeviceCapabilities().getResolvedCapabilities()).transform(AVAILABLE_CAPABILITY_TRANSFORMER).toList());
-        final AvailableCapabilitiesBuilder avCapabalitiesBuilder = new AvailableCapabilitiesBuilder();
-        avCapabalitiesBuilder.setAvailableCapability(capabilityList);
-
-        final UnavailableCapabilities unavailableCapabilities =
-                new UnavailableCapabilitiesBuilder().setUnavailableCapability(FluentIterable.from(netconfSessionPreferences.getNetconfDeviceCapabilities().getUnresolvedCapabilites().entrySet())
-                        .transform(UNAVAILABLE_CAPABILITY_TRANSFORMER).toList()).build();
-
-        final NetconfNode netconfNode = currentConfig.getAugmentation(NetconfNode.class);
-        currentOperationalNode = new NodeBuilder().setNodeId(new NodeId(nodeId))
-                .addAugmentation(NetconfNode.class,
-                        new NetconfNodeBuilder()
-                                .setConnectionStatus(ConnectionStatus.Connected)
-                                .setClusteredConnectionStatus(
-                                        new ClusteredConnectionStatusBuilder()
-                                                .setNodeStatus(
-                                                        Collections.singletonList(
-                                                                new NodeStatusBuilder()
-                                                                        .setNode(clusterExtension.selfAddress().toString())
-                                                                        .setStatus(Status.Connected)
-                                                                        .build()))
-                                                .build())
-                                .setHost(netconfNode.getHost())
-                                .setPort(netconfNode.getPort())
-                                .setAvailableCapabilities(avCapabalitiesBuilder.build())
-                                .setUnavailableCapabilities(unavailableCapabilities)
-                                .build())
-                .build();
-        topologyManager.notifyNodeStatusChange(new NodeId(nodeId));
-    }
-
-    @Override
-    public void onDeviceDisconnected() {
-        // we need to notify the higher level that something happened, get a current status from all other nodes, and aggregate a new result
-        LOG.debug("onDeviceDisconnected received, unregistered role candidate");
-        connected = false;
-        if (isMaster) {
-            // set master to false since we are unregistering, the ownershipChanged callback can sometimes lag behind causing multiple nodes behaving as masters
-            isMaster = false;
-            // onRoleChanged() callback can sometimes lag behind, so unregister the mount right when it disconnects
-            topologyDispatcher.unregisterMountPoint(new NodeId(nodeId));
-        }
-
-        final NetconfNode netconfNode = currentConfig.getAugmentation(NetconfNode.class);
-        currentOperationalNode = new NodeBuilder().setNodeId(new NodeId(nodeId))
-                .addAugmentation(NetconfNode.class,
-                        new NetconfNodeBuilder()
-                                .setConnectionStatus(ConnectionStatus.Connecting)
-                                .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                .setClusteredConnectionStatus(
-                                        new ClusteredConnectionStatusBuilder()
-                                                .setNodeStatus(
-                                                        Collections.singletonList(
-                                                                new NodeStatusBuilder()
-                                                                        .setNode(clusterExtension.selfAddress().toString())
-                                                                        .setStatus(Status.Unavailable)
-                                                                        .build()))
-                                                .build())
-                                .setHost(netconfNode.getHost())
-                                .setPort(netconfNode.getPort())
-                                .build()).build();
-        topologyManager.notifyNodeStatusChange(new NodeId(nodeId));
-    }
-
-    @Override
-    public void onDeviceFailed(Throwable throwable) {
-        // we need to notify the higher level that something happened, get a current status from all other nodes, and aggregate a new result
-        // no need to remove mountpoint, we should receive onRoleChanged callback after unregistering from election that unregisters the mountpoint
-        LOG.warn("Netconf node {} failed with {}", nodeId, throwable);
-        connected = false;
-        String reason = (throwable != null && throwable.getMessage() != null) ? throwable.getMessage() : UNKNOWN_REASON;
-
-        currentOperationalNode = new NodeBuilder().setNodeId(new NodeId(nodeId))
-                .addAugmentation(NetconfNode.class,
-                        new NetconfNodeBuilder()
-                                .setConnectionStatus(ConnectionStatus.UnableToConnect)
-                                .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                .setClusteredConnectionStatus(
-                                        new ClusteredConnectionStatusBuilder()
-                                                .setNodeStatus(
-                                                        Collections.singletonList(
-                                                                new NodeStatusBuilder()
-                                                                        .setNode(clusterExtension.selfAddress().toString())
-                                                                        .setStatus(Status.Failed)
-                                                                        .build()))
-                                                .build())
-                                .setConnectedMessage(reason)
-                                .build()).build();
-        topologyManager.notifyNodeStatusChange(new NodeId(nodeId));
-    }
-
-    @Override
-    public void onNotification(DOMNotification domNotification) {
-        //NOOP
-    }
-
-    @Override
-    public void close() {
-        //NOOP
-    }
-
-    @Override
-    public void onReceive(Object message, ActorRef actorRef) {
-        LOG.debug("Netconf node callback received message {}", message);
-        if (message instanceof AnnounceMasterMountPoint) {
-            masterDataBrokerRef = actorRef;
-            // candidate gets registered when mount point is already prepared so we can go ahead a register it
-            if (connected) {
-                topologyDispatcher.registerMountPoint(TypedActor.context(), new NodeId(nodeId), masterDataBrokerRef);
-            } else {
-                LOG.debug("Announce master mount point msg received but mount point is not ready yet");
-            }
-        } else if (message instanceof AnnounceMasterMountPointDown) {
-            LOG.debug("Master mountpoint went down");
-            masterDataBrokerRef = null;
-            topologyDispatcher.unregisterMountPoint(new NodeId(nodeId));
-        }
-    }
-
-    @Override
-    public void onSessionUp(NetconfClientSession netconfClientSession) {
-        //NetconfClientSession is up, we can register role candidate
-        LOG.debug("Netconf client session is up, registering role candidate");
-        roleChangeStrategy.registerRoleCandidate(nodeManager);
-    }
-
-    @Override
-    public void onSessionDown(NetconfClientSession netconfClientSession, Exception e) {
-        LOG.debug("Netconf client session is down, unregistering role candidate");
-        roleChangeStrategy.unregisterRoleCandidate();
-    }
-
-    @Override
-    public void onSessionTerminated(NetconfClientSession netconfClientSession, NetconfTerminationReason netconfTerminationReason) {
-        LOG.debug("Netconf client session is down, unregistering role candidate");
-        roleChangeStrategy.unregisterRoleCandidate();
-    }
-
-    @Override
-    public void onMessage(NetconfClientSession netconfClientSession, NetconfMessage netconfMessage) {
-        //NOOP
-    }
-}
\ No newline at end of file
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfNodeOperationalDataAggregator.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfNodeOperationalDataAggregator.java
deleted file mode 100644 (file)
index 4a739f9..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.impl;
-
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import java.util.ArrayList;
-import java.util.List;
-import org.opendaylight.netconf.topology.StateAggregator;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilities;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NetconfNodeOperationalDataAggregator implements StateAggregator{
-
-    private static final Logger LOG = LoggerFactory.getLogger(NetconfNodeOperationalDataAggregator.class);
-
-    @Override
-    public ListenableFuture<Node> combineCreateAttempts(final List<ListenableFuture<Node>> stateFutures) {
-        final SettableFuture<Node> future = SettableFuture.create();
-        final ListenableFuture<List<Node>> allAsList = Futures.allAsList(stateFutures);
-        Futures.addCallback(allAsList, new FutureCallback<List<Node>>() {
-            @Override
-            public void onSuccess(final List<Node> result) {
-                Node base = null;
-                NetconfNode baseAugmentation = null;
-                AvailableCapabilities masterCaps = null;
-                UnavailableCapabilities unavailableMasterCaps = null;
-                final ArrayList<NodeStatus> statusList = new ArrayList<>();
-                for (final Node node : result) {
-                    final NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
-                    if (base == null && netconfNode.getConnectionStatus().equals(ConnectionStatus.Connected)) {
-                        base = node;
-                        baseAugmentation = netconfNode;
-                    }
-                    // we need to pull out caps from master, since slave does not go through resolution
-                    if (masterCaps == null) {
-                        masterCaps = netconfNode.getAvailableCapabilities();
-                        unavailableMasterCaps = netconfNode.getUnavailableCapabilities();
-                    }
-                    if (netconfNode.getAvailableCapabilities().getAvailableCapability().size() > masterCaps.getAvailableCapability().size()) {
-                        masterCaps = netconfNode.getAvailableCapabilities();
-                        unavailableMasterCaps = netconfNode.getUnavailableCapabilities();
-                    }
-                    LOG.debug(netconfNode.toString());
-                    statusList.addAll(netconfNode.getClusteredConnectionStatus().getNodeStatus());
-                }
-
-                if (base == null) {
-                    base = result.get(0);
-                    baseAugmentation = result.get(0).getAugmentation(NetconfNode.class);
-                    LOG.debug("All results {}", result.toString());
-                }
-
-                final Node aggregatedNode =
-                        new NodeBuilder(base)
-                                .addAugmentation(NetconfNode.class,
-                                        new NetconfNodeBuilder(baseAugmentation)
-                                                .setClusteredConnectionStatus(
-                                                        new ClusteredConnectionStatusBuilder()
-                                                                .setNodeStatus(statusList)
-                                                                .build())
-                                                .setAvailableCapabilities(masterCaps)
-                                                .setUnavailableCapabilities(unavailableMasterCaps)
-                                                .build())
-                                .build();
-
-                future.set(aggregatedNode);
-            }
-
-            @Override
-            public void onFailure(final Throwable t) {
-                LOG.error("One of the combined create attempts failed {}", t);
-                future.setException(t);
-            }
-        });
-        return future;
-    }
-
-    @Override
-    public ListenableFuture<Node> combineUpdateAttempts(final List<ListenableFuture<Node>> stateFutures) {
-        final SettableFuture<Node> future = SettableFuture.create();
-        final ListenableFuture<List<Node>> allAsList = Futures.allAsList(stateFutures);
-        Futures.addCallback(allAsList, new FutureCallback<List<Node>>() {
-            @Override
-            public void onSuccess(final List<Node> result) {
-                Node base = null;
-                NetconfNode baseAugmentation = null;
-                AvailableCapabilities masterCaps = null;
-                UnavailableCapabilities unavailableMasterCaps = null;
-                final ArrayList<NodeStatus> statusList = new ArrayList<>();
-                for (final Node node : result) {
-                    final NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
-                    if (base == null && netconfNode.getConnectionStatus().equals(ConnectionStatus.Connected)) {
-                        base = node;
-                        baseAugmentation = netconfNode;
-                    }
-                    // we need to pull out caps from master, since slave does not go through resolution
-                    if (masterCaps == null) {
-                        masterCaps = netconfNode.getAvailableCapabilities();
-                        unavailableMasterCaps = netconfNode.getUnavailableCapabilities();
-                    }
-                    if (netconfNode.getAvailableCapabilities().getAvailableCapability().size() > masterCaps.getAvailableCapability().size()) {
-                        masterCaps = netconfNode.getAvailableCapabilities();
-                        unavailableMasterCaps = netconfNode.getUnavailableCapabilities();
-                    }
-                    LOG.debug(netconfNode.toString());
-                    statusList.addAll(netconfNode.getClusteredConnectionStatus().getNodeStatus());
-                }
-
-                if (base == null) {
-                    base = result.get(0);
-                    baseAugmentation = result.get(0).getAugmentation(NetconfNode.class);
-                    LOG.debug("All results {}", result.toString());
-                }
-
-                final Node aggregatedNode =
-                        new NodeBuilder(base)
-                                .addAugmentation(NetconfNode.class,
-                                        new NetconfNodeBuilder(baseAugmentation)
-                                                .setClusteredConnectionStatus(
-                                                        new ClusteredConnectionStatusBuilder()
-                                                                .setNodeStatus(statusList)
-                                                                .build())
-                                                .setAvailableCapabilities(masterCaps)
-                                                .setUnavailableCapabilities(unavailableMasterCaps)
-                                                .build())
-                                .build();
-                future.set(aggregatedNode);
-            }
-
-            @Override
-            public void onFailure(final Throwable t) {
-                LOG.error("One of the combined update attempts failed {}", t);
-                future.setException(t);
-            }
-        });
-        return future;
-    }
-
-    @Override
-    public ListenableFuture<Void> combineDeleteAttempts(final List<ListenableFuture<Void>> stateFutures) {
-        final SettableFuture<Void> future = SettableFuture.create();
-        final ListenableFuture<List<Void>> allAsList = Futures.allAsList(stateFutures);
-        Futures.addCallback(allAsList, new FutureCallback<List<Void>>() {
-            @Override
-            public void onSuccess(final List<Void> result) {
-                future.set(null);
-            }
-
-            @Override
-            public void onFailure(final Throwable t) {
-                LOG.error("One of the combined delete attempts failed {}", t);
-                future.setException(t);
-            }
-        });
-        return future;
-    }
-}
index c1e41189e3353a05dac9aa010cd1ec855ef2f6c8..0553a5aa5b4753ccf1af8c94a26c331cefda5177 100644 (file)
@@ -8,8 +8,6 @@
 
 package org.opendaylight.netconf.topology.impl;
 
-import akka.actor.ActorContext;
-import akka.actor.ActorRef;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import io.netty.util.concurrent.EventExecutor;
@@ -34,11 +32,8 @@ import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.topology.AbstractNetconfTopology;
 import org.opendaylight.netconf.topology.SchemaRepositoryProvider;
-import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade.ConnectionStatusListenerRegistration;
-import org.opendaylight.netconf.topology.util.TopologyUtil;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
@@ -84,26 +79,6 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology implements Data
         return new NetconfDeviceSalFacade(id, domBroker, bindingAwareBroker);
     }
 
-    @Override
-    public void registerMountPoint(ActorContext context, NodeId nodeId) {
-        throw new UnsupportedOperationException("MountPoint registration is not supported in regular topology, this happens automaticaly in the netconf pipeline");
-    }
-
-    @Override
-    public void registerMountPoint(ActorContext context, NodeId nodeId, ActorRef masterRef) {
-        throw new UnsupportedOperationException("MountPoint registration is not supported in regular topology, this happens automaticaly in the netconf pipeline");
-    }
-
-    @Override
-    public void unregisterMountPoint(NodeId nodeId) {
-        throw new UnsupportedOperationException("MountPoint registration is not supported in regular topology, this happens automaticaly in the netconf pipeline");
-    }
-
-    @Override
-    public ConnectionStatusListenerRegistration registerConnectionStatusListener(NodeId node, RemoteDeviceHandler<NetconfSessionPreferences> listener) {
-        throw new UnsupportedOperationException("Registering a listener on a regular netconf device is not supported(supported only in clustered netconf topology)");
-    }
-
     @Override
     public void onSessionInitiated(ProviderContext session) {
         dataBroker = session.getSALService(DataBroker.class);
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyManagerCallback.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyManagerCallback.java
deleted file mode 100644 (file)
index 3a9c8db..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.impl;
-
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netconf.topology.NodeManager;
-import org.opendaylight.netconf.topology.NodeManagerCallback.NodeManagerCallbackFactory;
-import org.opendaylight.netconf.topology.TopologyManagerCallback;
-import org.opendaylight.netconf.topology.util.BaseNodeManager.BaseNodeManagerBuilder;
-import org.opendaylight.netconf.topology.util.NodeWriter;
-import org.opendaylight.netconf.topology.util.NoopRoleChangeStrategy;
-import org.opendaylight.netconf.topology.util.SalNodeWriter;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NetconfTopologyManagerCallback implements TopologyManagerCallback {
-
-    private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyManagerCallback.class);
-
-    private final ActorSystem actorSystem;
-    private boolean isMaster;
-
-    private final String topologyId;
-    private final NodeWriter naSalNodeWriter;
-    private final Map<NodeId, NodeManager> nodes = new HashMap<>();
-    private final NodeManagerCallbackFactory nodeHandlerFactory;
-
-    public NetconfTopologyManagerCallback(final ActorSystem actorSystem,
-                                          final DataBroker dataBroker,
-                                          final String topologyId,
-                                          final NodeManagerCallbackFactory nodeHandlerFactory) {
-        this(actorSystem, topologyId, nodeHandlerFactory, new SalNodeWriter(dataBroker, topologyId));
-    }
-
-    public NetconfTopologyManagerCallback(final ActorSystem actorSystem,
-                                          final String topologyId,
-                                          final NodeManagerCallbackFactory nodeHandlerFactory,
-                                          final NodeWriter naSalNodeWriter) {
-        this(actorSystem, topologyId, nodeHandlerFactory, naSalNodeWriter, false);
-
-    }
-
-    public NetconfTopologyManagerCallback(final ActorSystem actorSystem,
-                                          final String topologyId,
-                                          final NodeManagerCallbackFactory nodeHandlerFactory,
-                                          final NodeWriter naSalNodeWriter,
-                                          boolean isMaster) {
-        this.actorSystem = actorSystem;
-        this.topologyId = topologyId;
-        this.nodeHandlerFactory = nodeHandlerFactory;
-        this.naSalNodeWriter = naSalNodeWriter;
-
-        this.isMaster = isMaster;
-    }
-
-    @Override
-    public ListenableFuture<Node> onNodeCreated(final NodeId nodeId, final Node node) {
-
-        // if this node was already configured, and whole config was pushed again, reinit with update
-        if (nodes.containsKey(nodeId)) {
-            return onNodeUpdated(nodeId, node);
-        }
-
-        // Init node admin
-        final NodeManager naBaseNodeManager =
-                createNodeManager(nodeId);
-        nodes.put(nodeId, naBaseNodeManager);
-
-        // only master should put initial state into datastore
-        if (isMaster) {
-            naSalNodeWriter.init(nodeId, naBaseNodeManager.getInitialState(nodeId, node));
-        }
-
-        // trigger connect on this node
-        return naBaseNodeManager.onNodeCreated(nodeId, node);
-    }
-
-    @Override
-    public ListenableFuture<Node> onNodeUpdated(final NodeId nodeId, final Node node) {
-        // only master should put initial state into datastore
-        if (isMaster) {
-            naSalNodeWriter.init(nodeId, nodes.get(nodeId).getInitialState(nodeId, node));
-        }
-
-        // Trigger onNodeUpdated only on this node
-        return nodes.get(nodeId).onNodeUpdated(nodeId, node);
-    }
-
-    @Override
-    public ListenableFuture<Void> onNodeDeleted(final NodeId nodeId) {
-        // Trigger delete only on this node
-        final ListenableFuture<Void> future = nodes.get(nodeId).onNodeDeleted(nodeId);
-        Futures.addCallback(future, new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-                // remove proxy from node list and stop the actor
-                LOG.debug("Stopping node actor for node : {}", nodeId.getValue());
-                final NodeManager remove = nodes.remove(nodeId);
-                TypedActor.get(actorSystem).stop(remove);
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                // NOOP will be handled on higher level
-            }
-        });
-        return future;
-    }
-
-    @Nonnull
-    @Override
-    public ListenableFuture<Node> getCurrentStatusForNode(@Nonnull NodeId nodeId) {
-        if (!nodes.containsKey(nodeId)) {
-            nodes.put(nodeId, createNodeManager(nodeId));
-        }
-        return nodes.get(nodeId).getCurrentStatusForNode(nodeId);
-    }
-
-    @Override
-    public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-        isMaster = roleChangeDTO.isOwner();
-        // our post-election logic
-    }
-
-    private NodeManager createNodeManager(NodeId nodeId) {
-        return new BaseNodeManagerBuilder().setNodeId(nodeId.getValue())
-                .setActorContext(TypedActor.context())
-                .setDelegateFactory(nodeHandlerFactory)
-                .setRoleChangeStrategy(new NoopRoleChangeStrategy())
-                .setTopologyId(topologyId)
-                .build();
-    }
-
-    @Override
-    public void onReceive(Object o, ActorRef actorRef) {
-
-    }
-
-    @Nonnull
-    @Override
-    public Node getInitialState(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-        return nodes.get(nodeId).getInitialState(nodeId, configNode);
-    }
-
-    @Nonnull
-    @Override
-    public Node getFailedState(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-        return nodes.get(nodeId).getFailedState(nodeId, configNode);
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriter.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriter.java
deleted file mode 100644 (file)
index 8106799..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.impl;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import java.util.concurrent.locks.ReentrantLock;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
-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.AsyncTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.netconf.topology.util.NodeWriter;
-import org.opendaylight.netconf.topology.util.TopologyUtil;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TopologyNodeWriter implements NodeWriter{
-
-    private static final Logger LOG = LoggerFactory.getLogger(TopologyNodeWriter.class);
-
-    private final String topologyId;
-    private final BindingTransactionChain txChain;
-
-    private final InstanceIdentifier<NetworkTopology> networkTopologyPath;
-    private final KeyedInstanceIdentifier<Topology, TopologyKey> topologyListPath;
-
-    private final ReentrantLock lock = new ReentrantLock(true);
-
-    public TopologyNodeWriter(final String topologyId, final DataBroker dataBroker) {
-        this.topologyId = topologyId;
-        this.txChain = Preconditions.checkNotNull(dataBroker).createTransactionChain(new TransactionChainListener() {
-            @Override
-            public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction, Throwable cause) {
-                LOG.error("{}: TransactionChain({}) {} FAILED!", chain,
-                        transaction.getIdentifier(), cause);
-                throw new IllegalStateException("Clustered topology writer TransactionChain(" + chain + ") not committed correctly", cause);
-            }
-
-            @Override
-            public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
-                LOG.trace("Clustered topology writer TransactionChain({}) SUCCESSFUL", chain);
-            }
-        });
-
-        this.networkTopologyPath = InstanceIdentifier.builder(NetworkTopology.class).build();
-        this.topologyListPath = networkTopologyPath.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
-
-        // write an empty topology container at the start
-        final WriteTransaction wTx = txChain.newWriteOnlyTransaction();
-        createNetworkTopologyIfNotPresent(wTx, LogicalDatastoreType.OPERATIONAL);
-        createNetworkTopologyIfNotPresent(wTx, LogicalDatastoreType.CONFIGURATION);
-        commitTransaction(wTx, "init topology container", new NodeId("topology-netconf"));
-    }
-
-    @Override
-    public void init(@Nonnull NodeId id, @Nonnull Node operationalDataNode) {
-        lock.lock();
-        try {
-            final WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
-
-            createNetworkTopologyIfNotPresent(writeTx, LogicalDatastoreType.OPERATIONAL);
-            final InstanceIdentifier<Node> path = TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId);
-
-            LOG.trace("{}: Init device state transaction {} putting if absent operational data started. Putting data on path {}",
-                    id.getValue(), writeTx.getIdentifier(), path);
-            writeTx.put(LogicalDatastoreType.OPERATIONAL, path, operationalDataNode);
-            LOG.trace("{}: Init device state transaction {} putting operational data ended.",
-                    id.getValue(), writeTx.getIdentifier());
-
-            commitTransaction(writeTx, "init", id);
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    @Override
-    public void update(@Nonnull NodeId id, @Nonnull Node operationalDataNode) {
-        lock.lock();
-        try {
-            final WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
-
-            final InstanceIdentifier<Node> path = TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId);
-            LOG.trace("{}: Update device state transaction {} merging operational data started. Putting data on path {}",
-                    id, writeTx.getIdentifier(), operationalDataNode);
-            writeTx.put(LogicalDatastoreType.OPERATIONAL, path, operationalDataNode);
-            LOG.trace("{}: Update device state transaction {} merging operational data ended.",
-                    id, writeTx.getIdentifier());
-
-            commitTransaction(writeTx, "update", id);
-        } finally {
-            lock.unlock();
-        }
-
-    }
-
-    @Override
-    public void delete(@Nonnull NodeId id) {
-        lock.lock();
-        try {
-            final WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
-
-            final InstanceIdentifier<Node> path = TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId);
-
-            LOG.trace(
-                    "{}: Close device state transaction {} removing all data started. Path: {}",
-                    id, writeTx.getIdentifier(), path);
-            writeTx.delete(LogicalDatastoreType.OPERATIONAL, path);
-            LOG.trace(
-                    "{}: Close device state transaction {} removing all data ended.",
-                    id, writeTx.getIdentifier());
-
-            commitTransaction(writeTx, "close", id);
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    private void commitTransaction(final WriteTransaction transaction, final String txType, final NodeId id) {
-        LOG.trace("{}: Committing Transaction {}:{}", id.getValue(), txType,
-                transaction.getIdentifier());
-        final CheckedFuture<Void, TransactionCommitFailedException> result = transaction.submit();
-
-        Futures.addCallback(result, new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(final Void result) {
-                LOG.trace("{}: Transaction({}) {} SUCCESSFUL", id.getValue(), txType,
-                        transaction.getIdentifier());
-            }
-
-            @Override
-            public void onFailure(final Throwable t) {
-                LOG.error("{}: Transaction({}) {} FAILED!", id.getValue(), txType,
-                        transaction.getIdentifier(), t);
-                throw new IllegalStateException(id.getValue() + "  Transaction(" + txType + ") not committed correctly", t);
-            }
-        });
-    }
-
-    private void createNetworkTopologyIfNotPresent(final WriteTransaction writeTx, final LogicalDatastoreType datastoreType) {
-
-        final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
-        LOG.trace("{}: Merging {} container to ensure its presence", topologyId,
-                NetworkTopology.QNAME, writeTx.getIdentifier());
-        writeTx.merge(datastoreType, networkTopologyPath, networkTopology);
-
-        final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
-        LOG.trace("{}: Merging {} container to ensure its presence", topologyId,
-                Topology.QNAME, writeTx.getIdentifier());
-        writeTx.merge(datastoreType, topologyListPath, topology);
-    }
-}
similarity index 84%
rename from netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyUtil.java
rename to netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyUtil.java
index d7c700d1a99a4946452e88a53370e963a0592110..336589de405bca783c171a5c11da49898f5eaf9e 100644 (file)
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.netconf.topology.util;
+package org.opendaylight.netconf.topology.impl;
 
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
@@ -47,12 +47,4 @@ public final class TopologyUtil {
         final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
         return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
     }
-
-    public static InstanceIdentifier<Node> createTopologyNodeListPath(final NodeKey key, final String topologyId) {
-        return createTopologyListPath(topologyId).child(Node.class, new NodeKey(new NodeId(key.getNodeId().getValue())));
-    }
-
-    public static InstanceIdentifier<Node> createTopologyNodePath(final String topologyId) {
-        return createTopologyListPath(topologyId).child(Node.class);
-    }
 }
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredDeviceSourcesResolver.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredDeviceSourcesResolver.java
deleted file mode 100644 (file)
index 6e0c1d1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import akka.actor.TypedActor;
-import java.util.Set;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-import scala.concurrent.Future;
-
-public interface ClusteredDeviceSourcesResolver extends TypedActor.Receiver, TypedActor.PreStart {
-
-    Future<Set<SourceIdentifier>> getResolvedSources();
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredDeviceSourcesResolverImpl.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredDeviceSourcesResolverImpl.java
deleted file mode 100644 (file)
index 8ea8d3d..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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
- */
-
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import akka.actor.TypedProps;
-import akka.cluster.Cluster;
-import akka.cluster.Member;
-import akka.dispatch.Futures;
-import akka.dispatch.OnComplete;
-import java.util.List;
-import java.util.Set;
-import org.opendaylight.controller.cluster.schema.provider.impl.RemoteSchemaProvider;
-import org.opendaylight.netconf.topology.pipeline.messages.AnnounceClusteredDeviceSourcesResolverUp;
-import org.opendaylight.netconf.topology.pipeline.messages.AnnounceMasterOnSameNodeUp;
-import org.opendaylight.netconf.topology.pipeline.messages.AnnounceMasterSourceProviderUp;
-import org.opendaylight.netconf.util.NetconfTopologyPathCreator;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
-import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
-import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import scala.concurrent.Future;
-import scala.concurrent.Promise;
-
-
-public class ClusteredDeviceSourcesResolverImpl implements ClusteredDeviceSourcesResolver {
-
-    private static Logger LOG = LoggerFactory.getLogger(ClusteredDeviceSourcesResolver.class);
-
-    private final String topologyId;
-    private final String nodeId;
-    private final ActorSystem actorSystem;
-    private final SchemaSourceRegistry schemaRegistry;
-    private final List<SchemaSourceRegistration<? extends SchemaSourceRepresentation>> sourceRegistrations;
-
-    private final Promise<Set<SourceIdentifier>> resolvedSourcesPromise;
-    private MasterSourceProvider remoteYangTextSourceProvider;
-
-    public ClusteredDeviceSourcesResolverImpl(String topologyId, String nodeId, ActorSystem actorSystem,
-                                              SchemaSourceRegistry schemaRegistry,
-                                              List<SchemaSourceRegistration<? extends SchemaSourceRepresentation>> sourceRegistrations) {
-        this.topologyId = topologyId;
-        this.nodeId = nodeId;
-        this.actorSystem = actorSystem;
-        this.schemaRegistry = schemaRegistry;
-        this.sourceRegistrations = sourceRegistrations;
-        resolvedSourcesPromise = Futures.promise();
-    }
-
-    @Override
-    public void preStart(){
-        Cluster cluster = Cluster.get(actorSystem);
-        for(Member node : cluster.state().getMembers()) {
-            if(!node.address().equals(cluster.selfAddress())) {
-                final NetconfTopologyPathCreator pathCreator = new NetconfTopologyPathCreator(node.address().toString(), topologyId);
-                final String path = pathCreator.withSuffix(nodeId).withSuffix(NetconfTopologyPathCreator.MASTER_SOURCE_PROVIDER).build();
-                actorSystem.actorSelection(path).tell(new AnnounceClusteredDeviceSourcesResolverUp(), TypedActor.context().self());
-            }
-        }
-    }
-
-    @Override
-    public void onReceive(Object o, ActorRef actorRef) {
-        if(o instanceof AnnounceMasterSourceProviderUp) {
-            if(remoteYangTextSourceProvider == null) {
-                remoteYangTextSourceProvider = TypedActor.get(actorSystem).typedActorOf(
-                        new TypedProps<>(MasterSourceProvider.class,
-                                MasterSourceProviderImpl.class), actorRef);
-                registerProvidedSourcesToSchemaRegistry();
-            }
-        } else if(o instanceof AnnounceMasterOnSameNodeUp) {
-            resolvedSourcesPromise.failure(new MasterSourceProviderOnSameNodeException());
-        }
-    }
-
-    private void registerProvidedSourcesToSchemaRegistry() {
-        Future<Set<SourceIdentifier>> sourcesFuture = remoteYangTextSourceProvider.getProvidedSources();
-        resolvedSourcesPromise.completeWith(sourcesFuture);
-        final RemoteSchemaProvider remoteProvider = new RemoteSchemaProvider(remoteYangTextSourceProvider, actorSystem.dispatcher());
-
-        sourcesFuture.onComplete(new OnComplete<Set<SourceIdentifier>>() {
-            @Override
-            public void onComplete(Throwable throwable, Set<SourceIdentifier> sourceIdentifiers) throws Throwable {
-                for (SourceIdentifier sourceId : sourceIdentifiers) {
-                   sourceRegistrations.add(schemaRegistry.registerSchemaSource(remoteProvider,
-                           PotentialSchemaSource.create(sourceId, YangTextSchemaSource.class, PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
-                }
-            }
-        }, actorSystem.dispatcher());
-    }
-
-    @Override
-    public Future<Set<SourceIdentifier>> getResolvedSources() {
-        return resolvedSourcesPromise.future();
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDevice.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDevice.java
deleted file mode 100644 (file)
index cf0a857..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import akka.actor.ActorContext;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import akka.actor.TypedProps;
-import akka.dispatch.OnComplete;
-import akka.japi.Creator;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.api.NetconfMessage;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
-import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.util.NetconfTopologyPathCreator;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
-import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ClusteredNetconfDevice extends NetconfDevice implements EntityOwnershipListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ClusteredNetconfDevice.class);
-
-    private NetconfDeviceCommunicator listener;
-    private NetconfSessionPreferences sessionPreferences;
-    private SchemaRepository schemaRepo;
-    private final ActorSystem actorSystem;
-    private final String topologyId;
-    private final String nodeId;
-    private final ActorContext cachedContext;
-
-    private MasterSourceProvider masterSourceProvider = null;
-    private ClusteredDeviceSourcesResolver resolver = null;
-
-    public ClusteredNetconfDevice(final SchemaResourcesDTO schemaResourcesDTO, final RemoteDeviceId id, final RemoteDeviceHandler<NetconfSessionPreferences> salFacade,
-                                  final ExecutorService globalProcessingExecutor, final ActorSystem actorSystem, final String topologyId, final String nodeId,
-                                  final ActorContext cachedContext, final boolean reconnectOnSchemaChanged) {
-        super(schemaResourcesDTO, id, salFacade, globalProcessingExecutor, reconnectOnSchemaChanged);
-        this.schemaRepo = (SchemaRepository) schemaResourcesDTO.getSchemaRegistry();
-        this.actorSystem = actorSystem;
-        this.topologyId = topologyId;
-        this.nodeId = nodeId;
-        this.cachedContext = cachedContext;
-    }
-
-    @Override
-    public void onRemoteSessionUp(NetconfSessionPreferences remoteSessionCapabilities, NetconfDeviceCommunicator listener) {
-        LOG.warn("Node {} SessionUp, with capabilities {}", nodeId, remoteSessionCapabilities);
-        this.listener = listener;
-        this.sessionPreferences = remoteSessionCapabilities;
-        slaveSetupSchema();
-    }
-
-
-    @Override
-    protected void handleSalInitializationSuccess(SchemaContext result, NetconfSessionPreferences remoteSessionCapabilities, DOMRpcService deviceRpc) {
-        super.handleSalInitializationSuccess(result, remoteSessionCapabilities, deviceRpc);
-
-        final Set<SourceIdentifier> sourceIds = Sets.newHashSet();
-        for(ModuleIdentifier id : result.getAllModuleIdentifiers()) {
-            sourceIds.add(SourceIdentifier.create(id.getName(), (SimpleDateFormatUtil.DEFAULT_DATE_REV == id.getRevision() ? Optional.<String>absent() :
-                    Optional.of(SimpleDateFormatUtil.getRevisionFormat().format(id.getRevision())))));
-        }
-
-        //TODO extract string constant to util class
-        LOG.debug("Creating master source provider");
-        masterSourceProvider = TypedActor.get(cachedContext).typedActorOf(
-                new TypedProps<>(MasterSourceProvider.class,
-                        new Creator<MasterSourceProviderImpl>() {
-                            @Override
-                            public MasterSourceProviderImpl create() throws Exception {
-                                return new MasterSourceProviderImpl(schemaRepo, sourceIds, actorSystem, topologyId, nodeId);
-                            }
-                        }), NetconfTopologyPathCreator.MASTER_SOURCE_PROVIDER);
-    }
-
-    @Override
-    public void onRemoteSessionDown() {
-        super.onRemoteSessionDown();
-        listener = null;
-        sessionPreferences = null;
-        if (masterSourceProvider != null) {
-            // if we have master the slave that started on this node should be already killed via PoisonPill, so stop master only now
-            LOG.debug("Stopping master source provider for node {}", nodeId);
-            TypedActor.get(actorSystem).stop(masterSourceProvider);
-            masterSourceProvider = null;
-        } else {
-            LOG.debug("Stopping slave source resolver for node {}", nodeId);
-            TypedActor.get(actorSystem).stop(resolver);
-            resolver = null;
-        }
-    }
-
-    private void slaveSetupSchema() {
-        //TODO extract string constant to util class
-        resolver = TypedActor.get(cachedContext).typedActorOf(
-                new TypedProps<>(ClusteredDeviceSourcesResolver.class,
-                        new Creator<ClusteredDeviceSourcesResolverImpl>() {
-                            @Override
-                            public ClusteredDeviceSourcesResolverImpl create() throws Exception {
-                                return new ClusteredDeviceSourcesResolverImpl(topologyId, nodeId, actorSystem, schemaRegistry, sourceRegistrations);
-                            }
-                        }), NetconfTopologyPathCreator.CLUSTERED_DEVICE_SOURCES_RESOLVER);
-
-        final FutureCallback<SchemaContext> schemaContextFuture = new FutureCallback<SchemaContext>() {
-            @Override
-            public void onSuccess(SchemaContext schemaContext) {
-                LOG.debug("{}: Schema context built successfully.", id);
-
-                final NetconfDeviceCapabilities deviceCap = sessionPreferences.getNetconfDeviceCapabilities();
-                final Set<QName> providedSourcesQnames = Sets.newHashSet();
-                for(ModuleIdentifier id : schemaContext.getAllModuleIdentifiers()) {
-                    providedSourcesQnames.add(QName.create(id.getQNameModule(), id.getName()));
-                }
-
-                deviceCap.addNonModuleBasedCapabilities(sessionPreferences.getNonModuleCaps());
-                deviceCap.addCapabilities(providedSourcesQnames);
-
-                ClusteredNetconfDevice.super.handleSalInitializationSuccess(
-                        schemaContext, sessionPreferences, getDeviceSpecificRpc(schemaContext, listener));
-            }
-
-            @Override
-            public void onFailure(Throwable throwable) {
-                LOG.warn("{}: Unexpected error resolving device sources: {}", id, throwable);
-                handleSalInitializationFailure(throwable, listener);
-            }
-        };
-
-        resolver.getResolvedSources().onComplete(
-                new OnComplete<Set<SourceIdentifier>>() {
-                    @Override
-                    public void onComplete(Throwable throwable, Set<SourceIdentifier> sourceIdentifiers) throws Throwable {
-                        if(throwable != null) {
-                            if(throwable instanceof MasterSourceProviderOnSameNodeException) {
-                                //do nothing
-                            } else {
-                                LOG.warn("{}: Unexpected error resolving device sources: {}", id, throwable);
-                                handleSalInitializationFailure(throwable, listener);
-                            }
-                        } else {
-                            LOG.trace("{}: Trying to build schema context from {}", id, sourceIdentifiers);
-                            Futures.addCallback(schemaContextFactory.createSchemaContext(sourceIdentifiers), schemaContextFuture);
-                        }
-                    }
-                }, actorSystem.dispatcher());
-    }
-
-    private NetconfDeviceRpc getDeviceSpecificRpc(SchemaContext result, RemoteDeviceCommunicator<NetconfMessage> listener) {
-        return new NetconfDeviceRpc(result, listener, new NetconfMessageTransformer(result, true));
-    }
-
-    @Override
-    public void ownershipChanged(EntityOwnershipChange ownershipChange) {
-        LOG.debug("Entity ownership change received {}", ownershipChange);
-        if(ownershipChange.isOwner()) {
-            super.onRemoteSessionUp(sessionPreferences, listener);
-        } else if (ownershipChange.wasOwner()) {
-            slaveSetupSchema();
-        }
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceCommunicator.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceCommunicator.java
deleted file mode 100644 (file)
index 061024c..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import java.util.ArrayList;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.netconf.api.NetconfMessage;
-import org.opendaylight.netconf.api.NetconfTerminationReason;
-import org.opendaylight.netconf.client.NetconfClientSession;
-import org.opendaylight.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-
-public class ClusteredNetconfDeviceCommunicator extends NetconfDeviceCommunicator {
-
-    private final EntityOwnershipService ownershipService;
-
-    private final ArrayList<NetconfClientSessionListener> netconfClientSessionListeners = new ArrayList<>();
-    private EntityOwnershipListenerRegistration ownershipListenerRegistration = null;
-
-    public ClusteredNetconfDeviceCommunicator(RemoteDeviceId id, NetconfDevice remoteDevice, EntityOwnershipService ownershipService, final int rpcMessageLimit) {
-        super(id, remoteDevice, rpcMessageLimit);
-        this.ownershipService = ownershipService;
-    }
-
-    @Override
-    public void onMessage(NetconfClientSession session, NetconfMessage message) {
-        super.onMessage(session, message);
-        for(NetconfClientSessionListener listener : netconfClientSessionListeners) {
-            listener.onMessage(session, message);
-        }
-    }
-
-    @Override
-    public void onSessionDown(NetconfClientSession session, Exception e) {
-        super.onSessionDown(session, e);
-        ownershipListenerRegistration.close();
-        for(NetconfClientSessionListener listener : netconfClientSessionListeners) {
-            listener.onSessionDown(session, e);
-        }
-    }
-
-    @Override
-    public void onSessionUp(NetconfClientSession session) {
-        super.onSessionUp(session);
-        ownershipListenerRegistration = ownershipService.registerListener("netconf-node/" + id.getName(), (ClusteredNetconfDevice) remoteDevice);
-        for(NetconfClientSessionListener listener : netconfClientSessionListeners) {
-            listener.onSessionUp(session);
-        }
-    }
-
-    @Override
-    public void onSessionTerminated(NetconfClientSession session, NetconfTerminationReason reason) {
-        super.onSessionTerminated(session, reason);
-        ownershipListenerRegistration.close();
-        for(NetconfClientSessionListener listener : netconfClientSessionListeners) {
-            listener.onSessionTerminated(session, reason);
-        }
-    }
-
-    public NetconfClientSessionListenerRegistration registerNetconfClientSessionListener(NetconfClientSessionListener listener) {
-        netconfClientSessionListeners.add(listener);
-        return new NetconfClientSessionListenerRegistration(listener);
-    }
-
-    public class NetconfClientSessionListenerRegistration {
-
-        private final NetconfClientSessionListener listener;
-
-        public NetconfClientSessionListenerRegistration(NetconfClientSessionListener listener) {
-            this.listener = listener;
-        }
-
-        public void close() {
-            netconfClientSessionListeners.remove(listener);
-        }
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceMountInstanceProxy.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceMountInstanceProxy.java
deleted file mode 100644 (file)
index 7367512..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import com.google.common.base.Preconditions;
-import java.util.Collection;
-import java.util.Collections;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalProvider.MountInstance;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ClusteredNetconfDeviceMountInstanceProxy implements Provider, AutoCloseable{
-
-    private static final Logger LOG = LoggerFactory.getLogger(ClusteredNetconfDeviceMountInstanceProxy.class);
-
-    private final RemoteDeviceId id;
-    private MountInstance mountInstance;
-
-    public ClusteredNetconfDeviceMountInstanceProxy(final RemoteDeviceId deviceId) {
-        this.id = deviceId;
-    }
-
-    public MountInstance getMountInstance() {
-        Preconditions.checkState(mountInstance != null,
-                "%s: Mount instance was not initialized by sal. Cannot get mount instance", id);
-        return mountInstance;
-    }
-
-    @Override
-    public void close() throws Exception {
-        mountInstance.close();
-    }
-
-    @Override
-    public void onSessionInitiated(final Broker.ProviderSession session) {
-        LOG.debug("{}: (BI)Session with sal established {}", id, session);
-
-        final DOMMountPointService mountService = session.getService(DOMMountPointService.class);
-        if (mountService != null) {
-            mountInstance = new MountInstance(mountService, id);
-        }
-    }
-
-    @Override
-    public Collection<ProviderFunctionality> getProviderFunctionality() {
-        return Collections.emptySet();
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProvider.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProvider.java
deleted file mode 100644 (file)
index f9726f4..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import akka.actor.TypedActor;
-import org.opendaylight.controller.cluster.schema.provider.RemoteYangTextSourceProvider;
-
-public interface MasterSourceProvider
-        extends TypedActor.PreStart, TypedActor.Receiver, RemoteYangTextSourceProvider {
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProviderImpl.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProviderImpl.java
deleted file mode 100644 (file)
index 618de81..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.PoisonPill;
-import akka.actor.TypedActor;
-import akka.cluster.Cluster;
-import akka.cluster.Member;
-import java.util.Set;
-import org.opendaylight.controller.cluster.schema.provider.impl.RemoteYangTextSourceProviderImpl;
-import org.opendaylight.netconf.topology.pipeline.messages.AnnounceClusteredDeviceSourcesResolverUp;
-import org.opendaylight.netconf.topology.pipeline.messages.AnnounceMasterOnSameNodeUp;
-import org.opendaylight.netconf.topology.pipeline.messages.AnnounceMasterSourceProviderUp;
-import org.opendaylight.netconf.util.NetconfTopologyPathCreator;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class MasterSourceProviderImpl extends RemoteYangTextSourceProviderImpl
-        implements MasterSourceProvider {
-
-    private static Logger LOG = LoggerFactory.getLogger(MasterSourceProviderImpl.class);
-
-    private final ActorSystem actorSystem;
-    private final String topologyId;
-    private final String nodeId;
-
-    public MasterSourceProviderImpl(SchemaRepository schemaRepo, Set<SourceIdentifier> providedSources, ActorSystem actorSystem, String topologyId, String nodeId) {
-        super(schemaRepo, providedSources);
-        this.actorSystem = actorSystem;
-        this.topologyId = topologyId;
-        this.nodeId = nodeId;
-    }
-
-    @Override
-    public void onReceive(Object o, ActorRef actorRef) {
-        if(o instanceof AnnounceClusteredDeviceSourcesResolverUp) {
-            LOG.debug("Received source resolver up");
-            actorRef.tell(new AnnounceMasterSourceProviderUp(), TypedActor.context().self());
-        }
-    }
-
-    @Override
-    public void preStart() {
-        Cluster cluster = Cluster.get(actorSystem);
-        cluster.join(cluster.selfAddress());
-        LOG.debug("Notifying members master schema source provider is up.");
-        for(Member node : cluster.state().getMembers()) {
-            final NetconfTopologyPathCreator pathCreator = new NetconfTopologyPathCreator(node.address().toString(),topologyId);
-            final String path = pathCreator.withSuffix(nodeId).withSuffix(NetconfTopologyPathCreator.CLUSTERED_DEVICE_SOURCES_RESOLVER).build();
-            if(node.address().equals(cluster.selfAddress())) {
-                actorSystem.actorSelection(path).tell(new AnnounceMasterOnSameNodeUp(), TypedActor.context().self());
-                actorSystem.actorSelection(path).tell(PoisonPill.getInstance(), TypedActor.context().self());
-            } else {
-                //TODO extract string constant to util class
-                actorSystem.actorSelection(path).tell(new AnnounceMasterSourceProviderUp(), TypedActor.context().self());
-            }
-        }
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProviderOnSameNodeException.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/MasterSourceProviderOnSameNodeException.java
deleted file mode 100644 (file)
index 71f3005..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-public class MasterSourceProviderOnSameNodeException extends Exception {
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceMasterDataBroker.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceMasterDataBroker.java
deleted file mode 100644 (file)
index 17bb793..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Collections;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceDataBroker;
-import org.opendaylight.netconf.sal.connect.netconf.sal.tx.ReadWriteTx;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.pipeline.tx.ProxyReadOnlyTransaction;
-import org.opendaylight.netconf.topology.pipeline.tx.ProxyWriteOnlyTransaction;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import scala.concurrent.Future;
-import scala.concurrent.impl.Promise.DefaultPromise;
-
-public class NetconfDeviceMasterDataBroker implements ProxyNetconfDeviceDataBroker {
-
-    private final RemoteDeviceId id;
-
-    private final NetconfDeviceDataBroker delegateBroker;
-    private final ActorSystem actorSystem;
-
-    private DOMDataReadOnlyTransaction readTx;
-    private DOMDataWriteTransaction writeTx;
-
-    public NetconfDeviceMasterDataBroker(final ActorSystem actorSystem, final RemoteDeviceId id,
-                                         final SchemaContext schemaContext, final DOMRpcService rpc,
-                                         final NetconfSessionPreferences netconfSessionPreferences) {
-        this.id = id;
-        delegateBroker = new NetconfDeviceDataBroker(id, schemaContext, rpc, netconfSessionPreferences);
-        this.actorSystem = actorSystem;
-
-        // only ever need 1 readTx since it doesnt need to be closed
-        readTx = delegateBroker.newReadOnlyTransaction();
-    }
-
-    @Override
-    public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
-        return new ProxyReadOnlyTransaction(actorSystem, id, TypedActor.<NetconfDeviceMasterDataBroker>self());
-    }
-
-    @Override
-    public DOMDataReadWriteTransaction newReadWriteTransaction() {
-        return new ReadWriteTx(new ProxyReadOnlyTransaction(actorSystem, id, TypedActor.<NetconfDeviceMasterDataBroker>self()),
-                newWriteOnlyTransaction());
-    }
-
-    @Override
-    public DOMDataWriteTransaction newWriteOnlyTransaction() {
-        writeTx = delegateBroker.newWriteOnlyTransaction();
-        return new ProxyWriteOnlyTransaction(actorSystem, TypedActor.<NetconfDeviceMasterDataBroker>self());
-    }
-
-    @Override
-    public ListenerRegistration<DOMDataChangeListener> registerDataChangeListener(LogicalDatastoreType store, YangInstanceIdentifier path, DOMDataChangeListener listener, DataChangeScope triggeringScope) {
-        throw new UnsupportedOperationException(id + ": Data change listeners not supported for netconf mount point");
-    }
-
-    @Override
-    public DOMTransactionChain createTransactionChain(TransactionChainListener listener) {
-        throw new UnsupportedOperationException(id + ": Transaction chains not supported for netconf mount point");
-    }
-
-    @Nonnull
-    @Override
-    public Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> getSupportedExtensions() {
-        return Collections.emptyMap();
-    }
-
-    @Override
-    public Future<Optional<NormalizedNodeMessage>> read(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
-        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readFuture = readTx.read(store, path);
-
-        final DefaultPromise<Optional<NormalizedNodeMessage>> promise = new DefaultPromise<>();
-        Futures.addCallback(readFuture, new FutureCallback<Optional<NormalizedNode<?, ?>>>() {
-            @Override
-            public void onSuccess(Optional<NormalizedNode<?, ?>> result) {
-                if (!result.isPresent()) {
-                    promise.success(Optional.<NormalizedNodeMessage>absent());
-                } else {
-                    promise.success(Optional.of(new NormalizedNodeMessage(path, result.get())));
-                }
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                promise.failure(t);
-            }
-        });
-        return promise.future();
-    }
-
-    @Override
-    public Future<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
-        final CheckedFuture<Boolean, ReadFailedException> existsFuture = readTx.exists(store, path);
-
-        final DefaultPromise<Boolean> promise = new DefaultPromise<>();
-        Futures.addCallback(existsFuture, new FutureCallback<Boolean>() {
-            @Override
-            public void onSuccess(Boolean result) {
-                promise.success(result);
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                promise.failure(t);
-            }
-        });
-        return promise.future();
-    }
-
-    @Override
-    public void put(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
-        if (writeTx == null) {
-            writeTx = delegateBroker.newWriteOnlyTransaction();
-        }
-        writeTx.put(store, data.getIdentifier(), data.getNode());
-    }
-
-    @Override
-    public void merge(final LogicalDatastoreType store, final NormalizedNodeMessage data) {
-        if (writeTx == null) {
-            writeTx = delegateBroker.newWriteOnlyTransaction();
-        }
-        writeTx.merge(store, data.getIdentifier(), data.getNode());
-    }
-
-    @Override
-    public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
-        if (writeTx == null) {
-            writeTx = delegateBroker.newWriteOnlyTransaction();
-        }
-        writeTx.delete(store, path);
-    }
-
-    @Override
-    public boolean cancel() {
-        return writeTx.cancel();
-    }
-
-    @Override
-    public Future<Void> submit() {
-        final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = writeTx.submit();
-        final DefaultPromise<Void> promise = new DefaultPromise<>();
-        Futures.addCallback(submitFuture, new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-                promise.success(result);
-                writeTx = null;
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                promise.failure(t);
-                writeTx = null;
-            }
-        });
-        return promise.future();
-    }
-
-    @Override
-    @Deprecated
-    public Future<RpcResult<TransactionStatus>> commit() {
-        final ListenableFuture<RpcResult<TransactionStatus>> commitFuture = writeTx.commit();
-        final DefaultPromise<RpcResult<TransactionStatus>> promise = new DefaultPromise<>();
-        Futures.addCallback(commitFuture, new FutureCallback<RpcResult<TransactionStatus>>() {
-            @Override
-            public void onSuccess(RpcResult<TransactionStatus> result) {
-                promise.success(result);
-                writeTx = null;
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                promise.failure(t);
-                writeTx = null;
-            }
-        });
-        return promise.future();
-    }
-
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ProxyNetconfDeviceDataBroker.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/ProxyNetconfDeviceDataBroker.java
deleted file mode 100644 (file)
index 3ef7688..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import com.google.common.base.Optional;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import scala.concurrent.Future;
-
-public interface ProxyNetconfDeviceDataBroker extends DOMDataBroker{
-    Future<Optional<NormalizedNodeMessage>> read(LogicalDatastoreType store, YangInstanceIdentifier path);
-
-    Future<Boolean> exists(LogicalDatastoreType store, YangInstanceIdentifier path);
-
-    void put(LogicalDatastoreType store, NormalizedNodeMessage data);
-
-    void merge(LogicalDatastoreType store, NormalizedNodeMessage data);
-
-    void delete(LogicalDatastoreType store, YangInstanceIdentifier path);
-
-    boolean cancel();
-
-    Future<Void> submit();
-
-    @Deprecated
-    Future<RpcResult<TransactionStatus>> commit();
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacade.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacade.java
deleted file mode 100644 (file)
index a44bf47..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import akka.actor.ActorContext;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import akka.actor.TypedProps;
-import akka.cluster.Cluster;
-import akka.cluster.Member;
-import akka.japi.Creator;
-import com.google.common.base.Preconditions;
-import java.util.ArrayList;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceNotificationService;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.util.messages.AnnounceMasterMountPoint;
-import org.opendaylight.netconf.topology.util.messages.AnnounceMasterMountPointDown;
-import org.opendaylight.netconf.util.NetconfTopologyPathCreator;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TopologyMountPointFacade implements AutoCloseable, RemoteDeviceHandler<NetconfSessionPreferences> {
-
-    private static final Logger LOG = LoggerFactory.getLogger(TopologyMountPointFacade.class);
-
-    private static final String MOUNT_POINT = "mountpoint";
-
-    private final String topologyId;
-    private final RemoteDeviceId id;
-    private final Broker domBroker;
-    private final BindingAwareBroker bindingBroker;
-
-    private SchemaContext remoteSchemaContext = null;
-    private NetconfSessionPreferences netconfSessionPreferences = null;
-    private DOMRpcService deviceRpc = null;
-    private final ClusteredNetconfDeviceMountInstanceProxy salProvider;
-
-    private ActorSystem actorSystem;
-    private DOMDataBroker deviceDataBroker = null;
-
-    private final ArrayList<RemoteDeviceHandler<NetconfSessionPreferences>> connectionStatusListeners = new ArrayList<>();
-
-    public TopologyMountPointFacade(final String topologyId,
-                                    final RemoteDeviceId id,
-                                    final Broker domBroker,
-                                    final BindingAwareBroker bindingBroker) {
-        this.topologyId = topologyId;
-        this.id = id;
-        this.domBroker = domBroker;
-        this.bindingBroker = bindingBroker;
-        this.salProvider = new ClusteredNetconfDeviceMountInstanceProxy(id);
-        registerToSal(domBroker);
-    }
-
-    public void registerToSal(final Broker domRegistryDependency) {
-        domRegistryDependency.registerProvider(salProvider);
-    }
-
-    @Override
-    public void onDeviceConnected(final SchemaContext remoteSchemaContext,
-                                  final NetconfSessionPreferences netconfSessionPreferences,
-                                  final DOMRpcService deviceRpc) {
-        // prepare our prerequisites for mountpoint
-        LOG.debug("Mount point facade onConnected capabilities {}", netconfSessionPreferences);
-        this.remoteSchemaContext = remoteSchemaContext;
-        this.netconfSessionPreferences = netconfSessionPreferences;
-        this.deviceRpc = deviceRpc;
-        for (RemoteDeviceHandler<NetconfSessionPreferences> listener : connectionStatusListeners) {
-            listener.onDeviceConnected(remoteSchemaContext, netconfSessionPreferences, deviceRpc);
-        }
-    }
-
-    @Override
-    public void onDeviceDisconnected() {
-        // do not unregister mount point here, this gets handle by the underlying call from role change callback
-        for (RemoteDeviceHandler<NetconfSessionPreferences> listener : connectionStatusListeners) {
-            listener.onDeviceDisconnected();
-        }
-    }
-
-    @Override
-    public void onDeviceFailed(Throwable throwable) {
-        // do not unregister mount point here, this gets handle by the underlying call from role change callback
-        for (RemoteDeviceHandler<NetconfSessionPreferences> listener : connectionStatusListeners) {
-            listener.onDeviceFailed(throwable);
-        }
-    }
-
-    @Override
-    public void onNotification(DOMNotification domNotification) {
-        salProvider.getMountInstance().publish(domNotification);
-    }
-
-    public void registerMountPoint(final ActorSystem actorSystem, final ActorContext context) {
-        if (remoteSchemaContext == null || netconfSessionPreferences == null) {
-            LOG.debug("Master mount point does not have schemas ready yet, delaying registration");
-            return;
-        }
-
-        Preconditions.checkNotNull(id);
-        Preconditions.checkNotNull(remoteSchemaContext, "Device has no remote schema context yet. Probably not fully connected.");
-        Preconditions.checkNotNull(netconfSessionPreferences, "Device has no capabilities yet. Probably not fully connected.");
-        this.actorSystem = actorSystem;
-        final NetconfDeviceNotificationService notificationService = new NetconfDeviceNotificationService();
-
-        LOG.warn("Creating master data broker for device {}", id);
-        deviceDataBroker = TypedActor.get(context).typedActorOf(new TypedProps<>(ProxyNetconfDeviceDataBroker.class, new Creator<NetconfDeviceMasterDataBroker>() {
-            @Override
-            public NetconfDeviceMasterDataBroker create() throws Exception {
-                return new NetconfDeviceMasterDataBroker(actorSystem, id, remoteSchemaContext, deviceRpc, netconfSessionPreferences);
-            }
-        }), MOUNT_POINT);
-        LOG.debug("Master data broker registered on path {}", TypedActor.get(actorSystem).getActorRefFor(deviceDataBroker).path());
-        salProvider.getMountInstance().onTopologyDeviceConnected(remoteSchemaContext, deviceDataBroker, deviceRpc, notificationService);
-        final Cluster cluster = Cluster.get(actorSystem);
-        final Iterable<Member> members = cluster.state().getMembers();
-        final ActorRef deviceDataBrokerRef = TypedActor.get(actorSystem).getActorRefFor(deviceDataBroker);
-        for (final Member member : members) {
-            if (!member.address().equals(cluster.selfAddress())) {
-                final NetconfTopologyPathCreator pathCreator = new NetconfTopologyPathCreator(member.address().toString(),topologyId);
-                final String path = pathCreator.withSuffix(id.getName()).build();
-                actorSystem.actorSelection(path).tell(new AnnounceMasterMountPoint(), deviceDataBrokerRef);
-            }
-        }
-    }
-
-    public void registerMountPoint(final ActorSystem actorSystem, final ActorContext context, final ActorRef masterRef) {
-        if (remoteSchemaContext == null || netconfSessionPreferences == null) {
-            LOG.debug("Slave mount point does not have schemas ready yet, delaying registration");
-            return;
-        }
-
-        Preconditions.checkNotNull(id);
-        Preconditions.checkNotNull(remoteSchemaContext, "Device has no remote schema context yet. Probably not fully connected.");
-        Preconditions.checkNotNull(netconfSessionPreferences, "Device has no capabilities yet. Probably not fully connected.");
-        this.actorSystem = actorSystem;
-        final NetconfDeviceNotificationService notificationService = new NetconfDeviceNotificationService();
-
-        final ProxyNetconfDeviceDataBroker masterDataBroker = TypedActor.get(actorSystem).typedActorOf(new TypedProps<>(ProxyNetconfDeviceDataBroker.class, NetconfDeviceMasterDataBroker.class), masterRef);
-        LOG.warn("Creating slave data broker for device {}", id);
-        final DOMDataBroker deviceDataBroker = new NetconfDeviceSlaveDataBroker(actorSystem, id, masterDataBroker);
-        salProvider.getMountInstance().onTopologyDeviceConnected(remoteSchemaContext, deviceDataBroker, deviceRpc, notificationService);
-    }
-
-    public void unregisterMountPoint() {
-        salProvider.getMountInstance().onTopologyDeviceDisconnected();
-        if (deviceDataBroker != null) {
-            LOG.debug("Stopping master data broker for device {}", id.getName());
-            for (final Member member : Cluster.get(actorSystem).state().getMembers()) {
-                if (member.address().equals(Cluster.get(actorSystem).selfAddress())) {
-                    continue;
-                }
-                final NetconfTopologyPathCreator pathCreator = new NetconfTopologyPathCreator(member.address().toString(), topologyId);
-                final String path = pathCreator.withSuffix(id.getName()).build();
-                actorSystem.actorSelection(path).tell(new AnnounceMasterMountPointDown(), null);
-            }
-            TypedActor.get(actorSystem).stop(deviceDataBroker);
-            deviceDataBroker = null;
-        }
-    }
-
-    public ConnectionStatusListenerRegistration registerConnectionStatusListener(final RemoteDeviceHandler<NetconfSessionPreferences> listener) {
-        connectionStatusListeners.add(listener);
-        return new ConnectionStatusListenerRegistration(listener);
-    }
-
-    @Override
-    public void close() {
-        closeGracefully(salProvider);
-    }
-
-    private void closeGracefully(final AutoCloseable resource) {
-        if (resource != null) {
-            try {
-                resource.close();
-            } catch (final Exception e) {
-                LOG.warn("{}: Ignoring exception while closing {}", id, resource, e);
-            }
-        }
-    }
-
-    public class ConnectionStatusListenerRegistration{
-
-        private final RemoteDeviceHandler<NetconfSessionPreferences> listener;
-
-        public ConnectionStatusListenerRegistration(final RemoteDeviceHandler<NetconfSessionPreferences> listener) {
-            this.listener = listener;
-        }
-
-        public void close() {
-            connectionStatusListeners.remove(listener);
-        }
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceClusteredDeviceSourcesResolverUp.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceClusteredDeviceSourcesResolverUp.java
deleted file mode 100644 (file)
index f8328e7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline.messages;
-
-import java.io.Serializable;
-
-public class AnnounceClusteredDeviceSourcesResolverUp implements Serializable {
-    public static final long serialVersionUID = 1L;
-
-    public AnnounceClusteredDeviceSourcesResolverUp() {}
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceMasterOnSameNodeUp.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceMasterOnSameNodeUp.java
deleted file mode 100644 (file)
index 793321c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline.messages;
-
-import java.io.Serializable;
-
-public class AnnounceMasterOnSameNodeUp  implements Serializable {
-    public static long serialVersionUID = 1L;
-
-    public AnnounceMasterOnSameNodeUp() {
-
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceMasterSourceProviderUp.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/messages/AnnounceMasterSourceProviderUp.java
deleted file mode 100644 (file)
index 7bec681..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline.messages;
-
-import java.io.Serializable;
-
-public class AnnounceMasterSourceProviderUp implements Serializable {
-    public static final long serialVersionUID = 1L;
-
-    public AnnounceMasterSourceProviderUp() {
-
-    }
-}
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyWriteOnlyTransaction.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyWriteOnlyTransaction.java
deleted file mode 100644 (file)
index d7a3c87..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline.tx;
-
-import akka.actor.ActorSystem;
-import akka.dispatch.OnComplete;
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import javax.annotation.Nullable;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.netconf.topology.pipeline.ProxyNetconfDeviceDataBroker;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import scala.concurrent.Future;
-
-public class ProxyWriteOnlyTransaction implements DOMDataWriteTransaction {
-
-    private final ProxyNetconfDeviceDataBroker delegate;
-    private final ActorSystem actorSystem;
-
-    public ProxyWriteOnlyTransaction(ActorSystem actorSystem, final ProxyNetconfDeviceDataBroker delegate) {
-        this.delegate = delegate;
-        this.actorSystem = actorSystem;
-    }
-
-    @Override
-    public void put (final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode < ?,?>data){
-        delegate.put(store, new NormalizedNodeMessage(path, data));
-    }
-
-    @Override
-    public void merge (final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode < ?,?>data){
-        delegate.merge(store, new NormalizedNodeMessage(path, data));
-    }
-
-    @Override
-    public boolean cancel () {
-        return delegate.cancel();
-    }
-
-    @Override
-    public void delete (final LogicalDatastoreType store, final YangInstanceIdentifier path){
-        delegate.delete(store, path);
-    }
-
-    @Override
-    public CheckedFuture<Void, TransactionCommitFailedException> submit() {
-        final Future<Void> submit = delegate.submit();
-        final SettableFuture<Void> settableFuture = SettableFuture.create();
-        final CheckedFuture<Void, TransactionCommitFailedException> checkedFuture = Futures.makeChecked(settableFuture, new Function<Exception, TransactionCommitFailedException>() {
-            @Nullable
-            @Override
-            public TransactionCommitFailedException apply(Exception input) {
-                return new TransactionCommitFailedException("Transaction commit failed", input);
-            }
-        });
-        submit.onComplete(new OnComplete<Void>() {
-            @Override
-            public void onComplete(Throwable throwable, Void aVoid) throws Throwable {
-                if (throwable == null) {
-                    settableFuture.set(aVoid);
-                } else {
-                    settableFuture.setException(throwable);
-                }
-            }
-        }, actorSystem.dispatcher());
-        return checkedFuture;
-    }
-
-    @Override
-    public ListenableFuture<RpcResult<TransactionStatus>> commit () {
-        final Future<RpcResult<TransactionStatus>> commit = delegate.commit();
-        final SettableFuture<RpcResult<TransactionStatus>> settableFuture = SettableFuture.create();
-        commit.onComplete(new OnComplete<RpcResult<TransactionStatus>>() {
-            @Override
-            public void onComplete(Throwable throwable, RpcResult<TransactionStatus> transactionStatusRpcResult) throws Throwable {
-                if (throwable == null) {
-                    settableFuture.set(transactionStatusRpcResult);
-                } else {
-                    settableFuture.setException(throwable);
-                }
-            }
-        }, actorSystem.dispatcher());
-        return settableFuture;
-    }
-
-    @Override
-    public Object getIdentifier () {
-        return this;
-    }
-}
diff --git a/netconf/netconf-topology/src/main/yang/clustered-netconf-topology.yang b/netconf/netconf-topology/src/main/yang/clustered-netconf-topology.yang
deleted file mode 100644 (file)
index 6e72443..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-module clustered-netconf-topology {
-
-    yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology";
-    prefix "nt";
-
-    import config { prefix config; revision-date 2013-04-05; }
-    import threadpool {prefix th;}
-    import netty {prefix netty;}
-    import opendaylight-md-sal-dom {prefix dom;}
-    import opendaylight-md-sal-binding {prefix md-sal-binding; revision-date 2013-10-28;}
-    import odl-netconf-cfg { prefix cfg-net; revision-date 2014-04-08; }
-    import shared-schema-repository { prefix sh; revision-date 2015-07-27; }
-    import netconf-topology { prefix topo; revision-date 2015-07-27; }
-    import opendaylight-entity-ownership-service { prefix eos; revision-date 2015-08-10; }
-    import actor-system-provider-service { prefix asp; revision-date 2015-10-05; }
-
-    description
-            "Module definition for Netconf topolgy. Netconf topology provides a set of common configuration ";
-
-    revision "2015-11-04" {
-        description
-            "Initial revision";
-    }
-
-    identity clustered-netconf-topology-impl {
-        base config:module-type;
-        config:java-name-prefix ClusteredNetconfTopology;
-        config:provided-service topo:netconf-topology;
-    }
-
-    augment "/config:modules/config:module/config:configuration" {
-        case clustered-netconf-topology-impl {
-            when "/config:modules/config:module/config:type = 'clustered-netconf-topology-impl'";
-
-            leaf topology-id {
-                mandatory true;
-                type string;
-            }
-
-            container dom-registry {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity dom:dom-broker-osgi-registry;
-                    }
-                }
-            }
-
-            container binding-registry {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
-                    }
-                }
-            }
-
-            container event-executor {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity netty:netty-event-executor;
-                    }
-                }
-            }
-
-            container processing-executor {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity th:threadpool;
-                    }
-                }
-
-                description "Makes up for flaws in netty threading design";
-            }
-
-            container client-dispatcher {
-                uses config:service-ref {
-                    refine type {
-                        mandatory false;
-                        config:required-identity cfg-net:netconf-client-dispatcher;
-                    }
-                }
-            }
-
-            container keepalive-executor {
-                uses config:service-ref {
-                    refine type {
-                        mandatory false;
-                        config:required-identity th:scheduled-threadpool;
-                    }
-                }
-
-                description "Dedicated solely to keepalive execution";
-            }
-
-            container shared-schema-repository {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity sh:shared-schema-repository;
-                    }
-                }
-            }
-
-            container entity-ownership-service {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity eos:entity-ownership-service;
-                    }
-                }
-            }
-
-            container actor-system-provider-service {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity asp:actor-system-provider-service;
-                    }
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java
deleted file mode 100644 (file)
index a9d3e38..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import akka.actor.ActorContext;
-import akka.actor.ActorRef;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import io.netty.util.concurrent.EventExecutor;
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.ImmediateEventExecutor;
-import io.netty.util.concurrent.SucceededFuture;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.concurrent.ExecutionException;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
-import org.opendaylight.controller.config.threadpool.ThreadPool;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.netconf.client.NetconfClientDispatcher;
-import org.opendaylight.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
-import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
-import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
-
-public class AbstractNetconfTopologyTest {
-
-    private static final NodeId NODE_ID = new NodeId("testing-node");
-    private static final String TOPOLOGY_ID = "testing-topology";
-
-    @Mock
-    private Broker mockedDataBroker;
-
-    @Mock
-    private NetconfClientDispatcher mockedClientDispatcher;
-
-    @Mock
-    private BindingAwareBroker mockedBindingAwareBroker;
-
-    @Mock
-    private EventExecutor mockedEventExecutor;
-
-    @Mock
-    private ScheduledThreadPool mockedKeepaliveExecutor;
-
-    @Mock
-    private ThreadPool mockedProcessingExecutor;
-
-    @Mock
-    private SchemaRepositoryProvider mockedSchemaRepositoryProvider;
-
-
-    private TestingAbstractNetconfTopology topology;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        when(mockedSchemaRepositoryProvider.getSharedSchemaRepository()).thenReturn(new SharedSchemaRepository("testingSharedSchemaRepo"));
-        when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
-        Future<Void> future = new SucceededFuture<>(ImmediateEventExecutor.INSTANCE, null);
-        when(mockedClientDispatcher.createReconnectingClient(any(NetconfReconnectingClientConfiguration.class))).thenReturn(future);
-
-        topology = new TestingAbstractNetconfTopology(TOPOLOGY_ID, mockedClientDispatcher, mockedBindingAwareBroker,
-                mockedDataBroker, mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider);
-    }
-
-    @Test
-    public void testCreateSalFacade() {
-        NetconfNode testingNode = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(9999))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(1000L)
-                .setBetweenAttemptsTimeoutMillis(100)
-                .setSchemaless(false)
-                .build();
-
-        AbstractNetconfTopology.NetconfConnectorDTO connectorDTO = topology.createDeviceCommunicator(NODE_ID, testingNode);
-        assertSame(connectorDTO.getFacade(), topology.getFacade());
-    }
-
-    @Test
-    public void testCreateKeepAliveSalFacade() {
-        NetconfNode testingNode = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(9999))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(1000L)
-                .setBetweenAttemptsTimeoutMillis(100)
-                .setKeepaliveDelay(1L)
-                .setSchemaless(false)
-                .build();
-
-        AbstractNetconfTopology.NetconfConnectorDTO connectorDTO = topology.createDeviceCommunicator(NODE_ID, testingNode);
-        assertTrue(connectorDTO.getFacade() instanceof KeepaliveSalFacade);
-    }
-
-    @Test
-    public void testSetupSchemaResourceDTO() {
-        NetconfNode testingNode = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(9999))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(1000L)
-                .setBetweenAttemptsTimeoutMillis(100)
-                .setKeepaliveDelay(1000L).build();
-
-        NetconfDevice.SchemaResourcesDTO resultDTO = topology.setupSchemaCacheDTO(NODE_ID, testingNode);
-        SharedSchemaRepository repo = (SharedSchemaRepository) resultDTO.getSchemaRegistry();
-        assertEquals(repo.getIdentifier(), "sal-netconf-connector");
-
-        testingNode = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(9999))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(1000L)
-                .setBetweenAttemptsTimeoutMillis(100)
-                .setKeepaliveDelay(1000L)
-                .setSchemaCacheDirectory("test-directory")
-                .build();
-
-        resultDTO = topology.setupSchemaCacheDTO(NODE_ID, testingNode);
-        repo = (SharedSchemaRepository) resultDTO.getSchemaRegistry();
-        assertEquals(repo.getIdentifier(), "test-directory");
-    }
-
-    @Test
-    public void testGetClientConfig() throws UnknownHostException {
-        NetconfClientSessionListener listener = mock(NetconfClientSessionListener.class);
-        Host host = new Host(new IpAddress(new Ipv4Address("127.0.0.1")));
-        PortNumber portNumber = new PortNumber(9999);
-        NetconfNode testingNode = new NetconfNodeBuilder()
-                .setConnectionTimeoutMillis(1000L)
-                .setDefaultRequestTimeoutMillis(2000L)
-                .setHost(host)
-                .setPort(portNumber)
-                .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
-                .setTcpOnly(true)
-                .build();
-        NetconfReconnectingClientConfiguration defaultClientConfig = topology.getClientConfig(listener, testingNode);
-
-        assertEquals(defaultClientConfig.getConnectionTimeoutMillis().longValue(), 1000L);
-        assertEquals(defaultClientConfig.getAddress(), new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999));
-        assertSame(defaultClientConfig.getSessionListener(), listener);
-        assertEquals(defaultClientConfig.getAuthHandler().getUsername(), "testuser");
-        assertEquals(defaultClientConfig.getProtocol(), NetconfClientConfiguration.NetconfClientProtocol.TCP);
-    }
-
-    @Test
-    public void testGetClientConfigNotSupportedCredentialsFail() {
-        NetconfClientSessionListener listener = mock(NetconfClientSessionListener.class);
-        Host host = new Host(new IpAddress(new Ipv4Address("127.0.0.1")));
-        PortNumber portNumber = new PortNumber(9999);
-
-        Credentials notSupportedCredentials = new Credentials() {
-            @Override
-            public Class<? extends DataContainer> getImplementedInterface() {
-                return Credentials.class;
-            }
-        };
-
-        NetconfNode testingNode = new NetconfNodeBuilder()
-                .setConnectionTimeoutMillis(1000L)
-                .setDefaultRequestTimeoutMillis(2000L)
-                .setHost(host)
-                .setPort(portNumber)
-                .setCredentials(notSupportedCredentials)
-                .setTcpOnly(true)
-                .build();
-        try {
-            topology.getClientConfig(listener, testingNode);
-            fail("Exception expected here.");
-        } catch(Exception e) {
-            assertTrue(e instanceof IllegalStateException);
-        }
-    }
-
-    @Test
-    public void testConnectNode() {
-        NetconfNode testingNode = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(9999))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(1000L)
-                .setBetweenAttemptsTimeoutMillis(100)
-                .setKeepaliveDelay(1000L)
-                .setTcpOnly(true)
-                .setSchemaless(false)
-                .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
-                .build();
-        Node nd = mock(Node.class);
-        when(nd.getAugmentation(NetconfNode.class)).thenReturn(testingNode);
-        topology.connectNode(NODE_ID, nd);
-        assertTrue(topology.activeConnectors.containsKey(NODE_ID));
-    }
-
-    @Test
-    public void testDisconnectNode() {
-        NetconfNode testingNode = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(9999))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(1000L)
-                .setBetweenAttemptsTimeoutMillis(100)
-                .setKeepaliveDelay(1000L)
-                .setTcpOnly(true)
-                .setSchemaless(false)
-                .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
-                .build();
-        Node nd = mock(Node.class);
-        when(nd.getAugmentation(NetconfNode.class)).thenReturn(testingNode);
-        topology.connectNode(NODE_ID, nd);
-        assertTrue(topology.activeConnectors.containsKey(NODE_ID));
-        assertTrue(topology.disconnectNode(NODE_ID).isDone());
-        assertTrue(!topology.activeConnectors.containsKey(NODE_ID));
-        verify(topology.getFacade()).close();
-    }
-
-    @Test
-    public void testDisconnectNotConnectedNode() throws ExecutionException, InterruptedException {
-        ListenableFuture disconnectFuture = topology.disconnectNode(NODE_ID);
-        assertTrue(disconnectFuture.isDone());
-        try {
-            disconnectFuture.get();
-            fail("Exception expected!");
-        } catch(Exception e) {
-            assertTrue(e instanceof ExecutionException);
-            assertTrue(e.getCause() instanceof  IllegalStateException);
-        }
-    }
-
-    public static class TestingAbstractNetconfTopology extends AbstractNetconfTopology {
-
-        private RemoteDeviceHandler salFacade;
-
-        protected TestingAbstractNetconfTopology(String topologyId, NetconfClientDispatcher clientDispatcher,
-                                                 BindingAwareBroker bindingAwareBroker, Broker domBroker,
-                                                 EventExecutor eventExecutor, ScheduledThreadPool keepaliveExecutor,
-                                                 ThreadPool processingExecutor,
-                                                 SchemaRepositoryProvider schemaRepositoryProvider) {
-            super(topologyId, clientDispatcher, bindingAwareBroker, domBroker, eventExecutor, keepaliveExecutor, processingExecutor, schemaRepositoryProvider);
-            salFacade = mock(RemoteDeviceHandler.class);
-        }
-
-        public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
-            return salFacade;
-        }
-
-        @Override
-        public void onSessionInitiated(BindingAwareBroker.ProviderContext session) {
-
-        }
-
-        @Override
-        protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker) {
-            return salFacade;
-        }
-
-        @Override
-        public TopologyMountPointFacade.ConnectionStatusListenerRegistration registerConnectionStatusListener(NodeId node, RemoteDeviceHandler<NetconfSessionPreferences> listener) {
-            return null;
-        }
-
-        @Override
-        public void registerMountPoint(ActorContext context, NodeId nodeId) {
-
-        }
-
-        @Override
-        public void registerMountPoint(ActorContext context, NodeId nodeId, ActorRef masterRef) {
-
-        }
-
-        @Override
-        public void unregisterMountPoint(NodeId nodeId) {
-
-        }
-    }
-}
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/ActorTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/ActorTest.java
deleted file mode 100644 (file)
index ced7d01..0000000
+++ /dev/null
@@ -1,719 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import static com.jayway.awaitility.Awaitility.await;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.when;
-
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.TypedActor;
-import akka.actor.TypedActorExtension;
-import akka.actor.TypedProps;
-import akka.japi.Creator;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import com.typesafe.config.ConfigFactory;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import javassist.ClassPool;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.topology.NodeManagerCallback.NodeManagerCallbackFactory;
-import org.opendaylight.netconf.topology.TopologyManagerCallback.TopologyManagerCallbackFactory;
-import org.opendaylight.netconf.topology.example.ExampleNodeManagerCallback;
-import org.opendaylight.netconf.topology.example.ExampleTopologyManagerCallback;
-import org.opendaylight.netconf.topology.example.LoggingSalNodeWriter;
-import org.opendaylight.netconf.topology.impl.NetconfNodeOperationalDataAggregator;
-import org.opendaylight.netconf.topology.util.BaseTopologyManager;
-import org.opendaylight.netconf.topology.util.NoopRoleChangeStrategy;
-import org.opendaylight.netconf.topology.util.TopologyRoleChangeStrategy;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.$YangModuleInfoImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus.Status;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
-import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
-import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
-import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ActorTest {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ActorTest.class);
-
-    private static final String TOPOLOGY_NETCONF = "TopologyNetconf";
-
-    @Mock
-    private EntityOwnershipService entityOwnershipService;
-
-    @Mock
-    private DataBroker dataBroker;
-
-    @Mock
-    private ReadOnlyTransaction mockedReadOnlyTx;
-
-    private static final BindingNormalizedNodeCodecRegistry CODEC_REGISTRY;
-
-    static {
-        final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
-        moduleInfoBackedContext.addModuleInfos(Collections.singletonList($YangModuleInfoImpl.getInstance()));
-        final Optional<SchemaContext> schemaContextOptional = moduleInfoBackedContext.tryToCreateSchemaContext();
-        Preconditions.checkState(schemaContextOptional.isPresent());
-        final SchemaContext topologySchemaCtx = schemaContextOptional.get();
-
-        final JavassistUtils javassist = JavassistUtils.forClassPool(ClassPool.getDefault());
-        CODEC_REGISTRY = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(javassist));
-        CODEC_REGISTRY.onBindingRuntimeContextUpdated(BindingRuntimeContext.create(moduleInfoBackedContext, topologySchemaCtx));
-    }
-
-    private static final String PATH_MASTER = "akka.tcp://NetconfNode@127.0.0.1:2552/user/TopologyNetconf";
-    private static final String PATH_SLAVE1 = "akka.tcp://NetconfNode@127.0.0.1:2553/user/TopologyNetconf";
-    private static final String PATH_SLAVE2 = "akka.tcp://NetconfNode@127.0.0.1:2554/user/TopologyNetconf";
-
-    private static final List<String> PATHS_MASTER = Lists.newArrayList(PATH_SLAVE1, PATH_SLAVE2);
-    private static final List<String> PATHS_SLAVE1 = Lists.newArrayList(PATH_MASTER, PATH_SLAVE2);
-    private static final List<String> PATHS_SLAVE2 = Lists.newArrayList(PATH_MASTER, PATH_SLAVE1);
-
-    private static final ActorSystem ACTOR_SYSTEM = ActorSystem.create("NetconfNode", ConfigFactory.load("netconf-node1"));
-    private static final ActorSystem ACTOR_SYSTEM_SLAVE1 = ActorSystem.create("NetconfNode", ConfigFactory.load("netconf-node2"));
-    private static final ActorSystem ACTOR_SYSTEM_SLAVE2 = ActorSystem.create("NetconfNode", ConfigFactory.load("netconf-node3"));
-
-    private static final ExecutorService callbackExecutor = Executors.newFixedThreadPool(8);
-
-    private TopologyManager master = null;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        final SettableFuture<Optional<Topology>> settableFuture = SettableFuture.create();
-        final CheckedFuture<Optional<Topology>, ReadFailedException> checkedFuture = Futures.makeChecked(settableFuture, new Function<Exception, ReadFailedException>() {
-            @Nullable
-            @Override
-            public ReadFailedException apply(Exception input) {
-                return new ReadFailedException("Dummy future should never return this");
-            }
-        });
-        settableFuture.set(Optional.<Topology>absent());
-        when(mockedReadOnlyTx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(checkedFuture);
-        when(dataBroker.registerDataChangeListener(
-                any(LogicalDatastoreType.class),
-                any(InstanceIdentifier.class),
-                any(DataChangeListener.class),
-                any(DataChangeScope.class))).thenReturn(null);
-        when(dataBroker.newReadOnlyTransaction()).thenReturn(mockedReadOnlyTx);
-    }
-
-    private void setMaster(final TopologyManager manager) {
-
-    }
-
-    @Test
-    public void testRealActors() throws Exception {
-
-        EntityOwnershipService topoOwnership = new TestingEntityOwnershipService();
-        // load from config
-        final TopologyManager master = createManagerWithOwnership(ACTOR_SYSTEM, TOPOLOGY_NETCONF, true, createRealTopoTestingNodeCallbackFactory(), new TopologyRoleChangeStrategy(dataBroker, topoOwnership, TOPOLOGY_NETCONF, "topology-manager"));
-        Thread.sleep(1000);
-        final TopologyManager slave1 = createManagerWithOwnership(ACTOR_SYSTEM_SLAVE1, TOPOLOGY_NETCONF, false, createRealTopoTestingNodeCallbackFactory(), new TopologyRoleChangeStrategy(dataBroker, topoOwnership, TOPOLOGY_NETCONF, "topology-manager"));
-        final TopologyManager slave2 = createManagerWithOwnership(ACTOR_SYSTEM_SLAVE2, TOPOLOGY_NETCONF, false, createRealTopoTestingNodeCallbackFactory(), new TopologyRoleChangeStrategy(dataBroker, topoOwnership, TOPOLOGY_NETCONF, "topology-manager"));
-
-        await().atMost(30L, TimeUnit.SECONDS).until(new Callable<Boolean>() {
-            @Override
-            public Boolean call() throws Exception {
-                return master.hasAllPeersUp();
-            }
-        });
-
-        final List<ListenableFuture<Node>> futures = new ArrayList<>();
-        for (int i = 0; i <= 1; i++) {
-            final String nodeid = "testing-node" + i;
-            final Node testingNode = new NodeBuilder()
-                    .setNodeId(new NodeId(nodeid))
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                                    .setPort(new PortNumber(10000 + i))
-                                    .build())
-                    .build();
-            final ListenableFuture<Node> nodeListenableFuture = master.onNodeCreated(new NodeId(nodeid), testingNode);
-            futures.add(nodeListenableFuture);
-            Futures.addCallback(nodeListenableFuture, new FutureCallback<Node>() {
-                @Override
-                public void onSuccess(Node result) {
-                    LOG.warn("Node {} created succesfully on all nodes", result.getNodeId().getValue());
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.warn("Node creation failed. ", t);
-                }
-            });
-        }
-
-        for (int i = 0; i <= 1; i++) {
-            final String nodeid = "testing-node" + i;
-            final Node testingNode = new NodeBuilder()
-                    .setNodeId(new NodeId(nodeid))
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                                    .setPort(new PortNumber(10000 + i))
-                                    .build())
-                    .build();
-            final ListenableFuture<Node> nodeListenableFuture = master.onNodeUpdated(new NodeId(nodeid), testingNode);
-            futures.add(nodeListenableFuture);
-            Futures.addCallback(nodeListenableFuture, new FutureCallback<Node>() {
-                @Override
-                public void onSuccess(Node result) {
-                    LOG.warn("Node {} updated succesfully on all nodes", result.getNodeId().getValue());
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.warn("Node update failed. ", t);
-                }
-            });
-        }
-        LOG.debug("Waiting for updates to finish");
-        Futures.allAsList(futures).get();
-
-
-        final List<ListenableFuture<Void>> deleteFutures = new ArrayList<>();
-        for (int i = 0; i <= 1; i++) {
-            final String nodeid = "testing-node" + i;
-            final ListenableFuture<Void> nodeListenableFuture = master.onNodeDeleted(new NodeId(nodeid));
-            deleteFutures.add(nodeListenableFuture);
-            Futures.addCallback(nodeListenableFuture, new FutureCallback<Void>() {
-                @Override
-                public void onSuccess(Void result) {
-                    LOG.warn("Node {} succesfully deleted on all nodes", nodeid);
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.warn("Node delete failed. ", t);
-                }
-            });
-
-        }
-        LOG.warn("All tasks submitted");
-        Futures.allAsList(futures).get();
-        Futures.allAsList(deleteFutures).get();
-
-        TypedActor.get(ACTOR_SYSTEM).stop(master);
-        TypedActor.get(ACTOR_SYSTEM_SLAVE1).stop(slave1);
-        TypedActor.get(ACTOR_SYSTEM_SLAVE2).stop(slave2);
-
-    }
-
-    // TODO seems like stopping actors is not enough to create an actor with same name, split this into multiple classes?
-    @Ignore
-    @Test
-    public void testWithDummyOwnershipService() throws Exception {
-
-        final TestingEntityOwnershipService ownershipService = new TestingEntityOwnershipService();
-        // load from config
-        final TopologyManager master = createNoopRoleChangeNode(ACTOR_SYSTEM, TOPOLOGY_NETCONF, true, createRealTopoCallbackFactory(ownershipService));
-        final TopologyManager slave1 = createNoopRoleChangeNode(ACTOR_SYSTEM_SLAVE1, TOPOLOGY_NETCONF, false, createRealTopoCallbackFactory(ownershipService));
-        final TopologyManager slave2 = createNoopRoleChangeNode(ACTOR_SYSTEM_SLAVE2, TOPOLOGY_NETCONF, false, createRealTopoCallbackFactory(ownershipService));
-
-        await().atMost(10L, TimeUnit.SECONDS).until(new Callable<Boolean>() {
-            @Override
-            public Boolean call() throws Exception {
-                return master.hasAllPeersUp();
-            }
-        });
-
-        final List<ListenableFuture<Node>> futures = new ArrayList<>();
-        for (int i = 0; i <= 0; i++) {
-            final String nodeid = "testing-node" + i;
-            final Node testingNode = new NodeBuilder()
-                    .setNodeId(new NodeId(nodeid))
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                                    .setPort(new PortNumber(10000 + i))
-                                    .build())
-                    .build();
-            final ListenableFuture<Node> nodeListenableFuture = master.onNodeCreated(new NodeId(nodeid), testingNode);
-            futures.add(nodeListenableFuture);
-            Futures.addCallback(nodeListenableFuture, new FutureCallback<Node>() {
-                @Override
-                public void onSuccess(Node result) {
-                    LOG.warn("Node {} created succesfully on all nodes", result.getNodeId().getValue());
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.warn("Node creation failed. ", t);
-                }
-            });
-        }
-
-        Futures.allAsList(futures).get();
-        ownershipService.distributeOwnership();
-
-        Thread.sleep(30000);
-        TypedActor.get(ACTOR_SYSTEM).stop(master);
-        TypedActor.get(ACTOR_SYSTEM_SLAVE1).stop(slave1);
-        TypedActor.get(ACTOR_SYSTEM_SLAVE2).stop(slave2);
-    }
-
-    private TopologyManager createNoopRoleChangeNode(final ActorSystem actorSystem, final String topologyId, final boolean isMaster,
-                                                     final TopologyManagerCallbackFactory topologyManagerCallbackFactory) {
-
-        final TypedActorExtension typedActorExtension = TypedActor.get(actorSystem);
-        return typedActorExtension.typedActorOf(new TypedProps<>(TopologyManager.class, new Creator<BaseTopologyManager>() {
-            @Override
-            public BaseTopologyManager create() throws Exception {
-                return new BaseTopologyManager(actorSystem,
-                        CODEC_REGISTRY,
-                        dataBroker,
-                        topologyId,
-                        topologyManagerCallbackFactory,
-                        new TestingSuccesfulStateAggregator(),
-                        new LoggingSalNodeWriter(),
-                        new NoopRoleChangeStrategy(),
-                        isMaster);
-            }
-        }), TOPOLOGY_NETCONF);
-    }
-
-    private TopologyManager createManagerWithOwnership(final ActorSystem actorSystem, final String topologyId, final boolean isMaster,
-                                                       final TopologyManagerCallbackFactory topologyManagerCallbackFactory, final RoleChangeStrategy roleChangeStrategy) {
-        final TypedActorExtension typedActorExtension = TypedActor.get(actorSystem);
-        return typedActorExtension.typedActorOf(new TypedProps<>(TopologyManager.class, new Creator<BaseTopologyManager>() {
-            @Override
-            public BaseTopologyManager create() throws Exception {
-                return new BaseTopologyManager(actorSystem,
-                        CODEC_REGISTRY,
-                        dataBroker,
-                        topologyId,
-                        topologyManagerCallbackFactory,
-                        new NetconfNodeOperationalDataAggregator(),
-                        new LoggingSalNodeWriter(),
-                        roleChangeStrategy,
-                        isMaster);
-            }
-        }), TOPOLOGY_NETCONF);
-    }
-
-    private TopologyManagerCallbackFactory createRealTopoTestingNodeCallbackFactory() {
-        final NodeManagerCallbackFactory nodeManagerCallbackFactory = new NodeManagerCallbackFactory() {
-            @Override
-            public NodeManagerCallback create(String nodeId, String topologyId, ActorSystem actorSystem) {
-                return new LoggingNodeManagerCallback();
-            }
-        };
-
-        return new TopologyManagerCallbackFactory() {
-            @Override
-            public TopologyManagerCallback create(ActorSystem actorSystem, String topologyId) {
-                return new ExampleTopologyManagerCallback(actorSystem, dataBroker, topologyId, nodeManagerCallbackFactory, new LoggingSalNodeWriter());
-            }
-        };
-    }
-
-    private TopologyManagerCallbackFactory createRealTopoCallbackFactory(final EntityOwnershipService entityOwnershipService) {
-        final NodeManagerCallbackFactory nodeManagerCallbackFactory = new NodeManagerCallbackFactory() {
-            @Override
-            public NodeManagerCallback create(String nodeId, String topologyId, ActorSystem actorSystem) {
-                return new ExampleNodeManagerCallback();
-            }
-        };
-
-        return new TopologyManagerCallbackFactory() {
-            @Override
-            public TopologyManagerCallback create(ActorSystem actorSystem, String topologyId) {
-                return new ExampleTopologyManagerCallback(actorSystem, dataBroker, topologyId, nodeManagerCallbackFactory);
-            }
-        };
-    }
-
-    private TopologyManagerCallbackFactory createTestingTopoCallbackFactory() {
-        return new TopologyManagerCallbackFactory() {
-            @Override
-            public TopologyManagerCallback create(ActorSystem actorSystem, String topologyId) {
-                return new TestingTopologyManagerCallback();
-            }
-        };
-    }
-
-    public static class LoggingNodeManagerCallback implements NodeManagerCallback {
-
-        @Nonnull
-        @Override
-        public Node getInitialState(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-            final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
-            return new NodeBuilder()
-                    .setNodeId(nodeId)
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setHost(netconfNode.getHost())
-                                    .setPort(netconfNode.getPort())
-                                    .setConnectionStatus(ConnectionStatus.Connecting)
-                                    .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                    .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                    .setClusteredConnectionStatus(
-                                            new ClusteredConnectionStatusBuilder()
-                                                    .setNodeStatus(
-                                                            Lists.newArrayList(
-                                                                    new NodeStatusBuilder()
-                                                                            .setNode("testing-node")
-                                                                            .setStatus(Status.Unavailable)
-                                                                            .build()))
-                                                    .build())
-                                    .build())
-                    .build();
-        }
-
-        @Nonnull
-        @Override
-        public Node getFailedState(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-            final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
-            return new NodeBuilder()
-                    .setNodeId(nodeId)
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setHost(netconfNode.getHost())
-                                    .setPort(netconfNode.getPort())
-                                    .setConnectionStatus(ConnectionStatus.UnableToConnect)
-                                    .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                    .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                    .setClusteredConnectionStatus(
-                                            new ClusteredConnectionStatusBuilder()
-                                                    .setNodeStatus(
-                                                            Collections.singletonList(
-                                                                    new NodeStatusBuilder()
-                                                                            .setNode("testing-node")
-                                                                            .setStatus(Status.Failed)
-                                                                            .build()))
-                                                    .build())
-                                    .build())
-                    .build();
-        }
-
-        @Nonnull
-        @Override
-        public ListenableFuture<Node> onNodeCreated(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-            LOG.debug("Creating node {} with config {}", nodeId, configNode);
-            final NetconfNode augmentation = configNode.getAugmentation(NetconfNode.class);
-            return Futures.immediateFuture(new NodeBuilder()
-                    .setNodeId(nodeId)
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setConnectionStatus(ConnectionStatus.Connected)
-                                    .setHost(augmentation.getHost())
-                                    .setPort(augmentation.getPort())
-                                    .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                    .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                    .setClusteredConnectionStatus(
-                                            new ClusteredConnectionStatusBuilder()
-                                                    .setNodeStatus(
-                                                            Collections.singletonList(
-                                                                    new NodeStatusBuilder()
-                                                                            .setNode("testing-node")
-                                                                            .setStatus(Status.Connected)
-                                                                            .build()))
-                                                    .build())
-                                    .build())
-                    .build());
-        }
-
-        @Nonnull
-        @Override
-        public ListenableFuture<Node> onNodeUpdated(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-            LOG.debug("Updating node {} with config {}", nodeId, configNode);
-            final NetconfNode augmentation = configNode.getAugmentation(NetconfNode.class);
-            return Futures.immediateFuture(new NodeBuilder()
-                    .setNodeId(nodeId)
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setConnectionStatus(ConnectionStatus.Connected)
-                                    .setHost(augmentation.getHost())
-                                    .setPort(augmentation.getPort())
-                                    .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                    .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                    .setClusteredConnectionStatus(
-                                            new ClusteredConnectionStatusBuilder()
-                                                    .setNodeStatus(
-                                                            Collections.singletonList(
-                                                                    new NodeStatusBuilder()
-                                                                            .setNode("testing-node")
-                                                                            .setStatus(Status.Connected)
-                                                                            .build()))
-                                                    .build())
-                                    .build())
-                    .build());
-        }
-
-        @Nonnull
-        @Override
-        public ListenableFuture<Void> onNodeDeleted(@Nonnull NodeId nodeId) {
-            LOG.debug("Deleting node {}", nodeId);
-            return Futures.immediateFuture(null);
-        }
-
-        @Nonnull
-        @Override
-        public ListenableFuture<Node> getCurrentStatusForNode(@Nonnull NodeId nodeId) {
-            return null;
-        }
-
-        @Override
-        public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-
-        }
-
-        @Override
-        public void onReceive(Object o, ActorRef actorRef) {
-
-        }
-
-        @Override
-        public void onDeviceConnected(SchemaContext remoteSchemaContext, NetconfSessionPreferences netconfSessionPreferences, DOMRpcService deviceRpc) {
-
-        }
-
-        @Override
-        public void onDeviceDisconnected() {
-
-        }
-
-        @Override
-        public void onDeviceFailed(Throwable throwable) {
-
-        }
-
-        @Override
-        public void onNotification(DOMNotification domNotification) {
-
-        }
-
-        @Override
-        public void close() {
-
-        }
-    }
-
-    public static class TestingTopologyManagerCallback implements TopologyManagerCallback {
-
-        public TestingTopologyManagerCallback() {
-
-        }
-
-        @Override
-        public ListenableFuture<Node> onNodeCreated(NodeId nodeId, Node node) {
-            LOG.warn("Actor system that called this: {}", TypedActor.context().system().settings().toString());
-            return Futures.immediateFuture(new NodeBuilder()
-                    .setNodeId(nodeId)
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setConnectionStatus(ConnectionStatus.Connected)
-                                    .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                                    .setPort(new PortNumber(2555))
-                                    .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                    .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                    .build())
-                    .build());
-        }
-
-        @Override
-        public ListenableFuture<Node> onNodeUpdated(NodeId nodeId, Node node) {
-            LOG.warn("Actor system that called this: {}", TypedActor.context().system().settings().toString());
-            LOG.debug("Update called on node {}, with config {}", nodeId.getValue(), node);
-            return Futures.immediateFuture(new NodeBuilder()
-                    .setNodeId(nodeId)
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setConnectionStatus(ConnectionStatus.Connected)
-                                    .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                                    .setPort(new PortNumber(65535))
-                                    .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                    .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                    .build())
-                    .build());
-        }
-
-        @Override
-        public ListenableFuture<Void> onNodeDeleted(NodeId nodeId) {
-            LOG.debug("Delete called on node {}", nodeId.getValue());
-            return Futures.immediateFuture(null);
-        }
-
-        @Nonnull
-        @Override
-        public ListenableFuture<Node> getCurrentStatusForNode(@Nonnull NodeId nodeId) {
-            return null;
-        }
-
-        @Override
-        public void onRoleChanged(RoleChangeDTO roleChangeDTO) {
-
-        }
-
-        @Override
-        public void onReceive(Object o, ActorRef actorRef) {
-
-        }
-
-        @Nonnull
-        @Override
-        public Node getInitialState(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-            return new NodeBuilder()
-                    .setNodeId(nodeId)
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setConnectionStatus(ConnectionStatus.Connecting)
-                                    .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                                    .setPort(new PortNumber(65535))
-                                    .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                    .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                    .build())
-                    .build();
-        }
-
-        @Nonnull
-        @Override
-        public Node getFailedState(@Nonnull NodeId nodeId, @Nonnull Node configNode) {
-            return new NodeBuilder()
-                    .setNodeId(nodeId)
-                    .addAugmentation(NetconfNode.class,
-                            new NetconfNodeBuilder()
-                                    .setConnectionStatus(ConnectionStatus.UnableToConnect)
-                                    .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                                    .setPort(new PortNumber(65535))
-                                    .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                    .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                    .build())
-                    .build();
-        }
-    }
-
-    public class TestingSuccesfulStateAggregator implements StateAggregator {
-
-        @Override
-        public ListenableFuture<Node> combineCreateAttempts(List<ListenableFuture<Node>> stateFutures) {
-            final SettableFuture<Node> future = SettableFuture.create();
-            final ListenableFuture<List<Node>> allAsList = Futures.allAsList(stateFutures);
-            Futures.addCallback(allAsList, new FutureCallback<List<Node>>() {
-                @Override
-                public void onSuccess(List<Node> result) {
-                    for (int i = 0; i < result.size() - 1; i++) {
-                        if (!result.get(i).equals(result.get(i + 1))) {
-                            LOG.warn("Node 1 {}: {}", result.get(i).getClass(), result.get(i));
-                            LOG.warn("Node 2 {}: {}", result.get(i + 1).getClass(), result.get(i + 1));
-                            future.setException(new IllegalStateException("Create futures have different result"));
-                            LOG.warn("Future1 : {}  Future2 : {}", result.get(i), result.get(i+1));
-                        }
-                    }
-                    future.set(result.get(0));
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.error("One of the combined create attempts failed {}", t);
-                    future.setException(t);
-                }
-            }, TypedActor.context().dispatcher());
-
-            return future;
-        }
-
-        @Override
-        public ListenableFuture<Node> combineUpdateAttempts(List<ListenableFuture<Node>> stateFutures) {
-            final SettableFuture<Node> future = SettableFuture.create();
-            final ListenableFuture<List<Node>> allAsList = Futures.allAsList(stateFutures);
-            Futures.addCallback(allAsList, new FutureCallback<List<Node>>() {
-                @Override
-                public void onSuccess(List<Node> result) {
-                    for (int i = 0; i < result.size() - 1; i++) {
-                        if (!result.get(i).equals(result.get(i + 1))) {
-                            future.setException(new IllegalStateException("Update futures have different result"));
-                        }
-                    }
-                    future.set(result.get(0));
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.error("One of the combined update attempts failed {}", t);
-                    future.setException(t);
-                }
-            });
-            return future;
-        }
-
-        @Override
-        public ListenableFuture<Void> combineDeleteAttempts(List<ListenableFuture<Void>> stateFutures) {
-            final SettableFuture<Void> future = SettableFuture.create();
-            final ListenableFuture<List<Void>> allAsList = Futures.allAsList(stateFutures);
-            Futures.addCallback(allAsList, new FutureCallback<List<Void>>() {
-                @Override
-                public void onSuccess(List<Void> result) {
-                    future.set(null);
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.error("One of the combined delete attempts failed {}", t);
-                    future.setException(t);
-                }
-            });
-            return future;
-        }
-    }
-}
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/TestingEntityOwnershipService.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/TestingEntityOwnershipService.java
deleted file mode 100644 (file)
index 4b0bc31..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import com.google.common.base.Optional;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
-import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TestingEntityOwnershipService implements EntityOwnershipService{
-
-    private static final Logger LOG = LoggerFactory.getLogger(TestingEntityOwnershipService.class);
-
-    private final List<EntityOwnershipListener> listeners = new ArrayList<>();
-    private final ExecutorService executorService = Executors.newFixedThreadPool(1);
-
-    private Entity entity;
-    private boolean masterSet = false;
-
-    @Override
-    public EntityOwnershipCandidateRegistration registerCandidate(final Entity entity) throws CandidateAlreadyRegisteredException {
-        LOG.warn("Registering Candidate");
-        this.entity = entity;
-        return new EntityOwnershipCandidateRegistration() {
-            @Override
-            public void close() {
-                LOG.debug("Closing candidate registration");
-            }
-
-            @Override
-            public Entity getInstance() {
-                return entity;
-            }
-        };
-    }
-
-    @Override
-    public EntityOwnershipListenerRegistration registerListener(final String entityType, final EntityOwnershipListener listener) {
-        listeners.add(listener);
-        if (listeners.size() == 3) {
-            distributeOwnership();
-        }
-        return new EntityOwnershipListenerRegistration() {
-            @Nonnull
-            @Override
-            public String getEntityType() {
-                return entityType;
-            }
-
-            @Override
-            public void close() {
-                listeners.remove(listener);
-            }
-
-            @Override
-            public EntityOwnershipListener getInstance() {
-                return listener;
-            }
-        };
-    }
-
-    @Override
-    public Optional<EntityOwnershipState> getOwnershipState(final Entity forEntity) {
-        return null;
-    }
-
-    @Override
-    public boolean isCandidateRegistered(@Nonnull Entity entity) {
-        return true;
-    }
-
-    public void distributeOwnership() {
-        LOG.debug("Distributing ownership");
-        executorService.submit(new Runnable() {
-            @Override
-            public void run() {
-                masterSet = false;
-                LOG.debug("Distributing ownership for {} listeners", listeners.size());
-                for (final EntityOwnershipListener listener : listeners) {
-                    if (!masterSet) {
-                        listener.ownershipChanged(new EntityOwnershipChange(entity, false, true, true));
-                        masterSet = true;
-                    } else {
-                        listener.ownershipChanged(new EntityOwnershipChange(entity, false, false, true));
-                    }
-                }
-
-            }
-        });
-    }
-}
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/TestingTopologyDispatcher.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/TestingTopologyDispatcher.java
deleted file mode 100644 (file)
index 28a1f97..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology;
-
-import akka.actor.ActorContext;
-import akka.actor.ActorRef;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade.ConnectionStatusListenerRegistration;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TestingTopologyDispatcher implements NetconfTopology{
-
-    private static final Logger LOG = LoggerFactory.getLogger(TestingTopologyDispatcher.class);
-
-    private final String topologyId;
-
-    private final ExecutorService executorService = Executors.newSingleThreadExecutor();
-    private final Set<NodeId> connected = new HashSet<>();
-    private final Map<NodeId, RemoteDeviceHandler<NetconfSessionPreferences>> listeners = new HashMap<>();
-
-
-    public TestingTopologyDispatcher(final String topologyId) {
-
-        this.topologyId = topologyId;
-    }
-
-    @Override
-    public String getTopologyId() {
-        return topologyId;
-    }
-
-    @Override
-    public DataBroker getDataBroker() {
-        return null;
-    }
-
-    // log the current connection attempt and return a successful future asynchronously
-    @Override
-    public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
-        final NetconfNode augmentation = configNode.getAugmentation(NetconfNode.class);
-        LOG.debug("Connecting node {}, with config: {} ", nodeId.getValue(),
-                augmentation.getHost().getIpAddress().toString() + ":" + augmentation.getPort());
-        connected.add(nodeId);
-        final SettableFuture<NetconfDeviceCapabilities> future = SettableFuture.create();
-        executorService.submit(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    Thread.sleep(4000);
-                    executorService.submit(new Runnable() {
-                        @Override
-                        public void run() {
-                            future.set(new NetconfDeviceCapabilities());
-                        }
-                    });
-                } catch (InterruptedException e) {
-                    LOG.error("Cannot sleep thread", e);
-                }
-            }
-        });
-        return future;
-    }
-
-    @Override
-    public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
-        Preconditions.checkState(connected.contains(nodeId), "Node is not connected yet");
-        LOG.debug("Disconnecting node {}", nodeId.getValue());
-        final SettableFuture<Void> future = SettableFuture.create();
-        executorService.submit(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    Thread.sleep(4000);
-                    executorService.submit(new Runnable() {
-                        @Override
-                        public void run() {
-                            connected.remove(nodeId);
-                            future.set(null);
-                        }
-                    });
-                } catch (InterruptedException e) {
-                    LOG.error("Cannot sleep thread", e);
-                }
-
-            }
-        });
-        return future;
-    }
-
-    @Override
-    public void registerMountPoint(ActorContext context, NodeId nodeId) {
-        LOG.debug("Registering mount point for node {}", nodeId.getValue());
-    }
-
-    @Override
-    public void registerMountPoint(ActorContext context, NodeId nodeId, ActorRef masterRef) {
-        LOG.debug("Registering mount point for node {}", nodeId.getValue());
-    }
-
-    @Override
-    public void unregisterMountPoint(NodeId nodeId) {
-        LOG.debug("Unregistering mount point for node {}", nodeId.getValue());
-    }
-
-    @Override
-    public ConnectionStatusListenerRegistration registerConnectionStatusListener(final NodeId node, final RemoteDeviceHandler<NetconfSessionPreferences> listener) {
-        Preconditions.checkState(connected.contains(node), "Node is not connected yet");
-
-        LOG.debug("Registering a connection status listener for node {}", node.getValue());
-        listeners.put(node, listener);
-        executorService.submit(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    Thread.sleep(10000);
-
-                    boolean up = false;
-                    for (int i = 0; i < 20; i++) {
-                        if (up) {
-                            LOG.debug("Device has connected {}", node.getValue());
-                            listener.onDeviceConnected(null, null, null);
-                            up = false;
-                        } else {
-                            LOG.debug("Device has diconnected {}", node.getValue());
-                            listener.onDeviceDisconnected();
-                            up = true;
-                        }
-                        try {
-                            Thread.sleep(5000);
-                        } catch (InterruptedException e) {
-                            LOG.error("Cannot sleep thread", e);
-                        }
-                    }
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-
-            }
-        });
-
-        return null;
-    }
-}
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfNodeOperationalDataAggregatorTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfNodeOperationalDataAggregatorTest.java
deleted file mode 100644 (file)
index d0976b4..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.impl;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-
-public class NetconfNodeOperationalDataAggregatorTest {
-
-    private List<ListenableFuture<Node>> stateFutures;
-
-    private NetconfNodeOperationalDataAggregator aggregator;
-
-    @Before
-    public void setUp() {
-        aggregator = new NetconfNodeOperationalDataAggregator();
-        stateFutures = Lists.newArrayList();
-    }
-
-    @Test
-    public void testCombineCreateAttempts() throws ExecutionException, InterruptedException {
-        NetconfNode testingNode = new NetconfNodeBuilder().setAvailableCapabilities(
-                new AvailableCapabilitiesBuilder().setAvailableCapability(Lists.<String>newArrayList()).build())
-                .setClusteredConnectionStatus(new ClusteredConnectionStatusBuilder().setNodeStatus(Lists.newArrayList(
-                        new NodeStatusBuilder().setStatus(NodeStatus.Status.Connected).build())).build())
-                .setConnectionStatus(NetconfNodeConnectionStatus.ConnectionStatus.Connected).build();
-        stateFutures.add(Futures.immediateFuture(new NodeBuilder().addAugmentation(NetconfNode.class, testingNode).build()));
-
-        ListenableFuture<Node> aggregatedCreateFuture = aggregator.combineCreateAttempts(stateFutures);
-        assertTrue(aggregatedCreateFuture.isDone());
-
-        NetconfNode aggregatedNode = aggregatedCreateFuture.get().getAugmentation(NetconfNode.class);
-        assertEquals(aggregatedNode.getClusteredConnectionStatus().getNodeStatus().get(0).getStatus(),
-                NodeStatus.Status.Connected);
-    }
-
-    @Test
-    public void testSuccessfulCombineUpdateAttempts() throws ExecutionException, InterruptedException {
-        NetconfNode testingNode = new NetconfNodeBuilder().setAvailableCapabilities(
-                new AvailableCapabilitiesBuilder().setAvailableCapability(Lists.<String>newArrayList()).build())
-                .setClusteredConnectionStatus(new ClusteredConnectionStatusBuilder().setNodeStatus(Lists.newArrayList(
-                        new NodeStatusBuilder().setStatus(NodeStatus.Status.Connected).build())).build())
-                .setConnectionStatus(NetconfNodeConnectionStatus.ConnectionStatus.Connected).build();
-        stateFutures.add(Futures.immediateFuture(new NodeBuilder().addAugmentation(NetconfNode.class, testingNode).build()));
-
-        ListenableFuture<Node> aggregatedUpdateFuture = aggregator.combineUpdateAttempts(stateFutures);
-        assertTrue(aggregatedUpdateFuture.isDone());
-
-        NetconfNode aggregatedNode = aggregatedUpdateFuture.get().getAugmentation(NetconfNode.class);
-        assertEquals(aggregatedNode.getClusteredConnectionStatus().getNodeStatus().get(0).getStatus(),
-                NodeStatus.Status.Connected);
-    }
-
-    @Test
-    public void testSuccessfulCombineDeleteAttempts() throws ExecutionException, InterruptedException {
-        List deleteStateFutures = Lists.newArrayList(Futures.immediateFuture(null), Futures.immediateFuture(null));
-
-        ListenableFuture<Void> deleteFuture = aggregator.combineDeleteAttempts(deleteStateFutures);
-        assertTrue(deleteFuture.isDone());
-        assertEquals(deleteFuture.get(), null);
-    }
-
-    @Test
-    public void testFailedCombineDeleteAttempts() {
-        Exception cause = new Exception("Fail");
-        List deleteStateFutures = Lists.newArrayList(Futures.immediateFuture(null), Futures.immediateFuture(null),
-                Futures.immediateFailedFuture(cause));
-
-        ListenableFuture<Void> deleteFuture = aggregator.combineDeleteAttempts(deleteStateFutures);
-        assertTrue(deleteFuture.isDone());
-
-        try {
-            deleteFuture.get();
-            fail("Exception expected");
-        } catch(Exception e) {
-            assertSame(e.getCause(), cause);
-        }
-    }
-}
index 1db1c3a7e836bed895bc9fe03f8d2daa6d7a5815..2a2f2f4125c6d1fd1e3125972e5de531c199eb80 100644 (file)
@@ -16,7 +16,6 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import akka.actor.ActorContext;
 import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -42,11 +41,8 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.topology.SchemaRepositoryProvider;
-import org.opendaylight.netconf.topology.util.TopologyUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
@@ -113,23 +109,6 @@ public class NetconfTopologyImplTest {
         spyTopology = spy(topology);
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testRegisterMountPointNotSupported() {
-        ActorContext context = mock(ActorContext.class);
-        topology.registerMountPoint(context, NODE_ID);
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testUnregisterMountPointNotSupported() {
-        topology.unregisterMountPoint(NODE_ID);
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testRegisterConnectionStatusListener() {
-        RemoteDeviceHandler<NetconfSessionPreferences> listener = mock(RemoteDeviceHandler.class);
-        topology.registerConnectionStatusListener(NODE_ID, listener);
-    }
-
     @Test
     public void testOnSessionInitiated() {
         BindingAwareBroker.ProviderContext session = mock(BindingAwareBroker.ProviderContext.class);
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriterTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriterTest.java
deleted file mode 100644 (file)
index 4e11457..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.impl;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.MockitoAnnotations.initMocks;
-
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Futures;
-import java.util.ArrayList;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
-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.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus.Status;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatusBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-
-public class TopologyNodeWriterTest {
-
-    private static final NodeId NODE_ID = new NodeId("testing-node");
-    private static final String TOPOLOGY_ID = "testing-topology";
-
-    private static final InstanceIdentifier<NetworkTopology> NETWORK_TOPOLOGY_IID = InstanceIdentifier.builder(NetworkTopology.class).build();
-    private static final KeyedInstanceIdentifier<Topology, TopologyKey> TOPOLOGY_LIST_IID;
-
-    private static final KeyedInstanceIdentifier<Node, NodeKey> OPERATIONAL_NODE_IID;
-
-    static {
-        TOPOLOGY_LIST_IID = NETWORK_TOPOLOGY_IID.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID)));
-        OPERATIONAL_NODE_IID = TOPOLOGY_LIST_IID.child(Node.class, new NodeKey(new NodeId(NODE_ID)));
-    }
-
-    @Mock
-    private DataBroker dataBroker;
-
-    @Mock
-    private BindingTransactionChain txChain;
-
-    @Mock
-    private WriteTransaction wtx;
-
-    private Node operationalNode;
-
-    private TopologyNodeWriter writer;
-
-    @Before
-    public void setUp() throws Exception {
-        initMocks(this);
-        doReturn(txChain).when(dataBroker).createTransactionChain(any(TransactionChainListener.class));
-        doReturn(wtx).when(txChain).newWriteOnlyTransaction();
-        doNothing().when(wtx).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
-        doReturn(Futures.immediateCheckedFuture(null)).when(wtx).submit();
-        writer = new TopologyNodeWriter(TOPOLOGY_ID, dataBroker);
-
-        operationalNode = new NodeBuilder()
-                .setNodeId(NODE_ID)
-                .addAugmentation(NetconfNode.class,
-                        new NetconfNodeBuilder()
-                                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                                .setPort(new PortNumber(17830))
-                                .setConnectionStatus(ConnectionStatus.Connected)
-                                .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
-                                .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
-                                .setClusteredConnectionStatus(
-                                        new ClusteredConnectionStatusBuilder()
-                                                .setNodeStatus(
-                                                        Lists.newArrayList(
-                                                                new NodeStatusBuilder()
-                                                                        .setNode("10.10.10.10")
-                                                                        .setStatus(Status.Connected)
-                                                                        .build()))
-                                                .build())
-                                .build())
-                .build();
-
-    }
-
-    @Test
-    public void testInit() throws Exception {
-        writer.init(NODE_ID, operationalNode);
-        // once in constructor + once in init
-        verify(txChain, times(2)).newWriteOnlyTransaction();
-        verify(wtx, times(2)).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(NETWORK_TOPOLOGY_IID), eq(new NetworkTopologyBuilder().build()));
-        verify(wtx, times(2)).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(TOPOLOGY_LIST_IID), eq(new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build()));
-        // actual write
-        verify(wtx, times(1)).put(eq(LogicalDatastoreType.OPERATIONAL), eq(OPERATIONAL_NODE_IID), eq(operationalNode));
-
-        // once in constructor + once in init()
-        verify(wtx, times(2)).submit();
-    }
-
-    @Test
-    public void testUpdate() throws Exception {
-        writer.update(NODE_ID, operationalNode);
-
-        verify(txChain, times(2)).newWriteOnlyTransaction();
-        verify(wtx, times(1)).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(NETWORK_TOPOLOGY_IID), eq(new NetworkTopologyBuilder().build()));
-        verify(wtx, times(1)).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(TOPOLOGY_LIST_IID), eq(new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build()));
-        // actual write
-        verify(wtx, times(1)).put(eq(LogicalDatastoreType.OPERATIONAL), eq(OPERATIONAL_NODE_IID), eq(operationalNode));
-        verify(wtx, times(2)).submit();
-
-    }
-
-    @Test
-    public void testDelete() throws Exception {
-        writer.delete(NODE_ID);
-        verify(txChain, times(2)).newWriteOnlyTransaction();
-        verify(wtx, times(1)).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(NETWORK_TOPOLOGY_IID), eq(new NetworkTopologyBuilder().build()));
-        verify(wtx, times(1)).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(TOPOLOGY_LIST_IID), eq(new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build()));
-        verify(wtx, times(1)).delete(eq(LogicalDatastoreType.OPERATIONAL), eq(OPERATIONAL_NODE_IID));
-        verify(wtx, times(2)).submit();
-    }
-}
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceCommunicatorTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/ClusteredNetconfDeviceCommunicatorTest.java
deleted file mode 100644 (file)
index aa6b69d..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import java.net.InetSocketAddress;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.netconf.api.NetconfTerminationReason;
-import org.opendaylight.netconf.client.NetconfClientSession;
-import org.opendaylight.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-
-public class ClusteredNetconfDeviceCommunicatorTest {
-
-    private static final RemoteDeviceId REMOTE_DEVICE_ID = new RemoteDeviceId("testing-device", new InetSocketAddress(9999));
-
-    @Mock
-    private ClusteredNetconfDevice remoteDevice;
-
-    @Mock
-    private EntityOwnershipService ownershipService;
-
-    @Mock
-    private NetconfClientSession session;
-
-    @Mock
-    private NetconfClientSessionListener listener1;
-
-    @Mock
-    private NetconfClientSessionListener listener2;
-
-    @Mock
-    private EntityOwnershipListenerRegistration ownershipListenerRegistration;
-
-    private ClusteredNetconfDeviceCommunicator communicator;
-
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        doReturn(ownershipListenerRegistration).when(ownershipService).registerListener(
-                "netconf-node/" + REMOTE_DEVICE_ID.getName(), remoteDevice);
-
-        communicator = new ClusteredNetconfDeviceCommunicator(REMOTE_DEVICE_ID, remoteDevice, ownershipService, 10);
-        communicator.registerNetconfClientSessionListener(listener1);
-        communicator.registerNetconfClientSessionListener(listener2);
-    }
-
-    @Test
-    public void testOnSessionDown() {
-        communicator.onSessionUp(session);
-
-        Exception exception = mock(Exception.class);
-        communicator.onSessionDown(session, exception);
-
-        verify(ownershipListenerRegistration).close();
-
-        verify(listener1).onSessionDown(eq(session), eq(exception));
-        verify(listener2).onSessionDown(eq(session), eq(exception));
-    }
-
-    @Test
-    public void testOnSessionUp() {
-        communicator.onSessionUp(session);
-
-        verify(ownershipService).registerListener("netconf-node/" + REMOTE_DEVICE_ID.getName(), remoteDevice);
-
-        verify(listener1).onSessionUp(eq(session));
-        verify(listener2).onSessionUp(eq(session));
-    }
-
-    @Test
-    public void testOnSessionTerminated() {
-        communicator.onSessionUp(session);
-
-        NetconfTerminationReason reason = mock(NetconfTerminationReason.class);
-        communicator.onSessionTerminated(session, reason);
-
-        verify(ownershipListenerRegistration).close();
-
-        verify(listener1).onSessionTerminated(eq(session), eq(reason));
-        verify(listener2).onSessionTerminated(eq(session), eq(reason));
-    }
-}
\ No newline at end of file
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBrokerTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBrokerTest.java
deleted file mode 100644 (file)
index 417978d..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
-import akka.actor.ActorSystem;
-import java.net.InetSocketAddress;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-public class NetconfDeviceSlaveDataBrokerTest {
-
-    private static final RemoteDeviceId REMOTE_DEVICE_ID = new RemoteDeviceId("testing-device", new InetSocketAddress(9999));
-
-    @Mock
-    private ProxyNetconfDeviceDataBroker mockedDataBroker;
-
-    @Mock
-    private ActorSystem mockedActorSystem;
-
-    private NetconfDeviceSlaveDataBroker slaveDataBroker;
-
-    @Before
-    public void setUp() {
-        slaveDataBroker = new NetconfDeviceSlaveDataBroker(mockedActorSystem, REMOTE_DEVICE_ID, mockedDataBroker);
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testRegisterDataChangeListener() {
-        slaveDataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY,
-                mock(DOMDataChangeListener.class), AsyncDataBroker.DataChangeScope.SUBTREE);
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testCreateTransactionChain() {
-        slaveDataBroker.createTransactionChain(mock(TransactionChainListener.class));
-    }
-
-    @Test
-    public void testGetSupportedExtensions() {
-        assertTrue(slaveDataBroker.getSupportedExtensions().isEmpty());
-    }
-}
\ No newline at end of file
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacadeTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacadeTest.java
deleted file mode 100644 (file)
index 68342a5..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline;
-
-import java.net.InetSocketAddress;
-import java.util.Collections;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class TopologyMountPointFacadeTest {
-
-    private static final RemoteDeviceId REMOTE_DEVICE_ID = new RemoteDeviceId("testing-device", new InetSocketAddress(9999));
-    private static final String TOPOLOGY_ID = "testing-topology";
-
-    @Mock
-    Broker domBroker;
-
-    @Mock
-    BindingAwareBroker bindingBroker;
-
-    @Mock
-    RemoteDeviceHandler<NetconfSessionPreferences> connectionStatusListener1;
-
-    @Mock
-    RemoteDeviceHandler<NetconfSessionPreferences> connectionStatusListener2;
-
-
-    private TopologyMountPointFacade mountPointFacade;
-
-    @Before
-    public void setUp() {
-
-        MockitoAnnotations.initMocks(this);
-
-        mountPointFacade = new TopologyMountPointFacade(TOPOLOGY_ID, REMOTE_DEVICE_ID, domBroker, bindingBroker);
-
-        mountPointFacade.registerConnectionStatusListener(connectionStatusListener1);
-        mountPointFacade.registerConnectionStatusListener(connectionStatusListener2);
-
-    }
-
-    @Test
-    public void testOnDeviceConnected() {
-        SchemaContext mockedContext = Mockito.mock(SchemaContext.class);
-        NetconfSessionPreferences mockedPreferences = NetconfSessionPreferences.fromStrings(Collections.<String>emptyList());
-        DOMRpcService mockedRpcService = Mockito.mock(DOMRpcService.class);
-        mountPointFacade.onDeviceConnected(mockedContext, mockedPreferences, mockedRpcService);
-
-        Mockito.verify(connectionStatusListener1).onDeviceConnected(mockedContext, mockedPreferences, mockedRpcService);
-        Mockito.verify(connectionStatusListener2).onDeviceConnected(mockedContext, mockedPreferences, mockedRpcService);
-    }
-
-    @Test
-    public void testOnDeviceDisconnected() {
-        mountPointFacade.onDeviceDisconnected();
-
-        Mockito.verify(connectionStatusListener1).onDeviceDisconnected();
-        Mockito.verify(connectionStatusListener2).onDeviceDisconnected();
-    }
-
-    @Test
-    public void testOnDeviceFailed() {
-        Throwable mockedException = Mockito.mock(Throwable.class);
-        mountPointFacade.onDeviceFailed(mockedException);
-
-        Mockito.verify(connectionStatusListener1).onDeviceFailed(mockedException);
-        Mockito.verify(connectionStatusListener2).onDeviceFailed(mockedException);
-    }
-
-}
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransactionTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransactionTest.java
deleted file mode 100644 (file)
index afde0a0..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline.tx;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import akka.actor.ActorSystem;
-import akka.dispatch.ExecutionContexts;
-import akka.dispatch.Futures;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.net.InetSocketAddress;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.pipeline.ProxyNetconfDeviceDataBroker;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-public class ProxyReadOnlyTransactionTest {
-    private static final RemoteDeviceId REMOTE_DEVICE_ID = new RemoteDeviceId("testing-device", new InetSocketAddress(9999));
-    private static final YangInstanceIdentifier path = YangInstanceIdentifier.create();
-
-    @Mock
-    private ProxyNetconfDeviceDataBroker mockedProxyDataBroker;
-
-    @Mock
-    private ActorSystem mockedActorSystem;
-
-    @Mock
-    private NormalizedNodeMessage mockedNodeMessage;
-
-    @Mock
-    private NormalizedNode mockedNode;
-
-    private ProxyReadOnlyTransaction proxyReadOnlyTx;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        when(mockedActorSystem.dispatcher()).thenReturn(ExecutionContexts.fromExecutorService(MoreExecutors.newDirectExecutorService()));
-        when(mockedNodeMessage.getNode()).thenReturn(mockedNode);
-
-        proxyReadOnlyTx = new ProxyReadOnlyTransaction(mockedActorSystem, REMOTE_DEVICE_ID, mockedProxyDataBroker);
-    }
-
-    @Test
-    public void testSuccessfulRead() throws ReadFailedException {
-        when(mockedProxyDataBroker.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class)))
-                .thenReturn(Futures.successful(Optional.of(mockedNodeMessage)));
-        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readResultFuture =  proxyReadOnlyTx.read(LogicalDatastoreType.CONFIGURATION, path);
-        verify(mockedProxyDataBroker).read(eq(LogicalDatastoreType.CONFIGURATION), eq(path));
-        assertTrue(readResultFuture.isDone());
-        assertEquals(readResultFuture.checkedGet().get(), mockedNode);
-    }
-
-    @Test
-    public void testFailedRead() {
-        when(mockedProxyDataBroker.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class)))
-                .thenReturn(Futures.<Optional<NormalizedNodeMessage>>failed(new ReadFailedException("Test read failed!")));
-        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readResultFuture =  proxyReadOnlyTx.read(LogicalDatastoreType.CONFIGURATION, path);
-        verify(mockedProxyDataBroker).read(eq(LogicalDatastoreType.CONFIGURATION), eq(path));
-        assertTrue(readResultFuture.isDone());
-        try {
-            readResultFuture.checkedGet();
-            fail("Exception expected");
-        } catch(Exception e) {
-            assertTrue(e instanceof ReadFailedException);
-        }
-    }
-
-    @Test
-    public void testDataOnPathDoesNotExistPathRead() throws ReadFailedException {
-        when(mockedProxyDataBroker.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class)))
-                .thenReturn(Futures.successful(Optional.absent()));
-        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readResultFuture =  proxyReadOnlyTx.read(LogicalDatastoreType.CONFIGURATION, path);
-        verify(mockedProxyDataBroker).read(eq(LogicalDatastoreType.CONFIGURATION), eq(path));
-        assertTrue(readResultFuture.isDone());
-        assertTrue(!readResultFuture.checkedGet().isPresent());
-    }
-
-    @Test
-    public void testFailedExists() {
-        when(mockedProxyDataBroker.exists(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class)))
-                .thenReturn(Futures.<Boolean>failed(new ReadFailedException("Test read failed!")));
-        CheckedFuture existsFuture = proxyReadOnlyTx.exists(LogicalDatastoreType.OPERATIONAL, path);
-        verify(mockedProxyDataBroker).exists(eq(LogicalDatastoreType.OPERATIONAL), eq(path));
-        assertTrue(existsFuture.isDone());
-        try {
-            existsFuture.checkedGet();
-            fail("Exception expected");
-        } catch(Exception e) {
-            assertTrue(e instanceof ReadFailedException);
-        }
-    }
-
-    @Test
-    public void testExists() throws Exception {
-        when(mockedProxyDataBroker.exists(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class)))
-            .thenReturn(Futures.successful(true));
-        CheckedFuture<Boolean, ReadFailedException> existsFuture = proxyReadOnlyTx.exists(LogicalDatastoreType.OPERATIONAL, path);
-        verify(mockedProxyDataBroker).exists(eq(LogicalDatastoreType.OPERATIONAL), eq(path));
-        assertTrue(existsFuture.isDone());
-        assertTrue(existsFuture.checkedGet());
-    }
-}
\ No newline at end of file
diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyWriteOnlyTransactionTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyWriteOnlyTransactionTest.java
deleted file mode 100644 (file)
index 83c118f..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.topology.pipeline.tx;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import akka.actor.ActorSystem;
-import akka.dispatch.ExecutionContexts;
-import akka.dispatch.Futures;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.util.concurrent.ExecutionException;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.netconf.topology.pipeline.ProxyNetconfDeviceDataBroker;
-import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-public class ProxyWriteOnlyTransactionTest {
-    private static final YangInstanceIdentifier path = YangInstanceIdentifier.create();
-    private ArgumentCaptor<NormalizedNodeMessage> nodeMessageArgumentCaptor;
-
-    @Mock
-    private ProxyNetconfDeviceDataBroker mockedDelegate;
-
-    @Mock
-    private ActorSystem mockedActorSystem;
-
-    @Mock
-    private NormalizedNode<?, ?> normalizedNode;
-
-    private ProxyWriteOnlyTransaction tx;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        when(mockedActorSystem.dispatcher()).thenReturn(ExecutionContexts.fromExecutorService(MoreExecutors.newDirectExecutorService()));
-
-        nodeMessageArgumentCaptor = ArgumentCaptor.forClass(NormalizedNodeMessage.class);
-        tx = new ProxyWriteOnlyTransaction(mockedActorSystem, mockedDelegate);
-    }
-
-    @Test
-    public void testPut() {
-        doNothing().when(mockedDelegate).put(any(LogicalDatastoreType.class), any(NormalizedNodeMessage.class));
-        tx.put(LogicalDatastoreType.OPERATIONAL, path, normalizedNode);
-        verify(mockedDelegate).put(eq(LogicalDatastoreType.OPERATIONAL), nodeMessageArgumentCaptor.capture());
-        assertEquals(path, nodeMessageArgumentCaptor.getValue().getIdentifier());
-        assertEquals(normalizedNode, nodeMessageArgumentCaptor.getValue().getNode());
-    }
-
-    @Test
-    public void testMerge() {
-        doNothing().when(mockedDelegate).merge(any(LogicalDatastoreType.class), any(NormalizedNodeMessage.class));
-        tx.merge(LogicalDatastoreType.CONFIGURATION, path, normalizedNode);
-        verify(mockedDelegate).merge(eq(LogicalDatastoreType.CONFIGURATION), nodeMessageArgumentCaptor.capture());
-        assertEquals(path, nodeMessageArgumentCaptor.getValue().getIdentifier());
-        assertEquals(normalizedNode, nodeMessageArgumentCaptor.getValue().getNode());
-    }
-
-    @Test
-    public void testCancel() {
-        when(mockedDelegate.cancel()).thenReturn(true);
-        assertTrue(tx.cancel());
-        verify(mockedDelegate).cancel();
-    }
-
-    @Test
-    public void testDelete() {
-        doNothing().when(mockedDelegate).delete(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class));
-        tx.delete(LogicalDatastoreType.OPERATIONAL, path);
-        verify(mockedDelegate).delete(eq(LogicalDatastoreType.OPERATIONAL), eq(path));
-    }
-
-    @Test
-    public void testSuccessfulSubmit() throws Exception {
-        when(mockedDelegate.submit()).thenReturn(Futures.<Void>successful(null));
-        CheckedFuture submitFuture = tx.submit();
-        verify(mockedDelegate).submit();
-        assertTrue(submitFuture.isDone());
-        assertEquals(submitFuture.checkedGet(), null);
-    }
-
-    @Test
-    public void testFailedSubmit() {
-        when(mockedDelegate.submit()).thenReturn(Futures.<Void>failed(new TransactionCommitFailedException("fail")));
-        CheckedFuture submitFuture = tx.submit();
-        verify(mockedDelegate).submit();
-        assertTrue(submitFuture.isDone());
-        try {
-            submitFuture.checkedGet();
-            fail("Exception expected");
-        } catch(Exception e) {
-            assertTrue(e instanceof TransactionCommitFailedException);
-        }
-    }
-
-    @Test
-    public void testSuccessfulCommit() throws ExecutionException, InterruptedException {
-        RpcResult<TransactionStatus> rpcResult = mock(RpcResult.class);
-        when(mockedDelegate.commit()).thenReturn(Futures.successful(rpcResult));
-        ListenableFuture<RpcResult<TransactionStatus>> submitFuture = tx.commit();
-        verify(mockedDelegate).commit();
-        assertTrue(submitFuture.isDone());
-        assertEquals(submitFuture.get(), rpcResult);
-    }
-
-    @Test
-    public void testFailedCommit() {
-        when(mockedDelegate.commit()).thenReturn(Futures.<RpcResult<TransactionStatus>>failed(new TransactionCommitFailedException("faile")));
-        ListenableFuture<RpcResult<TransactionStatus>> submitFuture = tx.commit();
-        verify(mockedDelegate).commit();
-        assertTrue(submitFuture.isDone());
-        try {
-            submitFuture.get();
-            fail("Exception expected");
-        } catch(Exception e) {
-            assertTrue(e.getCause() instanceof TransactionCommitFailedException);
-        }
-    }
-}
\ No newline at end of file
diff --git a/netconf/netconf-topology/src/test/resources/netconf-node1.conf b/netconf/netconf-topology/src/test/resources/netconf-node1.conf
deleted file mode 100644 (file)
index ed0aac1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-include "test.conf"
-
-akka {
-  # LISTEN on tcp port 2552
-  remote.netty.tcp.port = 2552
-
-  cluster {
-    seed-nodes = [
-      "akka.tcp://NetconfNode@127.0.0.1:2553",
-      "akka.tcp://NetconfNode@127.0.0.1:2554"]
-
-    auto-down-unreachable-after = 10s
-  }
-}
diff --git a/netconf/netconf-topology/src/test/resources/netconf-node2.conf b/netconf/netconf-topology/src/test/resources/netconf-node2.conf
deleted file mode 100644 (file)
index 6090891..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-include "test.conf"
-
-akka {
-  # LISTEN on tcp port 2553
-  remote.netty.tcp.port = 2553
-
-  cluster {
-    seed-nodes = [
-      "akka.tcp://NetconfNode@127.0.0.1:2552",
-      "akka.tcp://NetconfNode@127.0.0.1:2554"]
-
-    auto-down-unreachable-after = 10s
-  }
-}
diff --git a/netconf/netconf-topology/src/test/resources/netconf-node3.conf b/netconf/netconf-topology/src/test/resources/netconf-node3.conf
deleted file mode 100644 (file)
index 620ede3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-include "test.conf"
-
-akka {
-  # LISTEN on tcp port 2554
-  remote.netty.tcp.port = 2554
-
-  cluster {
-    seed-nodes = [
-      "akka.tcp://NetconfNode@127.0.0.1:2552",
-      "akka.tcp://NetconfNode@127.0.0.1:2553"]
-
-    auto-down-unreachable-after = 10s
-  }
-}
diff --git a/netconf/netconf-topology/src/test/resources/test.conf b/netconf/netconf-topology/src/test/resources/test.conf
deleted file mode 100644 (file)
index b8c7294..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-akka {
-
-  actor {
-    provider = "akka.cluster.ClusterActorRefProvider"
-
-    serializers {
-      java = "akka.serialization.JavaSerializer"
-    }
-
-    serialization-bindings {
-      "[B" = bytes
-      "java.io.Serializable" = java
-    }
-  }
-
-  remote {
-    enabled-transports = ["akka.remote.netty.tcp"]
-    netty.tcp {
-      hostname = "127.0.0.1"
-    }
-  }
-}
index 56108b9d0d12fd7aba1b439272da19ef84bf871a..110872bf88c085de0276dae2089ffa6bddfc46ff 100644 (file)
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
     <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Bundle-Activator>org.opendaylight.netconf.util.osgi.NetconfConfigurationActivator</Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/netconf.cfg</file>
+                  <type>cfg</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
index 9a6ff2e054e7e351ee441e00c8bf10fa028036e7..9d4b5a123839fa39eaa39a119560dc116deb7cb3 100644 (file)
@@ -11,8 +11,12 @@ package org.opendaylight.netconf.util.osgi;
 import com.google.common.base.Optional;
 import io.netty.channel.local.LocalAddress;
 import java.net.InetSocketAddress;
+import java.util.Collection;
 import java.util.concurrent.TimeUnit;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ManagedService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -109,4 +113,21 @@ public final class NetconfConfigUtil {
         }
         return Optional.fromNullable(value);
     }
+
+    public static java.util.Optional<NetconfConfiguration> getNetconfConfigurationService(BundleContext bundleContext) {
+        final Collection<ServiceReference<ManagedService>> serviceReferences;
+        try {
+            serviceReferences = bundleContext.getServiceReferences(ManagedService.class, null);
+            for (final ServiceReference<ManagedService> serviceReference : serviceReferences) {
+                ManagedService service = bundleContext.getService(serviceReference);
+                if (service instanceof NetconfConfiguration){
+                    return java.util.Optional.of((NetconfConfiguration) service);
+                }
+            }
+        } catch (InvalidSyntaxException e) {
+            LOG.error("Unable to retrieve references for ManagedService: {}", e);
+        }
+        LOG.error("Unable to retrieve NetconfConfiguration service. Not found. Bundle netconf-util probably failed.");
+        return java.util.Optional.empty();
+    }
 }
diff --git a/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfiguration.java b/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfiguration.java
new file mode 100644 (file)
index 0000000..e33f7e2
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.util.osgi;
+
+import java.net.InetSocketAddress;
+import java.util.Dictionary;
+import org.osgi.service.cm.ManagedService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfConfiguration implements ManagedService {
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfConfiguration.class);
+
+    private static final NetconfConfiguration instance = new NetconfConfiguration();
+    private NetconfConfigurationHolder netconfConfiguration;
+
+    public static final String KEY_SSH_ADDRESS = "ssh-address";
+    public static final String KEY_SSH_PORT = "ssh-port";
+    public static final String KEY_TCP_ADDRESS = "tcp-address";
+    public static final String KEY_TCP_PORT = "tcp-port";
+    public static final String KEY_SSH_PK_PATH = "ssh-pk-path";
+
+    public static NetconfConfiguration getInstance() {
+        return instance;
+    }
+
+    private NetconfConfiguration() {
+        netconfConfiguration = new NetconfConfigurationHolder(NetconfConfigUtil.DEFAULT_TCP_SERVER_ADRESS,
+                NetconfConfigUtil.DEFAULT_SSH_SERVER_ADRESS, NetconfConfigUtil.DEFAULT_PRIVATE_KEY_PATH);
+    }
+
+    @Override
+    public void updated(final Dictionary<String, ?> dictionaryConfig) {
+        if (dictionaryConfig == null) {
+            LOG.warn("Netconf configuration cannot be updated.");
+            return;
+        }
+        final InetSocketAddress sshServerAddress = new InetSocketAddress((String) dictionaryConfig.get(KEY_SSH_ADDRESS),
+                Integer.parseInt((String) dictionaryConfig.get(KEY_SSH_PORT)));
+        final InetSocketAddress tcpServerAddress = new InetSocketAddress((String) dictionaryConfig.get(KEY_TCP_ADDRESS),
+                Integer.parseInt((String) dictionaryConfig.get(KEY_TCP_PORT)));
+
+        netconfConfiguration = new NetconfConfigurationHolder(tcpServerAddress, sshServerAddress,
+                (String) dictionaryConfig.get(KEY_SSH_PK_PATH));
+
+        LOG.info("Netconf configuration was updated: {}", dictionaryConfig.toString());
+    }
+
+    public InetSocketAddress getSshServerAddress(){
+        return netconfConfiguration.getSshServerAddress();
+    }
+
+    public InetSocketAddress getTcpServerAddress(){
+        return netconfConfiguration.getTcpServerAddress();
+    }
+
+    public String getPrivateKeyPath() {
+        return netconfConfiguration.getPrivateKeyPath();
+    }
+}
\ No newline at end of file
diff --git a/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfigurationActivator.java b/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfigurationActivator.java
new file mode 100644 (file)
index 0000000..a752322
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.util.osgi;
+
+import java.util.Hashtable;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
+
+public class NetconfConfigurationActivator implements BundleActivator {
+    private static final String CONFIG_PID = "netconf";
+    private ServiceRegistration configService;
+
+    @Override
+    public void start(BundleContext bundleContext) {
+        configService = bundleContext.registerService(ManagedService.class,
+                NetconfConfiguration.getInstance(), getNetconfConfigProperties());
+    }
+
+    @Override
+    public void stop(BundleContext bundleContext) {
+        if (configService != null) {
+          configService.unregister();
+          configService = null;
+        }
+    }
+
+    private Hashtable<String, String> getNetconfConfigProperties(){
+        Hashtable<String, String> properties = new Hashtable<>();
+        properties.put(Constants.SERVICE_PID, CONFIG_PID);
+        return properties;
+    }
+}
diff --git a/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfigurationHolder.java b/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/osgi/NetconfConfigurationHolder.java
new file mode 100644 (file)
index 0000000..74b3a08
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.util.osgi;
+
+import java.net.InetSocketAddress;
+
+final class NetconfConfigurationHolder {
+
+    private final InetSocketAddress tcpServerAddress;
+    private final InetSocketAddress sshServerAddress;
+    private final String privateKeyPath;
+
+    NetconfConfigurationHolder(InetSocketAddress tcpServerAddress, InetSocketAddress sshServerAddress, String privateKeyPath){
+        this.tcpServerAddress = tcpServerAddress;
+        this.sshServerAddress = sshServerAddress;
+        this.privateKeyPath = privateKeyPath;
+    }
+
+    String getPrivateKeyPath() {
+        return privateKeyPath;
+    }
+
+    InetSocketAddress getSshServerAddress() {
+        return sshServerAddress;
+    }
+
+    InetSocketAddress getTcpServerAddress() {
+        return tcpServerAddress;
+    }
+
+}
diff --git a/netconf/netconf-util/src/main/resources/netconf.cfg b/netconf/netconf-util/src/main/resources/netconf.cfg
new file mode 100644 (file)
index 0000000..01437d8
--- /dev/null
@@ -0,0 +1,11 @@
+# netconf-tcp:
+
+tcp-address=127.0.0.1
+tcp-port=8383
+
+# netconf-ssh:
+
+ssh-address=0.0.0.0
+ssh-port=1830
+# Use Linux style path
+ssh-pk-path = ./configuration/RSA.pk
\ No newline at end of file
diff --git a/netconf/netconf-util/src/test/resources/netconfMessages/copy-config.xml b/netconf/netconf-util/src/test/resources/netconfMessages/copy-config.xml
new file mode 100644 (file)
index 0000000..ec32fc1
--- /dev/null
@@ -0,0 +1,18 @@
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<rpc message-id="m-0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <copy-config>
+        <target>
+            <candidate/>
+        </target>
+        <source>
+            <running/>
+        </source>
+    </copy-config>
+</rpc>
\ No newline at end of file
diff --git a/netconf/netconf-util/src/test/resources/netconfMessages/edit-config-test-module-running.xml b/netconf/netconf-util/src/test/resources/netconfMessages/edit-config-test-module-running.xml
new file mode 100644 (file)
index 0000000..107121d
--- /dev/null
@@ -0,0 +1,22 @@
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<rpc message-id="m-0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <running/>
+        </target>
+        <default-operation>merge</default-operation>
+        <error-option>rollback-on-error</error-option>
+        <config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <c xmlns="test:namespace">
+                <a xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="replace">leaf-value</a>
+            </c>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/netconf/netconf-util/src/test/resources/netconfMessages/edit-config-test-module.xml b/netconf/netconf-util/src/test/resources/netconfMessages/edit-config-test-module.xml
new file mode 100644 (file)
index 0000000..81907d3
--- /dev/null
@@ -0,0 +1,21 @@
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<rpc message-id="m-0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <error-option>rollback-on-error</error-option>
+        <config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <c xmlns="test:namespace">
+                <a xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="replace">leaf-value</a>
+            </c>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/netconf/netconf-util/src/test/resources/netconfMessages/getConfig_candidate-filter.xml b/netconf/netconf-util/src/test/resources/netconfMessages/getConfig_candidate-filter.xml
new file mode 100644 (file)
index 0000000..7ebbe15
--- /dev/null
@@ -0,0 +1,18 @@
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<rpc message-id="m-0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <get-config>
+        <source>
+            <candidate/>
+        </source>
+        <filter xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:type="subtree">
+            <c xmlns="test:namespace"/>
+        </filter>
+    </get-config>
+</rpc>
\ No newline at end of file
diff --git a/netconf/netconf-util/src/test/resources/netconfMessages/lock-running.xml b/netconf/netconf-util/src/test/resources/netconfMessages/lock-running.xml
new file mode 100644 (file)
index 0000000..9c202ec
--- /dev/null
@@ -0,0 +1,16 @@
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<rpc message-id="101"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <lock>
+        <target>
+            <running/>
+        </target>
+    </lock>
+</rpc>
\ No newline at end of file
diff --git a/netconf/netconf-util/src/test/resources/netconfMessages/rpc-reply_get.xml b/netconf/netconf-util/src/test/resources/netconfMessages/rpc-reply_get.xml
new file mode 100644 (file)
index 0000000..b3209d7
--- /dev/null
@@ -0,0 +1,11 @@
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" message-id="a">
+    <data/>
+</rpc-reply>
\ No newline at end of file
diff --git a/netconf/netconf-util/src/test/resources/netconfMessages/unlock-running.xml b/netconf/netconf-util/src/test/resources/netconfMessages/unlock-running.xml
new file mode 100644 (file)
index 0000000..a74377a
--- /dev/null
@@ -0,0 +1,16 @@
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<rpc message-id="101"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <unlock>
+        <target>
+            <running/>
+        </target>
+    </unlock>
+</rpc>
\ No newline at end of file
diff --git a/netconf/netconf-util/src/test/resources/netconfMessages/validate-running.xml b/netconf/netconf-util/src/test/resources/netconfMessages/validate-running.xml
new file mode 100644 (file)
index 0000000..783192d
--- /dev/null
@@ -0,0 +1,15 @@
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+    <validate>
+        <source>
+            <running/>
+        </source>
+    </validate>
+</rpc>
index d3e2f76f2ec3de83409cb50488faee278ca98728..925488cc637dd78e57a7df7336610a538a216089 100644 (file)
@@ -47,7 +47,7 @@
     <module>netconf-notifications-impl</module>
     <module>netconf-notifications-api</module>
     <module>netconf-topology</module>
-    <module>abstract-topology</module>
+    <module>netconf-topology-singleton</module>
     <module>netconf-topology-config</module>
     <module>sal-netconf-connector</module>
     <module>messagebus-netconf</module>
index 88eb368b9bb0a3a3a754f9e679f89b87c8876ec9..ffb5c7501763a2bf8b1222158f770591f5c403ba 100644 (file)
@@ -87,7 +87,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
 
     private boolean isHostAddressPresent(final Host address) {
         return address.getDomainName() != null ||
-               address.getIpAddress() != null && (address.getIpAddress().getIpv4Address() != null || address.getIpAddress().getIpv6Address() != null);
+                address.getIpAddress() != null && (address.getIpAddress().getIpv4Address() != null || address.getIpAddress().getIpv6Address() != null);
     }
 
     @Override
index 31aa51a3b9caaa239d3fd9880b34f6b5072cf6c7..04953133a3506b18e1783d545ba736c3a9d74b33 100644 (file)
@@ -50,6 +50,8 @@ import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessag
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -111,7 +113,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
         return new NetconfDeviceRpc(baseSchema.getSchemaContext(), listener, new NetconfMessageTransformer(baseSchema.getSchemaContext(), false, baseSchema));
     }
 
-    protected NetconfDevice(final SchemaResourcesDTO schemaResourcesDTO, final RemoteDeviceId id, final RemoteDeviceHandler<NetconfSessionPreferences> salFacade,
+    public NetconfDevice(final SchemaResourcesDTO schemaResourcesDTO, final RemoteDeviceId id, final RemoteDeviceHandler<NetconfSessionPreferences> salFacade,
                          final ExecutorService globalProcessingExecutor, final boolean reconnectOnSchemasChange) {
         this.id = id;
         this.reconnectOnSchemasChange = reconnectOnSchemasChange;
@@ -203,7 +205,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
         return remoteSessionCapabilities.isNotificationsSupported() && reconnectOnSchemasChange;
     }
 
-    protected void handleSalInitializationSuccess(final SchemaContext result, final NetconfSessionPreferences remoteSessionCapabilities, final DOMRpcService deviceRpc) {
+    void handleSalInitializationSuccess(final SchemaContext result, final NetconfSessionPreferences remoteSessionCapabilities, final DOMRpcService deviceRpc) {
         final BaseSchema baseSchema =
                 remoteSessionCapabilities.isNotificationsSupported() ?
                 BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS :
@@ -218,7 +220,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
         LOG.info("{}: Netconf connector initialized successfully", id);
     }
 
-    protected void handleSalInitializationFailure(final Throwable t, final RemoteDeviceCommunicator<NetconfMessage> listener) {
+    void handleSalInitializationFailure(final Throwable t, final RemoteDeviceCommunicator<NetconfMessage> listener) {
         LOG.error("{}: Initialization in sal failed, disconnecting from device", id, t);
         listener.close();
         onRemoteSessionDown();
@@ -452,8 +454,14 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
                     final SchemaContext result = schemaBuilderFuture.checkedGet();
                     LOG.debug("{}: Schema context built successfully from {}", id, requiredSources);
                     final Collection<QName> filteredQNames = Sets.difference(deviceSources.getRequiredSourcesQName(), capabilities.getUnresolvedCapabilites().keySet());
-                    capabilities.addCapabilities(filteredQNames);
-                    capabilities.addNonModuleBasedCapabilities(remoteSessionCapabilities.getNonModuleCaps());
+                    capabilities.addCapabilities(filteredQNames.stream().map(entry -> new AvailableCapabilityBuilder()
+                            .setCapability(entry.toString()).setCapabilityOrigin(remoteSessionCapabilities.getModuleBasedCapsOrigin().get(entry)).build())
+                            .collect(Collectors.toList()));
+
+                    capabilities.addNonModuleBasedCapabilities(remoteSessionCapabilities.getNonModuleCaps().stream().map(entry -> new AvailableCapabilityBuilder()
+                            .setCapability(entry).setCapabilityOrigin(AvailableCapability.CapabilityOrigin.DeviceAdvertised).build())
+                            .collect(Collectors.toList()));
+
                     handleSalInitializationSuccess(result, remoteSessionCapabilities, getDeviceSpecificRpc(result));
                     return;
                 } catch (final Throwable t) {
index e349a939c29380e5fcb010a069b51f3a0812cc7c..5b1dd458c1144d3562e12eb91e54fb2dc7ccea02 100644 (file)
@@ -13,14 +13,14 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability.FailureReason;
 import org.opendaylight.yangtools.yang.common.QName;
 
 public final class NetconfDeviceCapabilities {
     private final Map<QName, FailureReason> unresolvedCapabilites;
-    private final Set<QName> resolvedCapabilities;
-
-    private final Set<String> nonModuleBasedCapabilities;
+    private final Set<AvailableCapability>  resolvedCapabilities;
+    private final Set<AvailableCapability> nonModuleBasedCapabilities;
 
     public NetconfDeviceCapabilities() {
         this.unresolvedCapabilites = new HashMap<>();
@@ -38,15 +38,15 @@ public final class NetconfDeviceCapabilities {
         }
     }
 
-    public void addCapabilities(Collection<QName> availableSchemas) {
+    public void addCapabilities(Collection<AvailableCapability>  availableSchemas) {
         resolvedCapabilities.addAll(availableSchemas);
     }
 
-    public void addNonModuleBasedCapabilities(Collection<String> nonModuleCapabilities) {
+    public void addNonModuleBasedCapabilities(Collection<AvailableCapability> nonModuleCapabilities) {
         this.nonModuleBasedCapabilities.addAll(nonModuleCapabilities);
     }
 
-    public Set<String> getNonModuleBasedCapabilities() {
+    public Set<AvailableCapability> getNonModuleBasedCapabilities() {
         return nonModuleBasedCapabilities;
     }
 
@@ -54,7 +54,7 @@ public final class NetconfDeviceCapabilities {
         return unresolvedCapabilites;
     }
 
-    public Set<QName> getResolvedCapabilities() {
+    public Set<AvailableCapability>  getResolvedCapabilities() {
         return resolvedCapabilities;
     }
 
index 084481eec736096ff700801aeb2efc1d75a9b75b..7fb1b05db32f32d96622e36fcbfdb6736921e17e 100644 (file)
@@ -14,16 +14,20 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import java.net.URI;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 import org.opendaylight.netconf.client.NetconfClientSession;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -67,15 +71,19 @@ public final class NetconfSessionPreferences {
         }
     };
 
-    private final Set<QName> moduleBasedCaps;
+    private final Map<QName, CapabilityOrigin> moduleBasedCaps;
     private final Set<String> nonModuleCaps;
 
-    NetconfSessionPreferences(final Set<String> nonModuleCaps, final Set<QName> moduleBasedCaps) {
+    NetconfSessionPreferences(final Set<String> nonModuleCaps, final Map<QName, CapabilityOrigin> moduleBasedCaps) {
         this.nonModuleCaps = Preconditions.checkNotNull(nonModuleCaps);
         this.moduleBasedCaps = Preconditions.checkNotNull(moduleBasedCaps);
     }
 
     public Set<QName> getModuleBasedCaps() {
+        return moduleBasedCaps.keySet();
+    }
+
+    public Map<QName, CapabilityOrigin> getModuleBasedCapsOrigin() {
         return moduleBasedCaps;
     }
 
@@ -100,7 +108,7 @@ public final class NetconfSessionPreferences {
     }
 
     public boolean containsModuleCapability(final QName capability) {
-        return moduleBasedCaps.contains(capability);
+        return moduleBasedCaps.containsKey(capability);
     }
 
     @Override
@@ -145,9 +153,9 @@ public final class NetconfSessionPreferences {
      * @return new instance of preferences with merged module-based capabilities
      */
     public NetconfSessionPreferences addModuleCaps(final NetconfSessionPreferences netconfSessionModuleCapabilities) {
-        final HashSet<QName> mergedCaps = Sets.newHashSetWithExpectedSize(moduleBasedCaps.size() + netconfSessionModuleCapabilities.getModuleBasedCaps().size());
-        mergedCaps.addAll(moduleBasedCaps);
-        mergedCaps.addAll(netconfSessionModuleCapabilities.getModuleBasedCaps());
+        final Map<QName, CapabilityOrigin> mergedCaps = Maps.newHashMapWithExpectedSize(moduleBasedCaps.size() + netconfSessionModuleCapabilities.getModuleBasedCaps().size());
+        mergedCaps.putAll(moduleBasedCaps);
+        mergedCaps.putAll(netconfSessionModuleCapabilities.getModuleBasedCapsOrigin());
         return new NetconfSessionPreferences(getNonModuleCaps(), mergedCaps);
     }
 
@@ -159,7 +167,11 @@ public final class NetconfSessionPreferences {
      * @return new instance of preferences with replaced module-based capabilities
      */
     public NetconfSessionPreferences replaceModuleCaps(final NetconfSessionPreferences netconfSessionPreferences) {
-        return new NetconfSessionPreferences(getNonModuleCaps(), netconfSessionPreferences.getModuleBasedCaps());
+        return new NetconfSessionPreferences(getNonModuleCaps(), netconfSessionPreferences.getModuleBasedCapsOrigin());
+    }
+
+    public NetconfSessionPreferences replaceModuleCaps(Map<QName, CapabilityOrigin> newModuleBasedCaps) {
+        return new NetconfSessionPreferences(getNonModuleCaps(), newModuleBasedCaps);
     }
 
     public static NetconfSessionPreferences fromNetconfSession(final NetconfClientSession session) {
@@ -175,7 +187,12 @@ public final class NetconfSessionPreferences {
     }
 
     public static NetconfSessionPreferences fromStrings(final Collection<String> capabilities) {
-        final Set<QName> moduleBasedCaps = new HashSet<>();
+        // we do not know origin of capabilities from only Strings, so we set it to default value
+        return fromStrings(capabilities, CapabilityOrigin.DeviceAdvertised);
+    }
+
+    public static NetconfSessionPreferences fromStrings(final Collection<String> capabilities, CapabilityOrigin capabilityOrigin) {
+        final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
         final Set<String> nonModuleCaps = Sets.newHashSet(capabilities);
 
         for (final String capability : capabilities) {
@@ -193,7 +210,7 @@ public final class NetconfSessionPreferences {
 
             String revision = REVISION_PARAM.from(queryParams);
             if (!Strings.isNullOrEmpty(revision)) {
-                addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, revision, moduleName));
+                addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, revision, moduleName), capabilityOrigin);
                 continue;
             }
 
@@ -207,23 +224,22 @@ public final class NetconfSessionPreferences {
                 revision = BROKEN_REVISON_PARAM.from(queryParams);
                 if (Strings.isNullOrEmpty(revision)) {
                     LOG.warn("Netconf device returned revision incorrectly escaped for {}, ignoring it", capability);
-                    addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, moduleName));
+                    addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, moduleName), capabilityOrigin);
                 } else {
-                    addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, revision, moduleName));
+                    addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, revision, moduleName), capabilityOrigin);
                 }
                 continue;
             }
 
             // Fallback, no revision provided for module
-            addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, moduleName));
+            addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, moduleName), capabilityOrigin);
         }
 
-        return new NetconfSessionPreferences(ImmutableSet.copyOf(nonModuleCaps), ImmutableSet.copyOf(moduleBasedCaps));
+        return new NetconfSessionPreferences(ImmutableSet.copyOf(nonModuleCaps), ImmutableMap.copyOf(moduleBasedCaps));
     }
 
-
-    private static void addModuleQName(final Set<QName> moduleBasedCaps, final Set<String> nonModuleCaps, final String capability, final QName qName) {
-        moduleBasedCaps.add(qName);
+    private static void addModuleQName(final Map<QName, CapabilityOrigin> moduleBasedCaps, final Set<String> nonModuleCaps, final String capability, final QName qName, CapabilityOrigin capabilityOrigin) {
+        moduleBasedCaps.put(qName, capabilityOrigin);
         nonModuleCaps.remove(capability);
     }
 
index b440b1d900fa7b81c9419ae68c2e2fa05aa5fad2..b0617cfca91f36a397530f602858a8334580e790 100644 (file)
@@ -18,6 +18,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -29,8 +30,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev15
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilities;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability.FailureReason;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapabilityBuilder;
@@ -51,7 +54,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class NetconfDeviceTopologyAdapter implements AutoCloseable {
+public final class NetconfDeviceTopologyAdapter implements AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(NetconfDeviceTopologyAdapter.class);
     public static final Function<Entry<QName, FailureReason>, UnavailableCapability> UNAVAILABLE_CAPABILITY_TRANSFORMER = new Function<Entry<QName, FailureReason>, UnavailableCapability>() {
@@ -62,13 +65,6 @@ final class NetconfDeviceTopologyAdapter implements AutoCloseable {
                     .setFailureReason(input.getValue()).build();
         }
     };
-    public static final Function<QName, String> AVAILABLE_CAPABILITY_TRANSFORMER = new Function<QName, String>() {
-        @Override
-        public String apply(QName qName) {
-            // intern string representation of a capability to avoid duplicates
-            return qName.toString().intern();
-        }
-    };
 
     private final RemoteDeviceId id;
     private BindingTransactionChain txChain;
@@ -134,6 +130,21 @@ final class NetconfDeviceTopologyAdapter implements AutoCloseable {
         commitTransaction(writeTx, "update");
     }
 
+    public void updateClusteredDeviceData(boolean up, String masterAddress, NetconfDeviceCapabilities capabilities) {
+        final NetconfNode data = buildDataForNetconfClusteredNode(up, masterAddress, capabilities);
+
+        final WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
+        LOG.trace(
+                "{}: Update device state transaction {} merging operational data started.",
+                id, writeTx.getIdentifier());
+        writeTx.put(LogicalDatastoreType.OPERATIONAL, id.getTopologyBindingPath().augmentation(NetconfNode.class), data, true);
+        LOG.trace(
+                "{}: Update device state transaction {} merging operational data ended.",
+                id, writeTx.getIdentifier());
+
+        commitTransaction(writeTx, "update");
+    }
+
     public void setDeviceAsFailed(Throwable throwable) {
         String reason = (throwable != null && throwable.getMessage() != null) ? throwable.getMessage() : UNKNOWN_REASON;
 
@@ -152,9 +163,10 @@ final class NetconfDeviceTopologyAdapter implements AutoCloseable {
     }
 
     private NetconfNode buildDataForNetconfNode(boolean up, NetconfDeviceCapabilities capabilities) {
-        List<String> capabilityList = new ArrayList<>();
+        List<AvailableCapability> capabilityList = new ArrayList<>();
         capabilityList.addAll(capabilities.getNonModuleBasedCapabilities());
-        capabilityList.addAll(FluentIterable.from(capabilities.getResolvedCapabilities()).transform(AVAILABLE_CAPABILITY_TRANSFORMER).toList());
+        capabilityList.addAll(capabilities.getResolvedCapabilities());
+
         final AvailableCapabilitiesBuilder avCapabalitiesBuilder = new AvailableCapabilitiesBuilder();
         avCapabalitiesBuilder.setAvailableCapability(capabilityList);
 
@@ -172,6 +184,30 @@ final class NetconfDeviceTopologyAdapter implements AutoCloseable {
         return netconfNodeBuilder.build();
     }
 
+    private NetconfNode buildDataForNetconfClusteredNode(boolean up, String masterNodeAddress, NetconfDeviceCapabilities capabilities) {
+        List<AvailableCapability> capabilityList = new ArrayList<>();
+        capabilityList.addAll(capabilities.getNonModuleBasedCapabilities());
+        capabilityList.addAll(capabilities.getResolvedCapabilities());
+        final AvailableCapabilitiesBuilder avCapabalitiesBuilder = new AvailableCapabilitiesBuilder();
+        avCapabalitiesBuilder.setAvailableCapability(capabilityList);
+
+        final UnavailableCapabilities unavailableCapabilities =
+                new UnavailableCapabilitiesBuilder().setUnavailableCapability(capabilities.getUnresolvedCapabilites()
+                        .entrySet().stream().map(UNAVAILABLE_CAPABILITY_TRANSFORMER::apply)
+                        .collect(Collectors.toList())).build();
+
+        final NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder()
+                .setHost(id.getHost())
+                .setPort(new PortNumber(id.getAddress().getPort()))
+                .setConnectionStatus(up ? ConnectionStatus.Connected : ConnectionStatus.Connecting)
+                .setAvailableCapabilities(avCapabalitiesBuilder.build())
+                .setUnavailableCapabilities(unavailableCapabilities)
+                .setClusteredConnectionStatus(
+                        new ClusteredConnectionStatusBuilder().setNetconfMasterNode(masterNodeAddress).build());
+
+        return netconfNodeBuilder.build();
+    }
+
     public void removeDeviceConfiguration() {
         final WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
 
index 6df2239f5140698f9072809366524d63ceeffecd..e2cedbc2a47f3737c86f3e1c3188e592bd2e8678 100644 (file)
@@ -22,9 +22,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfRpcFutureCallback;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
@@ -56,22 +54,6 @@ public class WriteCandidateTx extends AbstractWriteTx {
 
     private static final Logger LOG  = LoggerFactory.getLogger(WriteCandidateTx.class);
 
-    private static final Function<DOMRpcResult, RpcResult<TransactionStatus>> RPC_RESULT_TO_TX_STATUS = new Function<DOMRpcResult, RpcResult<TransactionStatus>>() {
-        @Override
-        public RpcResult<TransactionStatus> apply(final DOMRpcResult input) {
-            if (isSuccess(input)) {
-                return RpcResultBuilder.success(TransactionStatus.COMMITED).build();
-            } else {
-                final RpcResultBuilder<TransactionStatus> failed = RpcResultBuilder.failed();
-                for (final RpcError rpcError : input.getErrors()) {
-                    failed.withError(rpcError.getErrorType(), rpcError.getTag(), rpcError.getMessage(),
-                            rpcError.getApplicationTag(), rpcError.getInfo(), rpcError.getCause());
-                }
-                return failed.build();
-            }
-        }
-    };
-
     public WriteCandidateTx(final RemoteDeviceId id, final NetconfBaseOps rpc, final boolean rollbackSupport) {
         super(rpc, id, rollbackSupport);
     }
@@ -85,7 +67,7 @@ public class WriteCandidateTx extends AbstractWriteTx {
     private void lock() {
         final FutureCallback<DOMRpcResult> lockCandidateCallback = new FutureCallback<DOMRpcResult>() {
             @Override
-            public void onSuccess(DOMRpcResult result) {
+            public void onSuccess(final DOMRpcResult result) {
                 if (isSuccess(result)) {
                     if (LOG.isTraceEnabled()) {
                         LOG.trace("Lock candidate successful");
@@ -96,7 +78,7 @@ public class WriteCandidateTx extends AbstractWriteTx {
             }
 
             @Override
-            public void onFailure(Throwable t) {
+            public void onFailure(final Throwable t) {
                 LOG.warn("Lock candidate operation failed. {}", t);
                 discardChanges();
             }
@@ -138,16 +120,16 @@ public class WriteCandidateTx extends AbstractWriteTx {
     @Override
     public synchronized ListenableFuture<RpcResult<TransactionStatus>> performCommit() {
         resultsFutures.add(netOps.commit(new NetconfRpcFutureCallback("Commit", id)));
-        ListenableFuture<RpcResult<TransactionStatus>> txResult = resultsToTxStatus();
+        final ListenableFuture<RpcResult<TransactionStatus>> txResult = resultsToTxStatus();
 
         Futures.addCallback(txResult, new FutureCallback<RpcResult<TransactionStatus>>() {
             @Override
-            public void onSuccess(@Nullable RpcResult<TransactionStatus> result) {
+            public void onSuccess(@Nullable final RpcResult<TransactionStatus> result) {
                 cleanupOnSuccess();
             }
 
             @Override
-            public void onFailure(Throwable t) {
+            public void onFailure(final Throwable t) {
                 // TODO If lock is cause of this failure cleanup will issue warning log
                 // cleanup is trying to do unlock, but this will fail
                 cleanup();
@@ -168,7 +150,7 @@ public class WriteCandidateTx extends AbstractWriteTx {
                               final Optional<ModifyAction> defaultOperation,
                               final String operation) {
 
-        NetconfRpcFutureCallback editConfigCallback = new NetconfRpcFutureCallback("Edit candidate", id);
+        final NetconfRpcFutureCallback editConfigCallback = new NetconfRpcFutureCallback("Edit candidate", id);
 
         if (defaultOperation.isPresent()) {
             resultsFutures.add(netOps.editConfigCandidate(
index 62b88b974f2091e575b6a4f70b59ad4b1b7b1e55..169d41961638ae961fc8805c297f29f93a0c7e44 100644 (file)
@@ -153,6 +153,10 @@ module netconf-node-topology {
                     }
                 }
             }
+            leaf netconf-master-node {
+                config false;
+                type string;
+            }
         }
 
         leaf connected-message {
@@ -162,8 +166,16 @@ module netconf-node-topology {
 
         container available-capabilities {
             config false;
-            leaf-list available-capability {
-                type string;
+            list available-capability {
+                leaf capability {
+                    type string;
+                }
+                leaf capability-origin {
+                    type enumeration {
+                        enum user-defined;
+                        enum device-advertised;
+                    }
+                }
             }
         }
 
index ae6726b7802f64efcdde29e272711e85a315af1c..9708888f5d0c44fb24eab62ea88e101f21b0c8fe 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.netconf.sal.connect.netconf;
 
+import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyCollectionOf;
 import static org.mockito.Matchers.eq;
@@ -30,10 +31,13 @@ import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -48,11 +52,13 @@ import org.opendaylight.netconf.sal.connect.api.MessageTransformer;
 import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas;
 import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemasResolver;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -65,8 +71,8 @@ import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
@@ -329,6 +335,40 @@ public class NetconfDeviceTest {
         verify(facade, timeout(5000).times(2)).onDeviceConnected(any(SchemaContext.class), any(NetconfSessionPreferences.class), any(DOMRpcService.class));
     }
 
+    @Test
+    public void testNetconfDeviceAvailableCapabilitiesBuilding() throws Exception {
+        final RemoteDeviceHandler<NetconfSessionPreferences> facade = getFacade();
+        final NetconfDeviceCommunicator listener = getListener();
+
+        final SchemaContextFactory schemaContextProviderFactory = getSchemaFactory();
+
+        final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO
+                = new NetconfDevice.SchemaResourcesDTO(getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, stateSchemasResolver);
+        final NetconfDevice device = new NetconfDeviceBuilder()
+                .setReconnectOnSchemasChange(true)
+                .setSchemaResourcesDTO(schemaResourcesDTO)
+                .setGlobalProcessingExecutor(getExecutor())
+                .setId(getId())
+                .setSalFacade(facade)
+                .build();
+        NetconfDevice netconfSpy = Mockito.spy(device);
+
+        final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
+                Lists.newArrayList(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&amp;revision=" + TEST_REVISION));
+        Map<QName, AvailableCapability.CapabilityOrigin> moduleBasedCaps = new HashMap<>();
+        moduleBasedCaps.putAll(sessionCaps.getModuleBasedCapsOrigin());
+        moduleBasedCaps.put(QName.create("test:qname:side:loading"), AvailableCapability.CapabilityOrigin.UserDefined);
+
+        netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
+
+        ArgumentCaptor argument = ArgumentCaptor.forClass(NetconfSessionPreferences.class);
+        verify(netconfSpy, timeout(5000)).handleSalInitializationSuccess(any(SchemaContext.class), (NetconfSessionPreferences) argument.capture(), any(DOMRpcService.class));
+        NetconfDeviceCapabilities netconfDeviceCaps = ((NetconfSessionPreferences) argument.getValue()).getNetconfDeviceCapabilities();
+
+        netconfDeviceCaps.getResolvedCapabilities().forEach(entry -> assertEquals("Builded 'AvailableCapability' schemas should match input capabilities.",
+                moduleBasedCaps.get(QName.create(entry.getCapability())).getName(), entry.getCapabilityOrigin().getName()));
+    }
+
     private SchemaContextFactory getSchemaFactory() {
         final SchemaContextFactory schemaFactory = mockClass(SchemaContextFactory.class);
         doReturn(Futures.immediateCheckedFuture(getSchema())).when(schemaFactory).createSchemaContext(any(Collection.class));
index 7938f429a65c3b16bf0c6d85329777b04f0661e5..bf18b6f30277059a1012baa336ad51221209092d 100644 (file)
@@ -145,7 +145,7 @@ public class NetconfDeviceCommunicatorTest {
         assertEquals( "containsModuleCapability", false, actualCapabilites.containsNonModuleCapability(testCapability) );
         assertEquals( "getModuleBasedCaps", Sets.newHashSet(
                             QName.create( "urn:opendaylight:params:xml:ns:test", "2014-06-02", "test-module" )),
-                      actualCapabilites.getModuleBasedCaps() );
+                      actualCapabilites.getModuleBasedCaps());
         assertEquals( "isRollbackSupported", true, actualCapabilites.isRollbackSupported() );
         assertEquals( "isMonitoringSupported", true, actualCapabilites.isMonitoringSupported() );
     }
index 1e9c0fcd86f26a632d0d1ebcb76d10139821c6fd..8d67fbc78a234d57282fab1c1dea6e87b9d9edcd 100644 (file)
@@ -14,9 +14,8 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 import com.google.common.util.concurrent.Futures;
-
 import java.net.InetSocketAddress;
-
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
@@ -62,4 +61,24 @@ public class ReadOnlyTxTest {
         readOnlyTx.read(LogicalDatastoreType.OPERATIONAL, path);
         verify(rpc).invokeRpc(Mockito.eq(NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.NETCONF_GET_QNAME)), any(NormalizedNode.class));
     }
+
+    @Test
+    public void testExists() throws Exception {
+        final NetconfBaseOps netconfOps = new NetconfBaseOps(rpc, mock(SchemaContext.class));
+
+        final ReadOnlyTx readOnlyTx = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196)));
+
+        readOnlyTx.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create());
+        verify(rpc).invokeRpc(Mockito.eq(NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME)), any(NormalizedNode.class));
+        readOnlyTx.exists(LogicalDatastoreType.OPERATIONAL, path);
+        verify(rpc).invokeRpc(Mockito.eq(NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.NETCONF_GET_QNAME)), any(NormalizedNode.class));
+    }
+
+    @Test
+    public void testIdentifier() throws Exception {
+        final NetconfBaseOps netconfOps = new NetconfBaseOps(rpc, mock(SchemaContext.class));
+        final ReadOnlyTx tx1 = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196)));
+        final ReadOnlyTx tx2 = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196)));
+        Assert.assertNotEquals(tx1.getIdentifier(), tx2.getIdentifier());
+    }
 }
\ No newline at end of file
diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadWriteTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadWriteTxTest.java
new file mode 100644 (file)
index 0000000..748c210
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.sal.connect.netconf.sal.tx;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+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.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class ReadWriteTxTest {
+    @Mock
+    private DOMDataReadTransaction delegateReadTx;
+    @Mock
+    private DOMDataWriteTransaction delegateWriteTx;
+    private ReadWriteTx tx;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        tx = new ReadWriteTx(delegateReadTx, delegateWriteTx);
+    }
+
+    @Test
+    public void submit() throws Exception {
+        final YangInstanceIdentifier id1 = TxTestUtils.getContainerId();
+        final ContainerNode containerNode = TxTestUtils.getContainerNode();
+        tx.put(LogicalDatastoreType.CONFIGURATION, id1, containerNode);
+        verify(delegateWriteTx).put(LogicalDatastoreType.CONFIGURATION, id1, containerNode);
+        final YangInstanceIdentifier id2 = TxTestUtils.getLeafId();
+        final LeafNode<String> leafNode = TxTestUtils.getLeafNode();
+        tx.merge(LogicalDatastoreType.CONFIGURATION, id2, leafNode);
+        verify(delegateWriteTx).merge(LogicalDatastoreType.CONFIGURATION, id2, leafNode);
+        tx.delete(LogicalDatastoreType.CONFIGURATION, id2);
+        verify(delegateWriteTx).delete(LogicalDatastoreType.CONFIGURATION, id2);
+        tx.submit();
+        verify(delegateWriteTx).submit();
+    }
+
+    @Test
+    public void commit() throws Exception {
+        tx.commit();
+        verify(delegateWriteTx).commit();
+    }
+
+    @Test
+    public void cancel() throws Exception {
+        tx.cancel();
+        verify(delegateWriteTx).cancel();
+    }
+
+    @Test
+    public void read() throws Exception {
+        tx.read(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId());
+        verify(delegateReadTx).read(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId());
+    }
+
+    @Test
+    public void exists() throws Exception {
+        final YangInstanceIdentifier id = TxTestUtils.getContainerId();
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> resultFuture =
+                Futures.immediateCheckedFuture(Optional.of(TxTestUtils.getContainerNode()));
+        when(delegateReadTx.read(LogicalDatastoreType.CONFIGURATION, id)).thenReturn(resultFuture);
+        final CheckedFuture<Boolean, ReadFailedException> exists = tx.exists(LogicalDatastoreType.CONFIGURATION, id);
+        Assert.assertTrue(exists.get());
+    }
+
+    @Test
+    public void getIdentifier() throws Exception {
+        final ReadWriteTx tx2 = new ReadWriteTx(null, null);
+        Assert.assertNotEquals(tx.getIdentifier(), tx2.getIdentifier());
+    }
+
+}
\ No newline at end of file
diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/TxTestUtils.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/TxTestUtils.java
new file mode 100644 (file)
index 0000000..4b4481e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.sal.connect.netconf.sal.tx;
+
+import com.google.common.collect.ImmutableList;
+import java.io.InputStream;
+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.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+
+class TxTestUtils {
+
+    private static final QName Q_NAME_1 = QName.create("test:namespace", "2013-07-22", "c");
+    private static final QName Q_NAME_2 = QName.create(Q_NAME_1, "a");
+
+    static YangInstanceIdentifier getContainerId() {
+        return YangInstanceIdentifier.builder()
+                .node(Q_NAME_1)
+                .build();
+    }
+
+    static YangInstanceIdentifier getLeafId() {
+        return YangInstanceIdentifier.builder()
+                .node(Q_NAME_1)
+                .node(Q_NAME_2)
+                .build();
+    }
+
+    static ContainerNode getContainerNode() {
+        return Builders.containerBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(Q_NAME_1))
+                .build();
+    }
+
+    static LeafNode<String> getLeafNode() {
+        return Builders.<String>leafBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(Q_NAME_2))
+                .withValue("data")
+                .build();
+    }
+
+    static SchemaContext parseYangStreams(final InputStream... streams) {
+        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR
+                .newBuild();
+        final SchemaContext schemaContext;
+        try {
+            schemaContext = reactor.buildEffective(ImmutableList.copyOf(streams));
+        } catch (final ReactorException e) {
+            throw new RuntimeException("Unable to build schema context from " + streams, e);
+        }
+        return schemaContext;
+    }
+
+}
diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTxTest.java
new file mode 100644 (file)
index 0000000..5f3c986
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.sal.connect.netconf.sal.tx;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_LOCK_QNAME;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_TARGET_QNAME;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toId;
+
+import com.google.common.util.concurrent.Futures;
+import java.net.InetSocketAddress;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.copy.config.input.target.ConfigTarget;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class WriteCandidateRunningTxTest {
+    @Mock
+    private DOMRpcService rpc;
+    private NetconfBaseOps netconfOps;
+    private RemoteDeviceId id;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        final SchemaContext schemaContext = TxTestUtils.parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang"));
+        doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult())).when(rpc).invokeRpc(any(), any());
+        netconfOps = new NetconfBaseOps(rpc, schemaContext);
+        id = new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830));
+    }
+
+    @Test
+    public void testSubmit() throws Exception {
+        final WriteCandidateRunningTx tx = new WriteCandidateRunningTx(id, netconfOps, true);
+        //check, if lock is called
+        final ContainerNode candidateLock = getLockContent(NETCONF_LOCK_QNAME, NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME);
+        final ContainerNode runningLock = getLockContent(NETCONF_LOCK_QNAME, NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME);
+        verify(rpc).invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME), runningLock);
+        verify(rpc).invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME), candidateLock);
+        tx.put(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId(), TxTestUtils.getContainerNode());
+        tx.merge(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getLeafId(), TxTestUtils.getLeafNode());
+        //check, if both edits are called
+        verify(rpc, times(2)).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any());
+        tx.submit().get();
+        //check, if unlock is called
+        verify(rpc).invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME), NetconfMessageTransformUtil.COMMIT_RPC_CONTENT);
+        final ContainerNode candidateUnlock = getLockContent(NETCONF_UNLOCK_QNAME, NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME);
+        final ContainerNode runningUnlock = getLockContent(NETCONF_UNLOCK_QNAME, NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME);
+        verify(rpc).invokeRpc(SchemaPath.create(true, NETCONF_UNLOCK_QNAME), candidateUnlock);
+        verify(rpc).invokeRpc(SchemaPath.create(true, NETCONF_UNLOCK_QNAME), runningUnlock);
+    }
+
+    private static ContainerNode getLockContent(final QName op, final QName datastore) {
+        final LeafNode<Object> datastoreLeaf = Builders.leafBuilder().withNodeIdentifier(toId(datastore)).build();
+        final ChoiceNode choice = Builders.choiceBuilder()
+                .withNodeIdentifier(toId(ConfigTarget.QNAME))
+                .withChild(datastoreLeaf)
+                .build();
+        final ContainerNode target = Builders.containerBuilder()
+                .withNodeIdentifier(toId(NETCONF_TARGET_QNAME))
+                .withChild(choice).build();
+        return Builders.containerBuilder()
+                .withNodeIdentifier(toId(op))
+                .withChild(target)
+                .build();
+    }
+
+}
\ No newline at end of file
diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTxTest.java
new file mode 100644 (file)
index 0000000..3214505
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.sal.connect.netconf.sal.tx;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.util.concurrent.Futures;
+import java.net.InetSocketAddress;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class WriteCandidateTxTest {
+
+    @Mock
+    private DOMRpcService rpc;
+    private NetconfBaseOps netconfOps;
+    private RemoteDeviceId id;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        final SchemaContext schemaContext = TxTestUtils.parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang"));
+        doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult())).when(rpc).invokeRpc(any(), any());
+        netconfOps = new NetconfBaseOps(rpc, schemaContext);
+        id = new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830));
+    }
+
+    @Test
+    public void testSubmit() throws Exception {
+        final WriteCandidateTx tx = new WriteCandidateTx(id, netconfOps, true);
+        //check, if lock is called
+        verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME)), any());
+
+        tx.put(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId(), TxTestUtils.getContainerNode());
+        tx.merge(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getLeafId(), TxTestUtils.getLeafNode());
+        //check, if both edits are called
+        verify(rpc, times(2)).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any());
+        tx.submit().get();
+        //check, if unlock is called
+        verify(rpc).invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME), NetconfMessageTransformUtil.COMMIT_RPC_CONTENT);
+        verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME)), any());
+    }
+
+}
\ No newline at end of file
index 67e390410b71e4f2fc194ed0833011a6269c6f10..9668bb158a793641d44f5b76ac1e494b0f53f768 100644 (file)
@@ -15,9 +15,7 @@ import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.Futures;
-import java.io.InputStream;
 import java.net.InetSocketAddress;
 import org.junit.Before;
 import org.junit.Test;
@@ -29,16 +27,8 @@ import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-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.LeafNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
-import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
 
 public class WriteRunningTxTest {
 
@@ -50,7 +40,7 @@ public class WriteRunningTxTest {
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        final SchemaContext schemaContext = parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang"));
+        final SchemaContext schemaContext = TxTestUtils.parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang"));
         doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult())).when(rpc).invokeRpc(any(), any());
         netconfOps = new NetconfBaseOps(rpc, schemaContext);
         id = new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830));
@@ -61,24 +51,8 @@ public class WriteRunningTxTest {
         final WriteRunningTx tx = new WriteRunningTx(id, netconfOps, true);
         //check, if lock is called
         verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME)), any());
-        final QName qName1 = QName.create("test:namespace", "2013-07-22", "c");
-        final YangInstanceIdentifier yid1 = YangInstanceIdentifier.builder()
-                .node(qName1)
-                .build();
-        final QName qName2 = QName.create(qName1, "a");
-        final YangInstanceIdentifier yid2 = YangInstanceIdentifier.builder()
-                .node(qName1)
-                .node(qName2)
-                .build();
-        final ContainerNode data1 = Builders.containerBuilder()
-                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(qName1))
-                .build();
-        final LeafNode<String> data2 = Builders.<String>leafBuilder()
-                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(qName2))
-                .withValue("data")
-                .build();
-        tx.put(LogicalDatastoreType.CONFIGURATION, yid1, data1);
-        tx.merge(LogicalDatastoreType.CONFIGURATION, yid2, data2);
+        tx.put(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId(), TxTestUtils.getContainerNode());
+        tx.merge(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getLeafId(), TxTestUtils.getLeafNode());
         //check, if no edit-config is called before submit
         verify(rpc, never()).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any());
         tx.submit().get();
@@ -87,16 +61,4 @@ public class WriteRunningTxTest {
         //check, if unlock is called
         verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME)), any());
     }
-
-    private static SchemaContext parseYangStreams(final InputStream... streams) {
-        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR
-                .newBuild();
-        final SchemaContext schemaContext;
-        try {
-            schemaContext = reactor.buildEffective(ImmutableList.copyOf(streams));
-        } catch (final ReactorException e) {
-            throw new RuntimeException("Unable to build schema context from " + streams, e);
-        }
-        return schemaContext;
-    }
 }
\ No newline at end of file
diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/util/NetconfBaseOpsTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/util/NetconfBaseOpsTest.java
new file mode 100644 (file)
index 0000000..6b47a72
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.sal.connect.netconf.util;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.netconf.api.NetconfMessage;
+import org.opendaylight.netconf.sal.connect.api.MessageTransformer;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.xml.sax.SAXException;
+
+public class NetconfBaseOpsTest {
+
+    static {
+        XMLUnit.setIgnoreWhitespace(true);
+        XMLUnit.setIgnoreComments(true);
+    }
+
+    private static final QName CONTAINER_Q_NAME = QName.create("test:namespace", "2013-07-22", "c");
+
+    @Mock
+    private RemoteDeviceCommunicator<NetconfMessage> listener;
+    private NetconfRpcFutureCallback callback;
+    private NetconfBaseOps baseOps;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        final InputStream okStream = getClass().getResourceAsStream("/netconfMessages/rpc-reply_ok.xml");
+        final InputStream dataStream = getClass().getResourceAsStream("/netconfMessages/rpc-reply_get.xml");
+        final NetconfMessage ok = new NetconfMessage(XmlUtil.readXmlToDocument(okStream));
+        final NetconfMessage data = new NetconfMessage(XmlUtil.readXmlToDocument(dataStream));
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME)))
+                .thenReturn(RpcResultBuilder.success(data).buildFuture());
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_GET_QNAME)))
+                .thenReturn(RpcResultBuilder.success(data).buildFuture());
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)))
+                .thenReturn(RpcResultBuilder.success(ok).buildFuture());
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_COPY_CONFIG_QNAME)))
+                .thenReturn(RpcResultBuilder.success(ok).buildFuture());
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME)))
+                .thenReturn(RpcResultBuilder.success(ok).buildFuture());
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_VALIDATE_QNAME)))
+                .thenReturn(RpcResultBuilder.success(ok).buildFuture());
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_LOCK_QNAME)))
+                .thenReturn(RpcResultBuilder.success(ok).buildFuture());
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME)))
+                .thenReturn(RpcResultBuilder.success(ok).buildFuture());
+        when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME)))
+                .thenReturn(RpcResultBuilder.success(ok).buildFuture());
+        final SchemaContext schemaContext =
+                parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang"));
+        final MessageTransformer<NetconfMessage> transformer = new NetconfMessageTransformer(schemaContext, true);
+        final DOMRpcService rpc = new NetconfDeviceRpc(schemaContext, listener, transformer);
+        final RemoteDeviceId id =
+                new RemoteDeviceId("device-1", InetSocketAddress.createUnresolved("localhost", 17830));
+        callback = new NetconfRpcFutureCallback("prefix", id);
+        baseOps = new NetconfBaseOps(rpc, schemaContext);
+    }
+
+    @Test
+    public void testLock() throws Exception {
+        baseOps.lock(callback, NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME);
+        verifyMessageSent("lock", NetconfMessageTransformUtil.NETCONF_LOCK_QNAME);
+    }
+
+    @Test
+    public void testLockCandidate() throws Exception {
+        baseOps.lockCandidate(callback);
+        verifyMessageSent("lock", NetconfMessageTransformUtil.NETCONF_LOCK_QNAME);
+    }
+
+    @Test
+    public void testUnlock() throws Exception {
+        baseOps.unlock(callback, NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME);
+        verifyMessageSent("unlock", NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME);
+    }
+
+    @Test
+    public void testUnlockCandidate() throws Exception {
+        baseOps.unlockCandidate(callback);
+        verifyMessageSent("unlock", NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME);
+    }
+
+    @Test
+    public void testLockRunning() throws Exception {
+        baseOps.lockRunning(callback);
+        verifyMessageSent("lock-running", NetconfMessageTransformUtil.NETCONF_LOCK_QNAME);
+    }
+
+    @Test
+    public void testUnlockRunning() throws Exception {
+        baseOps.unlockRunning(callback);
+        verifyMessageSent("unlock-running", NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME);
+    }
+
+    @Test
+    public void testDiscardChanges() throws Exception {
+        baseOps.discardChanges(callback);
+        verifyMessageSent("discardChanges", NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME);
+    }
+
+    @Test
+    public void testCommit() throws Exception {
+        baseOps.commit(callback);
+        verifyMessageSent("commit", NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME);
+    }
+
+    @Test
+    public void testValidateCandidate() throws Exception {
+        baseOps.validateCandidate(callback);
+        verifyMessageSent("validate", NetconfMessageTransformUtil.NETCONF_VALIDATE_QNAME);
+    }
+
+    @Test
+    public void testValidateRunning() throws Exception {
+        baseOps.validateRunning(callback);
+        verifyMessageSent("validate-running", NetconfMessageTransformUtil.NETCONF_VALIDATE_QNAME);
+    }
+
+
+    @Test
+    public void testCopyConfig() throws Exception {
+        baseOps.copyConfig(callback, NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME,
+                NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME);
+        verifyMessageSent("copy-config", NetconfMessageTransformUtil.NETCONF_COPY_CONFIG_QNAME);
+    }
+
+    @Test
+    public void testCopyRunningToCandidate() throws Exception {
+        baseOps.copyRunningToCandidate(callback);
+        verifyMessageSent("copy-config", NetconfMessageTransformUtil.NETCONF_COPY_CONFIG_QNAME);
+    }
+
+
+    @Test
+    public void testGetConfigRunningData() throws Exception {
+        final Optional<NormalizedNode<?, ?>> dataOpt =
+                baseOps.getConfigRunningData(callback, Optional.of(YangInstanceIdentifier.EMPTY)).get();
+        Assert.assertTrue(dataOpt.isPresent());
+        Assert.assertEquals(NetconfMessageTransformUtil.NETCONF_DATA_QNAME, dataOpt.get().getNodeType());
+    }
+
+    @Test
+    public void testGetData() throws Exception {
+        final Optional<NormalizedNode<?, ?>> dataOpt =
+                baseOps.getData(callback, Optional.of(YangInstanceIdentifier.EMPTY)).get();
+        Assert.assertTrue(dataOpt.isPresent());
+        Assert.assertEquals(NetconfMessageTransformUtil.NETCONF_DATA_QNAME, dataOpt.get().getNodeType());
+    }
+
+    @Test
+    public void testGetConfigRunning() throws Exception {
+        baseOps.getConfigRunning(callback, Optional.absent());
+        verifyMessageSent("getConfig", NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME);
+    }
+
+    @Test
+    public void testGetConfigCandidate() throws Exception {
+        baseOps.getConfigCandidate(callback, Optional.absent());
+        verifyMessageSent("getConfig_candidate", NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME);
+    }
+
+    @Test
+    public void testGetConfigCandidateWithFilter() throws Exception {
+        final YangInstanceIdentifier id = YangInstanceIdentifier.builder()
+                .node(CONTAINER_Q_NAME)
+                .build();
+        baseOps.getConfigCandidate(callback, Optional.of(id));
+        verifyMessageSent("getConfig_candidate-filter", NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME);
+    }
+
+    @Test
+    public void testGet() throws Exception {
+        baseOps.get(callback, Optional.absent());
+        verifyMessageSent("get", NetconfMessageTransformUtil.NETCONF_GET_QNAME);
+    }
+
+    @Test
+    public void testEditConfigCandidate() throws Exception {
+        final QName leafQName = QName.create(CONTAINER_Q_NAME, "a");
+        final LeafNode<Object> leaf = Builders.leafBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(leafQName))
+                .withValue("leaf-value")
+                .build();
+        final YangInstanceIdentifier leafId = YangInstanceIdentifier.builder()
+                .node(CONTAINER_Q_NAME)
+                .node(leafQName)
+                .build();
+        final DataContainerChild<?, ?> structure = baseOps.createEditConfigStrcture(Optional.of(leaf),
+                Optional.of(ModifyAction.REPLACE), leafId);
+        baseOps.editConfigCandidate(callback, structure, true);
+        verifyMessageSent("edit-config-test-module", NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME);
+    }
+
+    @Test
+    public void testEditConfigRunning() throws Exception {
+        final QName containerQName = QName.create("test:namespace", "2013-07-22", "c");
+        final QName leafQName = QName.create(containerQName, "a");
+        final LeafNode<Object> leaf = Builders.leafBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(leafQName))
+                .withValue("leaf-value")
+                .build();
+        final YangInstanceIdentifier leafId = YangInstanceIdentifier.builder()
+                .node(containerQName)
+                .node(leafQName)
+                .build();
+        final DataContainerChild<?, ?> structure = baseOps.createEditConfigStrcture(Optional.of(leaf),
+                Optional.of(ModifyAction.REPLACE), leafId);
+        baseOps.editConfigRunning(callback, structure, ModifyAction.MERGE, true);
+        verifyMessageSent("edit-config-test-module-running", NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME);
+    }
+
+    private static SchemaContext parseYangStreams(final InputStream... streams) {
+        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR
+                .newBuild();
+        final SchemaContext schemaContext;
+        try {
+            schemaContext = reactor.buildEffective(Arrays.asList(streams));
+        } catch (final ReactorException e) {
+            throw new RuntimeException("Unable to build schema context from " + streams, e);
+        }
+        return schemaContext;
+    }
+
+    private void verifyMessageSent(final String fileName, final QName name) {
+        final String path = "/netconfMessages/" + fileName + ".xml";
+        verify(listener).sendRequest(msg(path), eq(name));
+    }
+
+    private static NetconfMessage msg(final String name) {
+        final InputStream stream = NetconfBaseOpsTest.class.getResourceAsStream(name);
+        try {
+            return argThat(new NetconfMessageMatcher(XmlUtil.readXmlToDocument(stream)));
+        } catch (SAXException | IOException e) {
+            throw new IllegalStateException("Failed to read xml file " + name, e);
+        }
+    }
+
+    private static class NetconfMessageMatcher extends BaseMatcher<NetconfMessage> {
+
+        private final Document expected;
+
+        private NetconfMessageMatcher(final Document expected) {
+            this.expected = removeAttrs(expected);
+        }
+
+        @Override
+        public boolean matches(final Object item) {
+            if (!(item instanceof NetconfMessage)) {
+                return false;
+            }
+            final NetconfMessage message = (NetconfMessage) item;
+            final Document actualDoc = removeAttrs(message.getDocument());
+            actualDoc.normalizeDocument();
+            expected.normalizeDocument();
+            final Diff diff = XMLUnit.compareXML(expected, actualDoc);
+            return diff.similar();
+        }
+
+        @Override
+        public void describeTo(final Description description) {
+            description.appendText(XmlUtil.toString(expected));
+        }
+
+        private static Document removeAttrs(final Document input) {
+            final Document copy = XmlUtil.newDocument();
+            copy.appendChild(copy.importNode(input.getDocumentElement(), true));
+            final Element element = copy.getDocumentElement();
+            final List<String> attrNames = new ArrayList<>();
+            final NamedNodeMap attributes = element.getAttributes();
+            for (int i = 0; i < attributes.getLength(); i++) {
+                final String nodeName = attributes.item(i).getNodeName();
+                if ("xmlns".equals(nodeName)) {
+                    continue;
+                }
+                attrNames.add(nodeName);
+            }
+            attrNames.forEach(element::removeAttribute);
+            return copy;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/util/NodeContainerProxyTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/util/NodeContainerProxyTest.java
new file mode 100644 (file)
index 0000000..534a952
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.netconf.sal.connect.netconf.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public class NodeContainerProxyTest {
+
+    private static final QName QNAME = QName.create("ns", "2016-10-19", "name");
+    private static final QName NODE_1_QNAME = QName.create(QNAME, "node-1");
+    private static final QName NODE_2_QNAME = QName.create(QNAME, "node-2");
+    @Mock
+    private AugmentationSchema augSchema1;
+    @Mock
+    private AugmentationSchema augSchema2;
+    @Mock
+    private DataSchemaNode schemaNode1;
+    @Mock
+    private DataSchemaNode schemaNode2;
+    private NodeContainerProxy proxy;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        final Map<QName, DataSchemaNode> childNodes = new HashMap<>();
+        childNodes.put(NODE_1_QNAME, schemaNode1);
+        childNodes.put(NODE_2_QNAME, schemaNode2);
+        final Set<AugmentationSchema> augmentations = new HashSet<>();
+        augmentations.add(augSchema1);
+        augmentations.add(augSchema2);
+        proxy = new NodeContainerProxy(QNAME, childNodes, augmentations);
+    }
+
+    @Test
+    public void testGetQName() throws Exception {
+        Assert.assertEquals(QNAME, proxy.getQName());
+    }
+
+    @Test
+    public void testGetChildNodes() throws Exception {
+        Assert.assertEquals(2, proxy.getChildNodes().size());
+    }
+
+    @Test
+    public void testGetAvailableAugmentations() throws Exception {
+        final Set<AugmentationSchema> augmentations = proxy.getAvailableAugmentations();
+        Assert.assertEquals(2, augmentations.size());
+        Assert.assertTrue(augmentations.contains(augSchema1));
+        Assert.assertTrue(augmentations.contains(augSchema2));
+    }
+
+    @Test
+    public void testGetDataChildByName() throws Exception {
+        final DataSchemaNode schemaNode = proxy.getDataChildByName(NODE_1_QNAME);
+        Assert.assertEquals(schemaNode1, schemaNode);
+    }
+
+    @Test
+    public void testGetTypeDefinitions() throws Exception {
+        Assert.assertTrue(proxy.getTypeDefinitions().isEmpty());
+    }
+
+    @Test
+    public void testGetGroupings() throws Exception {
+        Assert.assertTrue(proxy.getGroupings().isEmpty());
+    }
+
+    @Test
+    public void testGetUses() throws Exception {
+        Assert.assertTrue(proxy.getUses().isEmpty());
+    }
+
+    @Test
+    public void testGetUnknownSchemaNodes() throws Exception {
+        Assert.assertTrue(proxy.getUnknownSchemaNodes().isEmpty());
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testIsPresenceContainer() throws Exception {
+        proxy.isPresenceContainer();
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testIsAugmenting() throws Exception {
+        proxy.isAugmenting();
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testIsAddedByUses() throws Exception {
+        proxy.isAddedByUses();
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testIsConfiguration() throws Exception {
+        proxy.isConfiguration();
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetConstraints() throws Exception {
+        proxy.getConstraints();
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetPath() throws Exception {
+        proxy.getPath();
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetDescription() throws Exception {
+        proxy.getDescription();
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetReference() throws Exception {
+        proxy.getReference();
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetStatus() throws Exception {
+        proxy.getStatus();
+    }
+
+}
\ No newline at end of file
index 62b88b974f2091e575b6a4f70b59ad4b1b7b1e55..81fe494e615508101e482caa97e69f55c2f6ad96 100644 (file)
@@ -162,8 +162,16 @@ module netconf-node-topology {
 
         container available-capabilities {
             config false;
-            leaf-list available-capability {
-                type string;
+            list available-capability {
+                leaf capability {
+                    type string;
+                }
+                leaf capability-origin {
+                    type enumeration {
+                        enum user-defined;
+                        enum device-advertised;
+                    }
+                }
             }
         }
 
@@ -240,4 +248,4 @@ module netconf-node-topology {
 
         uses netconf-node-fields;
     }
-}
+}
\ No newline at end of file
index 79e849a32428e5046f1d6173a717cf5bc1bffa90..8218d73a15acc669599b0d03790b978ee9060076 100644 (file)
@@ -19,11 +19,13 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.lang.reflect.Field;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
+import java.util.StringJoiner;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -278,7 +280,7 @@ public class TesttoolParameters {
 
         if (controllerDestination != null) {
             Preconditions.checkArgument(controllerDestination.contains(":"), "Controller Destination needs to be in a following format <ip>:<port>");
-            String[] parts = controllerDestination.split(Pattern.quote(":"));
+            final String[] parts = controllerDestination.split(Pattern.quote(":"));
             Preconditions.checkArgument(Integer.parseInt(parts[1]) > 0, "Port =< 0");
         }
 
@@ -295,14 +297,14 @@ public class TesttoolParameters {
             for (final File file : files) {
                 final Matcher matcher = YANG_FILENAME_PATTERN.matcher(file.getName());
                 if (!matcher.matches()) {
-                    BufferedReader reader;
+                    final BufferedReader reader;
                     try {
                         reader = new BufferedReader(new FileReader(file));
                         String line = reader.readLine();
                         while (!DATE_PATTERN.matcher(line).find()) {
                             line = reader.readLine();
                         }
-                        Matcher m = DATE_PATTERN.matcher(line);
+                        final Matcher m = DATE_PATTERN.matcher(line);
 
                         if (m.find()) {
                             String moduleName = file.getAbsolutePath();
@@ -310,12 +312,12 @@ public class TesttoolParameters {
                                 moduleName = moduleName.substring(0, moduleName.length() - 5);
                             }
                             final String revision = m.group(1);
-                            String correctName = moduleName + "@" + revision + ".yang";
-                            File correctNameFile = new File(correctName);
+                            final String correctName = moduleName + "@" + revision + ".yang";
+                            final File correctNameFile = new File(correctName);
                             file.renameTo(correctNameFile);
                         }
 
-                    } catch (IOException e) {
+                    } catch (final IOException e) {
                         e.printStackTrace();
                     }
                 }
@@ -400,7 +402,7 @@ public class TesttoolParameters {
     }
 
     private String prepareMessage(final int openDevice, final String editContentString) {
-        StringBuilder messageBuilder = new StringBuilder(editContentString);
+        final StringBuilder messageBuilder = new StringBuilder(editContentString);
 
         if (editContentString.contains(HOST_KEY)) {
             messageBuilder.replace(messageBuilder.indexOf(HOST_KEY), messageBuilder.indexOf(HOST_KEY) + HOST_KEY.length(), generateConfigsAddress);
@@ -441,33 +443,22 @@ public class TesttoolParameters {
         return payloads;
     }
 
-    //TODO This may be more scalable enumerating parameters via reflection
     @Override
     public String toString() {
-        StringBuffer params = new StringBuffer("TesttoolParameters{");
-        params.append("edit-content='").append(editContent).append('\'');
-        params.append(", async='").append(async).append('\'');
-        params.append(", thread-amount='").append(threadAmount).append('\'');
-        params.append(", throttle='").append(throttle).append('\'');
-        params.append(", auth='").append(auth).append('\'');
-        params.append(", controller-destination='").append(controllerDestination).append('\'');
-        params.append(", schemas-dir='").append(schemasDir).append('\'');
-        params.append(", devices-count='").append(deviceCount).append('\'');
-        params.append(", devices-per-port='").append(devicesPerPort).append('\'');
-        params.append(", starting-port='").append(startingPort).append('\'');
-        params.append(", generate-config-connection-timeout='").append(generateConfigsTimeout).append('\'');
-        params.append(", generate-config-address='").append(generateConfigsAddress).append('\'');
-        params.append(", distro-folder='").append(distroFolder).append('\'');
-        params.append(", generate-configs-batch-size='").append(generateConfigBatchSize).append('\'');
-        params.append(", ssh='").append(ssh).append('\'');
-        params.append(", exi='").append(exi).append('\'');
-        params.append(", debug='").append(debug).append('\'');
-        params.append(", notification-file='").append(notificationFile).append('\'');
-        params.append(", md-sal='").append(mdSal).append('\'');
-        params.append(", initial-config-xml-file='").append(initialConfigXMLFile).append('\'');
-        params.append(", time-out='").append(timeOut).append('\'');
-        params.append('}');
-
-        return params.toString();
+        final List<Field> fields = Arrays.asList(this.getClass().getDeclaredFields());
+        final StringJoiner joiner = new StringJoiner(", \n", "TesttoolParameters{", "}\n");
+        fields.stream()
+                .filter(field -> field.getAnnotation(Arg.class) != null)
+                .map(this::getFieldString)
+                .forEach(joiner::add);
+        return joiner.toString();
+    }
+
+    private String getFieldString(final Field field) {
+        try {
+            return field.getName() + "='" + field.get(this) + "'";
+        } catch (final IllegalAccessException e) {
+            return field.getName() + "= UNKNOWN";
+        }
     }
 }
index 50012e643b4df92fca954fa7c407fc43f384be58..846320049d4f2bbb46e47698f8cd6967e395d7f3 100644 (file)
@@ -59,6 +59,7 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose
     private ListenerRegistration<SchemaContextListener> listenerRegistration;
     private static TransactionChainHandler transactionChainHandler;
     private static DOMDataBroker dataBroker;
+    private static DOMMountPointServiceHandler mountPointServiceHandler;
 
     @Override
     public void onSessionInitiated(final ProviderSession session) {
@@ -69,7 +70,7 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose
         final SchemaContextHandler schemaCtxHandler = new SchemaContextHandler();
         this.listenerRegistration = schemaService.registerSchemaContextListener(schemaCtxHandler);
 
-        final DOMMountPointServiceHandler domMountPointServiceHandler = new DOMMountPointServiceHandler(
+        RestConnectorProvider.mountPointServiceHandler = new DOMMountPointServiceHandler(
                 session.getService(DOMMountPointService.class));
 
         RestConnectorProvider.dataBroker = session.getService(DOMDataBroker.class);
@@ -81,7 +82,7 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose
         final DOMRpcService rpcService = session.getService(DOMRpcService.class);
         final RpcServiceHandler rpcServiceHandler = new RpcServiceHandler(rpcService);
 
-        wrapperServices.setHandlers(schemaCtxHandler, domMountPointServiceHandler,
+        wrapperServices.setHandlers(schemaCtxHandler, RestConnectorProvider.mountPointServiceHandler,
                 RestConnectorProvider.transactionChainHandler, brokerHandler, rpcServiceHandler);
     }
 
@@ -100,6 +101,14 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose
         );
     }
 
+    /**
+     * Get current {@link DOMMountPointService} from {@link DOMMountPointServiceHandler}.
+     * @return {@link DOMMountPointService}
+     */
+    public static DOMMountPointService getMountPointService() {
+        return RestConnectorProvider.mountPointServiceHandler.get();
+    }
+
     @Override
     public Collection<ProviderFunctionality> getProviderFunctionality() {
         return Collections.emptySet();
index 0e7999b2563664506b24f69ab3163737d3f829e1..ce948af3ea1e92101cf6cd19350221fde8a6ebfd 100644 (file)
@@ -138,7 +138,7 @@ public class ServicesWrapperImpl implements BaseServicesWrapper, TransactionServ
 
     @Override
     public NormalizedNodeContext invokeRpc(final String identifier, final NormalizedNodeContext payload,
-            final UriInfo uriInfo) {
+                                           final UriInfo uriInfo) {
         return this.delegRestconfInvokeOpsService.invokeRpc(identifier, payload, uriInfo);
     }
 
@@ -148,14 +148,16 @@ public class ServicesWrapperImpl implements BaseServicesWrapper, TransactionServ
     }
 
     public void setHandlers(final SchemaContextHandler schemaCtxHandler,
-            final DOMMountPointServiceHandler domMountPointServiceHandler,
-            final TransactionChainHandler transactionChainHandler, final DOMDataBrokerHandler domDataBrokerHandler,
-            final RpcServiceHandler rpcServiceHandler) {
+                            final DOMMountPointServiceHandler domMountPointServiceHandler,
+                            final TransactionChainHandler transactionChainHandler,
+                            final DOMDataBrokerHandler domDataBrokerHandler,
+                            final RpcServiceHandler rpcServiceHandler) {
         this.delegRestModService = new RestconfModulesServiceImpl(schemaCtxHandler, domMountPointServiceHandler);
         this.delegRestOpsService = new RestconfOperationsServiceImpl(schemaCtxHandler, domMountPointServiceHandler);
         this.delegRestSchService = new RestconfSchemaServiceImpl(schemaCtxHandler, domMountPointServiceHandler);
         this.delegRestStrsService = new RestconfStreamsServiceImpl(schemaCtxHandler);
-        this.delegRestconfDataService = new RestconfDataServiceImpl(schemaCtxHandler, transactionChainHandler);
+        this.delegRestconfDataService = new RestconfDataServiceImpl(schemaCtxHandler, transactionChainHandler,
+                domMountPointServiceHandler);
         this.delegRestconfInvokeOpsService = new RestconfInvokeOperationsServiceImpl(rpcServiceHandler,
                 schemaCtxHandler);
         this.delegRestconfSubscrService = new RestconfStreamsSubscriptionServiceImpl(domDataBrokerHandler);
index bcf95f7b6450ccb9925316951f773d8fc0b78aa4..69ebec275128f95f4eaaec1cf7fb6f0cbc96014b 100644 (file)
@@ -8,12 +8,14 @@
 
 package org.opendaylight.restconf.jersey.providers;
 
+import com.google.common.base.Optional;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Request;
 import javax.ws.rs.core.UriInfo;
 import org.opendaylight.netconf.sal.rest.api.RestconfConstants;
 import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.restconf.RestConnectorProvider;
 import org.opendaylight.restconf.utils.parser.ParserIdentifier;
 
 public class AbstractIdentifierAwareJaxRsProvider {
@@ -31,8 +33,10 @@ public class AbstractIdentifierAwareJaxRsProvider {
     }
 
     protected InstanceIdentifierContext<?> getInstanceIdentifierContext() {
-        return ParserIdentifier.toInstanceIdentifier(getIdentifier(),
-                ControllerContext.getInstance().getGlobalSchema());
+        return ParserIdentifier.toInstanceIdentifier(
+                getIdentifier(),
+                ControllerContext.getInstance().getGlobalSchema(),
+                Optional.of(RestConnectorProvider.getMountPointService()));
     }
 
     protected UriInfo getUriInfo() {
index b8033bbacebfc487d26ad4009d3951cafe02b881..9857c4493ff68d25d6c6b6acb91d08a11125a4b1 100644 (file)
@@ -163,7 +163,7 @@ class ModuleImpl implements Module {
 
     @Override
     public Set<Module> getSubmodules() {
-        throw new UnsupportedOperationException("Not supported operations.");
+        return new HashSet<>();
     }
 
     @Override
index e4bc1b423988e386efef7729538a5b3451d434eb..5b7a6ebd999441b36f456288e8e4632d2b86552b 100644 (file)
@@ -7,12 +7,12 @@
  */
 package org.opendaylight.restconf.rest.services.impl;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import java.util.Collections;
 import java.util.Set;
 import javax.ws.rs.core.UriInfo;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
@@ -80,11 +80,9 @@ public class RestconfModulesServiceImpl implements RestconfModulesService {
             throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
         }
         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
-        final InstanceIdentifierContext<?> mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
-                schemaContextRef.get());
-        final DOMMountPointService domMointPointService = this.domMountPointServiceHandler.get();
-        final DOMMountPoint mountPoint = domMointPointService
-                .getMountPoint(mountPointIdentifier.getInstanceIdentifier()).get();
+        final InstanceIdentifierContext<?> mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(
+                identifier, schemaContextRef.get(), Optional.of(this.domMountPointServiceHandler.get()));
+        final DOMMountPoint mountPoint = mountPointIdentifier.getMountPoint();
         return getModules(mountPoint.getSchemaContext().getModules(), schemaContextRef, mountPoint);
     }
 
@@ -94,13 +92,15 @@ public class RestconfModulesServiceImpl implements RestconfModulesService {
         Preconditions.checkNotNull(identifier);
         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
         final QName moduleQname = ParserIdentifier.makeQNameFromIdentifier(identifier);
-        Module module = null;
+        final Module module;
         DOMMountPoint mountPoint = null;
         if (identifier.contains(RestconfConstants.MOUNT)) {
-            final InstanceIdentifierContext<?> point = ParserIdentifier.toInstanceIdentifier(identifier,
-                    schemaContextRef.get());
-            final DOMMountPointService domMointPointService = this.domMountPointServiceHandler.get();
-            mountPoint = domMointPointService.getMountPoint(point.getInstanceIdentifier()).get();
+            // we only need to find mount point itself
+            final String mountPointPath = identifier.substring(
+                    0, identifier.indexOf(RestconfConstants.MOUNT) + RestconfConstants.MOUNT.length());
+            final InstanceIdentifierContext<?> mountPointContext = ParserIdentifier.toInstanceIdentifier(
+                    mountPointPath, schemaContextRef.get(), Optional.of(this.domMountPointServiceHandler.get()));
+            mountPoint = mountPointContext.getMountPoint();
             module = schemaContextRef.findModuleInMountPointByQName(mountPoint, moduleQname);
         } else {
             module = schemaContextRef.findModuleByQName(moduleQname);
index bddd086bd702a5427d63c99000a66df654ad74ea..e14fa8fe6bf8658199ca3750e31f21c04193aa2b 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.restconf.rest.services.impl;
 
+import com.google.common.base.Optional;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -73,12 +74,12 @@ public class RestconfOperationsServiceImpl implements RestconfOperationsService
 
     @Override
     public NormalizedNodeContext getOperations(final String identifier, final UriInfo uriInfo) {
-        Set<Module> modules = null;
-        DOMMountPoint mountPoint = null;
+        final Set<Module> modules;
+        final DOMMountPoint mountPoint;
         final SchemaContextRef ref = new SchemaContextRef(this.schemaContextHandler.get());
         if (identifier.contains(RestconfConstants.MOUNT)) {
-            final InstanceIdentifierContext<?> mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
-                    ref.get());
+            final InstanceIdentifierContext<?> mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(
+                    identifier, ref.get(), Optional.of(this.domMountPointServiceHandler.get()));
             mountPoint = mountPointIdentifier.getMountPoint();
             modules = ref.getModules(mountPoint);
 
index c27da7ab621e240beac41202bccc7c5bab5bd86e..cb17434392c1870ce602082d4719e8366a671abf 100644 (file)
@@ -12,10 +12,10 @@ import com.google.common.base.Preconditions;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.TimeZone;
+import javax.annotation.Nonnull;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
@@ -26,6 +26,7 @@ import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
 import org.opendaylight.restconf.RestConnectorProvider;
 import org.opendaylight.restconf.common.references.SchemaContextRef;
+import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler;
 import org.opendaylight.restconf.handlers.SchemaContextHandler;
 import org.opendaylight.restconf.handlers.TransactionChainHandler;
 import org.opendaylight.restconf.restful.services.api.RestconfDataService;
@@ -51,11 +52,14 @@ public class RestconfDataServiceImpl implements RestconfDataService {
 
     private final SchemaContextHandler schemaContextHandler;
     private final TransactionChainHandler transactionChainHandler;
+    private final DOMMountPointServiceHandler mountPointServiceHandler;
 
     public RestconfDataServiceImpl(final SchemaContextHandler schemaContextHandler,
-                                   final TransactionChainHandler transactionChainHandler) {
+                                   final TransactionChainHandler transactionChainHandler,
+                                   final DOMMountPointServiceHandler mountPointServiceHandler) {
         this.schemaContextHandler = schemaContextHandler;
         this.transactionChainHandler = transactionChainHandler;
+        this.mountPointServiceHandler = mountPointServiceHandler;
     }
 
     @Override
@@ -63,20 +67,20 @@ public class RestconfDataServiceImpl implements RestconfDataService {
         Preconditions.checkNotNull(identifier);
         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
 
-        final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
-                schemaContextRef.get());
+        final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(
+                identifier, schemaContextRef.get(), Optional.of(this.mountPointServiceHandler.get()));
         final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
         final String value = uriInfo.getQueryParameters().getFirst(RestconfDataServiceConstant.CONTENT);
 
-        final DOMTransactionChain transaction;
+        final DOMTransactionChain transactionChain;
         if (mountPoint == null) {
-            transaction = this.transactionChainHandler.get();
+            transactionChain = this.transactionChainHandler.get();
         } else {
-            transaction = transactionOfMountPoint(mountPoint);
+            transactionChain = transactionChainOfMountPoint(mountPoint);
         }
 
         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint,
-                transaction);
+                transactionChain);
         final NormalizedNode<?, ?> node = ReadDataTransactionUtil.readData(value, transactionNode);
         if (node == null) {
             throw new RestconfDocumentedException(
@@ -111,18 +115,18 @@ public class RestconfDataServiceImpl implements RestconfDataService {
         PutDataTransactionUtil.validateListKeysEqualityInPayloadAndUri(payload);
 
         final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
-        final DOMTransactionChain transaction;
+        final DOMTransactionChain transactionChain;
         final SchemaContextRef ref;
         if (mountPoint == null) {
-            transaction = this.transactionChainHandler.get();
+            transactionChain = this.transactionChainHandler.get();
             ref = new SchemaContextRef(this.schemaContextHandler.get());
         } else {
-            transaction = transactionOfMountPoint(mountPoint);
+            transactionChain = transactionChainOfMountPoint(mountPoint);
             ref = new SchemaContextRef(mountPoint.getSchemaContext());
         }
 
         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
-                payload.getInstanceIdentifierContext(), mountPoint, transaction);
+                payload.getInstanceIdentifierContext(), mountPoint, transactionChain);
         return PutDataTransactionUtil.putData(payload, ref, transactionNode);
     }
 
@@ -136,36 +140,36 @@ public class RestconfDataServiceImpl implements RestconfDataService {
         Preconditions.checkNotNull(payload);
 
         final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
-        final DOMTransactionChain transaction;
+        final DOMTransactionChain transactionChain;
         final SchemaContextRef ref;
         if (mountPoint == null) {
-            transaction = this.transactionChainHandler.get();
+            transactionChain = this.transactionChainHandler.get();
             ref = new SchemaContextRef(this.schemaContextHandler.get());
         } else {
-            transaction = transactionOfMountPoint(mountPoint);
+            transactionChain = transactionChainOfMountPoint(mountPoint);
             ref = new SchemaContextRef(mountPoint.getSchemaContext());
         }
         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
-                payload.getInstanceIdentifierContext(), mountPoint, transaction);
+                payload.getInstanceIdentifierContext(), mountPoint, transactionChain);
         return PostDataTransactionUtil.postData(uriInfo, payload, transactionNode, ref);
     }
 
     @Override
     public Response deleteData(final String identifier) {
         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
-        final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
-                schemaContextRef.get());
+        final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(
+                identifier, schemaContextRef.get(), Optional.of(this.mountPointServiceHandler.get()));
 
         final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
-        final DOMTransactionChain transaction;
+        final DOMTransactionChain transactionChain;
         if (mountPoint == null) {
-            transaction = this.transactionChainHandler.get();
+            transactionChain = this.transactionChainHandler.get();
         } else {
-            transaction = transactionOfMountPoint(mountPoint);
+            transactionChain = transactionChainOfMountPoint(mountPoint);
         }
 
         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint,
-                transaction);
+                transactionChain);
         return DeleteDataTransactionUtil.deleteData(transactionNode);
     }
 
@@ -179,29 +183,29 @@ public class RestconfDataServiceImpl implements RestconfDataService {
         Preconditions.checkNotNull(context);
         final DOMMountPoint mountPoint = context.getInstanceIdentifierContext().getMountPoint();
 
-        final DOMTransactionChain transaction;
+        final DOMTransactionChain transactionChain;
         final SchemaContextRef ref;
         if (mountPoint == null) {
-            transaction = this.transactionChainHandler.get();
+            transactionChain = this.transactionChainHandler.get();
             ref = new SchemaContextRef(this.schemaContextHandler.get());
         } else {
-            transaction = transactionOfMountPoint(mountPoint);
+            transactionChain = transactionChainOfMountPoint(mountPoint);
             ref = new SchemaContextRef(mountPoint.getSchemaContext());
         }
 
         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
-                context.getInstanceIdentifierContext(), mountPoint, transaction);
+                context.getInstanceIdentifierContext(), mountPoint, transactionChain);
 
         return PatchDataTransactionUtil.patchData(context, transactionNode, ref);
     }
 
     /**
-     * Prepare transaction to read data of mount point, if these data are
-     * present.
+     * Prepare transaction chain to access data of mount point
      * @param mountPoint
-     * @return {@link DOMDataReadWriteTransaction}
+     *            - mount point reference
+     * @return {@link DOMTransactionChain}
      */
-    private static DOMTransactionChain transactionOfMountPoint(final DOMMountPoint mountPoint) {
+    private static DOMTransactionChain transactionChainOfMountPoint(@Nonnull final DOMMountPoint mountPoint) {
         final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
         if (domDataBrokerService.isPresent()) {
             return domDataBrokerService.get().createTransactionChain(RestConnectorProvider.transactionListener);
index fc9c676c4ea36a4bcaeb60bd591765d019a57813..f0958d79e9345a77d1ec25756802d57c26ef0b34 100644 (file)
@@ -17,20 +17,10 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
-import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
-import org.opendaylight.restconf.RestConnectorProvider;
 import org.opendaylight.restconf.common.references.SchemaContextRef;
 import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
 import org.opendaylight.restconf.utils.parser.ParserIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -93,64 +83,35 @@ public final class PostDataTransactionUtil {
             final SchemaContext schemaContext) {
         final DOMTransactionChain transactionChain = transactionNode.getTransactionChain();
         final DOMDataReadWriteTransaction transaction = transactionChain.newReadWriteTransaction();
-        final NormalizedNode<?, ?> node = ImmutableNodes.fromInstanceId(schemaContext, path);
-        transaction.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(node.getIdentifier()), node);
-        TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
 
         if (data instanceof MapNode) {
+            boolean merge = false;
             for (final MapEntryNode child : ((MapNode) data).getValue()) {
-                putChild(child, transactionChain, transaction, path);
-            }
-        } else if (data instanceof AugmentationNode) {
-            for (final DataContainerChild<? extends PathArgument, ?> child : ((AugmentationNode) data).getValue()) {
-                putChild(child, transactionChain, transaction, path);
-            }
-        } else if (data instanceof ChoiceNode) {
-            for (final DataContainerChild<? extends PathArgument, ?> child : ((ChoiceNode) data).getValue()) {
-                putChild(child, transactionChain, transaction, path);
-            }
-        } else if (data instanceof LeafSetNode<?>) {
-            for (final LeafSetEntryNode<?> child : ((LeafSetNode<?>) data).getValue()) {
-                putChild(child, transactionChain, transaction, path);
-            }
-        } else if (data instanceof ContainerNode) {
-            for (final DataContainerChild<? extends PathArgument, ?> child : ((ContainerNode) data).getValue()) {
-                putChild(child, transactionChain, transaction, path);
+                final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
+                TransactionUtil.checkItemDoesNotExists(
+                        transactionChain, transaction, LogicalDatastoreType.CONFIGURATION, childPath,
+                        RestconfDataServiceConstant.PostData.POST_TX_TYPE);
+                if (!merge) {
+                    merge = true;
+                    TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
+                    final NormalizedNode<?, ?> emptySubTree = ImmutableNodes.fromInstanceId(schemaContext, path);
+                    transaction.merge(LogicalDatastoreType.CONFIGURATION,
+                            YangInstanceIdentifier.create(emptySubTree.getIdentifier()), emptySubTree);
+                }
+                transaction.put(LogicalDatastoreType.CONFIGURATION, childPath, child);
             }
         } else {
-            transaction.cancel();
-            RestConnectorProvider.resetTransactionChainForAdapaters(transactionChain);
+            TransactionUtil.checkItemDoesNotExists(
+                    transactionChain, transaction, LogicalDatastoreType.CONFIGURATION, path,
+                    RestconfDataServiceConstant.PostData.POST_TX_TYPE);
 
-            final String errMsg = "Only Map, Choice, Augmentation, LeafSet and Container nodes are supported";
-            LOG.trace("{}:{}", errMsg, path);
-            throw new RestconfDocumentedException(
-                    "Node not supported", RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.BAD_ELEMENT, path);
+            TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
+            transaction.put(LogicalDatastoreType.CONFIGURATION, path, data);
         }
 
         return transaction.submit();
     }
 
-    /**
-     * Prepare data for submit
-     *
-     * @param child
-     *            - data
-     * @param transactionChain
-     *            - transaction chain
-     * @param readWriteTx
-     *            - transaction
-     * @param path
-     *            - path to data
-     */
-    private static void putChild(final NormalizedNode<?, ?> child, final DOMTransactionChain transactionChain,
-                                 final DOMDataReadWriteTransaction readWriteTx, final YangInstanceIdentifier path) {
-        final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
-        TransactionUtil.checkItemDoesNotExists(
-                transactionChain, readWriteTx, LogicalDatastoreType.CONFIGURATION, childPath,
-                RestconfDataServiceConstant.PostData.POST_TX_TYPE);
-        readWriteTx.put(LogicalDatastoreType.CONFIGURATION, childPath, child);
-    }
-
     /**
      * Get location from {@link YangInstanceIdentifier} and {@link UriInfo}
      *
index 6dc8a9463622fcf36421aef22420e455bc186dd5..fe840990ed1f4db44d5eb076c9e3dc9aea81170b 100644 (file)
@@ -8,10 +8,13 @@
 package org.opendaylight.restconf.restful.utils;
 
 import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.CheckedFuture;
 import java.util.Collection;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
@@ -19,23 +22,23 @@ import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 
 /**
@@ -62,7 +65,8 @@ public final class ReadDataTransactionUtil {
      *            - {@link TransactionVarsWrapper} - wrapper for variables
      * @return {@link NormalizedNode}
      */
-    public static NormalizedNode<?, ?> readData(final String valueOfContent, final TransactionVarsWrapper transactionNode) {
+    public static @Nullable NormalizedNode<?, ?> readData(@Nullable final String valueOfContent,
+                                                          @Nonnull final TransactionVarsWrapper transactionNode) {
         final NormalizedNode<?, ?> data;
         if (valueOfContent != null) {
             switch (valueOfContent) {
@@ -78,7 +82,7 @@ public final class ReadDataTransactionUtil {
                     data = readAllData(transactionNode);
                     break;
                 default:
-                    throw new RestconfDocumentedException("Bad querry parameter for content.", ErrorType.APPLICATION,
+                    throw new RestconfDocumentedException("Bad query parameter for content.", ErrorType.APPLICATION,
                             ErrorTag.INVALID_VALUE);
             }
         } else {
@@ -97,14 +101,15 @@ public final class ReadDataTransactionUtil {
      *            - {@link TransactionVarsWrapper} - wrapper for variables
      * @return {@link NormalizedNode}
      */
-    private static NormalizedNode<?, ?> readDataViaTransaction(final TransactionVarsWrapper transactionNode) {
-            final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture = transactionNode
-                    .getTransactionChain().newReadOnlyTransaction().read(transactionNode.getLogicalDatastoreType(),
-                            transactionNode.getInstanceIdentifier().getInstanceIdentifier());
-            final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory();
-            FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
-                    dataFactory);
-            return dataFactory.build();
+    private static @Nullable NormalizedNode<?, ?> readDataViaTransaction(
+            @Nonnull final TransactionVarsWrapper transactionNode) {
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture = transactionNode
+                .getTransactionChain().newReadOnlyTransaction().read(transactionNode.getLogicalDatastoreType(),
+                        transactionNode.getInstanceIdentifier().getInstanceIdentifier());
+        final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory();
+        FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
+                dataFactory);
+        return dataFactory.build();
     }
 
     /**
@@ -114,7 +119,7 @@ public final class ReadDataTransactionUtil {
      *            - {@link TransactionVarsWrapper} - wrapper for variables
      * @return {@link NormalizedNode}
      */
-    private static NormalizedNode<?, ?> readAllData(final TransactionVarsWrapper transactionNode) {
+    private static @Nullable NormalizedNode<?, ?> readAllData(@Nonnull final TransactionVarsWrapper transactionNode) {
         // PREPARE STATE DATA NODE
         transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
         final NormalizedNode<?, ?> stateDataNode = readDataViaTransaction(transactionNode);
@@ -151,8 +156,8 @@ public final class ReadDataTransactionUtil {
      *            - data node of config data
      * @return {@link NormalizedNode}
      */
-    private static NormalizedNode<?, ?> mapNode(final NormalizedNode<?, ?> stateDataNode,
-            final NormalizedNode<?, ?> configDataNode) {
+    private static @Nonnull NormalizedNode<?, ?> mapNode(@Nonnull final NormalizedNode<?, ?> stateDataNode,
+                                                         @Nonnull final NormalizedNode<?, ?> configDataNode) {
         validPossibilityOfMergeNodes(stateDataNode, configDataNode);
         if (configDataNode instanceof RpcDefinition) {
             return prepareRpcData(configDataNode, stateDataNode);
@@ -161,6 +166,23 @@ public final class ReadDataTransactionUtil {
         }
     }
 
+    /**
+     * Valid of can be data merged together.
+     *
+     * @param stateDataNode
+     *            - data node of state data
+     * @param configDataNode
+     *            - data node of config data
+     */
+    private static void validPossibilityOfMergeNodes(@Nonnull final NormalizedNode<?, ?> stateDataNode,
+                                                     @Nonnull final NormalizedNode<?, ?> configDataNode) {
+        final QNameModule moduleOfStateData = stateDataNode.getIdentifier().getNodeType().getModule();
+        final QNameModule moduleOfConfigData = configDataNode.getIdentifier().getNodeType().getModule();
+        if (moduleOfStateData != moduleOfConfigData) {
+            throw new RestconfDocumentedException("It is not possible to merge ");
+        }
+    }
+
     /**
      * Prepare and map data for rpc
      *
@@ -170,8 +192,8 @@ public final class ReadDataTransactionUtil {
      *            - data node of state data
      * @return {@link NormalizedNode}
      */
-    private static NormalizedNode<?, ?> prepareRpcData(final NormalizedNode<?, ?> configDataNode,
-            final NormalizedNode<?, ?> stateDataNode) {
+    private static @Nonnull NormalizedNode<?, ?> prepareRpcData(@Nonnull final NormalizedNode<?, ?> configDataNode,
+                                                                @Nonnull final NormalizedNode<?, ?> stateDataNode) {
         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder = ImmutableNodes
                 .mapEntryBuilder();
         mapEntryBuilder.withNodeIdentifier((NodeIdentifierWithPredicates) configDataNode.getIdentifier());
@@ -192,11 +214,10 @@ public final class ReadDataTransactionUtil {
      * @param mapEntryBuilder
      *            - builder for mapping data
      */
-    private static void mapRpcDataNode(final NormalizedNode<?, ?> dataNode,
-            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
-        for (final DataContainerChild<? extends PathArgument, ?> child : ((ContainerNode) dataNode).getValue()) {
-            mapEntryBuilder.addChild(child);
-        }
+    private static void mapRpcDataNode(@Nonnull final NormalizedNode<?, ?> dataNode,
+                                       @Nonnull final DataContainerNodeBuilder<
+                                               NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
+        ((ContainerNode) dataNode).getValue().forEach(mapEntryBuilder::addChild);
     }
 
     /**
@@ -208,116 +229,120 @@ public final class ReadDataTransactionUtil {
      *            - data node of state data
      * @return {@link NormalizedNode}
      */
-    private static NormalizedNode<?, ?> prepareData(final NormalizedNode<?, ?> configDataNode,
-            final NormalizedNode<?, ?> stateDataNode) {
+    private static @Nonnull NormalizedNode<?, ?> prepareData(@Nonnull final NormalizedNode<?, ?> configDataNode,
+                                                             @Nonnull final NormalizedNode<?, ?> stateDataNode) {
+        if (configDataNode instanceof MapNode) {
+            final CollectionNodeBuilder<MapEntryNode, MapNode> builder = ImmutableNodes
+                    .mapNodeBuilder().withNodeIdentifier(((MapNode) configDataNode).getIdentifier());
 
-        if (configDataNode instanceof MapNode) { // part for lists mapping
-            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder = ImmutableNodes
-                .mapEntryBuilder();
-            final NodeIdentifierWithPredicates node = ((MapNode) configDataNode).getValue().iterator().next().getIdentifier();
-            mapEntryBuilder.withNodeIdentifier(node);
-
-            // MAP CONFIG DATA
-            mapDataNode((MapNode) configDataNode, mapEntryBuilder);
-            // MAP STATE DATA
-            mapDataNode((MapNode) stateDataNode, mapEntryBuilder);
-            return ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType()).addChild(mapEntryBuilder.build()).build();
-        } else if (configDataNode instanceof ContainerNode) { // part for containers mapping
-            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> containerBuilder = Builders
-                    .containerBuilder((ContainerNode) configDataNode);
-
-            // MAP CONFIG DATA
-            mapCont(containerBuilder, ((ContainerNode) configDataNode).getValue());
-            // MAP STATE DATA
-            mapCont(containerBuilder, ((ContainerNode) stateDataNode).getValue());
-            return containerBuilder.build();
+            mapValueToBuilder(
+                    ((MapNode) configDataNode).getValue(), ((MapNode) stateDataNode).getValue(), builder);
+
+            return builder.build();
+        } else if (configDataNode instanceof MapEntryNode) {
+            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = ImmutableNodes
+                    .mapEntryBuilder().withNodeIdentifier(((MapEntryNode) configDataNode).getIdentifier());
+
+            mapValueToBuilder(
+                    ((MapEntryNode) configDataNode).getValue(), ((MapEntryNode) stateDataNode).getValue(), builder);
+
+            return builder.build();
+        } else if (configDataNode instanceof ContainerNode) {
+            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder = Builders
+                    .containerBuilder().withNodeIdentifier(((ContainerNode) configDataNode).getIdentifier());
+
+            mapValueToBuilder(
+                    ((ContainerNode) configDataNode).getValue(), ((ContainerNode) stateDataNode).getValue(), builder);
+
+            return builder.build();
+        } else if (configDataNode instanceof AugmentationNode) {
+            final DataContainerNodeBuilder<AugmentationIdentifier, AugmentationNode> builder = Builders
+                    .augmentationBuilder().withNodeIdentifier(((AugmentationNode) configDataNode).getIdentifier());
+
+            mapValueToBuilder(
+                    ((AugmentationNode) configDataNode).getValue(), ((AugmentationNode) stateDataNode).getValue(), builder);
+
+            return builder.build();
+        } else if (configDataNode instanceof ChoiceNode) {
+            final DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> builder = Builders
+                    .choiceBuilder().withNodeIdentifier(((ChoiceNode) configDataNode).getIdentifier());
+
+            mapValueToBuilder(
+                    ((ChoiceNode) configDataNode).getValue(), ((ChoiceNode) stateDataNode).getValue(), builder);
+
+            return builder.build();
+        } else if (configDataNode instanceof LeafNode) {
+            return ImmutableNodes.leafNode(configDataNode.getNodeType(), configDataNode.getValue());
         } else {
             throw new RestconfDocumentedException("Bad type of node.");
         }
     }
 
     /**
-     * Map data to builder
+     * Map value from container node to builder.
      *
-     * @param containerBuilder
-     *            - builder for mapping data
-     * @param childs
-     *            - childs of data (container)
+     * @param configData
+     *            - collection of config data nodes
+     * @param stateData
+     *            - collection of state data nodes
+     * @param builder
+     *            - builder
      */
-    private static void mapCont(final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> containerBuilder,
-            final Collection<DataContainerChild<? extends PathArgument, ?>> childs) {
-        for (final DataContainerChild<? extends PathArgument, ?> child : childs) {
-            containerBuilder.addChild(child);
-        }
-    }
+    private static <T extends NormalizedNode<? extends PathArgument, ?>> void mapValueToBuilder(
+            @Nonnull final Collection<T> configData,
+            @Nonnull final Collection<T> stateData,
+            @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+        final Map<PathArgument, T> configMap = configData.stream().collect(
+                Collectors.toMap(NormalizedNode::getIdentifier, Function.identity()));
+        final Map<PathArgument, T> stateMap = stateData.stream().collect(
+                Collectors.toMap(NormalizedNode::getIdentifier, Function.identity()));
 
-    /**
-     * Map data to builder
-     *
-     * @param immutableData
-     *            - immutable data - {@link MapNode}
-     * @param mapEntryBuilder
-     *            - builder for mapping data
-     */
-    private static void mapDataNode(final MapNode immutableData,
-            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
-        for (final DataContainerChild<? extends PathArgument, ?> child : immutableData.getValue().iterator()
-                .next().getValue()) {
-            Preconditions.checkNotNull(child);
-            if (child instanceof ContainerNode) {
-                addChildToMap(ContainerNode.class, child, mapEntryBuilder);
-            } else if (child instanceof AugmentationNode) {
-                addChildToMap(AugmentationNode.class, child, mapEntryBuilder);
-            } else if(child instanceof MapNode){
-                final MapNode listNode = (MapNode) child;
-                for (final MapEntryNode listChild : listNode.getValue()) {
-                    for (final DataContainerChild<? extends PathArgument, ?> entryChild : listChild.getValue()) {
-                        addChildToMap(MapEntryNode.class, entryChild, mapEntryBuilder);
-                    }
-                }
-            } else if (child instanceof ChoiceNode) {
-                addChildToMap(ChoiceNode.class, child, mapEntryBuilder);
-            } else if ((child instanceof LeafSetNode<?>) || (child instanceof LeafNode)) {
-                mapEntryBuilder.addChild(child);
-            }
+        // merge config and state data of children with different identifiers
+        mapDataToBuilder(configMap, stateMap, builder);
 
-        }
+        // merge config and state data of children with the same identifiers
+        mergeDataToBuilder(configMap, stateMap, builder);
     }
 
     /**
-     * Mapping child
+     * Map data with different identifiers to builder. Data with different identifiers can be just added
+     * as childs to parent node.
      *
-     * @param type
-     *            - type of data
-     * @param child
-     *            - child to map
-     * @param mapEntryBuilder
-     *            - builder for mapping child
+     * @param configMap
+     *            - map of config data nodes
+     * @param stateMap
+     *            - map of state data nodes
+     * @param builder
+     *           - builder
      */
-    private static <T extends DataContainerNode<? extends PathArgument>> void addChildToMap(final Class<T> type,
-            final DataContainerChild<? extends PathArgument, ?> child,
-            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
-        @SuppressWarnings("unchecked")
-        final T node = (T) child;
-        for (final DataContainerChild<? extends PathArgument, ?> childNode : node.getValue()) {
-            mapEntryBuilder.addChild(childNode);
-        }
+    private static <T extends NormalizedNode<? extends PathArgument, ?>> void mapDataToBuilder(
+            @Nonnull final Map<PathArgument, T> configMap,
+            @Nonnull final Map<PathArgument, T> stateMap,
+            @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+        configMap.entrySet().stream().filter(x -> !stateMap.containsKey(x.getKey())).forEach(
+                y -> builder.addChild(y.getValue()));
+        stateMap.entrySet().stream().filter(x -> !configMap.containsKey(x.getKey())).forEach(
+                y -> builder.addChild(y.getValue()));
     }
 
     /**
-     * Valid of can be data merged together.
+     * Map data with the same identifiers to builder. Data with the same identifiers cannot be just added but we need to
+     * go one level down with {@code prepareData} method.
      *
-     * @param stateDataNode
-     *            - data node of state data
-     * @param configDataNode
-     *            - data node of config data
+     * @param configMap
+     *            - immutable config data
+     * @param stateMap
+     *            - immutable state data
+     * @param builder
+     *           - builder
      */
-    private static void validPossibilityOfMergeNodes(@Nonnull final NormalizedNode<?, ?> stateDataNode,
-            @Nonnull final NormalizedNode<?, ?> configDataNode) {
-        final QNameModule moduleOfStateData = stateDataNode.getIdentifier().getNodeType().getModule();
-        final QNameModule moduleOfConfigData = configDataNode.getIdentifier().getNodeType().getModule();
-        if (moduleOfStateData != moduleOfConfigData) {
-            throw new RestconfDocumentedException("It is not possible to merge ");
-        }
+    @SuppressWarnings("unchecked")
+    private static <T extends NormalizedNode<? extends PathArgument, ?>> void mergeDataToBuilder(
+            @Nonnull final Map<PathArgument, T> configMap,
+            @Nonnull final Map<PathArgument, T> stateMap,
+            @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+        // it is enough to process only config data because operational contains the same data
+        configMap.entrySet().stream().filter(x -> stateMap.containsKey(x.getKey())).forEach(
+                y -> builder.addChild((T) prepareData(y.getValue(), stateMap.get(y.getKey()))));
     }
 }
index d24c3deb07336c99016c453b3810d1cf44f556d9..fc2703f98be3a9eb3a2a4496e2554f0a9e05919d 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.restconf.utils.parser;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
@@ -14,7 +15,6 @@ import java.text.ParseException;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
-import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContext;
@@ -48,25 +48,62 @@ public final class ParserIdentifier {
     }
 
     /**
-     * Make {@link InstanceIdentifierContext} from identifier.
+     * Make {@link InstanceIdentifierContext} from {@link String} identifier
+     * <br>
+     * For identifiers of data NOT behind mount points returned
+     * {@link InstanceIdentifierContext} is prepared with {@code null} reference of {@link DOMMountPoint} and with
+     * controller's {@link SchemaContext}.
+     * <br>
+     * For identifiers of data behind mount points returned
+     * {@link InstanceIdentifierContext} is prepared with reference of {@link DOMMountPoint} and its
+     * own {@link SchemaContext}.
      *
      * @param identifier
-     *            - path identifier
+     *           - path identifier
      * @param schemaContext
-     *            - {@link SchemaContext}
+     *           - controller schema context
+     * @param mountPointService
+     *           - mount point service
      * @return {@link InstanceIdentifierContext}
      */
-    public static InstanceIdentifierContext<?> toInstanceIdentifier(@Nullable final String identifier,
-            final SchemaContext schemaContext) {
-        final YangInstanceIdentifier deserialize;
+    public static InstanceIdentifierContext<?> toInstanceIdentifier(
+            final String identifier,
+            final SchemaContext schemaContext,
+            final Optional<DOMMountPointService> mountPointService) {
         if (identifier != null && identifier.contains(RestconfConstants.MOUNT)) {
-            final String mountPointId = identifier.substring(0, identifier.indexOf("/" + RestconfConstants.MOUNT));
-            deserialize = IdentifierCodec.deserialize(mountPointId, schemaContext);
+            if (!mountPointService.isPresent()) {
+                throw new RestconfDocumentedException("Mount point service is not available");
+            }
+
+            final Iterator<String> pathsIt = Splitter.on("/" + RestconfConstants.MOUNT).split(identifier).iterator();
+
+            final String mountPointId = pathsIt.next();
+            final YangInstanceIdentifier mountYangInstanceIdentifier = IdentifierCodec.deserialize(
+                    mountPointId, schemaContext);
+            final Optional<DOMMountPoint> mountPoint = mountPointService.get().getMountPoint(mountYangInstanceIdentifier);
+
+            if (!mountPoint.isPresent()) {
+                throw new RestconfDocumentedException(
+                        "Mount point does not exist.", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
+            }
+
+            final String pathId = pathsIt.next().replaceFirst("/", "");
+            final YangInstanceIdentifier pathYangInstanceIdentifier = IdentifierCodec.deserialize(
+                    pathId, mountPoint.get().getSchemaContext());
+
+            final DataSchemaContextNode<?> child = DataSchemaContextTree.from(
+                    mountPoint.get().getSchemaContext()).getChild(pathYangInstanceIdentifier);
+
+            return new InstanceIdentifierContext<SchemaNode>(
+                    pathYangInstanceIdentifier, child.getDataSchemaNode(), mountPoint.get(),
+                    mountPoint.get().getSchemaContext());
         } else {
-            deserialize = IdentifierCodec.deserialize(identifier, schemaContext);
+            final YangInstanceIdentifier deserialize = IdentifierCodec.deserialize(identifier, schemaContext);
+            final DataSchemaContextNode<?> child = DataSchemaContextTree.from(schemaContext).getChild(deserialize);
+
+            return new InstanceIdentifierContext<SchemaNode>(
+                    deserialize, child.getDataSchemaNode(), null, schemaContext);
         }
-        final DataSchemaContextNode<?> child = DataSchemaContextTree.from(schemaContext).getChild(deserialize);
-        return new InstanceIdentifierContext<SchemaNode>(deserialize, child.getDataSchemaNode(), null, schemaContext);
     }
 
     /**
@@ -170,12 +207,11 @@ public final class ParserIdentifier {
                 pathBuilder.append(current);
             }
             final InstanceIdentifierContext<?> point = ParserIdentifier
-                    .toInstanceIdentifier(pathBuilder.toString(), schemaContext);
-            final DOMMountPoint mountPoint = domMountPointService.getMountPoint(point.getInstanceIdentifier()).get();
+                    .toInstanceIdentifier(pathBuilder.toString(), schemaContext, Optional.of(domMountPointService));
             final String moduleName = RestconfValidation.validateAndGetModulName(componentIter);
             final Date revision = RestconfValidation.validateAndGetRevision(componentIter);
-            final Module module = mountPoint.getSchemaContext().findModuleByName(moduleName, revision);
-            return new SchemaExportContext(mountPoint.getSchemaContext(), module);
+            final Module module = point.getMountPoint().getSchemaContext().findModuleByName(moduleName, revision);
+            return new SchemaExportContext(point.getMountPoint().getSchemaContext(), module);
         }
     }
 }
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.sal.rest.impl.test.providers;
+package org.opendaylight.restconf.jersey.providers;
 
 import static org.junit.Assert.assertNotNull;
 import static org.mockito.Mockito.mock;
@@ -24,25 +24,34 @@ import org.opendaylight.netconf.sal.rest.api.RestconfConstants;
 import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
 import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
-import org.opendaylight.restconf.jersey.providers.AbstractIdentifierAwareJaxRsProvider;
+import org.opendaylight.restconf.RestConnectorProvider;
+import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-public abstract class Draft17AbstractBodyReaderTest {
+abstract class AbstractBodyReaderTest {
 
     protected final static ControllerContext controllerContext = ControllerContext.getInstance();
     protected final MediaType mediaType;
     private static Field uriField;
     private static Field requestField;
+    protected final static DOMMountPointServiceHandler mountPointServiceHandler = mock(
+            DOMMountPointServiceHandler.class);
 
-    public Draft17AbstractBodyReaderTest() throws NoSuchFieldException,
-            SecurityException {
+    AbstractBodyReaderTest() throws NoSuchFieldException, IllegalAccessException {
         uriField = AbstractIdentifierAwareJaxRsProvider.class
                 .getDeclaredField("uriInfo");
         uriField.setAccessible(true);
+
         requestField = AbstractIdentifierAwareJaxRsProvider.class
                 .getDeclaredField("request");
         requestField.setAccessible(true);
+
         mediaType = getMediaType();
+
+        final Field mountPointServiceHandlerField = RestConnectorProvider.class.
+                getDeclaredField("mountPointServiceHandler");
+        mountPointServiceHandlerField.setAccessible(true);
+        mountPointServiceHandlerField.set(RestConnectorProvider.class, mountPointServiceHandler);
     }
 
     protected abstract MediaType getMediaType();
@@ -78,12 +87,6 @@ public abstract class Draft17AbstractBodyReaderTest {
         requestField.set(normalizedNodeProvider, request);
     }
 
-    protected static void checkMountPointNormalizedNodeContext(
-            final NormalizedNodeContext nnContext) {
-        checkNormalizedNodeContext(nnContext);
-        assertNotNull(nnContext.getInstanceIdentifierContext().getMountPoint());
-    }
-
     protected static void checkNormalizedNodeContext(
             final NormalizedNodeContext nnContext) {
         assertNotNull(nnContext.getData());
@@ -100,4 +103,10 @@ public abstract class Draft17AbstractBodyReaderTest {
         assertNotNull(patchContext.getInstanceIdentifierContext().getSchemaContext());
         assertNotNull(patchContext.getInstanceIdentifierContext().getSchemaNode());
     }
+
+    protected static void checkPATCHContextMountPoint(final PATCHContext patchContext) {
+        checkPATCHContext(patchContext);
+        assertNotNull(patchContext.getInstanceIdentifierContext().getMountPoint());
+        assertNotNull(patchContext.getInstanceIdentifierContext().getMountPoint().getSchemaContext());
+    }
 }
@@ -1,16 +1,19 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.controller.sal.rest.impl.test.providers;
+package org.opendaylight.restconf.jersey.providers;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import com.google.common.collect.Sets;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
@@ -21,9 +24,10 @@ import java.util.Collection;
 import javax.ws.rs.core.MediaType;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
+import org.opendaylight.controller.sal.rest.impl.test.providers.TestXmlBodyReader;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
-import org.opendaylight.restconf.jersey.providers.JsonNormalizedNodeBodyReader;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -34,9 +38,8 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-import com.google.common.collect.Sets;
 
-public class Draft17JsonBodyReaderTest extends Draft17AbstractBodyReaderTest {
+public class JsonBodyReaderTest extends AbstractBodyReaderTest {
 
     private final JsonNormalizedNodeBodyReader jsonBodyReader;
     private static SchemaContext schemaContext;
@@ -52,7 +55,7 @@ public class Draft17JsonBodyReaderTest extends Draft17AbstractBodyReaderTest {
         }
     }
 
-    public Draft17JsonBodyReaderTest() throws NoSuchFieldException, SecurityException {
+    public JsonBodyReaderTest() throws Exception {
         super();
         this.jsonBodyReader = new JsonNormalizedNodeBodyReader();
     }
@@ -70,6 +73,7 @@ public class Draft17JsonBodyReaderTest extends Draft17AbstractBodyReaderTest {
         testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc"));
         schemaContext = TestRestconfUtils.parseYangSources(testFiles);
         controllerContext.setSchemas(schemaContext);
+        when(mountPointServiceHandler.get()).thenReturn(mock(DOMMountPointService.class));
     }
 
     @Test
@@ -79,7 +83,7 @@ public class Draft17JsonBodyReaderTest extends Draft17AbstractBodyReaderTest {
         final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName());
         final String uri = "instance-identifier-module:cont";
         mockBodyReader(uri, this.jsonBodyReader, false);
-        final InputStream inputStream = Draft17JsonBodyReaderTest.class
+        final InputStream inputStream = JsonBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/json/jsondata.json");
         final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
@@ -96,7 +100,7 @@ public class Draft17JsonBodyReaderTest extends Draft17AbstractBodyReaderTest {
         final DataSchemaNode dataSchemaNodeOnPath = ((DataNodeContainer) dataSchemaNode).getDataChildByName(cont1QName);
         final String uri = "instance-identifier-module:cont/cont1";
         mockBodyReader(uri, this.jsonBodyReader, false);
-        final InputStream inputStream = Draft17JsonBodyReaderTest.class
+        final InputStream inputStream = JsonBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/json/json_sub_container.json");
         final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
@@ -112,7 +116,7 @@ public class Draft17JsonBodyReaderTest extends Draft17AbstractBodyReaderTest {
         final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName);
         final String uri = "instance-identifier-module:cont";
         mockBodyReader(uri, this.jsonBodyReader, true);
-        final InputStream inputStream = Draft17JsonBodyReaderTest.class
+        final InputStream inputStream = JsonBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/json/json_sub_container.json");
         final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/JsonPATCHBodyReaderMountPointTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/JsonPATCHBodyReaderMountPointTest.java
new file mode 100644 (file)
index 0000000..4bce4fd
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.restconf.jersey.providers;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import java.io.InputStream;
+import javax.ws.rs.core.MediaType;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.sal.rest.impl.test.providers.TestJsonBodyReader;
+import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class JsonPATCHBodyReaderMountPointTest extends AbstractBodyReaderTest {
+
+    private final JsonToPATCHBodyReader jsonPATCHBodyReader;
+    private static SchemaContext schemaContext;
+    private static final String MOUNT_POINT = "instance-identifier-module:cont/yang-ext:mount/";
+
+    public JsonPATCHBodyReaderMountPointTest() throws Exception {
+        super();
+        jsonPATCHBodyReader = new JsonToPATCHBodyReader();
+    }
+
+    @Override
+    protected MediaType getMediaType() {
+        return new MediaType(APPLICATION_JSON, null);
+    }
+
+    @BeforeClass
+    public static void initialization() {
+        schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext);
+
+        final DOMMountPointService mountPointService = mock(DOMMountPointService.class);
+        final DOMMountPoint mountPoint = mock(DOMMountPoint.class);
+
+        when(mountPointServiceHandler.get()).thenReturn(mountPointService);
+        when(mountPointService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountPoint));
+        when(mountPoint.getSchemaContext()).thenReturn(schemaContext);
+
+        controllerContext.setSchemas(schemaContext);
+    }
+
+    @Test
+    public void modulePATCHDataTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, jsonPATCHBodyReader, false);
+
+        final InputStream inputStream = TestJsonBodyReader.class
+                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdata.json");
+
+        final PATCHContext returnValue = jsonPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+
+    /**
+     * Test of successful PATCH consisting of create and delete PATCH operations.
+     */
+    @Test
+    public void modulePATCHCreateAndDeleteTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, jsonPATCHBodyReader, false);
+
+        final InputStream inputStream = TestJsonBodyReader.class
+                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataCreateAndDelete.json");
+
+        final PATCHContext returnValue = jsonPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+
+    /**
+     * Test trying to use PATCH create operation which requires value without value. Test should fail with
+     * {@link RestconfDocumentedException} with error code 400.
+     */
+    @Test
+    public void modulePATCHValueMissingNegativeTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, jsonPATCHBodyReader, false);
+
+        final InputStream inputStream = TestJsonBodyReader.class
+                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataValueMissing.json");
+
+        try {
+            jsonPATCHBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
+            fail("Test should return error 400 due to missing value node when attempt to invoke create operation");
+        } catch (final RestconfDocumentedException e) {
+            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
+        }
+    }
+
+    /**
+     * Test trying to use value with PATCH delete operation which does not support value. Test should fail with
+     * {@link RestconfDocumentedException} with error code 400.
+     */
+    @Test
+    public void modulePATCHValueNotSupportedNegativeTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, jsonPATCHBodyReader, false);
+
+        final InputStream inputStream = TestJsonBodyReader.class
+                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataValueNotSupported.json");
+
+        try {
+            jsonPATCHBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
+            fail("Test should return error 400 due to present value node when attempt to invoke delete operation");
+        } catch (final RestconfDocumentedException e) {
+            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
+        }
+    }
+
+    /**
+     * Test using PATCH when target is completely specified in request URI and thus target leaf contains only '/' sign.
+     */
+    @Test
+    public void modulePATCHCompleteTargetInURITest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont";
+        mockBodyReader(uri, jsonPATCHBodyReader, false);
+
+        final InputStream inputStream = TestJsonBodyReader.class
+                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataCompleteTargetInURI.json");
+
+        final PATCHContext returnValue = jsonPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+
+    /**
+     * Test of Yang PATCH merge operation on list. Test consists of two edit operations - replace and merge.
+     */
+    @Test
+    public void modulePATCHMergeOperationOnListTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, jsonPATCHBodyReader, false);
+
+        final InputStream inputStream = TestJsonBodyReader.class
+                .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnList.json");
+
+        final PATCHContext returnValue = jsonPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+
+    /**
+     * Test of Yang PATCH merge operation on container. Test consists of two edit operations - create and merge.
+     */
+    @Test
+    public void modulePATCHMergeOperationOnContainerTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont";
+        mockBodyReader(uri, jsonPATCHBodyReader, false);
+
+        final InputStream inputStream = TestJsonBodyReader.class
+                .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json");
+
+        final PATCHContext returnValue = jsonPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+}
@@ -6,27 +6,30 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.sal.rest.impl.test.providers;
+package org.opendaylight.restconf.jersey.providers;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import java.io.InputStream;
 import javax.ws.rs.core.MediaType;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.sal.rest.impl.test.providers.TestJsonBodyReader;
 import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.restconf.jersey.providers.JsonToPATCHBodyReader;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-public class TestDraft17JsonPATCHBodyReader extends Draft17AbstractBodyReaderTest {
+public class JsonPATCHBodyReaderTest extends AbstractBodyReaderTest {
 
     private final JsonToPATCHBodyReader jsonPATCHBodyReader;
     private static SchemaContext schemaContext;
 
-    public TestDraft17JsonPATCHBodyReader() throws NoSuchFieldException, SecurityException {
+    public JsonPATCHBodyReaderTest() throws Exception {
         super();
         jsonPATCHBodyReader = new JsonToPATCHBodyReader();
     }
@@ -39,6 +42,7 @@ public class TestDraft17JsonPATCHBodyReader extends Draft17AbstractBodyReaderTes
     @BeforeClass
     public static void initialization() {
         schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext);
+        when(mountPointServiceHandler.get()).thenReturn(mock(DOMMountPointService.class));
         controllerContext.setSchemas(schemaContext);
     }
 
@@ -1,16 +1,19 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.controller.sal.rest.impl.test.providers;
+package org.opendaylight.restconf.jersey.providers;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import com.google.common.collect.Sets;
 import java.io.File;
 import java.io.InputStream;
 import java.net.URI;
@@ -20,9 +23,9 @@ import java.util.Collection;
 import javax.ws.rs.core.MediaType;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
-import org.opendaylight.restconf.jersey.providers.XmlNormalizedNodeBodyReader;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -31,9 +34,8 @@ import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import com.google.common.collect.Sets;
 
-public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
+public class XmlBodyReaderTest extends AbstractBodyReaderTest {
 
     private final XmlNormalizedNodeBodyReader xmlBodyReader;
     private static SchemaContext schemaContext;
@@ -48,7 +50,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
         }
     }
 
-    public Draft17XmlBodyReaderTest() throws NoSuchFieldException, SecurityException {
+    public XmlBodyReaderTest() throws Exception {
         super();
         this.xmlBodyReader = new XmlNormalizedNodeBodyReader();
     }
@@ -65,6 +67,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
         testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc"));
         schemaContext = TestRestconfUtils.parseYangSources(testFiles);
         controllerContext.setSchemas(schemaContext);
+        when(mountPointServiceHandler.get()).thenReturn(mock(DOMMountPointService.class));
     }
 
     @Test
@@ -74,7 +77,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
         final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName());
         final String uri = "instance-identifier-module:cont";
         mockBodyReader(uri, this.xmlBodyReader, false);
-        final InputStream inputStream = Draft17XmlBodyReaderTest.class
+        final InputStream inputStream = XmlBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/xml/xmldata.xml");
         final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
@@ -91,7 +94,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
         final DataSchemaNode dataSchemaNodeOnPath = ((DataNodeContainer) dataSchemaNode).getDataChildByName(cont1QName);
         final String uri = "instance-identifier-module:cont/cont1";
         mockBodyReader(uri, this.xmlBodyReader, false);
-        final InputStream inputStream = Draft17XmlBodyReaderTest.class
+        final InputStream inputStream = XmlBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml");
         final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
@@ -107,7 +110,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
         final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName);
         final String uri = "instance-identifier-module:cont";
         mockBodyReader(uri, this.xmlBodyReader, true);
-        final InputStream inputStream = Draft17XmlBodyReaderTest.class
+        final InputStream inputStream = XmlBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml");
         final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
@@ -127,7 +130,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
                 .node(contAugmentQName);
         final String uri = "instance-identifier-module:cont";
         mockBodyReader(uri, this.xmlBodyReader, true);
-        final InputStream inputStream = Draft17XmlBodyReaderTest.class
+        final InputStream inputStream = XmlBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/xml/xml_augment_container.xml");
         final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
@@ -151,7 +154,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
                 .node(augmentChoice1QName).node(augChoice2II).node(augmentChoice2QName).node(containerQName);
         final String uri = "instance-identifier-module:cont";
         mockBodyReader(uri, this.xmlBodyReader, true);
-        final InputStream inputStream = Draft17XmlBodyReaderTest.class
+        final InputStream inputStream = XmlBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/xml/xml_augment_choice_container.xml");
         final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
@@ -175,7 +178,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
     @Test
     public void findFooContainerUsingNamespaceTest() throws Exception {
         mockBodyReader("", this.xmlBodyReader, true);
-        final InputStream inputStream = Draft17XmlBodyReaderTest.class
+        final InputStream inputStream = XmlBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/xml/xmlDataFindFooContainer.xml");
         final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
@@ -198,7 +201,7 @@ public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest {
     @Test
     public void findBarContainerUsingNamespaceTest() throws Exception {
         mockBodyReader("", this.xmlBodyReader, true);
-        final InputStream inputStream = Draft17XmlBodyReaderTest.class
+        final InputStream inputStream = XmlBodyReaderTest.class
                 .getResourceAsStream("/instanceidentifier/xml/xmlDataFindBarContainer.xml");
         final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null,
                 inputStream);
diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/XmlPATCHBodyReaderMountPointTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/XmlPATCHBodyReaderMountPointTest.java
new file mode 100644 (file)
index 0000000..9c6205a
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 org.opendaylight.restconf.jersey.providers;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import java.io.InputStream;
+import javax.ws.rs.core.MediaType;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.sal.rest.impl.test.providers.TestXmlBodyReader;
+import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class XmlPATCHBodyReaderMountPointTest extends AbstractBodyReaderTest {
+
+    private final XmlToPATCHBodyReader xmlPATCHBodyReader;
+    private static SchemaContext schemaContext;
+    private static final String MOUNT_POINT = "instance-identifier-module:cont/yang-ext:mount/";
+
+    public XmlPATCHBodyReaderMountPointTest() throws Exception {
+        super();
+        xmlPATCHBodyReader = new XmlToPATCHBodyReader();
+    }
+
+    @Override
+    protected MediaType getMediaType() {
+        return new MediaType(MediaType.APPLICATION_XML, null);
+    }
+
+    @BeforeClass
+    public static void initialization() {
+        schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext);
+
+        final DOMMountPointService mountPointService = mock(DOMMountPointService.class);
+        final DOMMountPoint mountPoint = mock(DOMMountPoint.class);
+
+        when(mountPointServiceHandler.get()).thenReturn(mountPointService);
+        when(mountPointService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountPoint));
+        when(mountPoint.getSchemaContext()).thenReturn(schemaContext);
+
+        controllerContext.setSchemas(schemaContext);
+    }
+
+    @Test
+    public void moduleDataTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, xmlPATCHBodyReader, false);
+        final InputStream inputStream = TestXmlBodyReader.class
+                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdata.xml");
+        final PATCHContext returnValue = xmlPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+
+    /**
+     * Test trying to use PATCH create operation which requires value without value. Error code 400 should be returned.
+     */
+    @Test
+    public void moduleDataValueMissingNegativeTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, xmlPATCHBodyReader, false);
+        final InputStream inputStream = TestXmlBodyReader.class
+                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataValueMissing.xml");
+        try {
+            xmlPATCHBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
+            fail("Test should return error 400 due to missing value node when attempt to invoke create operation");
+        } catch (final RestconfDocumentedException e) {
+            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
+        }
+    }
+
+    /**
+     * Test trying to use value with PATCH delete operation which does not support value. Error code 400 should be
+     * returned.
+     */
+    @Test
+    public void moduleDataNotValueNotSupportedNegativeTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, xmlPATCHBodyReader, false);
+        final InputStream inputStream = TestXmlBodyReader.class
+                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataValueNotSupported.xml");
+        try {
+            xmlPATCHBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
+            fail("Test should return error 400 due to present value node when attempt to invoke delete operation");
+        } catch (final RestconfDocumentedException e) {
+            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
+        }
+    }
+
+
+    /**
+     * Test of Yang PATCH with absolute target path.
+     */
+    @Test
+    public void moduleDataAbsoluteTargetPathTest() throws Exception {
+        final String uri = MOUNT_POINT;
+        mockBodyReader(uri, xmlPATCHBodyReader, false);
+        final InputStream inputStream = TestXmlBodyReader.class
+                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml");
+        final PATCHContext returnValue = xmlPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+
+    /**
+     * Test using PATCH when target is completely specified in request URI and thus target leaf contains only '/' sign.
+     */
+    @Test
+    public void modulePATCHCompleteTargetInURITest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont";
+        mockBodyReader(uri, xmlPATCHBodyReader, false);
+        final InputStream inputStream = TestXmlBodyReader.class
+                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataCompleteTargetInURI.xml");
+        final PATCHContext returnValue = xmlPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+
+    /**
+     * Test of Yang PATCH merge operation on list. Test consists of two edit operations - replace and merge.
+     */
+    @Test
+    public void moduleDataMergeOperationOnListTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
+        mockBodyReader(uri, xmlPATCHBodyReader, false);
+        final InputStream inputStream = TestXmlBodyReader.class
+                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml");
+        final PATCHContext returnValue = xmlPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+
+    /**
+     * Test of Yang PATCH merge operation on container. Test consists of two edit operations - create and merge.
+     */
+    @Test
+    public void moduleDataMergeOperationOnContainerTest() throws Exception {
+        final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont";
+        mockBodyReader(uri, xmlPATCHBodyReader, false);
+        final InputStream inputStream = TestXmlBodyReader.class
+                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml");
+        final PATCHContext returnValue = xmlPATCHBodyReader
+                .readFrom(null, null, null, mediaType, null, inputStream);
+        checkPATCHContextMountPoint(returnValue);
+    }
+}
@@ -6,26 +6,29 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.sal.rest.impl.test.providers;
+package org.opendaylight.restconf.jersey.providers;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import java.io.InputStream;
 import javax.ws.rs.core.MediaType;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.sal.rest.impl.test.providers.TestXmlBodyReader;
 import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.restconf.jersey.providers.XmlToPATCHBodyReader;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-public class TestDraft17XmlPATCHBodyReader extends Draft17AbstractBodyReaderTest {
+public class XmlPATCHBodyReaderTest extends AbstractBodyReaderTest {
 
     private final XmlToPATCHBodyReader xmlPATCHBodyReader;
     private static SchemaContext schemaContext;
 
-    public TestDraft17XmlPATCHBodyReader() throws NoSuchFieldException, SecurityException {
+    public XmlPATCHBodyReaderTest() throws Exception {
         super();
         xmlPATCHBodyReader = new XmlToPATCHBodyReader();
     }
@@ -36,8 +39,9 @@ public class TestDraft17XmlPATCHBodyReader extends Draft17AbstractBodyReaderTest
     }
 
     @BeforeClass
-    public static void initialization() throws NoSuchFieldException, SecurityException {
+    public static void initialization() {
         schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext);
+        when(mountPointServiceHandler.get()).thenReturn(mock(DOMMountPointService.class));
         controllerContext.setSchemas(schemaContext);
     }
 
index 998c99c3c53c1b5d32be8a274f8e4bf5f8251b9f..523625ad82b3329db21152591adf08ac5f2749f0 100644 (file)
@@ -556,7 +556,8 @@ public class RestconfModulesServiceTest {
     /**
      * Negative test of getting specific module supported by the mount point when specified mount point is not found
      * (it is not registered in <code>DOMMountPointService</code>). Test is expected to fail with
-     * <code>IllegalStateException</code>.
+     * <code>RestconfDocumentedException</code> and error type, error tag and error status code are compared to
+     * expected values.
      */
     @Test
     public void getModuleMountPointNotFoundNegativeTest() throws Exception {
@@ -564,14 +565,21 @@ public class RestconfModulesServiceTest {
         final RestconfModulesService modulesService = setupNormalMountPoint();
 
         // make test
-        this.thrown.expect(IllegalStateException.class);
-        modulesService.getModule(TEST_MODULE_BEHIND_NOT_REGISTERED_MOUNT_POINT, null);
+        try {
+            modulesService.getModule(TEST_MODULE_BEHIND_NOT_REGISTERED_MOUNT_POINT, null);
+            fail("Test should fail due to missing mount point");
+        } catch (final RestconfDocumentedException e) {
+            assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
+            assertEquals("Error tag is not correct", ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
+            assertEquals("Error code is not correct", 404, e.getErrors().get(0).getErrorTag().getStatusCode());
+        }
     }
 
     /**
      * Negative test of getting all modules supported by the mount point when specified mount point is not found (it
      * is not registered in <code>DOMMountPointService</code>). Test is expected to fail with
-     * <code>IllegalStateException</code>.
+     * <code>RestconfDocumentedException</code> and error type, error tag and error status code are compared to
+     * expected values.
      */
     @Test
     public void getModulesMountPointNotFoundNegativeTest() throws Exception {
@@ -579,7 +587,13 @@ public class RestconfModulesServiceTest {
         final RestconfModulesService modulesService = setupNormalMountPoint();
 
         // make test
-        this.thrown.expect(IllegalStateException.class);
-        modulesService.getModules(NOT_REGISTERED_MOUNT_POINT, null);
+        try {
+            modulesService.getModules(NOT_REGISTERED_MOUNT_POINT, null);
+            fail("Test should fail due to missing mount point");
+        } catch (final RestconfDocumentedException e) {
+            assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
+            assertEquals("Error tag is not correct", ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
+            assertEquals("Error code is not correct", 404, e.getErrors().get(0).getErrorTag().getStatusCode());
+        }
     }
 }
index 7efab9708a55cc55eca8fcb43340ae59d43b66c1..485b522cf26e6c08ec3f9b631dce48578a2e4fb3 100644 (file)
@@ -11,7 +11,9 @@ package org.opendaylight.restconf.restful.services.impl;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -31,11 +33,13 @@ import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
@@ -46,6 +50,7 @@ import org.opendaylight.netconf.sal.restconf.impl.PATCHStatusContext;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.restconf.RestConnectorProvider;
 import org.opendaylight.restconf.common.references.SchemaContextRef;
+import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler;
 import org.opendaylight.restconf.handlers.SchemaContextHandler;
 import org.opendaylight.restconf.handlers.TransactionChainHandler;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -54,6 +59,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -64,14 +70,18 @@ public class RestconfDataServiceImplTest {
     private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
 
     private ContainerNode buildBaseCont;
+    private ContainerNode buildBaseContConfig;
+    private ContainerNode buildBaseContOperational;
     private SchemaContextRef contextRef;
     private YangInstanceIdentifier iidBase;
     private DataSchemaNode schemaNode;
     private RestconfDataServiceImpl dataService;
     private QName baseQName;
-    private QName containerQname;
+    private QName containerPlayerQname;
     private QName leafQname;
-    private ContainerNode buildBaseContToReplace;
+    private ContainerNode buildPlayerCont;
+    private ContainerNode buildLibraryCont;
+    private MapNode buildPlaylistList;
 
     @Mock
     private TransactionChainHandler transactionChainHandler;
@@ -85,52 +95,87 @@ public class RestconfDataServiceImplTest {
     private DOMDataReadOnlyTransaction read;
     @Mock
     private DOMDataWriteTransaction write;
+    @Mock
+    private DOMMountPointServiceHandler mountPointServiceHandler;
+    @Mock
+    private DOMMountPointService mountPointService;
+    @Mock
+    private DOMMountPoint mountPoint;
+    @Mock
+    private DOMDataBroker mountDataBroker;
+    @Mock
+    private DOMTransactionChain transactionChain;
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
         baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
-        containerQname = QName.create(baseQName, "player");
+        containerPlayerQname = QName.create(baseQName, "player");
         leafQname = QName.create(baseQName, "gap");
-        LeafNode buildLeaf = Builders.leafBuilder()
+
+        final QName containerLibraryQName = QName.create(baseQName, "library");
+        final QName listPlaylistQName = QName.create(baseQName, "playlist");
+
+        final LeafNode buildLeaf = Builders.leafBuilder()
                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(leafQname))
                 .withValue(0.2)
                 .build();
 
-        ContainerNode buildPlayerCont = Builders.containerBuilder()
-                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(containerQname))
+        buildPlayerCont = Builders.containerBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(containerPlayerQname))
                 .withChild(buildLeaf)
                 .build();
+
+        buildLibraryCont = Builders.containerBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(containerLibraryQName))
+                .build();
+
+        buildPlaylistList = Builders.mapBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(listPlaylistQName))
+                .build();
+
         buildBaseCont = Builders.containerBuilder()
                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(baseQName))
                 .withChild(buildPlayerCont)
                 .build();
-        buildLeaf = Builders.leafBuilder()
-                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(leafQname))
-                .withValue(0.5)
-                .build();
-        buildPlayerCont = Builders.containerBuilder()
-                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(containerQname))
-                .withChild(buildLeaf)
+
+        // config contains one child the same as in operational and one additional
+        buildBaseContConfig = Builders.containerBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(baseQName))
+                .withChild(buildPlayerCont)
+                .withChild(buildLibraryCont)
                 .build();
-        buildBaseContToReplace = Builders.containerBuilder()
+
+        // operational contains one child the same as in config and one additional
+        buildBaseContOperational = Builders.containerBuilder()
                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(baseQName))
                 .withChild(buildPlayerCont)
+                .withChild(buildPlaylistList)
                 .build();
+
         iidBase = YangInstanceIdentifier.builder()
                 .node(baseQName)
                 .build();
 
         contextRef = new SchemaContextRef(TestRestconfUtils.loadSchemaContext(PATH_FOR_NEW_SCHEMA_CONTEXT));
         schemaNode = DataSchemaContextTree.from(contextRef.get()).getChild(iidBase).getDataSchemaNode();
-        MockitoAnnotations.initMocks(this);
+
         final SchemaContextHandler schemaContextHandler = new SchemaContextHandler();
 
         schemaContextHandler.onGlobalContextUpdated(contextRef.get());
-        dataService = new RestconfDataServiceImpl(schemaContextHandler, transactionChainHandler);
+        dataService = new RestconfDataServiceImpl(schemaContextHandler, transactionChainHandler, mountPointServiceHandler);
         doReturn(domTransactionChain).when(transactionChainHandler).get();
         doReturn(read).when(domTransactionChain).newReadOnlyTransaction();
         doReturn(readWrite).when(domTransactionChain).newReadWriteTransaction();
         doReturn(write).when(domTransactionChain).newWriteOnlyTransaction();
+        doReturn(mountPointService).when(mountPointServiceHandler).get();
+        doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(any(YangInstanceIdentifier.class));
+        doReturn(contextRef.get()).when(mountPoint).getSchemaContext();
+        doReturn(Optional.of(mountDataBroker)).when(mountPoint).getService(DOMDataBroker.class);
+        doReturn(transactionChain).when(mountDataBroker).createTransactionChain(any(TransactionChainListener.class));
+        doReturn(read).when(transactionChain).newReadOnlyTransaction();
+        doReturn(readWrite).when(transactionChain).newReadWriteTransaction();
     }
 
     @Test
@@ -145,6 +190,33 @@ public class RestconfDataServiceImplTest {
         assertEquals(buildBaseCont, ((NormalizedNodeContext) response.getEntity()).getData());
     }
 
+    /**
+     * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
+     * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.
+     */
+    @Test
+    public void testReadDataMountPoint() {
+        doReturn(new MultivaluedHashMap<String, String>()).when(uriInfo).getQueryParameters();
+        doReturn(Futures.immediateCheckedFuture(Optional.of(buildBaseContConfig))).when(read)
+                .read(LogicalDatastoreType.CONFIGURATION, iidBase);
+        doReturn(Futures.immediateCheckedFuture(Optional.of(buildBaseContOperational))).when(read)
+                .read(LogicalDatastoreType.OPERATIONAL, iidBase);
+
+        final Response response = dataService.readData(
+                "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", uriInfo);
+
+        assertNotNull(response);
+        assertEquals(200, response.getStatus());
+
+        // response must contain all child nodes from config and operational containers merged in one container
+        final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
+        assertTrue(data instanceof ContainerNode);
+        assertEquals(3, ((ContainerNode) data).getValue().size());
+        assertTrue(((ContainerNode) data).getChild(buildPlayerCont.getIdentifier()).isPresent());
+        assertTrue(((ContainerNode) data).getChild(buildLibraryCont.getIdentifier()).isPresent());
+        assertTrue(((ContainerNode) data).getChild(buildPlaylistList.getIdentifier()).isPresent());
+    }
+
     @Test(expected = RestconfDocumentedException.class)
     public void testReadDataNoData() {
         doReturn(new MultivaluedHashMap<String, String>()).when(uriInfo).getQueryParameters();
@@ -152,7 +224,7 @@ public class RestconfDataServiceImplTest {
                 iidBase);
         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read).read(LogicalDatastoreType.OPERATIONAL,
                 iidBase);
-        final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
+        dataService.readData("example-jukebox:jukebox", uriInfo);
     }
 
     @Test
@@ -237,16 +309,29 @@ public class RestconfDataServiceImplTest {
         assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
     }
 
+    /**
+     * Test of deleting data on mount point
+     */
+    @Test
+    public void testDeleteDataMountPoint() {
+        doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidBase);
+        doReturn(Futures.immediateCheckedFuture(null)).when(readWrite).submit();
+        doReturn(Futures.immediateCheckedFuture(true)).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidBase);
+        final Response response = dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox");
+        assertNotNull(response);
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+    }
+
     @Test
     public void testPatchData() throws Exception {
         final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(iidBase, schemaNode, null, contextRef.get());
         final List<PATCHEntity> entity = new ArrayList<>();
         final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(iidBase)
-                .node(containerQname)
+                .node(containerPlayerQname)
                 .node(leafQname)
                 .build();
         entity.add(new PATCHEntity("create data", "CREATE", iidBase, buildBaseCont));
-        entity.add(new PATCHEntity("replace data", "REPLACE", iidBase, buildBaseContToReplace));
+        entity.add(new PATCHEntity("replace data", "REPLACE", iidBase, buildBaseCont));
         entity.add(new PATCHEntity("delete data", "DELETE", iidleaf));
         final PATCHContext patch = new PATCHContext(iidContext, entity, "test patch id");
 
@@ -264,6 +349,35 @@ public class RestconfDataServiceImplTest {
         assertEquals("replace data", status.getEditCollection().get(1).getEditId());
     }
 
+    @Test
+    public void testPatchDataMountPoint() throws Exception {
+        final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(
+                iidBase, schemaNode, mountPoint, contextRef.get());
+        final List<PATCHEntity> entity = new ArrayList<>();
+        final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(iidBase)
+                .node(containerPlayerQname)
+                .node(leafQname)
+                .build();
+        entity.add(new PATCHEntity("create data", "CREATE", iidBase, buildBaseCont));
+        entity.add(new PATCHEntity("replace data", "REPLACE", iidBase, buildBaseCont));
+        entity.add(new PATCHEntity("delete data", "DELETE", iidleaf));
+        final PATCHContext patch = new PATCHContext(iidContext, entity, "test patch id");
+
+        doReturn(Futures.immediateCheckedFuture(Optional.of(buildBaseCont))).when(read)
+                .read(LogicalDatastoreType.CONFIGURATION, iidBase);
+        doNothing().when(write).put(LogicalDatastoreType.CONFIGURATION, iidBase, buildBaseCont);
+        doReturn(Futures.immediateCheckedFuture(null)).when(write).submit();
+        doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
+        doReturn(Futures.immediateCheckedFuture(null)).when(readWrite).submit();
+        doReturn(Futures.immediateCheckedFuture(false)).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidBase);
+        doReturn(Futures.immediateCheckedFuture(true)).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
+
+        final PATCHStatusContext status = dataService.patchData(patch, uriInfo);
+        assertTrue(status.isOk());
+        assertEquals(3, status.getEditCollection().size());
+        assertNull(status.getGlobalErrors());
+    }
+
     @Test
     public void testPatchDataDeleteNotExist() throws Exception {
         final Field handler = RestConnectorProvider.class.getDeclaredField("transactionChainHandler");
@@ -277,7 +391,7 @@ public class RestconfDataServiceImplTest {
         final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(iidBase, schemaNode, null, contextRef.get());
         final List<PATCHEntity> entity = new ArrayList<>();
         final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(iidBase)
-                .node(containerQname)
+                .node(containerPlayerQname)
                 .node(leafQname)
                 .build();
         entity.add(new PATCHEntity("create data", "CREATE", iidBase, buildBaseCont));
@@ -311,5 +425,4 @@ public class RestconfDataServiceImplTest {
         final String errorMessage = status.getEditCollection().get(2).getEditErrors().get(0).getErrorMessage();
         assertEquals("Data does not exist", errorMessage);
     }
-
 }
\ No newline at end of file
index 51270bc51b220858dd629739c2ef4724f3268e9d..a86d9ce7a84a23d26aa0a91e5a0ad60aeef849b2 100644 (file)
@@ -12,7 +12,7 @@ import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
-import com.google.common.base.Optional;
+
 import com.google.common.util.concurrent.Futures;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
@@ -38,7 +38,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
@@ -125,7 +124,7 @@ public class PostDataTransactionUtilTest {
         final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iid2, null, null, this.schema);
         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
 
-        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iid2);
+        doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
         final YangInstanceIdentifier.NodeIdentifier identifier = ((ContainerNode) ((SingletonSet) payload.getData().getValue()).iterator().next()).getIdentifier();
         final YangInstanceIdentifier node = payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
         doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
@@ -134,8 +133,8 @@ public class PostDataTransactionUtilTest {
         final TransactionVarsWrapper wrapper = new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, this.transactionChain);
         final Response response = PostDataTransactionUtil.postData(this.uriInfo, payload, wrapper, this.refSchemaCtx);
         assertEquals(201, response.getStatus());
-        verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
-        verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, (NormalizedNode<?, ?>) ((SingletonSet) payload.getData().getValue()).iterator().next());
+        verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
+        verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
     }
 
     @Test
@@ -143,7 +142,6 @@ public class PostDataTransactionUtilTest {
         final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iid2, null, null, this.schema);
         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildList);
 
-        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iid2);
         final MapNode data = (MapNode) payload.getData();
         final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier = data.getValue().iterator().next().getIdentifier();
         final YangInstanceIdentifier node = payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
@@ -162,7 +160,7 @@ public class PostDataTransactionUtilTest {
         final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iid2, null, null, this.schema);
         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
 
-        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iid2);
+        doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
         final YangInstanceIdentifier.NodeIdentifier identifier = ((ContainerNode) ((SingletonSet) payload.getData().getValue()).iterator().next()).getIdentifier();
         final YangInstanceIdentifier node = payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
         doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
@@ -172,8 +170,8 @@ public class PostDataTransactionUtilTest {
         final TransactionVarsWrapper wrapper = new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, this.transactionChain);
         final Response response = PostDataTransactionUtil.postData(this.uriInfo, payload, wrapper, this.refSchemaCtx);
         assertEquals(Response.Status.INTERNAL_SERVER_ERROR, response.getStatusInfo());
-        verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
-        verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, (NormalizedNode<?, ?>) ((SingletonSet) payload.getData().getValue()).iterator().next());
+        verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iid2);
+        verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
     }
 
 }
index a5380a3004a55b27d54d132efbe12807e348ed00..368456a97c486c54ae0b2cc2a1af4b89e3ef71f3 100644 (file)
@@ -32,6 +32,8 @@ import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContext;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.restconf.utils.RestconfConstants;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
@@ -43,13 +45,10 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
  * Unit tests for {@link ParserIdentifier}
  */
 public class ParserIdentifierTest {
-    // mount point identifier + expected result
+    // mount point identifier
     private static final String MOUNT_POINT_IDENT =
             "mount-point:mount-container/point-number" + "/" + RestconfConstants.MOUNT;
 
-    private static final String MOUNT_POINT_IDENT_RESULT =
-            "/(mount:point?revision=2016-06-02)mount-container/point-number";
-
     // invalid mount point identifier
     private static final String INVALID_MOUNT_POINT_IDENT =
             "mount-point:point-number" + "/" + RestconfConstants.MOUNT;
@@ -79,6 +78,8 @@ public class ParserIdentifierTest {
 
     // schema context with test modules
     private SchemaContext schemaContext;
+    // contains the same modules but it is different object (it can be compared with equals)
+    private SchemaContext schemaContextOnMountPoint;
 
     private static final String TEST_MODULE_NAME = "test-module";
     private static final String TEST_MODULE_REVISION = "2016-06-02";
@@ -89,8 +90,10 @@ public class ParserIdentifierTest {
     private DOMMountPointService mountPointService;
 
     // mock mount point and mount point service
-    @Mock DOMMountPoint mockMountPoint;
-    @Mock DOMMountPointService mockMountPointService;
+    @Mock
+    private DOMMountPoint mockMountPoint;
+    @Mock
+    private DOMMountPointService mockMountPointService;
 
     @Rule
     public final ExpectedException thrown = ExpectedException.none();
@@ -99,6 +102,7 @@ public class ParserIdentifierTest {
     public void setup() throws Exception {
         MockitoAnnotations.initMocks(this);
         schemaContext = TestRestconfUtils.loadSchemaContext("/parser-identifier");
+        schemaContextOnMountPoint = TestRestconfUtils.loadSchemaContext("/parser-identifier");
 
         // create and register mount point
         mountPoint = SimpleDOMMountPoint.create(
@@ -107,7 +111,7 @@ public class ParserIdentifierTest {
                         .node(QName.create("mount:point", "2016-06-02", "point-number"))
                         .build(),
                 ImmutableClassToInstanceMap.copyOf(Maps.newHashMap()),
-                schemaContext
+                schemaContextOnMountPoint
         );
 
         mountPointService = new DOMMountPointServiceImpl();
@@ -129,7 +133,7 @@ public class ParserIdentifierTest {
     @Test
     public void toInstanceIdentifierTest() {
         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
-                TEST_IDENT, schemaContext);
+                TEST_IDENT, schemaContext, Optional.absent());
 
         assertEquals("Returned not expected identifier",
                 TEST_IDENT_RESULT, context .getInstanceIdentifier().toString());
@@ -142,7 +146,7 @@ public class ParserIdentifierTest {
     @Test
     public void toInstanceIdentifierOtherModulesTest() {
         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
-                TEST_IDENT_OTHERS, schemaContext);
+                TEST_IDENT_OTHERS, schemaContext, Optional.absent());
 
         assertEquals("Returned not expected identifier",
                 TEST_IDENT_OTHERS_RESULT, context.getInstanceIdentifier().toString());
@@ -155,10 +159,16 @@ public class ParserIdentifierTest {
     @Test
     public void toInstanceIdentifierMountPointTest() {
         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
-                MOUNT_POINT_IDENT, schemaContext);
+                MOUNT_POINT_IDENT + "/" + TEST_IDENT, schemaContext, Optional.of(mountPointService));
 
         assertEquals("Returned not expected identifier",
-                MOUNT_POINT_IDENT_RESULT, context.getInstanceIdentifier().toString());
+                TEST_IDENT_RESULT.toString(), context.getInstanceIdentifier().toString());
+
+        assertEquals("Mount point not found",
+                mountPoint, context.getMountPoint());
+
+        assertEquals("Schema context from mount point expected",
+                schemaContextOnMountPoint, context.getSchemaContext());
     }
 
     /**
@@ -167,7 +177,8 @@ public class ParserIdentifierTest {
      */
     @Test
     public void toInstanceIdentifierNullIdentifierTest() {
-        final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(null, schemaContext);
+        final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
+                null, schemaContext, Optional.absent());
         assertEquals("Returned not expected identifier",
                 YangInstanceIdentifier.EMPTY, context.getInstanceIdentifier());
     }
@@ -179,7 +190,7 @@ public class ParserIdentifierTest {
     @Test
     public void toInstanceIdentifierNullSchemaContextNegativeTest() {
         thrown.expect(NullPointerException.class);
-        ParserIdentifier.toInstanceIdentifier(TEST_IDENT, null);
+        ParserIdentifier.toInstanceIdentifier(TEST_IDENT, null, Optional.absent());
     }
 
     /**
@@ -187,19 +198,8 @@ public class ParserIdentifierTest {
      */
     @Test
     public void toInstanceIdentifierEmptyIdentifierTest() {
-        final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier("", schemaContext);
-        assertEquals("Returned not expected identifier",
-                YangInstanceIdentifier.EMPTY, context.getInstanceIdentifier());
-    }
-
-    /**
-     * Api path can be empty. <code>YangInstanceIdentifier.EMPTY</code> is expected to be returned.
-     * Test when identifier contains {@link RestconfConstants#MOUNT}.
-     */
-    @Test
-    public void toInstanceIdentifierEmptyIdentifierMountPointTest() {
         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
-                "" + "/" + RestconfConstants.MOUNT, schemaContext);
+                "", schemaContext, Optional.absent());
         assertEquals("Returned not expected identifier",
                 YangInstanceIdentifier.EMPTY, context.getInstanceIdentifier());
     }
@@ -210,7 +210,7 @@ public class ParserIdentifierTest {
     @Test
     public void toInstanceIdentifierInvalidIdentifierNegativeTest() {
         thrown.expect(IllegalArgumentException.class);
-        ParserIdentifier.toInstanceIdentifier(INVALID_TEST_IDENT, schemaContext);
+        ParserIdentifier.toInstanceIdentifier(INVALID_TEST_IDENT, schemaContext, Optional.absent());
     }
 
     /**
@@ -220,7 +220,48 @@ public class ParserIdentifierTest {
     @Test
     public void toInstanceIdentifierMountPointInvalidIdentifierNegativeTest() {
         thrown.expect(IllegalArgumentException.class);
-        ParserIdentifier.toInstanceIdentifier(INVALID_MOUNT_POINT_IDENT, schemaContext);
+        ParserIdentifier.toInstanceIdentifier(INVALID_MOUNT_POINT_IDENT, schemaContext, Optional.of(mountPointService));
+    }
+
+    /**
+     * Negative test when <code>DOMMountPoint</code> cannot be found. Test is expected to fail with
+     * <code>RestconfDocumentedException</code> error type, error tag and error status code are
+     * compared to expected values.
+     */
+    @Test
+    public void toInstanceIdentifierMissingMountPointNegativeTest() {
+        try {
+            ParserIdentifier.toInstanceIdentifier(
+                    "" + "/" + RestconfConstants.MOUNT, schemaContext, Optional.of(mountPointService));
+            fail("Test should fail due to missing mount point");
+        } catch (final RestconfDocumentedException e) {
+            assertEquals("Not expected error type",
+                    RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
+            assertEquals("Not expected error tag",
+                    ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
+            assertEquals("Not expected error status code",
+                    404, e.getErrors().get(0).getErrorTag().getStatusCode());
+        }
+    }
+
+    /**
+     * Negative test when <code>{@link DOMMountPointService}</code> is absent. Test is expected to fail with
+     * <code>RestconfDocumentedException</code> error type, error tag and error status code are
+     * compared to expected values.
+     */
+    @Test
+    public void toInstanceIdentifierMissingMountPointServiceNegativeTest() {
+        try {
+            ParserIdentifier.toInstanceIdentifier(RestconfConstants.MOUNT, schemaContext, Optional.absent());
+            fail("Test should fail due to absent mount point service");
+        } catch (final RestconfDocumentedException e) {
+            assertEquals("Not expected error type",
+                    ErrorType.APPLICATION, e.getErrors().get(0).getErrorType());
+            assertEquals("Not expected error tag",
+                    ErrorTag.OPERATION_FAILED, e.getErrors().get(0).getErrorTag());
+            assertEquals("Not expected error status code",
+                    500, e.getErrors().get(0).getErrorTag().getStatusCode());
+        }
     }
 
     /**
index fd750b45407860841024ad5ba193f24720e1804d..abf560ea78fe9d44cffa322a12b62f456e295f09 100644 (file)
@@ -201,12 +201,12 @@ public class BaseYangSwaggerGenerator {
                         hasAddRootPostLink = true;
                     }
 
-                    addApis(node, apis, resourcePath, pathParams, schemaContext, true);
+                    addApis(node, apis, resourcePath, pathParams, schemaContext, true, m.getName());
                 }
 
                 pathParams = new ArrayList<>();
                 resourcePath = getDataStorePath("/operational/", context);
-                addApis(node, apis, resourcePath, pathParams, schemaContext, false);
+                addApis(node, apis, resourcePath, pathParams, schemaContext, false, m.getName());
             }
         }
 
@@ -243,7 +243,7 @@ public class BaseYangSwaggerGenerator {
             final Api apiForRootPostUri = new Api();
             apiForRootPostUri.setPath(resourcePath);
             apiForRootPostUri.setOperations(operationPost(module.getName() + MODULE_NAME_SUFFIX,
-                    module.getDescription(), module, pathParams, true));
+                    module.getDescription(), module, pathParams, true, ""));
             apis.add(apiForRootPostUri);
         }
     }
@@ -266,7 +266,7 @@ public class BaseYangSwaggerGenerator {
     }
 
     private void addApis(final DataSchemaNode node, final List<Api> apis, final String parentPath, final List<Parameter> parentPathParams, final SchemaContext schemaContext,
-                         final boolean addConfigApi) {
+                         final boolean addConfigApi, final String parentName) {
 
         final Api api = new Api();
         final List<Parameter> pathParams = new ArrayList<>(parentPathParams);
@@ -280,18 +280,18 @@ public class BaseYangSwaggerGenerator {
             final DataNodeContainer dataNodeContainer = (DataNodeContainer) node;
             childSchemaNodes = dataNodeContainer.getChildNodes();
         }
-        api.setOperations(operation(node, pathParams, addConfigApi, childSchemaNodes));
+        api.setOperations(operation(node, pathParams, addConfigApi, childSchemaNodes, parentName));
         apis.add(api);
 
         for (final DataSchemaNode childNode : childSchemaNodes) {
             if (childNode instanceof ListSchemaNode || childNode instanceof ContainerSchemaNode) {
                 // keep config and operation attributes separate.
                 if (childNode.isConfiguration() == addConfigApi) {
-                    addApis(childNode, apis, resourcePath, pathParams, schemaContext, addConfigApi);
+                    final String newParent = parentName + "/" + node.getQName().getLocalName();
+                    addApis(childNode, apis, resourcePath, pathParams, schemaContext, addConfigApi, newParent);
                 }
             }
         }
-
     }
 
     private boolean containsListOrContainer(final Iterable<DataSchemaNode> nodes) {
@@ -303,15 +303,15 @@ public class BaseYangSwaggerGenerator {
         return false;
     }
 
-    private List<Operation> operation(final DataSchemaNode node, final List<Parameter> pathParams, final boolean isConfig, final Iterable<DataSchemaNode> childSchemaNodes) {
+    private List<Operation> operation(final DataSchemaNode node, final List<Parameter> pathParams, final boolean isConfig,
+                                      final Iterable<DataSchemaNode> childSchemaNodes, final String parentName) {
         final List<Operation> operations = new ArrayList<>();
 
         final Get getBuilder = new Get(node, isConfig);
         operations.add(getBuilder.pathParams(pathParams).build());
 
         if (isConfig) {
-            final Put putBuilder = new Put(node.getQName().getLocalName(),
-                    node.getDescription());
+            final Put putBuilder = new Put(node.getQName().getLocalName(), node.getDescription(), parentName);
             operations.add(putBuilder.pathParams(pathParams).build());
 
             final Delete deleteBuilder = new Delete(node);
@@ -319,16 +319,17 @@ public class BaseYangSwaggerGenerator {
 
             if (containsListOrContainer(childSchemaNodes)) {
                 operations.addAll(operationPost(node.getQName().getLocalName(), node.getDescription(),
-                        (DataNodeContainer) node, pathParams, isConfig));
+                        (DataNodeContainer) node, pathParams, isConfig, parentName + "/"));
             }
         }
         return operations;
     }
 
-    private List<Operation> operationPost(final String name, final String description, final DataNodeContainer dataNodeContainer, final List<Parameter> pathParams, final boolean isConfig) {
+    private List<Operation> operationPost(final String name, final String description, final DataNodeContainer dataNodeContainer,
+                                          final List<Parameter> pathParams, final boolean isConfig, final String parentName) {
         final List<Operation> operations = new ArrayList<>();
         if (isConfig) {
-            final Post postBuilder = new Post(name, description, dataNodeContainer);
+            final Post postBuilder = new Post(name, parentName + name, description, dataNodeContainer);
             operations.add(postBuilder.pathParams(pathParams).build());
         }
         return operations;
index 5813f1e4def9ccb5eb7cee0452cc3071ac3f962b..24768e836864ff76261c9dff5a102153304cdd86 100644 (file)
@@ -122,7 +122,8 @@ public class ModelGenerator {
     }
 
     private void processModules(final Module module, final JSONObject models) throws JSONException {
-        createConcreteModelForPost(models, module.getName() + BaseYangSwaggerGenerator.MODULE_NAME_SUFFIX, createPropertiesForPost(module));
+        createConcreteModelForPost(models, module.getName() + BaseYangSwaggerGenerator.MODULE_NAME_SUFFIX,
+                createPropertiesForPost(module, module.getName()));
     }
 
     private void processContainersAndLists(final Module module, final JSONObject models, final SchemaContext schemaContext)
@@ -253,15 +254,15 @@ public class ModelGenerator {
         }
     }
 
-    private JSONObject processDataNodeContainer(final DataNodeContainer dataNode, final String moduleName, final JSONObject models,
+    private JSONObject processDataNodeContainer(final DataNodeContainer dataNode, final String parentName, final JSONObject models,
                                                 final boolean isConfig, final SchemaContext schemaContext) throws JSONException, IOException {
         if (dataNode instanceof ListSchemaNode || dataNode instanceof ContainerSchemaNode) {
             Preconditions.checkArgument(dataNode instanceof SchemaNode, "Data node should be also schema node");
             final Iterable<DataSchemaNode> containerChildren = dataNode.getChildNodes();
-            final JSONObject properties = processChildren(containerChildren, moduleName, models, isConfig, schemaContext);
-
-            final String nodeName = (isConfig ? OperationBuilder.CONFIG : OperationBuilder.OPERATIONAL)
-                    + ((SchemaNode) dataNode).getQName().getLocalName();
+            final String localName = ((SchemaNode) dataNode).getQName().getLocalName();
+            final JSONObject properties = processChildren(containerChildren, parentName + "/" + localName, models, isConfig, schemaContext);
+            final String nodeName = parentName + (isConfig ? OperationBuilder.CONFIG : OperationBuilder.OPERATIONAL)
+                    + localName;
 
             final JSONObject childSchema = getSchemaTemplate();
             childSchema.put(TYPE_KEY, OBJECT_TYPE);
@@ -271,8 +272,8 @@ public class ModelGenerator {
             models.put(nodeName, childSchema);
 
             if (isConfig) {
-                createConcreteModelForPost(models, ((SchemaNode) dataNode).getQName().getLocalName(),
-                        createPropertiesForPost(dataNode));
+                createConcreteModelForPost(models, localName,
+                        createPropertiesForPost(dataNode, parentName + "/" + localName));
             }
 
             return processTopData(nodeName, models, (SchemaNode) dataNode);
@@ -290,12 +291,13 @@ public class ModelGenerator {
         models.put(nodePostName, postSchema);
     }
 
-    private JSONObject createPropertiesForPost(final DataNodeContainer dataNodeContainer) throws JSONException {
+    private JSONObject createPropertiesForPost(final DataNodeContainer dataNodeContainer, final String parentName)
+            throws JSONException {
         final JSONObject properties = new JSONObject();
         for (final DataSchemaNode childNode : dataNodeContainer.getChildNodes()) {
             if (childNode instanceof ListSchemaNode || childNode instanceof ContainerSchemaNode) {
                 final JSONObject items = new JSONObject();
-                items.put(REF_KEY, "(config)" + childNode.getQName().getLocalName());
+                items.put(REF_KEY, parentName + "(config)" + childNode.getQName().getLocalName());
                 final JSONObject property = new JSONObject();
                 property.put(TYPE_KEY, childNode instanceof ListSchemaNode ? ARRAY_TYPE : OBJECT_TYPE);
                 property.put(ITEMS_KEY, items);
@@ -316,7 +318,7 @@ public class ModelGenerator {
     /**
      * Processes the nodes.
      */
-    private JSONObject processChildren(final Iterable<DataSchemaNode> nodes, final String moduleName, final JSONObject models,
+    private JSONObject processChildren(final Iterable<DataSchemaNode> nodes, final String parentName, final JSONObject models,
                                        final boolean isConfig, final SchemaContext schemaContext)
             throws JSONException, IOException {
         final JSONObject properties = new JSONObject();
@@ -328,20 +330,20 @@ public class ModelGenerator {
                     property = processLeafNode((LeafSchemaNode) node);
 
                 } else if (node instanceof ListSchemaNode) {
-                    property = processDataNodeContainer((ListSchemaNode) node, moduleName, models, isConfig,
+                    property = processDataNodeContainer((ListSchemaNode) node, parentName, models, isConfig,
                             schemaContext);
 
                 } else if (node instanceof LeafListSchemaNode) {
                     property = processLeafListNode((LeafListSchemaNode) node);
 
                 } else if (node instanceof ChoiceSchemaNode) {
-                    property = processChoiceNode((ChoiceSchemaNode) node, moduleName, models, schemaContext);
+                    property = processChoiceNode((ChoiceSchemaNode) node, parentName, models, schemaContext);
 
                 } else if (node instanceof AnyXmlSchemaNode) {
                     property = processAnyXMLNode((AnyXmlSchemaNode) node);
 
                 } else if (node instanceof ContainerSchemaNode) {
-                    property = processDataNodeContainer((ContainerSchemaNode) node, moduleName, models, isConfig,
+                    property = processDataNodeContainer((ContainerSchemaNode) node, parentName, models, isConfig,
                             schemaContext);
 
                 } else {
@@ -368,15 +370,15 @@ public class ModelGenerator {
         return props;
     }
 
-    private JSONObject processChoiceNode(final ChoiceSchemaNode choiceNode, final String moduleName, final JSONObject models,
-            final SchemaContext schemaContext) throws JSONException, IOException {
+    private JSONObject processChoiceNode(final ChoiceSchemaNode choiceNode, final String parentName, final JSONObject models,
+                                         final SchemaContext schemaContext) throws JSONException, IOException {
 
         final Set<ChoiceCaseNode> cases = choiceNode.getCases();
 
         final JSONArray choiceProps = new JSONArray();
         for (final ChoiceCaseNode choiceCase : cases) {
             final String choiceName = choiceCase.getQName().getLocalName();
-            final JSONObject choiceProp = processChildren(choiceCase.getChildNodes(), moduleName, models, schemaContext);
+            final JSONObject choiceProp = processChildren(choiceCase.getChildNodes(), parentName, models, schemaContext);
             final JSONObject choiceObj = new JSONObject();
             choiceObj.put(choiceName, choiceProp);
             choiceObj.put(TYPE_KEY, OBJECT_TYPE);
index 385a08b4852d3d286b0a8b7cd65d570fb5827498..d24636bfee060451de3cf7cda594036fbfc027e1 100644 (file)
@@ -58,12 +58,14 @@ public final class OperationBuilder {
     public static class Put {
         protected Operation spec;
         protected String nodeName;
+        protected String parentName;
         private static final String METHOD_NAME = "PUT";
 
-        public Put(final String nodeName, final String description) {
+        public Put(final String nodeName, final String description, final String parentName) {
             this.nodeName = nodeName;
+            this.parentName = parentName;
             spec = new Operation();
-            spec.setType(CONFIG + nodeName);
+            spec.setType(parentName + CONFIG + nodeName + TOP);
             spec.setNotes(description);
             spec.setConsumes(CONSUMES_PUT_POST);
         }
@@ -72,7 +74,7 @@ public final class OperationBuilder {
             final List<Parameter> parameters = new ArrayList<>(params);
             final Parameter payload = new Parameter();
             payload.setParamType("body");
-            payload.setType(CONFIG + nodeName + TOP);
+            payload.setType(parentName + CONFIG + nodeName + TOP);
             payload.setName(CONFIG + nodeName);
             parameters.add(payload);
             spec.setParameters(parameters);
@@ -91,8 +93,8 @@ public final class OperationBuilder {
         public static final String METHOD_NAME = "POST";
         private final DataNodeContainer dataNodeContainer;
 
-        public Post(final String nodeName, final String description, final DataNodeContainer dataNodeContainer) {
-            super(nodeName, description);
+        public Post(final String nodeName, final String parentName, final String description, final DataNodeContainer dataNodeContainer) {
+            super(nodeName, description, parentName.replace("_module", ""));
             this.dataNodeContainer = dataNodeContainer;
             spec.setType(CONFIG + nodeName + METHOD_NAME);
             spec.setConsumes(CONSUMES_PUT_POST);
@@ -112,14 +114,13 @@ public final class OperationBuilder {
                 if (node instanceof ListSchemaNode || node instanceof ContainerSchemaNode) {
                     final Parameter payload = new Parameter();
                     payload.setParamType("body");
-                    payload.setType(CONFIG + node.getQName().getLocalName() + TOP);
+                    payload.setType(parentName + CONFIG + node.getQName().getLocalName() + TOP);
                     payload.setName("**" + CONFIG + node.getQName().getLocalName());
                     parameters.add(payload);
                 }
             }
             spec.setParameters(parameters);
             return this;
-
         }
 
         public Post summary(final String summary) {
index d0a200bcde0f2e5e17d110f87e486fea07083997..020290508097db36cf21a3fb0f65fabd94d42b7b 100644 (file)
@@ -94,12 +94,14 @@ public class ApiDocGeneratorTest {
         final Api lstApi = findApi("/config/toaster2:lst/", doc);
         assertNotNull("Api /config/toaster2:lst/ wasn't found", lstApi);
         assertTrue("POST for cont1 in lst is missing",
-                findOperation(lstApi.getOperations(), "POST", "(config)lstPOST", "(config)lst1-TOP", "(config)cont1-TOP"));
+                findOperation(lstApi.getOperations(), "POST", "(config)lstPOST", "toaster2/lst(config)lst1-TOP",
+                        "toaster2/lst(config)cont1-TOP"));
 
         final Api cont1Api = findApi("/config/toaster2:lst/cont1/", doc);
         assertNotNull("Api /config/toaster2:lst/cont1/ wasn't found", cont1Api);
         assertTrue("POST for cont11 in cont1 is missing",
-                findOperation(cont1Api.getOperations(), "POST", "(config)cont1POST", "(config)cont11-TOP", "(config)lst11-TOP"));
+                findOperation(cont1Api.getOperations(), "POST", "(config)cont1POST", "toaster2/lst/cont1(config)cont11-TOP",
+                        "toaster2/lst/cont1(config)lst11-TOP"));
 
         // no POST URI
         final Api cont11Api = findApi("/config/toaster2:lst/cont1/cont11/", doc);
@@ -167,47 +169,47 @@ public class ApiDocGeneratorTest {
         final JSONObject models = doc.getModels();
         assertNotNull(models);
         try {
-            final JSONObject configLstTop = models.getJSONObject("(config)lst-TOP");
+            final JSONObject configLstTop = models.getJSONObject("toaster2(config)lst-TOP");
             assertNotNull(configLstTop);
 
-            containsReferences(configLstTop, "lst");
+            containsReferences(configLstTop, "lst", "toaster2(config)");
 
-            final JSONObject configLst = models.getJSONObject("(config)lst");
+            final JSONObject configLst = models.getJSONObject("toaster2(config)lst");
             assertNotNull(configLst);
 
-            containsReferences(configLst, "lst1");
-            containsReferences(configLst, "cont1");
+            containsReferences(configLst, "lst1", "toaster2/lst(config)");
+            containsReferences(configLst, "cont1", "toaster2/lst(config)");
 
-            final JSONObject configLst1Top = models.getJSONObject("(config)lst1-TOP");
+            final JSONObject configLst1Top = models.getJSONObject("toaster2/lst(config)lst1-TOP");
             assertNotNull(configLst1Top);
 
-            containsReferences(configLst1Top, "lst1");
+            containsReferences(configLst1Top, "lst1", "toaster2/lst(config)");
 
-            final JSONObject configLst1 = models.getJSONObject("(config)lst1");
+            final JSONObject configLst1 = models.getJSONObject("toaster2/lst(config)lst1");
             assertNotNull(configLst1);
 
-            final JSONObject configCont1Top = models.getJSONObject("(config)cont1-TOP");
+            final JSONObject configCont1Top = models.getJSONObject("toaster2/lst(config)cont1-TOP");
             assertNotNull(configCont1Top);
 
-            containsReferences(configCont1Top, "cont1");
-            final JSONObject configCont1 = models.getJSONObject("(config)cont1");
+            containsReferences(configCont1Top, "cont1", "toaster2/lst(config)");
+            final JSONObject configCont1 = models.getJSONObject("toaster2/lst(config)cont1");
             assertNotNull(configCont1);
 
-            containsReferences(configCont1, "cont11");
-            containsReferences(configCont1, "lst11");
+            containsReferences(configCont1, "cont11", "toaster2/lst/cont1(config)");
+            containsReferences(configCont1, "lst11", "toaster2/lst/cont1(config)");
 
-            final JSONObject configCont11Top = models.getJSONObject("(config)cont11-TOP");
+            final JSONObject configCont11Top = models.getJSONObject("toaster2/lst/cont1(config)cont11-TOP");
             assertNotNull(configCont11Top);
 
-            containsReferences(configCont11Top, "cont11");
-            final JSONObject configCont11 = models.getJSONObject("(config)cont11");
+            containsReferences(configCont11Top, "cont11", "toaster2/lst/cont1(config)");
+            final JSONObject configCont11 = models.getJSONObject("toaster2/lst/cont1(config)cont11");
             assertNotNull(configCont11);
 
-            final JSONObject configlst11Top = models.getJSONObject("(config)lst11-TOP");
+            final JSONObject configlst11Top = models.getJSONObject("toaster2/lst/cont1(config)lst11-TOP");
             assertNotNull(configlst11Top);
 
-            containsReferences(configlst11Top, "lst11");
-            final JSONObject configLst11 = models.getJSONObject("(config)lst11");
+            containsReferences(configlst11Top, "lst11", "toaster2/lst/cont1(config)");
+            final JSONObject configLst11 = models.getJSONObject("toaster2/lst/cont1(config)lst11");
             assertNotNull(configLst11);
         } catch (final JSONException e) {
             fail("JSONException wasn't expected");
@@ -218,7 +220,8 @@ public class ApiDocGeneratorTest {
     /**
      * Checks whether object {@code mainObject} contains in properties/items key $ref with concrete value.
      */
-    private void containsReferences(final JSONObject mainObject, final String childObject) throws JSONException {
+    private void containsReferences(final JSONObject mainObject, final String childObject, final String prefix)
+            throws JSONException {
         final JSONObject properties = mainObject.getJSONObject("properties");
         assertNotNull(properties);
 
@@ -229,7 +232,7 @@ public class ApiDocGeneratorTest {
         assertNotNull(itemsInNodeInProperties);
 
         final String itemRef = itemsInNodeInProperties.getString("$ref");
-        assertEquals("(config)" + childObject, itemRef);
+        assertEquals(prefix + childObject, itemRef);
     }
 
     @Test
@@ -354,12 +357,12 @@ public class ApiDocGeneratorTest {
     private void validateTosterDocContainsModulePrefixes(final ApiDeclaration doc) {
         final JSONObject topLevelJson = doc.getModels();
         try {
-            final JSONObject configToaster = topLevelJson.getJSONObject("(config)toaster");
+            final JSONObject configToaster = topLevelJson.getJSONObject("toaster2(config)toaster");
             assertNotNull("(config)toaster JSON object missing", configToaster);
             // without module prefix
             containsProperties(configToaster, "toasterSlot");
 
-            final JSONObject toasterSlot = topLevelJson.getJSONObject("(config)toasterSlot");
+            final JSONObject toasterSlot = topLevelJson.getJSONObject("toaster2/toaster(config)toasterSlot");
             assertNotNull("(config)toasterSlot JSON object missing", toasterSlot);
             // with module prefix
             containsProperties(toasterSlot, "toaster-augmented:slotInfo");