Merge "Modifying user roles via GUI"
authorAlessandro Boch <aboch@cisco.com>
Mon, 11 Nov 2013 23:44:29 +0000 (23:44 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 11 Nov 2013 23:44:30 +0000 (23:44 +0000)
278 files changed:
opendaylight/clustering/services_implementation/pom.xml
opendaylight/commons/logback_settings/pom.xml [new file with mode: 0644]
opendaylight/commons/logback_settings/src/main/resources/logback.xml [moved from opendaylight/commons/opendaylight/logback.xml with 100% similarity]
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/parent/logback.xml [deleted file]
opendaylight/commons/parent/space_and_tabs_checks.xml [deleted file]
opendaylight/config/config-api/pom.xml
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/DependencyResolver.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/stat/ConfigProvider.java [deleted file]
opendaylight/config/config-manager/pom.xml
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/ModulesHolder.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/TransactionHolder.java
opendaylight/config/config-persister-api/pom.xml
opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/storage/StorageAdapter.java
opendaylight/config/config-persister-file-adapter/pom.xml
opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java
opendaylight/config/config-util/pom.xml
opendaylight/config/logback-config/pom.xml
opendaylight/config/netty-threadgroup-config/pom.xml [new file with mode: 0644]
opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java [new file with mode: 0644]
opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleFactory.java [new file with mode: 0644]
opendaylight/config/netty-threadgroup-config/src/main/yang/nsos-netty-threadgroup.yang [new file with mode: 0644]
opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java [new file with mode: 0644]
opendaylight/config/pom.xml
opendaylight/config/threadpool-config-api/pom.xml
opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang
opendaylight/config/threadpool-config-impl/pom.xml
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/async/AsyncEventBusConfigBeanTest.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/SyncEventBusConfigBeanTest.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/TestingEventBusModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/FixedThreadPoolConfigBeanTest.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/TestingFixedThreadPoolModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/flexible/FlexibleThreadPoolConfigBeanTest.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/NamingThreadPoolFactoryConfigBeanTest.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/TestingNamingThreadPoolFactoryModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/ScheduledThreadPoolConfigBeanTest.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/TestingScheduledThreadPoolModule.java [new file with mode: 0644]
opendaylight/config/yang-jmx-generator-it/pom.xml
opendaylight/config/yang-jmx-generator-plugin/pom.xml
opendaylight/config/yang-jmx-generator/pom.xml
opendaylight/config/yang-store-api/pom.xml
opendaylight/config/yang-store-impl/pom.xml
opendaylight/config/yang-test/pom.xml
opendaylight/distribution/opendaylight/pom.xml
opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java
opendaylight/hosttracker/implementation/pom.xml
opendaylight/hosttracker/implementation/src/test/resources/logback.xml [deleted file]
opendaylight/hosttracker_new/implementation/pom.xml
opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/pom.xml
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/ClusteredDataStore.java [new file with mode: 0644]
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/Activator.java
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStore.java [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java [new file with mode: 0644]
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManager.java [new file with mode: 0644]
opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ActivatorTest.java
opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java [new file with mode: 0644]
opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java [new file with mode: 0644]
opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreTest.java [deleted file]
opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/meter-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-config.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-service/src/main/yang/group-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/meter-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java [moved from opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/ClassLoaderUtils.java with 56% similarity]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-config/pom.xml
opendaylight/md-sal/sal-binding-it/pom.xml
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java
opendaylight/md-sal/sal-binding-it/src/test/resources/logback.xml [moved from opendaylight/statisticsmanager/implementation/src/test/resources/logback.xml with 100% similarity]
opendaylight/md-sal/sal-common-impl/pom.xml
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountService.java
opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataConsumerServiceImpl.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend [moved from opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/HashMapDataStore.xtend with 50% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/MountProviderServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/InventoryUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfInventoryUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/XmlDocumentUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/JsonMapper.xtend [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionJsonReaderTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionRegExTest.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java with 51% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json
opendaylight/md-sal/sal-zeromq-connector/pom.xml
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChange.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Activator.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Message.java [moved from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Message.java with 65% similarity]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/RouteIdentifierImpl.java [moved from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RouteIdentifierImpl.java with 73% similarity]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/RpcRequestImpl.java [moved from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcRequestImpl.java with 70% similarity]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/ZeroMqRpcRouter.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Activator.java [deleted file]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcReplyImpl.java [deleted file]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/ZeroMqRpcRouter.java [deleted file]
opendaylight/md-sal/samples/toaster-it/pom.xml
opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java
opendaylight/md-sal/samples/toaster-it/src/test/resources/logback.xml [moved from opendaylight/clustering/services_implementation/src/test/resources/logback.xml with 99% similarity]
opendaylight/md-sal/test/sal-rest-connector-it/pom.xml [new file with mode: 0644]
opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java [new file with mode: 0644]
opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/exam.properties [new file with mode: 0644]
opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/logback.xml [moved from opendaylight/switchmanager/implementation/src/test/resources/logback.xml with 96% similarity]
opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/tomcat-server.xml [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/pom.xml
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-persister-impl/pom.xml
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/NoOpStorageAdapter.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PersisterImpl.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/PersisterImplTest.java
opendaylight/netconf/netconf-api/pom.xml
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSession.java
opendaylight/netconf/netconf-client/pom.xml
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java
opendaylight/netconf/netconf-client/src/main/resources/client_hello.xml
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-impl/src/main/resources/server_hello.xml
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-it/pom.xml
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-mapping-api/pom.xml
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java
opendaylight/netconf/netconf-util/pom.xml
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml [new file with mode: 0644]
opendaylight/netconf/pom.xml
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFloatingIPInterface.java
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronNetworkInterface.java
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronPortInterface.java
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronRouterInterface.java
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSubnetInterface.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPAware.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPCRUD.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkAware.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkCRUD.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortAware.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortCRUD.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterAware.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterCRUD.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetAware.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetCRUD.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFloatingIP.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronNetwork.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_Interface.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_NetworkReference.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_HostRoute.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_IPAllocationPool.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/Neutron_IPs.java
opendaylight/northbound/hosttracker/enunciate.xml
opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java
opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPRequest.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworkRequest.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortRequest.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRouterRequest.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetRequest.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java
opendaylight/protocol_plugins/openflow/pom.xml
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/MessageReadWriteService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SecureMessageReadWriteService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java [new file with mode: 0644]
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SupportedFlowActions.java [new file with mode: 0644]
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java
opendaylight/statisticsmanager/implementation/pom.xml
opendaylight/switchmanager/implementation/pom.xml
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java
opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java
pom.xml
third-party/com.siemens.ct.exi/pom.xml [new file with mode: 0644]

index e4bdc218dbc2c9a1f96812afa587c6476d14c5fa..ab75eb8dd1414f777c41adb985ac475097c0cd2b 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/opendaylight/commons/logback_settings/pom.xml b/opendaylight/commons/logback_settings/pom.xml
new file mode 100644 (file)
index 0000000..c1ce36e
--- /dev/null
@@ -0,0 +1,17 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>commons.logback_settings</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+    <tag>HEAD</tag>
+  </scm>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.parent</artifactId>
+    <version>1.0.1-SNAPSHOT</version>
+    <relativePath>../parent</relativePath>
+  </parent>
+</project>
index 8ff25c35def4f93e9b0d1a98b81f21e5673b96bc..2a818067cec223101b907c90a79d4a4f84cea622 100644 (file)
@@ -76,8 +76,8 @@
     <yangtools.binding.version>0.6.0-SNAPSHOT</yangtools.binding.version>
     <!--versions for bits of the controller -->
     <controller.version>0.4.1-SNAPSHOT</controller.version>
-    <config.version>0.2.2-SNAPSHOT</config.version>
-    <netconf.version>0.2.2-SNAPSHOT</netconf.version>
+    <config.version>0.2.3-SNAPSHOT</config.version>
+    <netconf.version>0.2.3-SNAPSHOT</netconf.version>
     <mdsal.version>1.0-SNAPSHOT</mdsal.version>
     <containermanager.version>0.5.1-SNAPSHOT</containermanager.version>
     <switchmanager.api.version>0.6.1-SNAPSHOT</switchmanager.api.version>
     <java.version.target>1.7</java.version.target>
     <!-- enforcer version -->
     <enforcer.version>1.3.1</enforcer.version>
+    <exi.version>0.9.2-SNAPSHOT</exi.version>
   </properties>
 
   <dependencyManagement>
         <artifactId>org.openflow.openflowj</artifactId>
         <version>1.0.2</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.thirdparty</groupId>
+        <artifactId>exificient</artifactId>
+        <version>${exi.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller.thirdparty</groupId>
         <artifactId>com.sun.jersey.jersey-servlet</artifactId>
         <artifactId>jolokia-osgi</artifactId>
         <version>${jolokia.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>commons.logback_settings</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
 
   <build>
     <plugins>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>properties-maven-plugin</artifactId>
-        <version>${propertymavenplugin.version}</version>
-        <executions>
-          <execution>
-            <goals>
-              <goal>set-system-properties</goal>
-            </goals>
-            <configuration>
-              <properties>
-                <property>
-                  <name>logback.configurationFile</name>
-                  <value>${project.parent.basedir}/logback.xml</value>
-                </property>
-              </properties>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
-        <artifactId>maven-java-formatter-plugin</artifactId>
-        <version>0.3.1</version>
-        <configuration>
-          <compilerSource>1.6</compilerSource>
-          <compilerCompliance>1.6</compilerCompliance>
-          <compilerTargetPlatform>1.6</compilerTargetPlatform>
-          <configFile>${project.parent.basedir}/sun_coding_style.xml</configFile>
-        </configuration>
-      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
         <version>${failsafe.version}</version>
         <configuration>
           <argLine>${testvm.argLine}</argLine>
+          <systemProperties>
+            <property>
+              <name>logback.configurationFile</name>
+              <value>logback.xml</value>
+            </property>
+          </systemProperties>
         </configuration>
         <executions>
           <execution>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <version>${surefire.version}</version>
+        <configuration>
+          <systemProperties>
+            <property>
+              <name>logback.configurationFile</name>
+              <value>logback.xml</value>
+            </property>
+          </systemProperties>
+        </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
               </goals>
             </execution>
           </executions>
+          <dependencies>
+            <dependency>
+              <groupId>org.opendaylight.controller</groupId>
+              <artifactId>commons.logback_settings</artifactId>
+              <version>0.0.1-SNAPSHOT</version>
+            </dependency>
+          </dependencies>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
diff --git a/opendaylight/commons/parent/logback.xml b/opendaylight/commons/parent/logback.xml
deleted file mode 100644 (file)
index 05e6075..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<configuration scan="true">
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-
-  <root level="error">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/opendaylight/commons/parent/space_and_tabs_checks.xml b/opendaylight/commons/parent/space_and_tabs_checks.xml
deleted file mode 100644 (file)
index 49a5802..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0"?>\r
-<!DOCTYPE module PUBLIC\r
-    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"\r
-    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">\r
-\r
-<module name="Checker">\r
-    <module name="FileTabCharacter">\r
-        <property name="eachLine" value="true"/>\r
-    </module>\r
-\r
-    <module name="RegexpSingleline">\r
-        <!-- \s matches whitespace character, $ matches end of line. -->\r
-        <property name="format" value="\s+$"/>\r
-        <property name="message" value="Line has trailing spaces."/>\r
-    </module>\r
-\r
-</module>\r
index 394831d25263d08e816b9b429c843e6e574c1c44..d733834b438aee738b234d93b7814999c5817d8c 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
 
     <artifactId>config-api</artifactId>
@@ -49,7 +49,6 @@
                             org.opendaylight.controller.config.api.jmx,
                             org.opendaylight.controller.config.api.jmx.constants,
                             org.opendaylight.controller.config.api.runtime,
-                            org.opendaylight.controller.config.stat,
                         </Export-Package>
                     </instructions>
                 </configuration>
index 7cac1060ba6357fd1cdd4e8bc26d4d9bf7118b52..39845454ef5ed17d108255dbf5e47f5b774ab93b 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.config.api;
 import javax.management.ObjectName;
 
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.yangtools.concepts.Identifiable;
 
 /**
  * Each new {@link org.opendaylight.controller.config.spi.Module} can receive
@@ -18,7 +19,7 @@ import org.opendaylight.controller.config.api.annotations.AbstractServiceInterfa
  *
  * @see org.opendaylight.controller.config.spi.Module
  */
-public interface DependencyResolver {
+public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
 
     /**
      * To be used during validation phase to validate serice interface of
diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/stat/ConfigProvider.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/stat/ConfigProvider.java
deleted file mode 100644 (file)
index 3a81061..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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
- */
-
-package org.opendaylight.controller.config.stat;
-
-import org.osgi.framework.BundleContext;
-
-/**
- * Subset of {@link org.osgi.framework.BundleContext}
- */
-public interface ConfigProvider {
-    /**
-     * Returns the value of the specified property. If the key is not found in
-     * the Framework properties, the system properties are then searched. The
-     * method returns {@code null} if the property is not found.
-     *
-     * <p>
-     * All bundles must have permission to read properties whose names start
-     * with &quot;org.osgi.&quot;.
-     *
-     * @param key
-     *            The name of the requested property.
-     * @return The value of the requested property, or {@code null} if the
-     *         property is undefined.
-     * @throws SecurityException
-     *             If the caller does not have the appropriate
-     *             {@code PropertyPermission} to read the property, and the Java
-     *             Runtime Environment supports permissions.
-     */
-    String getProperty(String key);
-
-    public static class ConfigProviderImpl implements ConfigProvider {
-        private final BundleContext context;
-
-        public ConfigProviderImpl(BundleContext context) {
-            this.context = context;
-        }
-
-        @Override
-        public String getProperty(String key) {
-            return context.getProperty(key);
-        }
-
-        @Override
-        public String toString() {
-            return "ConfigProviderImpl{" + "context=" + context + '}';
-        }
-    }
-
-}
index 138f5007a7518d595d2909fcbf6027207174b545..b55b5da8a20735364c0d647aa0955ec52775a6b4 100644 (file)
@@ -4,7 +4,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>config-manager</artifactId>
index 343d45a236e99bd9208ff4846d13c1e0a43bc571..3f569ae324ebebe51cf0550aa74b21bbcc8d58b8 100644 (file)
@@ -138,8 +138,10 @@ class ConfigTransactionControllerImpl implements
         for (ModuleFactory moduleFactory : toBeAdded) {
             Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext);
             for (Module module : defaultModules) {
+                // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
+                DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
                 try {
-                    putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null);
+                    putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver);
                 } catch (InstanceAlreadyExistsException e) {
                     throw new IllegalStateException(e);
                 }
@@ -179,7 +181,7 @@ class ConfigTransactionControllerImpl implements
                     "Error while copying old configuration from %s to %s",
                     oldConfigBeanInfo, moduleFactory), e);
         }
-        putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo);
+        putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver);
     }
 
     @Override
@@ -196,19 +198,24 @@ class ConfigTransactionControllerImpl implements
         DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
         Module module = moduleFactory.createModule(instanceName, dependencyResolver, bundleContext);
         return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
-                moduleFactory, null);
+                moduleFactory, null, dependencyResolver);
     }
 
     private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
             ModuleIdentifier moduleIdentifier, Module module,
             ModuleFactory moduleFactory,
-            @Nullable ModuleInternalInfo maybeOldConfigBeanInfo)
+            @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver)
             throws InstanceAlreadyExistsException {
+
         logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
         if (moduleIdentifier.equals(module.getIdentifier())==false) {
             throw new IllegalStateException("Incorrect name reported by module. Expected "
              + moduleIdentifier + ", got " + module.getIdentifier());
         }
+        if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false ) {
+            throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected "
+                    + moduleIdentifier + ", got " + dependencyResolver.getIdentifier());
+        }
         DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper(
                 module, moduleIdentifier, transactionIdentifier,
                 readOnlyAtomicBoolean, transactionsMBeanServer,
@@ -224,8 +231,6 @@ class ConfigTransactionControllerImpl implements
                 maybeOldConfigBeanInfo, transactionModuleJMXRegistration);
 
         dependencyResolverManager.put(moduleInternalTransactionalInfo);
-        // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
-        dependencyResolverManager.getOrCreate(moduleIdentifier);
         return writableON;
     }
 
index f817b41c5f929b18f0ff3dfcd7b89003dbd2ea93..065a0f843f501cdb7e2a4230c9cc0b72caf31f3c 100644 (file)
@@ -7,15 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import static java.lang.String.format;
-
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.ObjectName;
-
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
@@ -25,7 +16,14 @@ import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.concepts.Identifiable;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.ObjectName;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.lang.String.format;
 
 /**
  * Protect {@link org.opendaylight.controller.config.spi.Module#getInstance()}
@@ -33,7 +31,7 @@ import org.opendaylight.yangtools.concepts.Identifiable;
  * during validation. Tracks dependencies for ordering purposes.
  */
 final class DependencyResolverImpl implements DependencyResolver,
-       Identifiable<ModuleIdentifier>, Comparable<DependencyResolverImpl> {
+       Comparable<DependencyResolverImpl> {
     private final ModulesHolder modulesHolder;
     private final ModuleIdentifier name;
     private final TransactionStatus transactionStatus;
@@ -47,11 +45,6 @@ final class DependencyResolverImpl implements DependencyResolver,
         this.modulesHolder = modulesHolder;
     }
 
-    @Deprecated
-    public ModuleIdentifier getName() {
-        return name;
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -177,7 +170,7 @@ final class DependencyResolverImpl implements DependencyResolver,
         int maxDepth = 0;
         LinkedHashSet<ModuleIdentifier> chainForDetectingCycles2 = new LinkedHashSet<>(
                 chainForDetectingCycles);
-        chainForDetectingCycles2.add(impl.getName());
+        chainForDetectingCycles2.add(impl.getIdentifier());
         for (ModuleIdentifier dependencyName : impl.dependencies) {
             DependencyResolverImpl dependentDRI = manager
                     .getOrCreate(dependencyName);
index 28f2e37ec187b5aaec8c18b98b568b4f47cc6dac..dea78c8b155d9f125783232bd7c5b531e673bce0 100644 (file)
@@ -7,15 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.JmxAttribute;
@@ -26,6 +17,14 @@ import org.opendaylight.controller.config.manager.impl.TransactionStatus;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Holds information about modules being created and destroyed within this
  * transaction. Observes usage of DependencyResolver within modules to figure
@@ -80,7 +79,7 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
         List<ModuleIdentifier> result = new ArrayList<>(
                 moduleIdentifiersToDependencyResolverMap.size());
         for (DependencyResolverImpl dri : getAllSorted()) {
-            ModuleIdentifier driName = dri.getName();
+            ModuleIdentifier driName = dri.getIdentifier();
             result.add(driName);
         }
         return result;
index f70c4bf57904b72b2e29d8071f671b2ea4042af5..6bbd7875a94b1fa8a1d4dd8662b2a9cb835420ea 100644 (file)
@@ -7,18 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
@@ -28,6 +16,17 @@ import org.opendaylight.controller.config.manager.impl.ModuleInternalTransaction
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Represents modules to be committed.
  */
@@ -117,8 +116,7 @@ class ModulesHolder implements TransactionHolder {
             throws InstanceAlreadyExistsException {
         if (commitMap.containsKey(moduleIdentifier)) {
             throw new InstanceAlreadyExistsException(
-                    "There is an instance registered with name "
-                            + moduleIdentifier);
+                    "There is an instance registered with name " + moduleIdentifier);
         }
     }
 
index f81e747f620950f71a1e0a217ee52e73d4b068fb..8f05ed75ae74a64d4c45c42969ee32d235880395 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.Map;
-
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.manager.impl.CommitInfo;
@@ -18,6 +14,9 @@ import org.opendaylight.controller.config.manager.impl.ModuleInternalTransaction
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.management.InstanceAlreadyExistsException;
+import java.util.Map;
+
 interface TransactionHolder {
     CommitInfo toCommitInfo();
 
index 504c295639cb630d6a1947f0263c158f1f95f74d..51f8c0b8257255d73b5e6d73643a99588a90fdce 100644 (file)
@@ -4,7 +4,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>config-persister-api</artifactId>
@@ -33,7 +33,6 @@
                             com.google.common.base,
                             org.w3c.dom,
                             org.osgi.framework,
-                            org.opendaylight.controller.config.stat
                         </Import-Package>
                         <Export-Package>
                             org.opendaylight.controller.config.persist.api,
index 447504027e1ba95b7c9987c658e268762e5accc4..9daf4a132502cb1c917b35065a2361fdcbeea552 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.controller.config.persist.api.storage;
 
 import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
 
 /**
  * Plugins for {@link org.opendaylight.controller.config.persist.api.Persister}
@@ -17,6 +17,6 @@ import org.opendaylight.controller.config.stat.ConfigProvider;
  */
 public interface StorageAdapter extends Persister {
 
-    void setProperties(ConfigProvider configProvider);
+    void setProperties(BundleContext bundleContext);
 
 }
index a5c026da27e2e60b3a44df72b9b1b6f3bf073ff3..b243eadcc66ff50776ba8c00561e38bcaa649864 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>config-persister-file-adapter</artifactId>
@@ -80,7 +80,6 @@
                             javax.xml.transform.stream,
                             org.apache.commons.lang3,
                             org.opendaylight.controller.config.persist.api,
-                            org.opendaylight.controller.config.stat,
                             org.opendaylight.controller.config.persist.api.storage,
                             org.slf4j,
                             org.w3c.dom,
index a866743b0dee6b2e11e3b85529e1b54bb1073bd5..775fb1f88192cb697b38e712716851c3a246e974 100644 (file)
@@ -16,7 +16,7 @@ import com.google.common.collect.Sets;
 import com.google.common.io.Files;
 import org.apache.commons.lang3.StringUtils;
 import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.SAXException;
@@ -55,8 +55,8 @@ public class FileStorageAdapter implements StorageAdapter {
     private File storage;
 
     @Override
-    public void setProperties(ConfigProvider configProvider) {
-        File storage = extractStorageFileFromProperties(configProvider);
+    public void setProperties(BundleContext bundleContext) {
+        File storage = extractStorageFileFromProperties(bundleContext);
         logger.debug("Using file {}", storage.getAbsolutePath());
         // Create file if it does not exist
         File parentFile = storage.getAbsoluteFile().getParentFile();
@@ -92,12 +92,12 @@ public class FileStorageAdapter implements StorageAdapter {
         numberOfStoredBackups = numberOfBackups;
     }
 
-    private static File extractStorageFileFromProperties(ConfigProvider configProvider) {
-        String fileStorageProperty = configProvider.getProperty(FILE_STORAGE_PROP);
+    private static File extractStorageFileFromProperties(BundleContext bundleContext) {
+        String fileStorageProperty = bundleContext.getProperty(FILE_STORAGE_PROP);
         Preconditions.checkNotNull(fileStorageProperty, "Unable to find " + FILE_STORAGE_PROP
-                + " in received properties :" + configProvider);
+                + " in received context :" + bundleContext);
         File result = new File(fileStorageProperty);
-        String numberOfBAckupsAsString = configProvider.getProperty(NUMBER_OF_BACKUPS);
+        String numberOfBAckupsAsString = bundleContext.getProperty(NUMBER_OF_BACKUPS);
         if (numberOfBAckupsAsString != null) {
             numberOfStoredBackups = Integer.valueOf(numberOfBAckupsAsString);
         } else {
index bf681b1065f60224d0d0f83396473e2385328497..206184ccce0b6f2f3209fa0a2c4a728f986eefa0 100644 (file)
@@ -4,7 +4,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>config-util</artifactId>
index 9abc8ccb637dd4a9d873f79c895b4111b70d6cd0..b63f3298c1af9602674894915664499bcb9d038f 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>config-subsystem</artifactId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
     <artifactId>logback-config</artifactId>
     <name>${project.artifactId}</name>
diff --git a/opendaylight/config/netty-threadgroup-config/pom.xml b/opendaylight/config/netty-threadgroup-config/pom.xml
new file mode 100644 (file)
index 0000000..ef63fce
--- /dev/null
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-subsystem</artifactId>
+        <version>0.2.3-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>netty-threadgroup-config</artifactId>
+    <description>Configuration Wrapper around netty's event group</description>
+    <packaging>bundle</packaging>
+    <name>${project.artifactId}</name>
+    <prerequisites>
+        <maven>3.0.4</maven>
+    </prerequisites>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>threadpool-config-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+
+        <!--test dependencies -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-manager</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-manager</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-util</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.bgpcep</groupId>
+            <artifactId>mockito-configuration</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+            </plugin>
+
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>2.3.7</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Export-Package>
+                        </Export-Package>
+                        <Import-Package>
+                            com.google.common.base,
+                            io.netty.channel.nio,
+                            org.opendaylight.controller.config.yang.threadpool,
+                            io.netty.util.concurrent,
+                            org.opendaylight.controller.config.api,
+                            org.opendaylight.controller.config.api.annotations,
+                            org.opendaylight.controller.config.api.runtime,
+                            org.opendaylight.controller.config.spi,
+                            org.slf4j,
+                            org.osgi.framework
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <distributionManagement>
+        <site>
+            <id>${project.artifactId}</id>
+            <name>NETTY-THREADGROUP-CONFIG Module site</name>
+            <url>${basedir}/target/site/${project.artifactId}</url>
+        </site>
+    </distributionManagement>
+
+</project>
diff --git a/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java b/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java
new file mode 100644 (file)
index 0000000..fd6b216
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+* Generated file
+
+* Generated from: yang module name: nsos-threadpool  yang module local name: netty-threadgroup-fixed
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Nov 08 08:31:45 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.netty.threadgroup;
+
+import com.google.common.base.Preconditions;
+import io.netty.channel.nio.NioEventLoopGroup;
+
+/**
+*
+*/
+public final class NettyThreadgroupModule extends org.opendaylight.controller.config.yang.netty.threadgroup.AbstractNettyThreadgroupModule
+{
+    public NettyThreadgroupModule(org.opendaylight.controller.config.api.ModuleIdentifier name, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(name, dependencyResolver);
+    }
+
+    public NettyThreadgroupModule(org.opendaylight.controller.config.api.ModuleIdentifier name, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, NettyThreadgroupModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(name, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate(){
+        if(getThreadCount()!=null) {
+            Preconditions.checkArgument(getThreadCount() > 0, "Thread count cannot be < 0");
+        }
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return getThreadCount()==null ? new NioEventLoopGroupCloseable() : new NioEventLoopGroupCloseable(getThreadCount());
+    }
+
+
+    private class NioEventLoopGroupCloseable extends NioEventLoopGroup implements AutoCloseable {
+
+
+        public NioEventLoopGroupCloseable(int threadCount) {
+            super(threadCount);
+        }
+
+        public NioEventLoopGroupCloseable() {
+            super();
+        }
+
+        @Override
+        public void close() throws Exception {
+            shutdownGracefully();
+        }
+    }
+}
diff --git a/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleFactory.java b/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleFactory.java
new file mode 100644 (file)
index 0000000..1dca381
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+* Generated file
+
+* Generated from: yang module name: nsos-threadpool  yang module local name: netty-threadgroup-fixed
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Nov 08 08:31:45 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.netty.threadgroup;
+
+/**
+*
+*/
+public class NettyThreadgroupModuleFactory extends org.opendaylight.controller.config.yang.netty.threadgroup.AbstractNettyThreadgroupModuleFactory
+{
+
+
+}
diff --git a/opendaylight/config/netty-threadgroup-config/src/main/yang/nsos-netty-threadgroup.yang b/opendaylight/config/netty-threadgroup-config/src/main/yang/nsos-netty-threadgroup.yang
new file mode 100644 (file)
index 0000000..f13cf39
--- /dev/null
@@ -0,0 +1,53 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module nsos-threadpool {
+    yang-version 1;
+       namespace "urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup";
+    prefix "netty-t";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import threadpool { prefix th; revision-date 2013-04-09; }
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Robert Varga <rovarga@cisco.com>";
+
+    description
+        "This module contains the base YANG definitions for NS-OS
+         thread-related services.
+
+        Copyright (c)2013 Cisco Systems, Inc. All rights reserved.";
+
+    revision "2013-11-07" {
+        description
+            "Initial revision";
+    }
+
+    identity netty-threadgroup-fixed {
+        base config:module-type;
+        config:provided-service th:netty-threadgroup;
+        config:java-name-prefix NettyThreadgroup;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case netty-threadgroup-fixed {
+            when "/config:modules/config:module/config:type = 'netty-threadgroup-fixed'";
+
+            leaf thread-count {
+                type uint16;
+
+                description "Number of threads to be used by NioEventLoopGroup. This attribute is optional and default value will be 2* Number of CPUs";
+            }
+
+            // TODO add optional thread factory dependency
+
+        }
+    }
+
+    augment "/config:modules/config:module/config:state" {
+        case netty-threadgroup-fixed {
+            when "/config:modules/config:module/config:type = 'netty-threadgroup-fixed'";
+        }
+    }
+
+
+}
diff --git a/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java b/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java
new file mode 100644 (file)
index 0000000..590bd91
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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
+ */
+package org.opendaylight.controller.config.yang.netty.threadgroup;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+
+public class NettyThreadgroupModuleTest extends AbstractConfigTest {
+
+    private NettyThreadgroupModuleFactory factory;
+    private final String instanceName = "netty1";
+
+    @Before
+    public void setUp() {
+        factory = new NettyThreadgroupModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createInstance(transaction, instanceName, 2);
+        createInstance(transaction, instanceName + 2, null);
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(2, factory.getImplementationName());
+        assertStatus(status, 2, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException, ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName, null);
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 0, 1);
+    }
+
+    @Test
+    public void testReconfigure() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException, InstanceNotFoundException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName, null);
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        NettyThreadgroupModuleMXBean mxBean = transaction.newMBeanProxy(
+                transaction.lookupConfigBean(AbstractNettyThreadgroupModuleFactory.NAME, instanceName),
+                NettyThreadgroupModuleMXBean.class);
+        mxBean.setThreadCount(1);
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 1, 0);
+    }
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName, Integer threads)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        NettyThreadgroupModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, NettyThreadgroupModuleMXBean.class);
+        mxBean.setThreadCount(threads);
+        return nameCreated;
+    }
+}
index 9db5b769887704d97a5eab02653dea9f9418489d..2842b5c450712f5a78d8df67abf534027620a6c3 100755 (executable)
@@ -10,7 +10,7 @@
     </parent>
 
 
-    <version>0.2.2-SNAPSHOT</version>
+    <version>0.2.3-SNAPSHOT</version>
     <artifactId>config-subsystem</artifactId>
     <packaging>pom</packaging>
     <name>${project.artifactId}</name>
@@ -31,6 +31,7 @@
         <module>logback-config</module>
         <module>threadpool-config-api</module>
         <module>threadpool-config-impl</module>
+        <module>netty-threadgroup-config</module>
     </modules>
 
     <profiles>
index b991b69213597c5a041ea906ed234a4102f5c218..d8ddc4f24d3d843270fb3704a1098e3012dcef33 100644 (file)
@@ -3,7 +3,7 @@
    <parent>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-subsystem</artifactId>
-      <version>0.2.2-SNAPSHOT</version>
+      <version>0.2.3-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>threadpool-config-api</artifactId>
       <maven>3.0.4</maven>
    </prerequisites>
 
-   <dependencies>
-      <dependency>
-         <groupId>org.opendaylight.controller</groupId>
-         <artifactId>config-api</artifactId>
-      </dependency>
-      <dependency>
-         <groupId>com.google.guava</groupId>
-         <artifactId>guava</artifactId>
-      </dependency>
-   </dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport</artifactId>
+        </dependency>
+    </dependencies>
 
    <build>
       <plugins>
@@ -34,6 +38,7 @@
                   <Import-Package>
                      org.opendaylight.controller.config.api.*,
                      com.google.common.eventbus,
+                     io.netty.channel,
                   </Import-Package>
                   <Export-Package>
                      org.opendaylight.controller.config.threadpool,
index 14a20fdebcc85703695f38ef50ff0c8ab3994ff2..5cc17e52ffa728ac03924708a804f055157b6ad9 100644 (file)
@@ -15,7 +15,7 @@ module threadpool {
          thread-related services.
 
         Copyright (c)2013 Cisco Systems, Inc. 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
@@ -74,4 +74,14 @@ module threadpool {
         config:java-class "org.opendaylight.controller.config.threadpool.ScheduledThreadPool";
        }
 
+
+    identity netty-threadgroup {
+        description
+            "Configuration wrapper around netty's threadgroup";
+
+        base "config:service-type";
+        config:java-class "io.netty.channel.EventLoopGroup";
+    }
+
+
 }
index 12279781a24ea1e771932baa01525f54bca9aba2..cde64363cfe4454c1ca6184ff6e3c81efef520e4 100644 (file)
@@ -3,7 +3,7 @@
    <parent>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-subsystem</artifactId>
-      <version>0.2.2-SNAPSHOT</version>
+      <version>0.2.3-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>threadpool-config-impl</artifactId>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
       </dependency>
+
+      <!--test dependencies -->
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-manager</artifactId>
+         <scope>test</scope>
+         <type>test-jar</type>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-manager</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-util</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.bgpcep</groupId>
+         <artifactId>mockito-configuration</artifactId>
+         <scope>test</scope>
+      </dependency>
    </dependencies>
 
    <build>
@@ -73,4 +96,4 @@
       </plugins>
    </build>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/async/AsyncEventBusConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/async/AsyncEventBusConfigBeanTest.java
new file mode 100644 (file)
index 0000000..b2fc75d
--- /dev/null
@@ -0,0 +1,100 @@
+package org.opendaylight.controller.config.threadpool.async;\r
+\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.ClassBasedModuleFactory;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.threadpool.scheduled.TestingScheduledThreadPoolModule;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusModuleMXBean;\r
+\r
+public class AsyncEventBusConfigBeanTest extends AbstractConfigTest {\r
+\r
+    private AsyncEventBusModuleFactory factory;\r
+    private final String instanceName = "async1";\r
+    private final String poolImplName = "fixed1";\r
+\r
+    @Before\r
+    public void setUp() {\r
+\r
+        ClassBasedModuleFactory scheduledThreadPoolConfigFactory = createClassBasedCBF(\r
+                TestingScheduledThreadPoolModule.class, poolImplName);\r
+\r
+        factory = new AsyncEventBusModuleFactory();\r
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,\r
+                scheduledThreadPoolConfigFactory));\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+            ConflictingVersionException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createAsynced(transaction, instanceName, transaction.createModule(poolImplName, "pool-test"));\r
+        transaction.validateConfig();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+        assertStatus(status, 2, 0, 0);\r
+    }\r
+\r
+    @Test\r
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+            ValidationException {\r
+\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createAsynced(transaction, instanceName, transaction.createModule(poolImplName, "pool-test"));\r
+\r
+        transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+        assertStatus(status, 0, 0, 2);\r
+\r
+    }\r
+\r
+    @Test\r
+    public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException,\r
+            InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        ObjectName poolCB = transaction.createModule(poolImplName, "pool-test");\r
+        createAsynced(transaction, instanceName, poolCB);\r
+        transaction.commit();\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        try {\r
+            createAsynced(transaction, instanceName, poolCB);\r
+            fail();\r
+        } catch (InstanceAlreadyExistsException e) {\r
+            assertThat(\r
+                    e.getMessage(),\r
+                    containsString("There is an instance registered with name ModuleIdentifier{factoryName='async-eventbus', instanceName='async1'}"));\r
+        }\r
+    }\r
+\r
+    private ObjectName createAsynced(ConfigTransactionJMXClient transaction, String instanceName, ObjectName threadPool)\r
+            throws InstanceAlreadyExistsException {\r
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);\r
+        AsyncEventBusModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, AsyncEventBusModuleMXBean.class);\r
+        mxBean.setThreadpool(threadPool);\r
+        return nameCreated;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/SyncEventBusConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/SyncEventBusConfigBeanTest.java
new file mode 100644 (file)
index 0000000..4cd279f
--- /dev/null
@@ -0,0 +1,97 @@
+package org.opendaylight.controller.config.threadpool.eventbus;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.threadpool.impl.EventBusModuleFactory;
+
+public class SyncEventBusConfigBeanTest extends AbstractConfigTest {
+
+    private EventBusModuleFactory factory;
+    private final String instanceName = "sync1";
+
+    @Before
+    public void setUp() {
+
+        factory = new EventBusModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,
+            ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createSynced(transaction, instanceName);
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());
+        assertEquals(1, status.getNewInstances().size());
+        assertEquals(0, status.getRecreatedInstances().size());
+        assertEquals(0, status.getReusedInstances().size());
+        // TODO test dead event collector
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createSynced(transaction, instanceName);
+
+        transaction.commit();
+
+        assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());
+
+        transaction = configRegistryClient.createTransaction();
+        CommitStatus status = transaction.commit();
+
+        assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());
+        assertEquals(0, status.getNewInstances().size());
+        assertEquals(0, status.getRecreatedInstances().size());
+        assertEquals(1, status.getReusedInstances().size());
+
+    }
+
+    @Test
+    public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        try {
+            createSynced(transaction, instanceName);
+            transaction.commit();
+        } catch (InstanceAlreadyExistsException e1) {
+            fail();
+        }
+
+        transaction = configRegistryClient.createTransaction();
+        try {
+            createSynced(transaction, instanceName);
+            fail();
+        } catch (InstanceAlreadyExistsException e) {
+            assertThat(
+                    e.getMessage(),
+                    containsString("There is an instance registered with name ModuleIdentifier{factoryName='eventbus', instanceName='sync1'}"));
+        }
+    }
+
+    private ObjectName createSynced(ConfigTransactionJMXClient transaction, String instanceName)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        return nameCreated;
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/TestingEventBusModule.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/TestingEventBusModule.java
new file mode 100644 (file)
index 0000000..ee6bbc5
--- /dev/null
@@ -0,0 +1,28 @@
+package org.opendaylight.controller.config.threadpool.eventbus;\r
+\r
+import static org.mockito.Mockito.doNothing;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;\r
+import org.opendaylight.controller.config.api.ModuleIdentifier;\r
+import org.opendaylight.controller.config.manager.impl.AbstractMockedModule;\r
+import org.opendaylight.controller.config.spi.Module;\r
+import org.opendaylight.controller.config.threadpool.util.CloseableEventBus;\r
+import org.opendaylight.controller.config.yang.threadpool.EventBusServiceInterface;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.EventBusModuleMXBean;\r
+\r
+public class TestingEventBusModule extends AbstractMockedModule implements Module, EventBusServiceInterface,\r
+        EventBusModuleMXBean {\r
+\r
+    public TestingEventBusModule(DynamicMBeanWithInstance old, ModuleIdentifier id) {\r
+        super(old, id);\r
+    }\r
+\r
+    @Override\r
+    protected AutoCloseable prepareMockedInstance() throws Exception {\r
+        CloseableEventBus bus = mock(CloseableEventBus.class);\r
+        doNothing().when(bus).close();\r
+        return bus;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/FixedThreadPoolConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/FixedThreadPoolConfigBeanTest.java
new file mode 100644 (file)
index 0000000..4fda06b
--- /dev/null
@@ -0,0 +1,129 @@
+package org.opendaylight.controller.config.threadpool.fixed;\r
+\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.FixedThreadPoolModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.FixedThreadPoolModuleMXBean;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+\r
+public class FixedThreadPoolConfigBeanTest extends AbstractConfigTest {\r
+\r
+    private FixedThreadPoolModuleFactory factory;\r
+    private final String nameInstance = "fixedInstance";\r
+\r
+    @Before\r
+    public void setUp() {\r
+        factory = new FixedThreadPoolModuleFactory();\r
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,\r
+                new NamingThreadFactoryModuleFactory()));\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+            ConflictingVersionException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createFixed(transaction, nameInstance, 2);\r
+\r
+        transaction.validateConfig();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+        assertStatus(status, 2, 0, 0);\r
+    }\r
+\r
+    @Test\r
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+            ValidationException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createFixed(transaction, nameInstance, 4);\r
+\r
+        transaction.validateConfig();\r
+        transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+        assertStatus(status, 0, 0, 2);\r
+    }\r
+\r
+    @Test\r
+    public void testNegative() throws ConflictingVersionException, ValidationException, InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createFixed(transaction, nameInstance, 5);\r
+        transaction.commit();\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        try {\r
+            createFixed(transaction, nameInstance, 0);\r
+            fail();\r
+        } catch (InstanceAlreadyExistsException e) {\r
+            assertThat(\r
+                    e.getMessage(),\r
+                    containsString("There is an instance registered with name ModuleIdentifier{factoryName='threadpool-fixed', instanceName='fixedInstance'}"));\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testDestroy() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException,\r
+            InstanceNotFoundException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createFixed(transaction, nameInstance, 1);\r
+\r
+        transaction.commit();\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        transaction.destroyConfigBean(factory.getImplementationName(), nameInstance);\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(0, factory.getImplementationName());\r
+        assertStatus(status, 0, 0, 1);\r
+    }\r
+\r
+    @Test\r
+    public void testValidationException() throws InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createFixed(transaction, nameInstance, -1);\r
+        try {\r
+            transaction.validateConfig();\r
+            fail();\r
+        } catch (ValidationException e) {\r
+            assertThat(e.getMessage(), containsString("MaxThreadCount must be greater than zero"));\r
+        }\r
+    }\r
+\r
+    private ObjectName createFixed(ConfigTransactionJMXClient transaction, String name, int numberOfThreads)\r
+            throws InstanceAlreadyExistsException {\r
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), name);\r
+        FixedThreadPoolModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, FixedThreadPoolModuleMXBean.class);\r
+        mxBean.setMaxThreadCount(numberOfThreads);\r
+\r
+        ObjectName threadFactoryON = transaction.createModule(NamingThreadFactoryModuleFactory.NAME, "naming");\r
+        NamingThreadFactoryModuleMXBean namingThreadFactoryModuleMXBean = transaction.newMXBeanProxy(threadFactoryON,\r
+                NamingThreadFactoryModuleMXBean.class);\r
+        namingThreadFactoryModuleMXBean.setNamePrefix("prefix");\r
+\r
+        mxBean.setThreadFactory(threadFactoryON);\r
+\r
+        return nameCreated;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/TestingFixedThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/TestingFixedThreadPoolModule.java
new file mode 100644 (file)
index 0000000..00be5d8
--- /dev/null
@@ -0,0 +1,30 @@
+package org.opendaylight.controller.config.threadpool.fixed;\r
+\r
+import static org.mockito.Mockito.doNothing;\r
+import static org.mockito.Mockito.doReturn;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import java.util.concurrent.ExecutorService;\r
+\r
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;\r
+import org.opendaylight.controller.config.api.ModuleIdentifier;\r
+import org.opendaylight.controller.config.manager.impl.AbstractMockedModule;\r
+import org.opendaylight.controller.config.spi.Module;\r
+import org.opendaylight.controller.config.threadpool.util.FixedThreadPoolWrapper;\r
+import org.opendaylight.controller.config.yang.threadpool.ThreadPoolServiceInterface;\r
+\r
+public class TestingFixedThreadPoolModule extends AbstractMockedModule implements ThreadPoolServiceInterface, Module {\r
+\r
+    public TestingFixedThreadPoolModule(DynamicMBeanWithInstance old, ModuleIdentifier id) {\r
+        super(old, id);\r
+    }\r
+\r
+    @Override\r
+    protected AutoCloseable prepareMockedInstance() throws Exception {\r
+        FixedThreadPoolWrapper pool = mock(FixedThreadPoolWrapper.class);\r
+        doNothing().when(pool).close();\r
+        doReturn(mock(ExecutorService.class)).when(pool).getExecutor();\r
+        return pool;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/flexible/FlexibleThreadPoolConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/flexible/FlexibleThreadPoolConfigBeanTest.java
new file mode 100644 (file)
index 0000000..ee1de8f
--- /dev/null
@@ -0,0 +1,173 @@
+package org.opendaylight.controller.config.threadpool.flexible;\r
+\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.FlexibleThreadPoolModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.FlexibleThreadPoolModuleMXBean;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+\r
+public class FlexibleThreadPoolConfigBeanTest extends AbstractConfigTest {\r
+\r
+    private FlexibleThreadPoolModuleFactory flexibleFactory;\r
+    private final String instanceName = "flexible1";\r
+    private final String threadFactoryName = "threadFactoryName";\r
+\r
+    @Before\r
+    public void setUp() {\r
+\r
+        flexibleFactory = new FlexibleThreadPoolModuleFactory();\r
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(flexibleFactory,\r
+                new NamingThreadFactoryModuleFactory()));\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+            ConflictingVersionException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createFlexible(transaction, instanceName, threadFactoryName, 1, 20, 20);\r
+        transaction.validateConfig();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, flexibleFactory.getImplementationName());\r
+        assertStatus(status, 2, 0, 0);\r
+    }\r
+\r
+    @Test\r
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+            ValidationException {\r
+\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createFlexible(transaction, instanceName, threadFactoryName, 1, 20, 10);\r
+\r
+        transaction.commit();\r
+\r
+        assertBeanCount(1, flexibleFactory.getImplementationName());\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, flexibleFactory.getImplementationName());\r
+        assertStatus(status, 0, 0, 2);\r
+\r
+    }\r
+\r
+    @Test\r
+    public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        try {\r
+            createFlexible(transaction, instanceName, threadFactoryName, 1, 1, 2);\r
+            transaction.commit();\r
+        } catch (InstanceAlreadyExistsException e1) {\r
+            fail();\r
+        }\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        try {\r
+            createFlexible(transaction, instanceName, "threadFactoryName1", 2, 2, 2);\r
+            fail();\r
+        } catch (InstanceAlreadyExistsException e) {\r
+            assertThat(\r
+                    e.getMessage(),\r
+                    containsString("There is an instance registered with name ModuleIdentifier{factoryName='threadpool-flexible', instanceName='flexible1'}"));\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testValidationException() throws InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createFlexible(transaction, instanceName, threadFactoryName, 0, 10, 10);\r
+\r
+        try {\r
+            transaction.validateConfig();\r
+            fail();\r
+        } catch (ValidationException e) {\r
+            assertThat(e.getMessage(), containsString("MinThreadCount must be greater than zero"));\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testValidationException2() throws InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createFlexible(transaction, instanceName, threadFactoryName, 0, 0, 10);\r
+\r
+        try {\r
+            transaction.validateConfig();\r
+            fail();\r
+        } catch (ValidationException e) {\r
+            assertThat(e.getMessage(), containsString("KeepAliveMillis must be greater than zero"));\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testValidationException3() throws InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createFlexible(transaction, instanceName, threadFactoryName, 10, 50, 0);\r
+\r
+        try {\r
+            transaction.validateConfig();\r
+            fail();\r
+        } catch (ValidationException e) {\r
+            assertThat(e.getMessage(), containsString("MaxThreadCount must be greater than zero"));\r
+        }\r
+    }\r
+\r
+    private ObjectName createFlexible(ConfigTransactionJMXClient transaction, String instanceName,\r
+            String threadFactoryName, int minThreadCount, long keepAliveMillis, int maxThreadCount)\r
+            throws InstanceAlreadyExistsException {\r
+\r
+        ObjectName threadFactoryON = transaction.createModule(NamingThreadFactoryModuleFactory.NAME, threadFactoryName);\r
+        NamingThreadFactoryModuleMXBean namingThreadFactoryModuleMXBean = transaction.newMXBeanProxy(threadFactoryON,\r
+                NamingThreadFactoryModuleMXBean.class);\r
+        namingThreadFactoryModuleMXBean.setNamePrefix("prefix");\r
+\r
+        ObjectName flexibleON = transaction.createModule(flexibleFactory.getImplementationName(), instanceName);\r
+        FlexibleThreadPoolModuleMXBean mxBean = transaction.newMBeanProxy(flexibleON,\r
+                FlexibleThreadPoolModuleMXBean.class);\r
+        mxBean.setKeepAliveMillis(keepAliveMillis);\r
+        mxBean.setMaxThreadCount(maxThreadCount);\r
+        mxBean.setMinThreadCount(minThreadCount);\r
+        mxBean.setThreadFactory(threadFactoryON);\r
+        return flexibleON;\r
+    }\r
+\r
+    @Test\r
+    public void testReconfigurationInstance() throws InstanceAlreadyExistsException, ValidationException,\r
+            ConflictingVersionException, InstanceNotFoundException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createFlexible(transaction, instanceName, threadFactoryName, 2, 2, 2);\r
+\r
+        transaction.commit();\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        ObjectName databaseNew = transaction.lookupConfigBean(flexibleFactory.getImplementationName(), instanceName);\r
+        FlexibleThreadPoolModuleMXBean proxy = transaction.newMXBeanProxy(databaseNew,\r
+                FlexibleThreadPoolModuleMXBean.class);\r
+        proxy.setMaxThreadCount(99);\r
+\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, flexibleFactory.getImplementationName());\r
+        assertStatus(status, 0, 1, 1);\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/NamingThreadPoolFactoryConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/NamingThreadPoolFactoryConfigBeanTest.java
new file mode 100644 (file)
index 0000000..9e9565a
--- /dev/null
@@ -0,0 +1,136 @@
+package org.opendaylight.controller.config.threadpool.naming;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.assertTrue;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.ThreadFactoryServiceInterface;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+\r
+public class NamingThreadPoolFactoryConfigBeanTest extends AbstractConfigTest {\r
+\r
+    private NamingThreadFactoryModuleFactory factory;\r
+    private final String instanceName = "named";\r
+\r
+    @Before\r
+    public void setUp() {\r
+\r
+        factory = new NamingThreadFactoryModuleFactory();\r
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+            ConflictingVersionException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createNamed(transaction, instanceName, "prefixes");\r
+        transaction.validateConfig();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());\r
+        assertEquals(1, status.getNewInstances().size());\r
+        assertEquals(0, status.getRecreatedInstances().size());\r
+        assertEquals(0, status.getReusedInstances().size());\r
+    }\r
+\r
+    @Test\r
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+            ValidationException {\r
+\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createNamed(transaction, instanceName, "prefixes");\r
+\r
+        transaction.commit();\r
+\r
+        assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());\r
+        assertEquals(0, status.getNewInstances().size());\r
+        assertEquals(0, status.getRecreatedInstances().size());\r
+        assertEquals(1, status.getReusedInstances().size());\r
+\r
+    }\r
+\r
+    @Test\r
+    public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException,\r
+            InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createNamed(transaction, instanceName, "prefixes");\r
+        transaction.commit();\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        try {\r
+            createNamed(transaction, instanceName, "prefixes1");\r
+            fail();\r
+        } catch (InstanceAlreadyExistsException e) {\r
+            assertThat(\r
+                    e.getMessage(),\r
+                    containsString("There is an instance registered with name ModuleIdentifier{factoryName='threadfactory-naming', instanceName='named'}"));\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testValidationException() throws InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);\r
+        transaction.newMXBeanProxy(nameCreated, ThreadFactoryServiceInterface.class);\r
+        try {\r
+            transaction.validateConfig();\r
+            fail();\r
+        } catch (ValidationException e) {\r
+            assertTrue(e.getFailedValidations().containsKey(factory.getImplementationName()));\r
+            assertEquals(1, e.getFailedValidations().get(factory.getImplementationName()).keySet().size());\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testReconfigurationInstance() throws InstanceAlreadyExistsException, ValidationException,\r
+            ConflictingVersionException, InstanceNotFoundException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createNamed(transaction, instanceName, "pref");\r
+\r
+        transaction.commit();\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        ObjectName databaseNew = transaction.lookupConfigBean(factory.getImplementationName(), instanceName);\r
+        NamingThreadFactoryModuleMXBean proxy = transaction.newMXBeanProxy(databaseNew,\r
+                NamingThreadFactoryModuleMXBean.class);\r
+        proxy.setNamePrefix("pref1");\r
+\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+        assertStatus(status, 0, 1, 0);\r
+    }\r
+\r
+    private ObjectName createNamed(ConfigTransactionJMXClient transaction, String instanceName, String prefixes)\r
+            throws InstanceAlreadyExistsException {\r
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);\r
+        NamingThreadFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,\r
+                NamingThreadFactoryModuleMXBean.class);\r
+        mxBean.setNamePrefix(prefixes);\r
+        return nameCreated;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/TestingNamingThreadPoolFactoryModule.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/TestingNamingThreadPoolFactoryModule.java
new file mode 100644 (file)
index 0000000..5c717cc
--- /dev/null
@@ -0,0 +1,59 @@
+package org.opendaylight.controller.config.threadpool.naming;\r
+\r
+import static org.mockito.Matchers.any;\r
+import static org.mockito.Mockito.doNothing;\r
+import static org.mockito.Mockito.doReturn;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import java.io.Closeable;\r
+import java.io.IOException;\r
+\r
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;\r
+import org.opendaylight.controller.config.api.ModuleIdentifier;\r
+import org.opendaylight.controller.config.spi.Module;\r
+import org.opendaylight.controller.config.threadpool.util.NamingThreadPoolFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.ThreadFactoryServiceInterface;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+\r
+public class TestingNamingThreadPoolFactoryModule implements Module, ThreadFactoryServiceInterface,\r
+        NamingThreadFactoryModuleMXBean {\r
+\r
+    private final NamingThreadPoolFactory fact;\r
+\r
+    public TestingNamingThreadPoolFactoryModule() throws IOException {\r
+        fact = mock(NamingThreadPoolFactory.class);\r
+        Thread thread = mock(Thread.class);\r
+        doNothing().when(thread).start();\r
+        doReturn(thread).when(fact).newThread(any(Runnable.class));\r
+        doNothing().when(fact).close();\r
+    }\r
+\r
+    public TestingNamingThreadPoolFactoryModule(DynamicMBeanWithInstance old) {\r
+        fact = (NamingThreadPoolFactory) old.getInstance();\r
+    }\r
+\r
+    @Override\r
+    public ModuleIdentifier getIdentifier() {\r
+        return new ModuleIdentifier(TestingNamingThreadPoolFactoryModule.class.getCanonicalName(), "mock");\r
+    }\r
+\r
+    @Override\r
+    public String getNamePrefix() {\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    public void setNamePrefix(String arg) {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    @Override\r
+    public void validate() {\r
+    }\r
+\r
+    @Override\r
+    public Closeable getInstance() {\r
+        return fact;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/ScheduledThreadPoolConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/ScheduledThreadPoolConfigBeanTest.java
new file mode 100644 (file)
index 0000000..b4b1b60
--- /dev/null
@@ -0,0 +1,154 @@
+package org.opendaylight.controller.config.threadpool.scheduled;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.assertTrue;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.ScheduledThreadPoolModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.ScheduledThreadPoolModuleMXBean;\r
+\r
+public class ScheduledThreadPoolConfigBeanTest extends AbstractConfigTest {\r
+\r
+    private ScheduledThreadPoolModuleFactory factory;\r
+    private final String instanceName = "scheduled1";\r
+\r
+    @Before\r
+    public void setUp() {\r
+\r
+        factory = new ScheduledThreadPoolModuleFactory();\r
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,\r
+                new NamingThreadFactoryModuleFactory()));\r
+    }\r
+\r
+    @Test\r
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+            ConflictingVersionException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+        createScheduled(transaction, instanceName, 1);\r
+        transaction.validateConfig();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+        assertStatus(status, 2, 0, 0);\r
+    }\r
+\r
+    @Test\r
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+            ValidationException {\r
+\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createScheduled(transaction, instanceName, 1);\r
+\r
+        transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+        assertStatus(status, 0, 0, 2);\r
+    }\r
+\r
+    @Test\r
+    public void testReconfigurationInstance() throws InstanceAlreadyExistsException, ValidationException,\r
+            ConflictingVersionException, InstanceNotFoundException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createScheduled(transaction, instanceName, 1);\r
+\r
+        transaction.commit();\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        ObjectName databaseNew = transaction.lookupConfigBean(factory.getImplementationName(), instanceName);\r
+        ScheduledThreadPoolModuleMXBean proxy = transaction.newMXBeanProxy(databaseNew,\r
+                ScheduledThreadPoolModuleMXBean.class);\r
+        proxy.setMaxThreadCount(99);\r
+\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(1, factory.getImplementationName());\r
+        assertStatus(status, 0, 1, 1);\r
+    }\r
+\r
+    @Test\r
+    public void testDestroy() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException,\r
+            InstanceNotFoundException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createScheduled(transaction, instanceName, 1);\r
+\r
+        transaction.commit();\r
+\r
+        transaction = configRegistryClient.createTransaction();\r
+        transaction.destroyConfigBean(factory.getImplementationName(), instanceName);\r
+        CommitStatus status = transaction.commit();\r
+\r
+        assertBeanCount(0, factory.getImplementationName());\r
+        assertStatus(status, 0, 0, 1);\r
+    }\r
+\r
+    @Test\r
+    public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException,\r
+            InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createScheduled(transaction, instanceName, 1);\r
+        transaction.commit();\r
+        transaction = configRegistryClient.createTransaction();\r
+        try {\r
+            createScheduled(transaction, instanceName, 2);\r
+            fail();\r
+        } catch (InstanceAlreadyExistsException e) {\r
+            assertThat(\r
+                    e.getMessage(),\r
+                    containsString("There is an instance registered with name ModuleIdentifier{factoryName='threadpool-scheduled', instanceName='scheduled1'}"));\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testValidationException() throws InstanceAlreadyExistsException {\r
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+        createScheduled(transaction, instanceName, 0);\r
+\r
+        try {\r
+            transaction.validateConfig();\r
+            fail();\r
+        } catch (ValidationException e) {\r
+            assertTrue(e.getFailedValidations().containsKey(factory.getImplementationName()));\r
+            assertEquals(1, e.getFailedValidations().get(factory.getImplementationName()).keySet().size());\r
+        }\r
+    }\r
+\r
+    private ObjectName createScheduled(ConfigTransactionJMXClient transaction, String instanceName, int maxThreadCount)\r
+            throws InstanceAlreadyExistsException {\r
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);\r
+        ScheduledThreadPoolModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,\r
+                ScheduledThreadPoolModuleMXBean.class);\r
+        mxBean.setMaxThreadCount(maxThreadCount);\r
+\r
+        ObjectName threadFactoryON = transaction.createModule(NamingThreadFactoryModuleFactory.NAME, "naming");\r
+        NamingThreadFactoryModuleMXBean namingThreadFactoryModuleMXBean = transaction.newMXBeanProxy(threadFactoryON,\r
+                NamingThreadFactoryModuleMXBean.class);\r
+        namingThreadFactoryModuleMXBean.setNamePrefix("prefix");\r
+\r
+        mxBean.setThreadFactory(threadFactoryON);\r
+\r
+        return nameCreated;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/TestingScheduledThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/TestingScheduledThreadPoolModule.java
new file mode 100644 (file)
index 0000000..27e60ee
--- /dev/null
@@ -0,0 +1,77 @@
+package org.opendaylight.controller.config.threadpool.scheduled;\r
+\r
+import static org.mockito.Matchers.any;\r
+import static org.mockito.Matchers.anyBoolean;\r
+import static org.mockito.Matchers.anyLong;\r
+import static org.mockito.Mockito.doNothing;\r
+import static org.mockito.Mockito.doReturn;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import java.util.concurrent.ScheduledExecutorService;\r
+import java.util.concurrent.ScheduledFuture;\r
+import java.util.concurrent.TimeUnit;\r
+\r
+import javax.management.ObjectName;\r
+\r
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;\r
+import org.opendaylight.controller.config.api.ModuleIdentifier;\r
+import org.opendaylight.controller.config.manager.impl.AbstractMockedModule;\r
+import org.opendaylight.controller.config.spi.Module;\r
+import org.opendaylight.controller.config.threadpool.util.ScheduledThreadPoolWrapper;\r
+import org.opendaylight.controller.config.yang.threadpool.ScheduledThreadPoolServiceInterface;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.ScheduledThreadPoolModuleMXBean;\r
+\r
+import com.google.common.util.concurrent.ListenableFutureTask;\r
+\r
+public class TestingScheduledThreadPoolModule extends AbstractMockedModule implements\r
+        ScheduledThreadPoolServiceInterface, Module, ScheduledThreadPoolModuleMXBean {\r
+\r
+    public TestingScheduledThreadPoolModule(DynamicMBeanWithInstance old, ModuleIdentifier id) {\r
+        super(old, id);\r
+    }\r
+\r
+    @Override\r
+    protected AutoCloseable prepareMockedInstance() throws Exception {\r
+        ScheduledThreadPoolWrapper instance = mock(ScheduledThreadPoolWrapper.class);\r
+        ScheduledExecutorService ses = mock(ScheduledExecutorService.class);\r
+        {// mockFuture\r
+            ScheduledFuture<?> future = mock(ScheduledFuture.class);\r
+            doReturn(false).when(future).cancel(anyBoolean());\r
+            try {\r
+                doReturn(mock(Object.class)).when(future).get();\r
+            } catch (Exception e) {\r
+                throw new RuntimeException(e);\r
+            }\r
+            doReturn(future).when(ses).schedule(any(Runnable.class), any(Long.class), any(TimeUnit.class));\r
+            doReturn(future).when(ses).scheduleWithFixedDelay(any(Runnable.class), anyLong(), anyLong(),\r
+                    any(TimeUnit.class));\r
+\r
+        }\r
+        doNothing().when(ses).execute(any(Runnable.class));\r
+        doNothing().when(ses).execute(any(ListenableFutureTask.class));\r
+        doReturn(ses).when(instance).getExecutor();\r
+        doNothing().when(instance).close();\r
+\r
+        doReturn(1).when(instance).getMaxThreadCount();\r
+        return instance;\r
+    }\r
+\r
+    @Override\r
+    public ObjectName getThreadFactory() {\r
+        return any(ObjectName.class);\r
+    }\r
+\r
+    @Override\r
+    public void setThreadFactory(ObjectName threadFactory) {\r
+    }\r
+\r
+    @Override\r
+    public Integer getMaxThreadCount() {\r
+        return 1;\r
+    }\r
+\r
+    @Override\r
+    public void setMaxThreadCount(Integer maxThreadCount) {\r
+    }\r
+\r
+}\r
index 336d0c3b824825cb6c284ed4f42f8aeb577e8775..bcec65f2e7db58d613dccedf500afb02d818adfb 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
 
     <artifactId>yang-jmx-generator-it</artifactId>
index 1d53f58d5c79bcbf633c3fe84586f69ab54dc251..f06c7bdad8a65a31345e4c615284cfc8fc564490 100644 (file)
@@ -4,7 +4,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>yang-jmx-generator-plugin</artifactId>
index 37846384bffc6d3113666422b7b06000c521e37a..cd985714d46804ecf84d713a0882811d9177aa38 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
 
     <artifactId>yang-jmx-generator</artifactId>
index 6e850b2566455ce4ed6239319cfb8a8253c89610..9b103df8d7f8900e7e474bf0e777ec30805670f4 100644 (file)
@@ -4,7 +4,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>yang-store-api</artifactId>
index 07ac4d4bb6e5ca7d7f3d9e20a50bba4d0548965f..ae59dde26ca461ee844df5486ae50fd6367a76b9 100644 (file)
@@ -4,7 +4,7 @@
     <parent>
         <artifactId>config-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>yang-store-impl</artifactId>
index 3de06882a62cb8afc15d56c3fe14a161fac5b4bc..b7540c8787b15b499d9542e46998de0c32cfa2e2 100644 (file)
@@ -5,7 +5,7 @@
     <parent>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>config-subsystem</artifactId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
 
     <artifactId>yang-test</artifactId>
index a0d7162b3f524630ecbe944eebe0551abfa07086..cc42fefd975662a61da91e5e17f4d45f206c6109 100644 (file)
           <artifactId>model-flow-management</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller.md</groupId>
+          <artifactId>inventory-manager</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
 
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-impl</artifactId>
           <version>${netconf.version}</version>
         </dependency>
-
+        <dependency>
+          <groupId>org.opendaylight.controller.thirdparty</groupId>
+          <artifactId>exificient</artifactId>
+          <version>${exi.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.servicemix.bundles</groupId>
+            <artifactId>org.apache.servicemix.bundles.xerces</artifactId>
+            <version>2.11.0_1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.birt.runtime.3_7_1</groupId>
+            <artifactId>org.apache.xml.resolver</artifactId>
+            <version>1.2.0</version>
+        </dependency>
 
           <!-- toaster example I'm pretty sure we should trim -->
-
          <dependency>
           <groupId>org.opendaylight.controller.samples</groupId>
           <artifactId>sample-toaster</artifactId>
          </dependency>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>binding-generator-util</artifactId>
+          <artifactId>binding-generator-spi</artifactId>
           <version>${yangtools.binding.version}</version>
          </dependency>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>binding-model-api</artifactId>
+          <artifactId>binding-generator-api</artifactId>
           <version>${yangtools.binding.version}</version>
          </dependency>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>binding-generator-spi</artifactId>
+          <artifactId>binding-generator-impl</artifactId>
+          <version>${yangtools.binding.version}</version>
+         </dependency>
+         <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>binding-generator-util</artifactId>
+          <version>${yangtools.binding.version}</version>
+         </dependency>
+         <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>binding-model-api</artifactId>
           <version>${yangtools.binding.version}</version>
          </dependency>
          <dependency>
         </dependency>
       </dependencies>
     </profile>
+    <profile>
+      <id>integrationtests</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <version>2.8</version>
+            <executions>
+              <execution>
+                <id>copy</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.opendaylight.controller</groupId>
+                  <artifactId>sanitytest</artifactId>
+                  <version>${controller.version}</version>
+                  <type>jar</type>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </plugin>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>exec-maven-plugin</artifactId>
+            <version>1.2.1</version>
+            <executions>
+              <execution>
+                <id>sanity-test</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>exec</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <executable>${java.home}/bin/java</executable>
+              <arguments>
+                <argument>-cp</argument>
+                <argument>./target/dependency/*</argument>
+                <argument>org.opendaylight.controller.distribution.Sanity</argument>
+              </arguments>
+              <environmentVariables>
+                <JAVA_HOME>
+                  ${java.home}
+                </JAVA_HOME>
+              </environmentVariables>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
   </profiles>
 
   <artifactId>distribution.opendaylight</artifactId>
           </execution>
         </executions>
       </plugin>
-
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.8</version>
-          <executions>
-            <execution>
-              <id>copy</id>
-              <phase>package</phase>
-              <goals>
-                <goal>copy</goal>
-              </goals>
-            </execution>
-          </executions>
-          <configuration>
-            <artifactItems>
-              <artifactItem>
-                <groupId>org.opendaylight.controller</groupId>
-                <artifactId>sanitytest</artifactId>
-                <version>${controller.version}</version>
-                <type>jar</type>
-              </artifactItem>
-            </artifactItems>
-          </configuration>
-      </plugin>
-
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>exec-maven-plugin</artifactId>
-        <version>1.2.1</version>
-        <executions>
-          <execution>
-            <id>sanity-test</id>
-            <phase>package</phase>
-            <goals>
-              <goal>exec</goal>
-            </goals>
-          </execution>
-        </executions>
-          <configuration>
-            <executable>${java.home}/bin/java</executable>
-            <arguments>
-                <argument>-cp</argument>
-                <argument>./target/dependency/*</argument>
-                <argument>org.opendaylight.controller.distribution.Sanity</argument>
-            </arguments>
-            <environmentVariables>
-              <JAVA_HOME>
-                ${java.home}
-              </JAVA_HOME>
-            </environmentVariables>
-          </configuration>
-      </plugin>
     </plugins>
   </build>
 </project>
index 9b96f86c92497c70ec8c5b03c0d01aae70538224..29de77270bb6d63c5f791f0ad70cce2eda6d9250 100644 (file)
             <Import-Package>
               org.opendaylight.controller.sal.binding.api,
               org.opendaylight.controller.sal.binding.api.data,
-              org.opendaylight.controller.md.sal.common.api.data,              
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow,
+              org.opendaylight.controller.md.sal.common.api.data, 
+              org.opendaylight.controller.sal.utils, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket,
               org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
+              org.opendaylight.controller.clustering.services, org.opendaylight.controller.sal.core, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction,
+              org.opendaylight.controller.switchmanager, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024,
               org.opendaylight.yangtools.concepts,              
               org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819,
               org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819,
index ae488b689f4788c95d017a07c53cb0ddecb9f0fd..e48e03867c89025fc62babeab7548a8947a27712 100644 (file)
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
 
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.NotificationService;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
-public class FRMConsumerImpl extends AbstractBindingAwareProvider {
+public class FRMConsumerImpl extends AbstractBindingAwareProvider implements CommandProvider{
        protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class);
        private static ProviderContext p_session;
     private static DataBrokerService dataBrokerService;         
@@ -28,11 +35,21 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
        private GroupConsumerImpl groupImplRef;
        private static DataProviderService dataProviderService;  
 
+       private static IClusterContainerServices clusterContainerService = null;
+       private static ISwitchManager switchManager;
+       private static IContainer container;
+       
        @Override
     public void onSessionInitiated(ProviderContext session) {
        
         FRMConsumerImpl.p_session = session;
         
+        if (!getDependentModule()) {
+            logger.error("Unable to fetch handlers for dependent modules");
+            System.out.println("Unable to fetch handlers for dependent modules");
+            return;
+        }
+        
         if (null != session) {
                notificationService = session.getSALService(NotificationService.class);
                
@@ -44,7 +61,8 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
                                
                                if (null != dataProviderService) {
                                        flowImplRef = new FlowConsumerImpl();
-                                       groupImplRef = new GroupConsumerImpl();
+                       //              groupImplRef = new GroupConsumerImpl();
+                                       registerWithOSGIConsole();
                                }
                                else {
                                        logger.error("Data Provider Service is down or NULL. " +
@@ -68,18 +86,85 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
                System.out.println("Consumer session is NULL. Please check if provider is registered");
         }
   
+    }
+       
+       public static IClusterContainerServices getClusterContainerService() {
+        return clusterContainerService;
+    }
+
+    public static void setClusterContainerService(
+            IClusterContainerServices clusterContainerService) {
+        FRMConsumerImpl.clusterContainerService = clusterContainerService;
+    }
+
+    public static ISwitchManager getSwitchManager() {
+        return switchManager;
+    }
+
+    public static void setSwitchManager(ISwitchManager switchManager) {
+        FRMConsumerImpl.switchManager = switchManager;
+    }
+
+    public static IContainer getContainer() {
+        return container;
     }
 
-       public static DataProviderService getDataProviderService() {
+    public static void setContainer(IContainer container) {
+        FRMConsumerImpl.container = container;
+    }
+
+    private void registerWithOSGIConsole() {
+        BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+        bundleContext.registerService(CommandProvider.class.getName(), this, null);
+    }
+       
+       private boolean getDependentModule() {
+           do {
+        clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(IClusterContainerServices.class, this);
+        try {
+            Thread.sleep(4);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+           } while(clusterContainerService == null);
+           
+           do {
+               
+           
+        container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+        try {
+            Thread.sleep(5);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+           } while (container == null);
+           
+           do {
+               switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, container.getName(), this);
+               try {
+                   Thread.sleep(5);
+               } catch (InterruptedException e) {
+                   // TODO Auto-generated catch block
+                   e.printStackTrace();
+               }
+           } while(null == switchManager);
+        return true;
+       }
+
+       
+
+    public static DataProviderService getDataProviderService() {
                return dataProviderService;
        }
 
        public FlowConsumerImpl getFlowImplRef() {
-               return flowImplRef;
+           return flowImplRef;
        }
 
        public GroupConsumerImpl getGroupImplRef() {
-                       return groupImplRef;
+           return groupImplRef;
        }
         
        public static ProviderContext getProviderSession() {
@@ -93,6 +178,15 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
        public static DataBrokerService getDataBrokerService() {
                return dataBrokerService;
        }
+       
+       /*
+     * OSGI COMMANDS
+     */
+    @Override
+    public String getHelp() {
+        StringBuffer help = new StringBuffer();
+        return help.toString();
+    }
 
 }
        
diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java
new file mode 100644 (file)
index 0000000..df34d19
--- /dev/null
@@ -0,0 +1,33 @@
+package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket.Actions;
+
+public class FRMUtil {
+    private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+    public enum operation {ADD, DELETE, UPDATE, GET};
+    
+    
+    public static boolean isNameValid(String name) {
+    
+        //  Name validation 
+        if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
+            return false;
+        }
+        return true;
+        
+    }
+    
+    public static boolean areActionsValid(Actions actions) {
+     //   List<Action> actionList;
+       // Action actionRef;
+      //  if (null != actions && null != actions.getAction()) {
+       //     actionList = actions.getAction();
+            
+
+               
+       // }
+        
+        return true;
+    }
+}
index a6a3c71325ed7e644918527ef600fbe739f7faee..59c7e043de823a83a4f6b0318c2d25650bd4b384 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
@@ -27,6 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -61,6 +63,7 @@ public class FlowConsumerImpl {
                }
                
                listener = new FlowDataListener();
+               
                if (null == FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path, listener)) {
                        logger.error("Failed to listen on flow data modifcation events");
                System.out.println("Consumer SAL Service is down or NULL.");
@@ -75,7 +78,7 @@ public class FlowConsumerImpl {
                System.out.println("Consumer SAL Service is down or NULL.");
                return;
                }
-               addFlowTest();
+               //addFlowTest();
                System.out.println("-------------------------------------------------------------------");
                allocateCaches();
                commitHandler = new FlowDataCommitHandler();
@@ -120,11 +123,19 @@ public class FlowConsumerImpl {
     private void addFlow(InstanceIdentifier<?> path, Flow dataObject) {
 
         AddFlowInputBuilder input = new AddFlowInputBuilder();
+        List<Instruction> inst = (dataObject).getInstructions().getInstruction();
         input.setNode((dataObject).getNode());
         input.setPriority((dataObject).getPriority());
         input.setMatch((dataObject).getMatch());
         input.setCookie((dataObject).getCookie());
-        input.setAction((dataObject).getAction());
+        input.setInstructions((dataObject).getInstructions());
+        dataObject.getMatch().getLayer3Match()
+        for (int i=0;i<inst.size();i++) {
+            System.out.println("i = "+ i + inst.get(i).getInstruction().toString());
+            System.out.println("i = "+ i + inst.get(i).toString());
+        }
+        
+        System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
 
         // We send flow to the sounthbound plugin
         flowService.addFlow(input.build());
@@ -132,9 +143,11 @@ public class FlowConsumerImpl {
     
     private void commitToPlugin(internalTransaction transaction) {
         for(Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+            System.out.println("Coming add cc in FlowDatacommitHandler");
             addFlow(entry.getKey(),entry.getValue());
         }
-        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.updates.entrySet()) {
+            System.out.println("Coming update cc in FlowDatacommitHandler");
            // updateFlow(entry.getKey(),entry.getValue());
         }
         
@@ -196,9 +209,11 @@ public class FlowConsumerImpl {
             Flow original = originalSwView.get(key);
             if (original != null) {
                 // It is update for us
+                System.out.println("Coming update  in FlowDatacommitHandler");
                 updates.put(key, flow);
             } else {
                 // It is addition for us
+                System.out.println("Coming add in FlowDatacommitHandler");
                 additions.put(key, flow);
             }
         }
@@ -273,7 +288,7 @@ public class FlowConsumerImpl {
                        for (DataObject dataObject : additions) {
                            if (dataObject instanceof NodeFlow) {
                                NodeRef nodeOne = createNodeRef("foo:node:1");
-                                       // validating the dataObject here
+                                       // validating the dataObject here                               
                                    AddFlowInputBuilder input = new AddFlowInputBuilder();
                                    input.setNode(((NodeFlow) dataObject).getNode());
                                    input.setNode(nodeOne);
@@ -300,18 +315,6 @@ public class FlowConsumerImpl {
         return new NodeRef(path);
     }
            
-         /*  private void loadFlowData() {
        
-                   DataModification modification = (DataModification) dataservice.beginTransaction();
-                   String id = "abc";
-                   FlowKey key = new FlowKey(id, new NodeRef());
-                   InstanceIdentifier<?> path1;
-                   FlowBuilder flow = new FlowBuilder();
-                   flow.setKey(key);
-                   path1 = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, key).toInstance();
-                   DataObject cls = (DataObject) modification.readConfigurationData(path);
-                   modification.putConfigurationData(path, flow.build());
-                   modification.commit();
-               }*/
 
 }
index cc42e21f2a1fc8e0199455f9d7cc65d6b3521183..acc0dc69cd4d059b074fc7691bc1b73d75130170 100644 (file)
@@ -1,7 +1,478 @@
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.Groups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("unused")
 public class GroupConsumerImpl {
-       public GroupConsumerImpl() {
-               
+    
+    protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class);
+    private GroupEventListener groupEventListener = new GroupEventListener();
+    private Registration<NotificationListener> groupListener;
+    private SalGroupService groupService;    
+    private GroupDataCommitHandler commitHandler;
+    
+    private ConcurrentMap<GroupKey, Group> originalSwGroupView;
+    private ConcurrentMap<GroupKey, Group> installedSwGroupView;
+    
+    private ConcurrentMap<Node, List<Group>> nodeGroups;
+    private ConcurrentMap<GroupKey, Group> inactiveGroups;
+    
+    private IClusterContainerServices clusterGroupContainerService = null;
+    private ISwitchManager switchGroupManager;
+    private IContainer container;
+    
+    public GroupConsumerImpl() {
+           InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class).toInstance();
+        groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
+        
+        clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
+        switchGroupManager = FRMConsumerImpl.getSwitchManager();
+        container = FRMConsumerImpl.getContainer();
+        
+        if (!(cacheStartup())) {
+            logger.error("Unanle to allocate/retrieve group cache");
+            System.out.println("Unable to allocate/retrieve group cache");
+        }
+        
+        if (null == groupService) {
+            logger.error("Consumer SAL Group Service is down or NULL. FRM may not function as intended");
+            System.out.println("Consumer SAL Group Service is down or NULL.");
+            return;
+        }     
+        
+        // For switch events
+        groupListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(groupEventListener);
+        
+        if (null == groupListener) {
+            logger.error("Listener to listen on group data modifcation events");
+            System.out.println("Listener to listen on group data modifcation events.");
+            return;
+        }       
+        
+        commitHandler = new GroupDataCommitHandler();
+        FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
        }
+       
+    private boolean allocateGroupCaches() {
+        if (this.clusterGroupContainerService == null) {
+            logger.warn("Group: Un-initialized clusterGroupContainerService, can't create cache");
+            return false;
+        }       
+
+        try {
+            clusterGroupContainerService.createCache("frm.originalSwGroupView",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.installedSwGroupView",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.inactiveGroups",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.nodeGroups",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            
+//TODO for cluster mode
+           /* clusterGroupContainerService.createCache(WORK_STATUS_CACHE,
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
+
+            clusterGroupContainerService.createCache(WORK_ORDER_CACHE,
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));*/
+            
+        } catch (CacheConfigException cce) {            
+            logger.error("Group CacheConfigException");
+            return false;
+            
+        } catch (CacheExistException cce) {
+            logger.error(" Group CacheExistException");           
+        }
+        
+        return true;
+    }
+    
+    private void nonClusterGroupObjectCreate() {
+        originalSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+        installedSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+        nodeGroups = new ConcurrentHashMap<Node, List<Group>>();        
+        inactiveGroups = new ConcurrentHashMap<GroupKey, Group>();
+    }
+    
+    @SuppressWarnings({ "unchecked" })
+    private boolean retrieveGroupCaches() {
+        ConcurrentMap<?, ?> map;
+
+        if (this.clusterGroupContainerService == null) {
+            logger.warn("Group: un-initialized clusterGroupContainerService, can't retrieve cache");
+            nonClusterGroupObjectCreate();
+            return false;
+        }       
+
+        map = clusterGroupContainerService.getCache("frm.originalSwGroupView");
+        if (map != null) {
+            originalSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(originalSwGroupView) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.installedSwGroupView");
+        if (map != null) {
+            installedSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(installedSwGroupView) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.inactiveGroups");
+        if (map != null) {
+            inactiveGroups = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(inactiveGroups) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.nodeGroups");
+        if (map != null) {
+            nodeGroups = (ConcurrentMap<Node, List<Group>>) map;
+        } else {
+            logger.error("Retrieval of cache(nodeGroup) failed");
+            return false;
+        }
+        
+        return true;
+    }
+       
+    private boolean cacheStartup() {
+        if (allocateGroupCaches()) {
+            if (retrieveGroupCaches()) {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
+    public Status validateGroup(Group group, FRMUtil.operation operation) {
+        String containerName;
+        String groupName;
+        Iterator<Bucket> bucketIterator;
+        boolean returnResult;
+        Buckets groupBuckets;
+        
+        if (null != group) {
+            containerName = group.getContainerName();
+            
+            if (null == containerName) {
+                containerName = GlobalConstants.DEFAULT.toString();
+            }
+            else if (!FRMUtil.isNameValid(containerName)) {
+                logger.error("Container Name is invalid %s" + containerName);
+                return new Status(StatusCode.BADREQUEST, "Container Name is invalid");
+            }
+            
+            groupName = group.getGroupName();
+            if (!FRMUtil.isNameValid(groupName)) {
+                logger.error("Group Name is invalid %s" + groupName);
+                return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
+            }
+            
+            returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
+            
+            if (FRMUtil.operation.ADD == operation && returnResult) {
+                logger.error("Record with same Group Name exists");
+                return new Status(StatusCode.BADREQUEST, "Group record exists");
+            }
+            else if (!returnResult) {
+                logger.error("Group record does not exist");
+                return new Status(StatusCode.BADREQUEST, "Group record does not exist");
+            }
+            
+            if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() && 
+                    group.getGroupType().getIntValue() <= GroupType.GroupFf.getIntValue())) {
+                logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
+                return new Status(StatusCode.BADREQUEST, "Invalid Group type");                
+            }
+            
+            groupBuckets = group.getBuckets();
+                    
+            if (null != groupBuckets && null != groupBuckets.getBucket()) {
+                bucketIterator = groupBuckets.getBucket().iterator();
+                
+                while (bucketIterator.hasNext()) {
+                    if(!(FRMUtil.areActionsValid(bucketIterator.next().getActions()))) {
+                        logger.error("Error in action bucket");
+                        return new Status(StatusCode.BADREQUEST, "Invalid Group bucket contents");
+                    }                                
+                }
+            }                
+        }
+        
+        return new Status(StatusCode.SUCCESS);
+        
+    }
+    
+    private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
+        if (! originalSwGroupView.containsKey(key)) {
+            return false;
+        }
+        
+        for (ConcurrentMap.Entry<GroupKey, Group> entry : originalSwGroupView.entrySet()) {
+            if (entry.getValue().getGroupName().equals(groupName)) {
+                if (entry.getValue().getContainerName().equals(containerName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    
+    /**
+     * Update Group entries to the southbound plugin/inventory and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private Status updateGroup(InstanceIdentifier<?> path, Group groupUpdateDataObject) {
+        GroupKey groupKey = groupUpdateDataObject.getKey();
+        Status groupOperationStatus = validateGroup(groupUpdateDataObject, FRMUtil.operation.UPDATE);
+        
+        if (!groupOperationStatus.isSuccess()) {
+            logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName());
+            return groupOperationStatus;
+        }
+            
+        originalSwGroupView.remove(groupKey);
+        originalSwGroupView.put(groupKey, groupUpdateDataObject);
+        
+        if (groupUpdateDataObject.isInstall()) {
+            UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
+            //TODO how to get original group and modified group. 
+            
+            if (installedSwGroupView.containsKey(groupKey)) {
+                installedSwGroupView.remove(groupKey);
+            }
+            
+            installedSwGroupView.put(groupKey, groupUpdateDataObject);
+            groupService.updateGroup(groupData.build());
+        }
+        
+        return groupOperationStatus;
+    }
+    
+    /**
+     * Adds Group to the southbound plugin and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private Status addGroup(InstanceIdentifier<?> path, Group groupAddDataObject) {
+        GroupKey groupKey = groupAddDataObject.getKey();
+        Status groupOperationStatus = validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+        
+        if (!groupOperationStatus.isSuccess()) {
+            logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
+            return groupOperationStatus;
+        }
+        validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+        originalSwGroupView.put(groupKey, groupAddDataObject);
+        
+        if (groupAddDataObject.isInstall()) {
+            AddGroupInputBuilder groupData = new AddGroupInputBuilder();
+            groupData.setBuckets(groupAddDataObject.getBuckets());
+            groupData.setContainerName(groupAddDataObject.getContainerName());
+            groupData.setGroupId(groupAddDataObject.getGroupId());
+            groupData.setGroupType(groupAddDataObject.getGroupType());
+            groupData.setNode(groupAddDataObject.getNode());  
+            installedSwGroupView.put(groupKey, groupAddDataObject);
+            groupService.addGroup(groupData.build());
+        }
+        
+        return groupOperationStatus;
+    }
+    
+       private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
+        for(Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+            
+            if (!addGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+                return Rpcs.getRpcResult(false, null, null);
+            }
+        }
+        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+           
+            if (!updateGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+                return Rpcs.getRpcResult(false, null, null);
+            }
+        }
+        
+        for(InstanceIdentifier<?> removal : transaction.removals) {
+           // removeFlow(removal);
+        }
+        
+        return Rpcs.getRpcResult(true, null, null);
+    }
+    
+    private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
+
+         @SuppressWarnings("unchecked")
+        @Override
+         public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+             // We should verify transaction
+             System.out.println("Coming in FlowDatacommitHandler");
+             internalTransaction transaction = new internalTransaction(modification);
+             transaction.prepareUpdate();
+             return transaction;
+         }
+    }
+
+    private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+
+        private final DataModification<InstanceIdentifier<?>, DataObject> modification;
+
+        @Override
+        public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
+            return modification;
+        }
+
+        public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+            this.modification = modification;
+        }
+
+        Map<InstanceIdentifier<?>, Group> additions = new HashMap<>();
+        Map<InstanceIdentifier<?>, Group> updates = new HashMap<>();
+        Set<InstanceIdentifier<?>> removals = new HashSet<>();
+
+        /**
+         * We create a plan which flows will be added, which will be updated and
+         * which will be removed based on our internal state.
+         * 
+         */
+        void prepareUpdate() {
+
+            Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
+            for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+                if (entry.getValue() instanceof Group) {                    
+                    Group group = (Group) entry.getValue();                    
+                    preparePutEntry(entry.getKey(), group);
+                }
+
+            }
+
+            removals = modification.getRemovedConfigurationData();
+        }
+
+        private void preparePutEntry(InstanceIdentifier<?> key, Group group) {
+            
+            Group original = originalSwGroupView.get(key);
+            if (original != null) {
+                // It is update for us
+                
+                updates.put(key, group);               
+            } else {
+                // It is addition for us
+                
+                additions.put(key, group);
+            }
+        }
+
+        /**
+         * We are OK to go with execution of plan
+         * 
+         */
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+            
+            RpcResult<Void> rpcStatus = commitToPlugin(this);
+            // We return true if internal transaction is successful.
+          //  return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return rpcStatus;
+        }
+
+        /**
+         * 
+         * We should rollback our preparation
+         * 
+         */
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            // NOOP - we did not modified any internal state during
+            // requestCommit phase
+           // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return Rpcs.getRpcResult(true, null, null);
+            
+        }
+        
+    }
+    
+       
+       final class GroupEventListener implements SalGroupListener {
+           
+        List<GroupAdded> addedGroups = new ArrayList<>();
+        List<GroupRemoved> removedGroups = new ArrayList<>();
+        List<GroupUpdated> updatedGroups = new ArrayList<>();
+       
+
+        @Override
+        public void onGroupAdded(GroupAdded notification) {
+            System.out.println("added Group..........................");
+            addedGroups.add(notification);            
+        }
+
+        @Override
+        public void onGroupRemoved(GroupRemoved notification) {
+            // TODO Auto-generated method stub
+            
+        }
+
+        @Override
+        public void onGroupUpdated(GroupUpdated notification) {
+            // TODO Auto-generated method stub
+            
+        }    
+    }
 }
index 241f926ae4b44c53477d6b0b938e8df164dbc084..6faf2e91782495efe48be290910f5958f80a8e92 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/opendaylight/hosttracker/implementation/src/test/resources/logback.xml b/opendaylight/hosttracker/implementation/src/test/resources/logback.xml
deleted file mode 100644 (file)
index 5fa21fe..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<configuration scan="true">\r
-\r
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
-    <encoder>\r
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
-      </pattern>\r
-    </encoder>\r
-  </appender>\r
-\r
-  <root level="error">\r
-    <appender-ref ref="STDOUT" />\r
-  </root>\r
-</configuration>\r
index 99760a68341edb9e11f0198dbec54d2089125d21..0405d45b6e1989cc186927a016794108c9ac86d2 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml b/opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml
deleted file mode 100644 (file)
index 5fa21fe..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<configuration scan="true">\r
-\r
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
-    <encoder>\r
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
-      </pattern>\r
-    </encoder>\r
-  </appender>\r
-\r
-  <root level="error">\r
-    <appender-ref ref="STDOUT" />\r
-  </root>\r
-</configuration>\r
index f822ac5d38ed7e971e45199dce3da3a28ba5265b..bb43809a5c63c4bdb08d8bc6cf2e2ca2a3a492f3 100644 (file)
     </plugins>
   </build>
   <dependencies>
+
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
     <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>sal-common-api</artifactId>
         <version>1.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-util</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+       <groupId>org.mockito</groupId>
+       <artifactId>mockito-all</artifactId>
+       <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
       <artifactId>org.eclipse.osgi</artifactId>
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/ClusteredDataStore.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/ClusteredDataStore.java
new file mode 100644 (file)
index 0000000..0a577ad
--- /dev/null
@@ -0,0 +1,18 @@
+
+/*
+ * 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
+ */
+
+
+package org.opendaylight.controller.datastore;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface ClusteredDataStore extends DataReader<InstanceIdentifier<? extends Object>, Object>, DataCommitHandler<InstanceIdentifier<? extends Object>,Object> {
+}
index 101da7ffa3474d95c4bc7a66797d172e913e4324..c94355d4f6b2597964d16a1ef5f64b293878c229 100644 (file)
@@ -9,14 +9,46 @@
 
 package org.opendaylight.controller.datastore.internal;
 
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.datastore.ClusteredDataStore;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Set;
+
 public class Activator extends ComponentActivatorAbstractBase {
     protected static final Logger logger = LoggerFactory
             .getLogger(Activator.class);
 
 
+    @Override
+    protected Object[] getGlobalImplementations(){
+       logger.debug("Calling getGlobalImplementations to return:", ClusteredDataStoreManager.class);
+        return new Object[] {
+            ClusteredDataStoreManager.class
+        };
+    }
+
+
+    @Override
+    protected void configureGlobalInstance(Component c, Object imp){
+        if (imp.equals(ClusteredDataStoreManager.class)) {
+            Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
+
+            c.setInterface(new String[] { ClusteredDataStore.class.getName() }, props);
+            logger.debug("configureGlobalInstance adding dependency:", IClusterGlobalServices.class);
+            
+            c.add(createServiceDependency().setService(
+                    IClusterGlobalServices.class).setCallbacks(
+                    "setClusterGlobalServices",
+                    "unsetClusterGlobalServices").setRequired(true));
+
+        }
+    }
+
 
 }
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStore.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStore.java
deleted file mode 100644 (file)
index 7c25b14..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.opendaylight.controller.datastore.internal;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class ClusteredDataStore implements DataReader<InstanceIdentifier<? extends Object>, Object>, DataCommitHandler<InstanceIdentifier<? extends Object>,Object> {
-    @Override
-    public DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> requestCommit(DataModification<InstanceIdentifier<? extends Object>, Object> modification) {
-        return null;
-    }
-
-    @Override
-    public Object readOperationalData(InstanceIdentifier<? extends Object> path) {
-        return null;
-    }
-
-    @Override
-    public Object readConfigurationData(InstanceIdentifier<? extends Object> path) {
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java
new file mode 100644 (file)
index 0000000..f2e7773
--- /dev/null
@@ -0,0 +1,122 @@
+
+/*
+ * 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
+ */
+
+package org.opendaylight.controller.datastore.internal;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.datastore.ClusteredDataStore;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * The ClusteredDataStoreImpl stores global data to be shared across a controller cluster. It uses Clustering Services.
+ */
+public class ClusteredDataStoreImpl implements ClusteredDataStore {
+
+
+    public static final String OPERATIONAL_DATA_CACHE = "clustered_data_store.operational_data_cache";
+    public static final String CONFIGURATION_DATA_CACHE = "clustered_data_store.configuration_data_cache";
+
+    private ConcurrentMap operationalDataCache;
+    private ConcurrentMap configurationDataCache;
+
+    public ClusteredDataStoreImpl(IClusterGlobalServices clusterGlobalServices) throws CacheExistException, CacheConfigException {
+        Preconditions.checkNotNull(clusterGlobalServices, "clusterGlobalServices cannot be null");
+
+        operationalDataCache = clusterGlobalServices.createCache(OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+        if(operationalDataCache == null){
+            Preconditions.checkNotNull(operationalDataCache, "operationalDataCache cannot be null");
+        }
+
+        configurationDataCache = clusterGlobalServices.createCache(CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+        if(configurationDataCache == null){
+            Preconditions.checkNotNull(configurationDataCache, "configurationDataCache cannot be null");
+        }
+
+    }
+
+    @Override
+    public DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> requestCommit(DataModification<InstanceIdentifier<? extends Object>, Object> modification) {
+        return new ClusteredDataStoreTransaction(modification);
+    }
+
+    @Override
+    public Object readOperationalData(InstanceIdentifier<? extends Object> path) {
+        Preconditions.checkNotNull(path, "path cannot be null");
+        return operationalDataCache.get(path);
+    }
+
+    @Override
+    public Object readConfigurationData(InstanceIdentifier<? extends Object> path) {
+        Preconditions.checkNotNull(path, "path cannot be null");
+        return configurationDataCache.get(path);
+    }
+
+    private RpcResult<Void> finish(final ClusteredDataStoreTransaction transaction) {
+      final DataModification<InstanceIdentifier<? extends Object>,Object> modification = transaction.getModification();
+
+      this.configurationDataCache.putAll(modification.getUpdatedConfigurationData());
+      this.operationalDataCache.putAll(modification.getUpdatedOperationalData());
+
+      for (final InstanceIdentifier<? extends Object> removal : modification.getRemovedConfigurationData()) {
+        this.configurationDataCache.remove(removal);
+      }
+
+      for (final InstanceIdentifier<? extends Object> removal : modification.getRemovedOperationalData()) {
+        this.operationalDataCache.remove(removal  );
+      }
+
+      Set<RpcError> _emptySet = Collections.<RpcError>emptySet();
+      return Rpcs.<Void>getRpcResult(true, null, _emptySet);
+    }
+
+    private RpcResult<Void> rollback(final ClusteredDataStoreTransaction transaction) {
+      Set<RpcError> _emptySet = Collections.<RpcError>emptySet();
+      return Rpcs.<Void>getRpcResult(true, null, _emptySet);
+    }
+
+    private class ClusteredDataStoreTransaction implements DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> {
+        private final DataModification<InstanceIdentifier<? extends Object>,Object> modification;
+
+        public ClusteredDataStoreTransaction(DataModification<InstanceIdentifier<? extends Object>,Object> modification){
+            Preconditions.checkNotNull(modification, "modification cannot be null");
+
+            this.modification = modification;
+        }
+
+        @Override
+        public DataModification<InstanceIdentifier<? extends Object>, Object> getModification() {
+            return this.modification;
+        }
+
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+            return ClusteredDataStoreImpl.this.finish(this);
+        }
+
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            return ClusteredDataStoreImpl.this.rollback(this);
+        }
+    }
+}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManager.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManager.java
new file mode 100644 (file)
index 0000000..e6acdb0
--- /dev/null
@@ -0,0 +1,75 @@
+
+/*
+ * 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
+ */
+
+
+
+package org.opendaylight.controller.datastore.internal;
+
+import com.google.common.base.Preconditions;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.datastore.ClusteredDataStore;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ClusteredDataStoreManager implements ClusteredDataStore {
+
+    private ClusteredDataStoreImpl clusteredDataStore = null;
+    private IClusterGlobalServices clusterGlobalServices = null;
+
+    @Override
+    public DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> requestCommit(DataModification<InstanceIdentifier<? extends Object>, Object> modification) {
+        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
+        return clusteredDataStore.requestCommit(modification);
+    }
+
+    @Override
+    public Object readOperationalData(InstanceIdentifier<? extends Object> path) {
+        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
+        return clusteredDataStore.readOperationalData(path);
+    }
+
+    @Override
+    public Object readConfigurationData(InstanceIdentifier<? extends Object> path) {
+        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
+        return clusteredDataStore.readConfigurationData(path);
+    }
+
+
+    public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices){
+        this.clusterGlobalServices = clusterGlobalServices;
+    }
+
+    public void unsetClusterGlobalServices(IClusterGlobalServices clusterGlobalServices){
+        this.clusterGlobalServices = null;
+        this.clusteredDataStore = null;
+    }
+
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        try {
+               //Adding creation of the clustered data store in its own method to make the method unit testable
+            clusteredDataStore = createClusteredDataStore(c);
+        } catch (CacheExistException e) {
+            throw new IllegalStateException("could not construct clusteredDataStore");
+        } catch (CacheConfigException e) {
+            throw new IllegalStateException("could not construct clusteredDataStore");
+        }
+    }
+    protected ClusteredDataStoreImpl createClusteredDataStore(Component c) throws CacheExistException,CacheConfigException{
+       return  new ClusteredDataStoreImpl(clusterGlobalServices);
+    }
+}
index d36e9baf2c956a68c787f8271888749e5cc71a75..5ced9d9a411d80da96a72fc9d2fe9c98c0ae4e00 100644 (file)
@@ -1,13 +1,70 @@
+
+/*
+ * 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
+ */
+
 package org.opendaylight.controller.datastore.internal;
 
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ServiceDependency;
+
+import org.junit.BeforeClass;
 import org.junit.Test;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 
 import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class ActivatorTest {
 
+       private static  ServiceDependency serviceDependency;
+       
+       @BeforeClass 
+       public static void initialize(){
+               serviceDependency = mock(ServiceDependency.class);
+       }
+       
+       private class ActivatorTestImpl extends Activator{
+                protected ServiceDependency createServiceDependency() {
+                       return ActivatorTest.serviceDependency;
+                   }
+       }
+       
     @Test
     public void construct(){
         assertNotNull(new Activator());
     }
+    
+    @Test
+    public void construct_OnInvokeOfGlobalImpl_ShouldReturnNotNullObject(){
+        Activator activator = new Activator();
+        
+        assertNotNull(activator.getGlobalImplementations());
+        assertEquals(ClusteredDataStoreManager.class,activator.getGlobalImplementations()[0]);
+    }
+    
+    @Test
+    public void construct_OnInvokeOfConfigGlobalInstance_ShouldNotThrowAnyExceptions(){
+       Activator activator = new ActivatorTestImpl();
+       
+       Component c = mock(Component.class);
+       Object clusterDataStoreMgr = ClusteredDataStoreManager.class;
+       
+       when(serviceDependency.setService(IClusterGlobalServices.class)).thenReturn(serviceDependency);
+       when(serviceDependency.setCallbacks("setClusterGlobalServices",
+                    "unsetClusterGlobalServices")).thenReturn(serviceDependency);
+       when(serviceDependency.setRequired(true)).thenReturn(serviceDependency);
+       
+       
+       activator.configureGlobalInstance(c, clusterDataStoreMgr);
+       
+       
+    }
+    
 }
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java
new file mode 100644 (file)
index 0000000..8049bae
--- /dev/null
@@ -0,0 +1,248 @@
+package org.opendaylight.controller.datastore.internal;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ClusteredDataStoreImplTest {
+    @Before
+    public void setUp(){
+
+    }
+
+    @Test
+    public void constructor_WhenPassedANullClusteringServices_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+        try {
+            new ClusteredDataStoreImpl(null);
+        } catch(NullPointerException npe){
+            assertEquals("clusterGlobalServices cannot be null", npe.getMessage());
+        }
+    }
+
+    @Test
+    public void constructor_WhenClusteringServicesReturnsANullOperationalDataCache_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+        try {
+            new ClusteredDataStoreImpl(mock(IClusterGlobalServices.class));
+        } catch(NullPointerException npe){
+            assertEquals("operationalDataCache cannot be null", npe.getMessage());
+        }
+    }
+
+    @Test
+    public void constructor_WhenClusteringServicesReturnsANullOConfigurationDataCache_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+        // Confused about the following line?
+        // See this http://stackoverflow.com/questions/10952629/a-strange-generics-edge-case-with-mockito-when-and-generic-type-inference
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(new ConcurrentHashMap<Object, Object>());
+
+
+        try {
+            new ClusteredDataStoreImpl(mockClusterGlobalServices);
+        } catch(NullPointerException npe){
+            assertEquals("configurationDataCache cannot be null", npe.getMessage());
+        }
+    }
+
+    @Test
+    public void constructor_WhenPassedAValidClusteringServices_ShouldNotThrowAnyExceptions() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+        new ClusteredDataStoreImpl(mockClusterGlobalServices);
+    }
+
+
+    @Test
+    public void readOperationalData_WhenPassedANullPath_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        try {
+            store.readOperationalData(null);
+        } catch(NullPointerException npe){
+            assertEquals("path cannot be null", npe.getMessage());
+        }
+    }
+
+    @Test
+    public void readOperationalData_WhenPassedAKeyThatDoesNotExistInTheCache_ShouldReturnNull() throws CacheExistException, CacheConfigException {
+        InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
+
+        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        assertNull(store.readOperationalData(path));
+    }
+
+    @Test
+    public void readOperationalData_WhenPassedAKeyThatDoesExistInTheCache_ShouldReturnTheValueObject() throws CacheExistException, CacheConfigException {
+        InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
+
+        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+        ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
+
+        Object valueObject = mock(Object.class);
+
+        when(mockOperationalDataCache.get(path)).thenReturn(valueObject);
+
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(new ConcurrentHashMap<Object, Object>());
+
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        assertEquals(valueObject, store.readOperationalData(path));
+    }
+
+
+
+    @Test
+    public void readConfigurationData_WhenPassedANullPath_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+
+        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        try {
+            store.readConfigurationData(null);
+        } catch(NullPointerException npe){
+            assertEquals("path cannot be null", npe.getMessage());
+        }
+    }
+
+
+    @Test
+    public void readConfigurationData_WhenPassedAKeyThatDoesNotExistInTheCache_ShouldReturnNull() throws CacheExistException, CacheConfigException {
+        InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
+
+        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        assertNull(store.readConfigurationData(path));
+    }
+
+    @Test
+    public void readConfigurationData_WhenPassedAKeyThatDoesExistInTheCache_ShouldReturnTheValueObject() throws CacheExistException, CacheConfigException {
+        InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
+
+        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+        ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
+
+        Object valueObject = mock(Object.class);
+
+        when(mockConfigurationDataCache.get(path)).thenReturn(valueObject);
+
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
+
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        assertEquals(valueObject, store.readConfigurationData(path));
+    }
+
+
+    @Test
+    public void requestCommit_ShouldReturnADataTransaction() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        assertNotNull(store.requestCommit(mock(DataModification.class)));
+
+
+    }
+
+    @Test
+    public void finishingADataTransaction_ShouldUpdateTheUnderlyingCache() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+        ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
+        ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
+
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        DataModification mockModification = mock(DataModification.class);
+
+        Map configurationData = mock(Map.class);
+        Map operationalData = mock(Map.class);
+
+        when(mockModification.getUpdatedConfigurationData()).thenReturn(configurationData);
+        when(mockModification.getUpdatedOperationalData()).thenReturn(operationalData);
+
+        DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> transaction = store.requestCommit(mockModification);
+
+        transaction.finish();
+
+        verify(mockConfigurationDataCache).putAll(mockModification.getUpdatedConfigurationData());
+        verify(mockOperationalDataCache).putAll(mockModification.getUpdatedOperationalData());
+    }
+
+
+    @Test
+    public void rollingBackADataTransaction_ShouldDoNothing() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+        ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
+        ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
+
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
+
+        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        DataModification mockModification = mock(DataModification.class);
+
+        Map configurationData = mock(Map.class);
+        Map operationalData = mock(Map.class);
+
+        when(mockModification.getUpdatedConfigurationData()).thenReturn(configurationData);
+        when(mockModification.getUpdatedOperationalData()).thenReturn(operationalData);
+
+        DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> transaction = store.requestCommit(mockModification);
+
+        transaction.rollback();
+
+        verify(mockConfigurationDataCache, never()).putAll(mockModification.getUpdatedConfigurationData());
+        verify(mockOperationalDataCache, never()).putAll(mockModification.getUpdatedOperationalData());
+
+    }
+
+
+    private IClusterGlobalServices createClusterGlobalServices() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
+
+        return mockClusterGlobalServices;
+    }
+}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java
new file mode 100644 (file)
index 0000000..84b07e7
--- /dev/null
@@ -0,0 +1,122 @@
+package org.opendaylight.controller.datastore.internal;
+
+import org.apache.felix.dm.Component;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+public class ClusteredDataStoreManagerTest {
+       
+       private  static ClusteredDataStoreManager clusteredDSMgr = null;
+       private IClusterGlobalServices icClusterGlbServices =  mock(IClusterGlobalServices.class);
+        
+       @BeforeClass
+       public static void construct(){
+               clusteredDSMgr = new ClusteredDataStoreManager();
+        assertNotNull(clusteredDSMgr);
+       }
+        
+       @Test
+       public void construct_OnSetClusterGlobalServices_AssertNoException(){
+               icClusterGlbServices =  mock(IClusterGlobalServices.class);
+                
+               clusteredDSMgr.setClusterGlobalServices(icClusterGlbServices);
+        }
+        
+        @Test
+        public void construct_OnUnSetClusterGlobalServices_AssertNoException(){
+                IClusterGlobalServices icClusterGlbServices =  mock(IClusterGlobalServices.class);
+                
+                clusteredDSMgr.unsetClusterGlobalServices(icClusterGlbServices);
+        }
+        
+        @Test
+        public void construct_init_AssertNoException() throws CacheExistException,CacheConfigException{
+                ClusteredDataStoreImpl clusteredDSImpl =  mock(ClusteredDataStoreImpl.class);
+                
+                ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+                doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+                Component c = mock(Component.class);
+                
+                clusteredDSManager.init(c);
+        }
+        
+        @Test(expected = IllegalStateException.class)
+        public void construct_init_AssertCacheExistException() throws CacheExistException,CacheConfigException{
+                ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+                doThrow(CacheExistException.class).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+                Component c = mock(Component.class);
+                
+                clusteredDSManager.init(c);
+        }
+        
+        @Test(expected = IllegalStateException.class)
+        public void construct_init_AssertCacheConfigException() throws CacheExistException,CacheConfigException{
+                ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+                doThrow(CacheConfigException.class).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+                Component c = mock(Component.class);
+                
+                clusteredDSManager.init(c);
+        }
+        
+        @Test
+        public void construct_readOperationalData_AssertNoException() throws CacheExistException,CacheConfigException{
+                ClusteredDataStoreImpl clusteredDSImpl =  mock(ClusteredDataStoreImpl.class);
+                
+                ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+                doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+                Component c = mock(Component.class);
+                
+                clusteredDSManager.init(c);
+                
+                Object o = mock(Object.class);
+                
+                when(clusteredDSImpl.readOperationalData(any(InstanceIdentifier.class))).thenReturn(o);
+                assertEquals(o,clusteredDSManager.readOperationalData(any(InstanceIdentifier.class)));
+        }
+        
+        
+        @Test
+        public void construct_readConfigurationData_AssertNoException() throws CacheExistException,CacheConfigException{
+                ClusteredDataStoreImpl clusteredDSImpl =  mock(ClusteredDataStoreImpl.class);
+                
+                ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+                doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+                Component c = mock(Component.class);
+                
+                clusteredDSManager.init(c);
+                Object o = mock(Object.class);
+                
+                when(clusteredDSImpl.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(o);
+                assertEquals(o,clusteredDSManager.readConfigurationData(any(InstanceIdentifier.class)));
+        }
+        
+        @Test
+        public void construct_requestCommit_AssertNoException() throws CacheExistException,CacheConfigException{
+                ClusteredDataStoreImpl clusteredDSImpl =  mock(ClusteredDataStoreImpl.class);
+                
+                ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+                doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+                Component c = mock(Component.class);
+                
+                clusteredDSManager.init(c);
+                DataCommitTransaction dataCommitTransaction = mock(DataCommitTransaction.class);
+                
+                when(clusteredDSImpl.requestCommit(any(DataModification.class))).thenReturn(dataCommitTransaction);
+                assertEquals(dataCommitTransaction,clusteredDSManager.requestCommit(any(DataModification.class)));
+        }
+}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreTest.java b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreTest.java
deleted file mode 100644 (file)
index 7a8e8e8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.opendaylight.controller.datastore.internal;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertNotNull;
-
-public class ClusteredDataStoreTest {
-    @Test
-    public void construct(){
-        assertNotNull(new ClusteredDataStore());
-    }
-}
index 8e77d26ea4afe61eea770873fea7d05a7bbd4818..03e36924e77968ab2815f9b391055945a62dc69b 100644 (file)
@@ -41,6 +41,10 @@ module opendaylight-group-types {
             type string; 
         }
         
+        leaf barrier {
+            type boolean; 
+        }       
+        
         container buckets {
             list bucket {
                 key "order";
index 99d4588cbc85b2491c3f06a346014b9072130b2e..20353af7852bd0b46834e7ad61364b222ec89640 100644 (file)
@@ -85,6 +85,17 @@ module opendaylight-meter-types {
             type meter-id;
         }
         
+        leaf install {
+            type boolean; 
+        }
+        leaf meter-name {
+            type string;
+        }
+        
+        leaf container-name {
+            type string; 
+        }
+        
         container meter-band-headers {
             list meter-band-header {
                 key "order";
index 6a83f75959edd624c35b43bf9de08290197ba89b..8338d185cc36abbbbc34613fe1e3df84d805550a 100644 (file)
@@ -20,10 +20,10 @@ module opendaylight-port-types {
     }
     
     typedef port-state {
-            type enumeration {
-                enum link-down;
-                enum blocked;
-                enum live;
+        type enumeration {
+            enum link-down;
+            enum blocked;
+            enum live;
         }
     }
 
@@ -125,7 +125,7 @@ module opendaylight-port-types {
                 uses common-port;
                 
                 leaf mask {
-                    type uint32;
+                    type port-config;
                     description "Bitmap of OFPPC-* flags to be changed";
                 }      
                 
@@ -135,7 +135,11 @@ module opendaylight-port-types {
             
                 leaf port-name {
                     type string; 
-                }                
+                } 
+
+                leaf barrier {
+                    type boolean; 
+                } 
             }            
         }    
     }
index 579ce70c626227234f7d07fbe7a2451b9fb4f81c..111d3d60faaf29fcfff6e93f05be3bad10b089e5 100644 (file)
@@ -11,11 +11,9 @@ module meter-management {
     }
 
     grouping meter-entry {
-    
         leaf node {
             type inv:node-ref;
         }
-        
         uses meter:meter;
     }   
      
diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang
new file mode 100644 (file)
index 0000000..483c0c9
--- /dev/null
@@ -0,0 +1,46 @@
+module flow-capable-transaction {
+       namespace "urn:opendaylight:flow:transaction";
+    prefix type;
+
+    import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    
+    revision "2013-11-03" {
+        description "Initial revision";
+    }
+
+    typedef transaction-id {
+       type uint64;
+    }
+    
+    grouping transaction-aware {
+        leaf transaction-id {
+            type transaction-id;
+        }
+    }
+
+    rpc get-next-transaction-id {
+        input {
+            leaf node {
+                ext:context-reference "inv:node-context";
+                type inv:node-ref;
+            }
+        }
+        output {
+               uses transaction-aware;
+        }
+    }
+
+    // Barier request?
+    rpc finish-transaction {
+        input {
+            leaf node {
+                ext:context-reference "inv:node-context";
+                type inv:node-ref;
+            }
+            leaf transaction-id {
+                type transaction-id;
+            }
+        }
+    }
+}
\ No newline at end of file
index fba1c0829c96b032f4094f82df13198b8a124730..bb010353280b8fa281c0901dde2e8d771f62ac13 100644 (file)
@@ -6,14 +6,14 @@ module sal-group {
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import ietf-inet-types {prefix inet;revision-date 2010-09-24;}
     import opendaylight-group-types {prefix group-type;revision-date 2013-10-18;}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-09-18" {
         description "Initial revision of group service";
     }        
     
     grouping node-group {
-        uses "inv:node-context-ref";
-        
+        uses "inv:node-context-ref";        
         uses group-type:group;
     }
 
@@ -32,18 +32,30 @@ module sal-group {
     rpc add-group {
         input {
             uses node-group;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc remove-group {
         input {
             uses group-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc update-group {
         input {
             uses group-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     } 
 
index d3777ff3320468bc55b5307ae6bdff61d016ae23..c187181e5e89099cc4720031cd3fa888629d69a2 100644 (file)
@@ -5,6 +5,7 @@ module sal-meter {
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-meter-types {prefix meter-type;revision-date "2013-09-18";}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-09-18" {
         description "Initial revision of meter service";
@@ -31,18 +32,30 @@ module sal-meter {
     rpc add-meter {
         input {
             uses node-meter;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc remove-meter {
         input {
             uses node-meter;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc update-meter {
         input {
             uses meter-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
         
diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang
new file mode 100644 (file)
index 0000000..df527ef
--- /dev/null
@@ -0,0 +1,46 @@
+module sal-port {
+    namespace "urn:opendaylight:port:service";
+    prefix port;
+
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import opendaylight-port-types {prefix port-type;revision-date "2013-09-25";}
+
+    revision "2013-11-07" {
+        description "Initial revision of port service";
+    }        
+    
+    grouping node-port {
+        uses "inv:node-context-ref";
+        
+        uses port-type:ofp-port-mod;
+    }
+
+    /** Base configuration structure **/
+    grouping port-update {
+        uses "inv:node-context-ref";
+
+        container original-port {
+            uses port-type:ofp-port-mod;
+        }
+        container updated-port {
+            uses port-type:ofp-port-mod;
+        }
+    }
+
+    rpc update-port {
+        input {
+            uses port-update;
+        }
+    }
+     
+    rpc get-port {
+        output {
+            uses port-type:flow-capable-port;
+        }
+    }  
+    
+    notification port-removed {
+        uses node-port;
+    }
+}
\ No newline at end of file
index e740f961d5a83d234342a94aa151d476f001b9cf..3a6f20f77d9554dda1812311e7510414d1a6658a 100644 (file)
@@ -5,13 +5,15 @@ module sal-table {
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-10-26" {
         description "Initial revision of table service";
-    }        
+    }
     
     /** Base configuration structure **/
     grouping table-update {
+        uses "inv:node-context-ref";
         container original-table {
             uses table-type:table-features;
         }
@@ -22,11 +24,11 @@ module sal-table {
     
     rpc update-table {
         input {
-            leaf node {
-                ext:context-reference "inv:node-context";
-                type inv:node-ref;
-            }
             uses table-update;
+            uses tr:transaction-aware;
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }     
 }
\ No newline at end of file
index fd89da4dd0c0e2b7876e8e0adcf6f90d87fc6cff..1ff7f2dc302e1218f8a494cdb0b4f0c9811a7548 100644 (file)
@@ -49,7 +49,6 @@
         <module>compatibility</module>
 
         <module>sal-zeromq-connector</module>
-        <module>test</module>
     </modules>
 
 
@@ -62,6 +61,7 @@
             <modules>
                 <module>sal-binding-it</module>
                 <module>clustered-data-store/integrationtest</module>
+                <module>test</module>
             </modules>
         </profile>
     </profiles>
     <build>
         <pluginManagement>
             <plugins>
-                <!--This plugin's configuration is used to store Eclipse
-                    m2e settings only. It has no influence on the Maven build itself. -->
-                <plugin>
-                    <groupId>org.eclipse.m2e</groupId>
-                    <artifactId>lifecycle-mapping</artifactId>
-                    <version>1.0.0</version>
-                    <configuration>
-                        <lifecycleMappingMetadata>
-                            <pluginExecutions>
-                                <pluginExecution>
-                                  <pluginExecutionFilter>
-                                    <groupId>org.jacoco</groupId>
-                                    <artifactId>jacoco-maven-plugin</artifactId>
-                                    <versionRange>[0.0,)</versionRange>
-                                    <goals>
-                                      <goal>prepare-agent</goal>
-                                      <goal>pre-test</goal>
-                                      <goal>post-test</goal>
-                                    </goals>
-                                  </pluginExecutionFilter>
-                                  <action>
-                                    <ignore />
-                                  </action>
-                                </pluginExecution>
-                            </pluginExecutions>
-                        </lifecycleMappingMetadata>
-                    </configuration>
-                </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-release-plugin</artifactId>
                             <pluginExecutions>
                                 <pluginExecution>
                                     <pluginExecutionFilter>
-                                        <groupId>
-                                            org.opendaylight.yangtools
-                                        </groupId>
-                                        <artifactId>
-                                            yang-maven-plugin
-                                        </artifactId>
-                                        <versionRange>
-                                            [0.5,)
-                                        </versionRange>
+                                        <groupId>org.opendaylight.yangtools</groupId>
+                                        <artifactId>yang-maven-plugin</artifactId>
+                                        <versionRange>[0,)</versionRange>
+                                        <goals>
+                                            <goal>generate-sources</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore/>
+                                    </action>
+                                </pluginExecution>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>net.alchim31.maven</groupId>
+                                        <artifactId>scala-maven-plugin</artifactId>
+                                        <versionRange>[0,)</versionRange>
                                         <goals>
-                                            <goal>
-                                                generate-sources
-                                            </goal>
+                                            <goal>compile</goal>
+                                            <goal>testCompile</goal>
                                         </goals>
                                     </pluginExecutionFilter>
                                     <action>
-                                        <ignore></ignore>
+                                      <ignore/>
                                     </action>
                                 </pluginExecution>
                                 <pluginExecution>
                                     <pluginExecutionFilter>
                                         <groupId>org.jacoco</groupId>
-                                        <artifactId>
-                                            jacoco-maven-plugin
-                                        </artifactId>
-                                        <versionRange>
-                                            [0.5.3.201107060350,)
-                                        </versionRange>
+                                        <artifactId>jacoco-maven-plugin</artifactId>
+                                        <versionRange>[0,)</versionRange>
                                         <goals>
                                             <goal>prepare-agent</goal>
                                         </goals>
                                     </pluginExecutionFilter>
                                     <action>
-                                        <ignore></ignore>
+                                        <ignore/>
                                     </action>
                                 </pluginExecution>
                             </pluginExecutions>
index 9ca025b393911d11ede993899a32e2488939c8a2..35264e74e6bd22bf1a69db6f97c3884270d3a5a5 100644 (file)
@@ -16,6 +16,7 @@
 
     <build>
         <plugins>
+        
             <plugin>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-maven-plugin</artifactId>
                     <dependency>
                         <groupId>org.opendaylight.controller</groupId>
                         <artifactId>yang-jmx-generator-plugin</artifactId>
-                        <version>0.2.2-SNAPSHOT</version>
+                        <version>0.2.3-SNAPSHOT</version>
                     </dependency>
                 </dependencies>
             </plugin>
+            
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <version>${osgi.core.version}</version>
+        <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>javassist</artifactId>
             <version>3.17.1-GA</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-impl</artifactId>
+            <version>0.6.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>runtime</scope>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <groupId>org.eclipse.xtend</groupId>
             <artifactId>org.eclipse.xtend.lib</artifactId>
         </dependency>
+       <dependency>
+       <groupId>org.eclipse.xtend</groupId>
+       <artifactId>org.eclipse.xtend.standalone</artifactId>
+       <version>2.4.3</version>
+       <scope>runtime</scope>
+       </dependency> 
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-config</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-service</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-util</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>${slf4j.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
index 87cc42c6e413d15502c068431da14d10c851fc99..ea6dc131c6583b3587b23cc172e61f62c3ad68af 100644 (file)
@@ -33,7 +33,7 @@ import java.util.Arrays
 import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
 import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
 import java.util.HashSet
-import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.*
+import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker
 import java.util.Set
index d9a3dd547f67a1cc448272f7d0a67c2284fb9ddb..31d5d0126fc8115546d1d1b7709671e946b2e026 100644 (file)
@@ -40,10 +40,11 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
 import org.opendaylight.yangtools.yang.binding.BaseIdentity
 import com.google.common.collect.Multimap
 import com.google.common.collect.HashMultimap
-import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.*
+import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
 import java.util.concurrent.Executors
 import java.util.Collections
 import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.sal.binding.impl.connect.dom.ConnectorActivator
 
 class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
     private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl)
@@ -86,7 +87,8 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
     
     ServiceRegistration<DataBrokerService> dataConsumerRegistration
     
-    private HashMapDataStore store = new HashMapDataStore();
+    ConnectorActivator connectorActivator
+   
     
     public new(BundleContext bundleContext) {
         _brokerBundleContext = bundleContext;
@@ -115,11 +117,9 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
         notifyConsumerRegistration = brokerBundleContext.registerService(NotificationService, notifyBroker, brokerProperties)
         dataProviderRegistration = brokerBundleContext.registerService(DataProviderService, dataBroker, brokerProperties)
         dataConsumerRegistration = brokerBundleContext.registerService(DataBrokerService, dataBroker, brokerProperties)
-        
-        
-        getDataBroker().registerDataReader(root, store);
-        getDataBroker().registerCommitHandler(root, store)
-        
+
+        connectorActivator = new ConnectorActivator(dataBroker,brokerBundleContext);
+        connectorActivator.start();
         log.info("MD-SAL: Binding Aware Broker Started");
     }
 
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java
new file mode 100644 (file)
index 0000000..7a1ca11
--- /dev/null
@@ -0,0 +1,93 @@
+package org.opendaylight.controller.sal.binding.impl;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+
+public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier<? extends DataObject>, DataObject, DataChangeListener> implements
+        DataProviderService {
+
+    public DataBrokerImpl() {
+        setDataReadRouter(new BindingAwareDataReaderRouter());
+    }
+
+    @Override
+    public DataTransactionImpl beginTransaction() {
+        return new DataTransactionImpl(this);
+    }
+
+    @Override
+    public <T extends DataRoot> T getData(DataStoreIdentifier store, Class<T> rootType) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T extends DataRoot> T getData(DataStoreIdentifier store, T filter) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, Class<T> rootType) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, T filter) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public RpcResult<DataRoot> editCandidateData(DataStoreIdentifier store, DataRoot changeSet) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> commit(DataStoreIdentifier store) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public DataObject getData(InstanceIdentifier<? extends DataObject> data) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public DataObject getConfigurationData(InstanceIdentifier<?> data) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void registerChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener changeListener) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void unregisterChangeListener(InstanceIdentifier<? extends DataObject> path,
+            DataChangeListener changeListener) {
+        // TODO Auto-generated method stub
+        
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend
deleted file mode 100644 (file)
index 6ed63b2..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.opendaylight.controller.sal.binding.impl
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
-import org.opendaylight.yangtools.concepts.ListenerRegistration
-import com.google.common.collect.Multimap
-import static com.google.common.base.Preconditions.*;
-import java.util.List
-import com.google.common.collect.HashMultimap
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Callable
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.controller.sal.common.util.Rpcs
-import java.util.Collections
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
-import java.util.ArrayList
-import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration
-import java.util.Arrays
-
-class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderService {
-
-    @Property
-    var ExecutorService executor;
-
-    val dataReadRouter = new BindingAwareDataReaderRouter;
-
-    Multimap<InstanceIdentifier, DataChangeListenerRegistration> listeners = HashMultimap.create();
-    Multimap<InstanceIdentifier, DataCommitHandlerRegistration> commitHandlers = HashMultimap.create();
-
-    override beginTransaction() {
-        return new DataTransactionImpl(this);
-    }
-
-    override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
-        return dataReadRouter.readConfigurationData(path);
-    }
-
-    override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
-        return dataReadRouter.readOperationalData(path);
-    }
-
-    override registerCommitHandler(InstanceIdentifier<? extends DataObject> path,
-        DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
-            val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
-            commitHandlers.put(path,registration)
-            return registration;
-    }
-
-    override registerDataChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener listener) {
-        val reg = new DataChangeListenerRegistration(path, listener, this);
-        listeners.put(path, reg);
-        return reg;
-    }
-
-    override registerDataReader(InstanceIdentifier<? extends DataObject> path,DataReader<InstanceIdentifier<? extends DataObject>,DataObject> reader) {
-        
-        val confReg = dataReadRouter.registerConfigurationReader(path,reader);
-        val dataReg = dataReadRouter.registerOperationalReader(path,reader);
-        
-        return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg));
-    }
-
-    protected def removeListener(DataChangeListenerRegistration registration) {
-        listeners.remove(registration.path, registration);
-    }
-
-    protected def removeCommitHandler(DataCommitHandlerRegistration registration) {
-        commitHandlers.remove(registration.path, registration);
-    }
-    
-    protected def getActiveCommitHandlers() {
-        return commitHandlers.entries.map[ value.instance].toSet
-    }
-
-    protected def commit(DataTransactionImpl transaction) {
-        checkNotNull(transaction);
-        transaction.changeStatus(TransactionStatus.SUBMITED);
-        val task = new TwoPhaseCommit(transaction, this);
-        return executor.submit(task);
-    }
-
-}
-
-package class DataChangeListenerRegistration extends AbstractObjectRegistration<DataChangeListener> implements ListenerRegistration<DataChangeListener> {
-
-    DataBrokerImpl dataBroker;
-
-    @Property
-    val InstanceIdentifier<?> path;
-
-    new(InstanceIdentifier<?> path, DataChangeListener instance, DataBrokerImpl broker) {
-        super(instance)
-        dataBroker = broker;
-        _path = path;
-    }
-
-    override protected removeRegistration() {
-        dataBroker.removeListener(this);
-        dataBroker = null;
-    }
-
-}
-
-package class DataCommitHandlerRegistration //
-extends AbstractObjectRegistration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> {
-
-    DataBrokerImpl dataBroker;
-
-    @Property
-    val InstanceIdentifier<?> path;
-
-    new(InstanceIdentifier<?> path, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> instance,
-        DataBrokerImpl broker) {
-        super(instance)
-        dataBroker = broker;
-        _path = path;
-    }
-
-    override protected removeRegistration() {
-        dataBroker.removeCommitHandler(this);
-        dataBroker = null;
-    }
-
-}
-
-package class TwoPhaseCommit implements Callable<RpcResult<TransactionStatus>> {
-
-    val DataTransactionImpl transaction;
-    val DataBrokerImpl dataBroker;
-
-    new(DataTransactionImpl transaction, DataBrokerImpl broker) {
-        this.transaction = transaction;
-        this.dataBroker = broker;
-    }
-
-    override call() throws Exception {
-
-        val Iterable<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> commitHandlers = dataBroker.activeCommitHandlers;
-
-        // requesting commits
-        val List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> handlerTransactions = new ArrayList();
-        try {
-            for (handler : commitHandlers) {
-                handlerTransactions.add(handler.requestCommit(transaction));
-            }
-        } catch (Exception e) {
-            return rollback(handlerTransactions,e);
-        }
-        val List<RpcResult<Void>> results = new ArrayList();
-        try {
-            for (subtransaction : handlerTransactions) {
-                results.add(subtransaction.finish());
-            }
-        } catch (Exception e) {
-            return rollback(handlerTransactions,e);
-        }
-
-        return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
-    }
-
-    def rollback(List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> transactions,Exception e) {
-        for (transaction : transactions) {
-            transaction.rollback()
-        }
-        // FIXME return encoutered error.
-        return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
-    }
-}
index c970fc5e920db0cfbfcd8a277ec9bcaa8a109fb6..f7967beaae6471a482885535e02d2aae26a06536 100644 (file)
@@ -1,89 +1,22 @@
 package org.opendaylight.controller.sal.binding.impl;
 
-import java.util.concurrent.Future;
-
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
-import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public class DataTransactionImpl extends AbstractDataModification<InstanceIdentifier<? extends DataObject>, DataObject>
-        implements DataModificationTransaction {
-
-    private final Object identifier;
-
-    private TransactionStatus status;
-    private ListenerRegistry<DataTransactionListener> listeners;
-
-    final DataBrokerImpl broker;
 
+public class DataTransactionImpl extends AbstractDataTransaction<InstanceIdentifier<? extends DataObject>, DataObject> 
+    implements DataModificationTransaction {
+    private final ListenerRegistry<DataTransactionListener> listeners = new ListenerRegistry<DataTransactionListener>();
+    
+    
+    
     public DataTransactionImpl(DataBrokerImpl dataBroker) {
         super(dataBroker);
-        identifier = new Object();
-        broker = dataBroker;
-        status = TransactionStatus.NEW;
-        listeners = new ListenerRegistry<>();
-    }
-
-    @Override
-    public Future<RpcResult<TransactionStatus>> commit() {
-        return broker.commit(this);
-    }
-
-    @Override
-    public DataObject readConfigurationData(
-            org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
-        return broker.readConfigurationData(path);
-    }
-
-    @Override
-    public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
-        return broker.readOperationalData(path);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((broker == null) ? 0 : broker.hashCode());
-        result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        DataTransactionImpl other = (DataTransactionImpl) obj;
-        if (broker == null) {
-            if (other.broker != null)
-                return false;
-        } else if (!broker.equals(other.broker))
-            return false;
-        if (identifier == null) {
-            if (other.identifier != null)
-                return false;
-        } else if (!identifier.equals(other.identifier))
-            return false;
-        return true;
-    }
-
-    @Override
-    public TransactionStatus getStatus() {
-        return status;
-    }
-
-    @Override
-    public Object getIdentifier() {
-        return identifier;
     }
 
     @Override
@@ -91,11 +24,9 @@ public class DataTransactionImpl extends AbstractDataModification<InstanceIdenti
         return listeners.register(listener);
     }
 
-    public void changeStatus(TransactionStatus status) {
-        this.status = status;
-        Iterable<ListenerRegistration<DataTransactionListener>> listenersToNotify = listeners.getListeners();
-        for (ListenerRegistration<DataTransactionListener> listenerRegistration : listenersToNotify) {
+    protected void onStatusChange(TransactionStatus status) {
+        for (ListenerRegistration<DataTransactionListener> listenerRegistration : listeners) {
             listenerRegistration.getInstance().onStatusUpdated(this, status);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java
new file mode 100644 (file)
index 0000000..ff897aa
--- /dev/null
@@ -0,0 +1,151 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.base.Preconditions;
+
+public class BindingIndependentDataServiceConnector implements //
+        RuntimeDataProvider, //
+        DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+    private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
+
+    private BindingIndependentMappingService mappingService;
+
+    private DataBrokerService biDataService;
+
+    private DataProviderService baDataService;
+
+    @Override
+    public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+        // TODO Auto-generated method stub
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+        CompositeNode result = biDataService.readOperationalData(biPath);
+        return mappingService.dataObjectFromDataDom(path, result);
+    }
+
+    @Override
+    public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+        CompositeNode result = biDataService.readConfigurationData(biPath);
+        return mappingService.dataObjectFromDataDom(path, result);
+    }
+
+    @Override
+    public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
+            DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+
+        DataModificationTransaction translated = translateTransaction(modification);
+        return new WrappedTransaction(translated, modification);
+    }
+
+    private DataModificationTransaction translateTransaction(
+            DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
+        DataModificationTransaction target = biDataService.beginTransaction();
+        for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
+                .entrySet()) {
+            Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+                    .toDataDom(entry);
+            target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
+        }
+        for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
+                .entrySet()) {
+            Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+                    .toDataDom(entry);
+            target.putOperationalData(biEntry.getKey(), biEntry.getValue());
+        }
+        for(InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+            target.removeConfigurationData(biEntry);
+        }
+        for(InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+            target.removeOperationalData(biEntry);
+        }
+        return target;
+    }
+
+    private class WrappedTransaction implements
+            DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+        private DataModificationTransaction backing;
+        private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+
+        public WrappedTransaction(DataModificationTransaction backing,
+                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+            this.backing = backing;
+            this.modification = modification;
+        }
+
+        @Override
+        public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
+            return modification;
+        }
+
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+            Future<RpcResult<TransactionStatus>> result = backing.commit();
+            try {
+                RpcResult<TransactionStatus> biresult = result.get();
+            } catch (InterruptedException e) {
+                throw new IllegalStateException("", e);
+            } catch (ExecutionException e) {
+                throw new IllegalStateException("", e);
+            }
+            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+        }
+
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            // backing.cancel();
+            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+        }
+
+    }
+
+    public DataBrokerService getBiDataService() {
+        return biDataService;
+    }
+
+    public void setBiDataService(DataBrokerService biDataService) {
+        this.biDataService = biDataService;
+    }
+
+    public DataProviderService getBaDataService() {
+        return baDataService;
+    }
+
+    public void setBaDataService(DataProviderService baDataService) {
+        this.baDataService = baDataService;
+    }
+
+    public void start() {
+        baDataService.registerDataReader(ROOT, this);
+        baDataService.registerCommitHandler(ROOT, this);
+    }
+
+    public void setMappingService(BindingIndependentMappingService mappingService) {
+        this.mappingService = mappingService;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java
new file mode 100644 (file)
index 0000000..d8fbc70
--- /dev/null
@@ -0,0 +1,19 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map.Entry;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface BindingIndependentMappingService {
+
+    CompositeNode toDataDom(DataObject data);
+
+    Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+            Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry);
+
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier<? extends DataObject> path);
+
+    DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java
new file mode 100644 (file)
index 0000000..d22da30
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class BindingIndependentRpcConnector {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend
new file mode 100644 (file)
index 0000000..9a6330e
--- /dev/null
@@ -0,0 +1,402 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom
+
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext
+import java.util.List
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import java.util.Map
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
+import org.opendaylight.yangtools.binding.generator.util.Types
+import java.util.HashMap
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.binding.DataContainer
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import java.util.Collections
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import org.opendaylight.yangtools.yang.model.util.ExtendedType
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import com.google.common.collect.FluentIterable
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
+import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition
+
+class BindingMapping {
+
+    val Map<Type, GeneratedTypeBuilder> typeToDefinition = new HashMap();
+    val Map<Type, SchemaNode> typeToSchemaNode = new HashMap();
+
+    def QName getSchemaNode(Class<?> cls) {
+        val ref = Types.typeForClass(cls);
+        return typeToSchemaNode.get(ref)?.QName;
+    }
+
+    def void updateBinding(SchemaContext schemaContext, ModuleContext moduleBindingContext) {
+        updateBindingFor(moduleBindingContext.childNodes, schemaContext);
+
+    }
+
+    def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+        InstanceIdentifier<? extends DataObject> obj) {
+        val pathArguments = obj.path;
+        var Class<? extends DataObject> parent;
+        val dataDomArgs = new ArrayList<PathArgument>();
+        for (pathArgument : pathArguments) {
+            dataDomArgs.add(pathArgument.toDataDomPathArgument(parent));
+            parent = pathArgument.type;
+        }
+
+        return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(dataDomArgs);
+    }
+
+    
+
+    def DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> identifier, CompositeNode node) {
+        if (node == null) {
+            return null;
+        }
+        val targetClass = identifier.targetType;
+        val classLoader = targetClass.classLoader;
+        val ref = Types.typeForClass(targetClass);
+        val targetType = typeToDefinition.get(ref);
+        val targetSchema = typeToSchemaNode.get(ref);
+        return node.toDataObject(classLoader, targetType.toInstance, targetSchema);
+
+    }
+
+    def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument, Class<? extends DataObject> parent) {
+        val Class rawType = argument.type;
+        val ref = Types.typeForClass(rawType);
+        val schemaType = typeToSchemaNode.get(ref);
+        val qname = schemaType.QName
+
+        val Object key = argument.key;
+        val predicates = key.toPredicates(schemaType as ListSchemaNode);
+
+        return new NodeIdentifierWithPredicates(qname, predicates);
+    }
+    
+    def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
+        val ref = Types.typeForClass(argument.type);
+        val qname = typeToSchemaNode.get(ref).QName
+        return new NodeIdentifier(qname);
+    }
+
+    def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
+        val keyDefinitions = node.keyDefinition;
+        val map = new HashMap<QName, Object>();
+        for (keydef : keyDefinitions) {
+            val keyNode = node.getDataChildByName(keydef) as LeafSchemaNode;
+            val value = identifier.getSimpleValue(keydef, keyNode.type);
+            map.put(keydef, value.value);
+        }
+        return map;
+    }
+
+    def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+        for (entry : map.entrySet) {
+            val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
+            typeToDefinition.put(entry.value, entry.value);
+            typeToSchemaNode.put(entry.value, schemaNode)
+        }
+    }
+
+    def CompositeNode toCompositeNode(DataContainer data) {
+        val type = data.implementedInterface;
+        val typeRef = Types.typeForClass(type);
+        val schemaNode = typeToSchemaNode.get(typeRef);
+        val generatedType = typeToDefinition.get(typeRef);
+
+        return data.toDataDom(schemaNode, generatedType);
+    }
+
+    private def dispatch CompositeNode toDataDom(DataContainer data, ContainerSchemaNode node,
+        GeneratedTypeBuilder builder) {
+        val subnodes = data.toDataDomComponents(node);
+        return new CompositeNodeTOImpl(node.QName, null, subnodes);
+    }
+
+    private def dispatch CompositeNode toDataDom(DataContainer data, NotificationDefinition node,
+        GeneratedTypeBuilder builder) {
+        val subnodes = data.toDataDomComponents(node);
+        return new CompositeNodeTOImpl(node.QName, null, subnodes);
+    }
+
+    private def dispatch CompositeNode toDataDom(DataContainer data, ListSchemaNode node,
+        GeneratedTypeBuilder builder) {
+        val subnodes = data.toDataDomComponents(node);
+        return new CompositeNodeTOImpl(node.QName, null, subnodes);
+    }
+
+    private def List<Node<?>> toDataDomComponents(DataContainer data, DataNodeContainer node) {
+        val subnodes = new ArrayList<Node<?>>();
+        for (childNode : node.childNodes) {
+            val value = childNode.dataDomFromParent(data);
+            if (value !== null) {
+                subnodes.addAll(value);
+            }
+        }
+        return subnodes;
+    }
+
+    private def List<Node<?>> dataDomFromParent(DataSchemaNode node, DataContainer container) {
+        if (node.augmenting) {
+            return Collections.emptyList();
+        }
+        return dataDomFromParentImpl(node, container);
+    }
+
+    private def dispatch List<Node<?>> dataDomFromParentImpl(LeafSchemaNode node, DataContainer container) {
+        val value = container.getSimpleValue(node.QName, node.type);
+        if (value !== null) {
+            return Collections.<Node<?>>singletonList(value);
+        }
+        return Collections.emptyList();
+    }
+
+    private def dispatch List<Node<?>> dataDomFromParentImpl(LeafListSchemaNode node, DataContainer container) {
+        val values = container.getSimpleValues(node);
+        if (values !== null) {
+            //val it = new ArrayList<Node<?>>();
+            //for (value : values) {
+            //}
+
+        }
+        return Collections.emptyList();
+    }
+
+    def getSimpleValues(DataContainer container, LeafListSchemaNode node) {
+        return Collections.emptyList();
+    }
+
+    private def dispatch List<Node<?>> dataDomFromParentImpl(ListSchemaNode node, DataContainer container) {
+        val qname = node.QName;
+        val values = container.<List>getValue(qname, List) as List<? extends DataContainer>;
+        if (values === null) {
+            return Collections.emptyList;
+        }
+        val it = new ArrayList<Node<?>>();
+        for (value : values) {
+            add(value.toCompositeNode());
+        }
+
+        return it;
+    }
+
+    private def dispatch List<Node<?>> dataDomFromParentImpl(ChoiceNode node, DataContainer container) {
+    }
+
+    private def dispatch List<Node<?>> serializeValueImpl(List<?> list, GeneratedTypeBuilder builder,
+        ListSchemaNode node) {
+        val it = new ArrayList<Node<?>>();
+        for (value : list) {
+
+            val serVal = value.serializeValueImpl(builder, node);
+            if (serVal !== null) {
+                addAll(serVal);
+            }
+        }
+        return it;
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, ExtendedType type) {
+        getSimpleValue(container, name, type.baseType);
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, StringTypeDefinition type) {
+        val value = container.getValue(name, String);
+        if(value === null) return null;
+        return new SimpleNodeTOImpl(name, null, value);
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, TypeDefinition<?> type) {
+        val value = container.getValue(name, Object);
+        if(value === null) return null;
+        return new SimpleNodeTOImpl(name, null, value);
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, BooleanTypeDefinition type) {
+        val value = container.getValue(name, Boolean);
+        if(value === null) return null;
+        return new SimpleNodeTOImpl(name, null, value);
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, BinaryTypeDefinition type) {
+        val Object value = container.getValue(name, Object); //Constants.BYTES_CLASS);
+        if(value === null) return null;
+        return new SimpleNodeTOImpl(name, null, value);
+    }
+
+    private def <T> T getValue(Object object, QName node, Class<T> type) {
+        val methodName = BindingGeneratorImpl.getterMethodName(node.localName, Types.typeForClass(type));
+        var clz = object.class;
+        if (object instanceof DataContainer) {
+            clz = (object as DataContainer).implementedInterface;
+        }
+        val method = clz.getMethod(methodName);
+        if (method === null) {
+            return null;
+        }
+        val value = method.invoke(object);
+        if (value === null) {
+            return null;
+        }
+        if (type.isAssignableFrom(value.class)) {
+            return value  as T;
+        }
+        return value.getEncapsulatedValue(type);
+    }
+
+    private def <T> T getEncapsulatedValue(Object value, Class<T> type) {
+        val method = value.class.getMethod("getValue");
+        if (method !== null && type.isAssignableFrom(method.returnType)) {
+            return method.invoke(value) as T;
+        }
+        return null;
+    }
+
+    private def dispatch List<Node<?>> serializeValueImpl(DataContainer data, GeneratedTypeBuilder builder,
+        SchemaNode node) {
+        return Collections.<Node<?>>singletonList(data.toDataDom(node, builder));
+    }
+
+    private def dispatch List<Node<?>> serializeValueImpl(Object object, GeneratedTypeBuilder builder,
+        SchemaNode node) {
+    }
+
+    def DataObject toDataObject(CompositeNode node, ClassLoader loader, GeneratedType type, SchemaNode schema) {
+
+        // Nasty reflection hack (for now)
+        val builderClass = loader.loadClass(type.builderFQN);
+        val builder = builderClass.newInstance;
+        val buildMethod = builderClass.getMethod("build");
+
+        node.fillDataObject(builder, loader, type, schema);
+
+        return buildMethod.invoke(builder) as DataObject;
+    }
+
+    def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
+        ListSchemaNode schema) {
+
+        if (schema.keyDefinition !== null && !schema.keyDefinition.empty) {
+
+            val value = node.keyToBindingKey(loader, type, schema);
+            builder.setProperty("key", value);
+        }
+    }
+
+    def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
+        ContainerSchemaNode schema) {
+    }
+
+    
+    def Object keyToBindingKey(CompositeNode node, ClassLoader loader, GeneratedType type, ListSchemaNode schema) {
+        val keyClass = loader.loadClass(type.keyFQN);
+        val constructor = keyClass.constructors.get(0);
+        val keyType = type.keyTypeProperties;
+        val args = new ArrayList();
+        for (key : schema.keyDefinition) {
+            val keyProperty = keyType.get(BindingGeneratorUtil.parseToClassName(key.localName));
+            val domKeyValue = node.getFirstSimpleByName(key);
+            val keyValue = domKeyValue.deserializeSimpleValue(loader, keyProperty.returnType,
+                schema.getDataChildByName(key));
+            args.add(keyValue);
+        }
+        return ClassLoaderUtils.construct(constructor, args);
+    }
+
+    def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        LeafSchemaNode node2) {
+        deserializeSimpleValueImpl(node, loader, type, node2.type);
+    }
+
+    def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        LeafListSchemaNode node2) {
+        deserializeSimpleValueImpl(node, loader, type, node2.type);
+    }
+
+    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        ExtendedType definition) {
+        deserializeSimpleValueImpl(node, loader, type, definition.baseType);
+    }
+
+    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        StringTypeDefinition definition) {
+        if (type instanceof GeneratedTransferObject) {
+            val cls = loader.getClassForType(type);
+            val const = cls.getConstructor(String);
+            val str = String.valueOf(node.value);
+            return const.newInstance(str);
+        }
+        return node.value;
+    }
+
+    def Class<?> getClassForType(ClassLoader loader, Type type) {
+        loader.loadClass(type.fullyQualifiedName);
+    }
+
+    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        TypeDefinition definition) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    def Map<String, GeneratedProperty> getKeyTypeProperties(GeneratedType type) {
+        val method = FluentIterable.from(type.methodDefinitions).findFirst[name == "getKey"]
+        val key = method.returnType as GeneratedTransferObject;
+        val ret = new HashMap<String, GeneratedProperty>();
+        for (prop : key.properties) {
+            ret.put(prop.name, prop);
+        }
+        return ret;
+    }
+
+    def void setProperty(Object object, String property, Object value) {
+        val cls = object.class;
+        val valMethod = cls.getMethod("set" + property.toFirstUpper, value.class);
+        if (valMethod != null)
+            valMethod.invoke(object, value);
+    }
+
+    def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder'''
+
+    def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key'''
+
+}
+
+@Data
+class PropertyCapture {
+
+    @Property
+    val Type returnType;
+    @Property
+    val String name;
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java
new file mode 100644 (file)
index 0000000..c96835b
--- /dev/null
@@ -0,0 +1,73 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class ConnectorActivator implements Provider, ServiceTrackerCustomizer<Broker, Broker> {
+
+    BindingIndependentDataServiceConnector dataConnector;
+    BindingIndependentMappingService mappingService;
+
+    private final DataProviderService baDataService;
+    private BundleContext context;
+
+    private ServiceTracker<Broker, Broker> brokerTracker;
+
+    public ConnectorActivator(DataProviderService dataService, BundleContext context) {
+        baDataService = dataService;
+        this.context = context;
+        brokerTracker = new ServiceTracker<>(context, Broker.class, this);
+    }
+
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+
+        MappingServiceImpl mappingImpl = new MappingServiceImpl();
+        mappingImpl.setSchemaService(session.getService(SchemaService.class));
+        mappingImpl.start();
+
+        mappingService = mappingImpl;
+        dataConnector = new BindingIndependentDataServiceConnector();
+        dataConnector.setBaDataService(baDataService);
+        dataConnector.setBiDataService(session.getService(DataBrokerService.class));
+        dataConnector.setMappingService(mappingService);
+        dataConnector.start();
+    }
+
+    @Override
+    public Broker addingService(ServiceReference<Broker> reference) {
+        Broker br= context.getService(reference);
+        br.registerProvider(this, context);
+        return br;
+    }
+
+    @Override
+    public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+        // NOOP
+    }
+
+    @Override
+    public void removedService(ServiceReference<Broker> reference, Broker service) {
+        // NOOP
+    }
+
+    public void start() {
+        brokerTracker.open();
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java
new file mode 100644 (file)
index 0000000..1c9a59d
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class Constants {
+    public static final Class<byte[]> BYTES_CLASS = byte[].class;
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend
new file mode 100644 (file)
index 0000000..84a0065
--- /dev/null
@@ -0,0 +1,68 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom
+
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import java.util.Collections
+import java.util.Map.Entry
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import java.util.AbstractMap.SimpleEntry
+import org.opendaylight.controller.sal.core.api.model.SchemaService
+
+class MappingServiceImpl implements SchemaServiceListener, BindingIndependentMappingService {
+
+    var extension BindingMapping mapping = new BindingMapping;
+
+    @Property
+    BindingGeneratorImpl binding;
+
+    @Property
+    SchemaService schemaService;
+
+    override onGlobalContextUpdated(SchemaContext arg0) {
+        recreateBindingContext(arg0);
+    }
+
+    def recreateBindingContext(SchemaContext schemaContext) {
+        val newBinding = new BindingGeneratorImpl();
+        newBinding.generateTypes(schemaContext);
+        val newMapping = new BindingMapping();
+        for (entry : newBinding.moduleContexts.entrySet) {
+            val module = entry.key;
+            val context = entry.value;
+            
+            newMapping.updateBinding(schemaContext, context);
+        }
+        mapping = newMapping
+    }
+
+    override CompositeNode toDataDom(DataObject data) {
+        mapping.toCompositeNode(data);
+    }
+
+    override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+        Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
+        val key = mapping.toDataDom(entry.key);
+        val data = mapping.toCompositeNode(entry.value);
+        return new SimpleEntry(key, data);
+    }
+
+    override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+        InstanceIdentifier<? extends DataObject> path) {
+        return mapping.toDataDom(path);
+    }
+    
+    override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) {
+        return mapping.dataObjectFromDataDom(path,result);
+    }
+    
+    public def void start() {
+        schemaService.registerSchemaServiceListener(this);
+        recreateBindingContext(schemaService.globalContext);
+    }
+}
@@ -1,10 +1,17 @@
-package org.opendaylight.controller.sal.binding.impl.osgi;
+package org.opendaylight.controller.sal.binding.impl.util;
 
 
 
 import java.util.concurrent.Callable;
+
 import static com.google.common.base.Preconditions.*;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
 public class ClassLoaderUtils {
     
     public static <V> V withClassLoader(ClassLoader cls,Callable<V> function) throws Exception {
@@ -21,4 +28,9 @@ public class ClassLoaderUtils {
             throw new Exception(e);
         }
     }
+
+    public static Object construct(Constructor<? extends Object> constructor, ArrayList<Object> objects) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+    Object[] initargs = objects.toArray(new Object[]{});
+    return constructor.newInstance(initargs);
+    }
 }
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java
new file mode 100644 (file)
index 0000000..0448238
--- /dev/null
@@ -0,0 +1,136 @@
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class BrokerIntegrationTest {
+
+    DataBrokerService biDataService;
+    DataProviderService baDataService;
+    private MappingServiceImpl mappingServiceImpl;
+    private MappingServiceImpl mappingService;
+    private DataBrokerImpl baDataImpl;
+    private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
+    private ListeningExecutorService executor;
+    private BindingIndependentDataServiceConnector connectorServiceImpl;
+    private HashMapDataStore dataStore;
+    
+    
+    @Before
+    public void setUp() {
+        executor = MoreExecutors.sameThreadExecutor();
+        baDataImpl = new DataBrokerImpl();
+        baDataService = baDataImpl;
+        baDataImpl.setExecutor(executor);
+        
+        biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
+        biDataService =  biDataImpl;
+        biDataImpl.setExecutor(executor);
+        
+        dataStore = new HashMapDataStore();
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().toInstance();
+        biDataImpl.registerConfigurationReader(treeRoot, dataStore);
+        biDataImpl.registerOperationalReader(treeRoot, dataStore);
+        biDataImpl.registerCommitHandler(treeRoot, dataStore);
+        
+        mappingServiceImpl = new MappingServiceImpl();
+        mappingService = mappingServiceImpl;
+        
+        
+        connectorServiceImpl = new BindingIndependentDataServiceConnector();
+        connectorServiceImpl.setBaDataService(baDataService);
+        connectorServiceImpl.setBiDataService(biDataService);
+        connectorServiceImpl.setMappingService(mappingServiceImpl);
+        connectorServiceImpl.start();
+        
+        String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+        "node-inventory.yang" };
+        
+        mappingService.onGlobalContextUpdated(MappingServiceTest.getContext(yangFiles));
+    }
+    
+    @Test
+    public void simpleModifyOperation() throws Exception {
+        
+        DataModificationTransaction transaction = baDataService.beginTransaction();
+        assertNotNull(transaction);
+        
+        NodeRef node1 = createNodeRef("0");
+        DataObject  node = baDataService.readConfigurationData(node1.getValue());
+        assertNull(node);
+        Node nodeData1 = createNode("0");
+        
+        transaction.putConfigurationData(node1.getValue(), nodeData1);
+        Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
+        assertNotNull(commitResult);
+        
+        RpcResult<TransactionStatus> result = commitResult.get();
+        
+        assertNotNull(result);
+        assertNotNull(result.getResult());
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
+        
+        Node readedData = (Node) baDataService.readConfigurationData(node1.getValue());
+        assertNotNull(readedData);
+        assertEquals(nodeData1.getKey(), readedData.getKey());
+        
+        
+        DataModificationTransaction transaction2 = baDataService.beginTransaction();
+        assertNotNull(transaction);
+        
+        transaction2.removeConfigurationData(node1.getValue());
+        
+        Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
+        assertNotNull(commitResult2);
+        
+        RpcResult<TransactionStatus> result2 = commitResult2.get();
+        
+        assertNotNull(result2);
+        assertNotNull(result2.getResult());
+        assertEquals(TransactionStatus.COMMITED, result2.getResult());
+    
+        DataObject readedData2 = baDataService.readConfigurationData(node1.getValue());
+        assertNull(readedData2);
+    }
+    
+    private static NodeRef createNodeRef(String string) {
+        NodeKey key = new NodeKey(new NodeId(string));
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
+                .toInstance();
+        return new NodeRef(path);
+    }
+    
+    private static Node createNode(String string) {
+        NodeBuilder ret = new NodeBuilder();
+        ret.setId(new NodeId(string));
+        ret.setKey(new NodeKey(ret.getId()));
+        return ret.build();
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java
new file mode 100644 (file)
index 0000000..b0c2e75
--- /dev/null
@@ -0,0 +1,118 @@
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import static org.junit.Assert.*;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class MappingServiceTest {
+
+    private static final QName NODES = QName.create("urn:opendaylight:inventory", "2013-08-19", "nodes");
+    private static final QName NODE = QName.create(NODES,"node");
+    private static final QName ID = QName.create(NODES,"id");
+    
+    BindingIndependentMappingService service;
+    private MappingServiceImpl impl;
+
+    @Before
+    public void setUp() {
+        impl = new MappingServiceImpl();
+        service = impl;
+    }
+
+    @Test
+    public void baDataToBiData() throws Exception {
+
+        String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+                "node-inventory.yang" };
+
+        SchemaContext ctx = getContext(yangFiles);
+
+        impl.onGlobalContextUpdated(ctx);
+
+        NodesBuilder nodes = new NodesBuilder();
+
+        List<Node> nodeList = new ArrayList<>();
+        nodeList.add(createChildNode("foo"));
+        nodeList.add(createChildNode("bar"));
+
+        nodes.setNode(nodeList);
+        Nodes nodesTO = nodes.build();
+        CompositeNode xmlNodes = service.toDataDom(nodesTO);
+        assertNotNull(xmlNodes);
+        List<CompositeNode> invNodes = xmlNodes.getCompositesByName(NODE);
+        assertNotNull(invNodes);
+        assertEquals(2, invNodes.size());
+    }
+
+    @Test
+    public void instanceIdentifierTest() throws Exception {
+
+        String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+                "node-inventory.yang" };
+        SchemaContext ctx = getContext(yangFiles);
+        impl.onGlobalContextUpdated(ctx);
+
+        NodeKey nodeKey = new NodeKey(new NodeId("foo"));
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).child(Node.class, nodeKey).toInstance();
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier result = service.toDataDom(path);
+        assertNotNull(result);
+        assertEquals(2, result.getPath().size());
+    }
+
+    public static SchemaContext getContext(String[] yangFiles) {
+
+        ClassLoader loader = MappingServiceTest.class.getClassLoader();
+
+        List<InputStream> streams = new ArrayList<>();
+        for (String string : yangFiles) {
+            InputStream stream = loader.getResourceAsStream("META-INF/yang/" + string);
+            streams.add(stream);
+
+        }
+        YangParserImpl parser = new YangParserImpl();
+
+        Set<Module> modules = parser.parseYangModelsFromStreams(streams);
+        return parser.resolveSchemaContext(modules);
+    }
+
+    private Node createChildNode(String id) {
+        NodeBuilder node = new NodeBuilder();
+        NodeId nodeId = new NodeId(id);
+
+        node.setId(nodeId);
+        node.setKey(new NodeKey(nodeId));
+
+        FlowCapableNodeBuilder aug = new FlowCapableNodeBuilder();
+        aug.setManufacturer(id);
+        node.addAugmentation(FlowCapableNode.class, aug.build());
+
+        return node.build();
+    }
+
+}
index 6638050ae0bc1484b8e9b476616a1b1899181bf9..3bc50cdd2ed1aecbf55d791f0c3fe02d9ed1bd04 100644 (file)
@@ -52,7 +52,7 @@
                     <dependency>
                         <groupId>org.opendaylight.controller</groupId>
                         <artifactId>yang-jmx-generator-plugin</artifactId>
-                        <version>0.2.2-SNAPSHOT</version>
+                        <version>0.2.3-SNAPSHOT</version>
                     </dependency>
                 </dependencies>
             </plugin>
@@ -82,7 +82,7 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-api</artifactId>
-            <version>0.2.2-SNAPSHOT</version>
+            <version>0.2.3-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
index 2b632b4ab0bccfaf1e34df182afe8d9c53021f05..e242b9ecee2c3e8f9cc8ff1d9b777a036d1f07eb 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-manager</artifactId>
-      <version>0.2.2-SNAPSHOT</version>
+      <version>0.2.3-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <version>1.0-SNAPSHOT</version>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+            <version>4.0</version>
+    </dependency>
   </dependencies>
 </project>
index 3e3ee3a8742e1af5ca3a14a30382217064e1d931..2f9c397632795d334799f32030be734fe38ae113 100644 (file)
@@ -25,6 +25,7 @@ public class TestHelper {
                 mavenBundle(CONTROLLER, "sal-common-api").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "sal-common-impl").versionAsInProject(), //
                 
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
                 mavenBundle("com.google.guava", "guava").versionAsInProject(), //
                 mavenBundle(YANGTOOLS + ".thirdparty", "xtend-lib-osgi").versionAsInProject() //
         );
@@ -44,8 +45,32 @@ public class TestHelper {
                 mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(),
                 mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), //
                 mavenBundle("org.javassist", "javassist").versionAsInProject(), //
-                mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject() //
-        );
+                mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), //
+        
+                mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                
+                
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
+                
+                
+                mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
+                
+                mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject() //
+       );
 
     }
 
index 4057d9d1bc0ec3807b85754764bbbc108dc095a6..41b1e310a06e6812d954cee64e7db3c895e8f996 100644 (file)
@@ -11,6 +11,7 @@ import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.options.DefaultCompositeOption;
+import org.ops4j.pax.exam.util.PathUtils;
 import org.osgi.framework.BundleContext;
 
 @RunWith(PaxExam.class)
@@ -48,6 +49,9 @@ public abstract class AbstractTest {
     public Option[] config() {
         return options(systemProperty("osgi.console").value("2401"), mavenBundle("org.slf4j", "slf4j-api")
                 .versionAsInProject(), //
+                systemProperty("logback.configurationFile").value(
+                        "file:" + PathUtils.getBaseDir()
+                                + "/src/test/resources/logback.xml"),
                 mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
                 mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
                 mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
index d26f2e7aa161fe4dbb247f301db414cfa703c4ff..e1f109b88dc2e923f8580b47e57c1795cc50d947 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -21,9 +22,15 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
+import com.google.inject.Inject;
+
 public class DataServiceTest extends AbstractTest {
 
     protected DataBrokerService consumerDataService;
+    
+    
+    @Inject
+    Broker broker2;
 
     @Before
     public void setUp() throws Exception {
@@ -61,9 +68,9 @@ public class DataServiceTest extends AbstractTest {
         assertNotNull(result.getResult());
         assertEquals(TransactionStatus.COMMITED, result.getResult());
         
-        DataObject readedData = consumerDataService.readConfigurationData(node1.getValue());
+        Node readedData = (Node) consumerDataService.readConfigurationData(node1.getValue());
         assertNotNull(readedData);
-        assertEquals(nodeData1, readedData);
+        assertEquals(nodeData1.getKey(), readedData.getKey());
         
         
         DataModificationTransaction transaction2 = consumerDataService.beginTransaction();
@@ -97,7 +104,9 @@ public class DataServiceTest extends AbstractTest {
     
     private static Node createNode(String string) {
         NodeBuilder ret = new NodeBuilder();
-        ret.setId(new NodeId(string));
+        NodeId id = new NodeId(string);
+        ret.setKey(new NodeKey(id));
+        ret.setId(id);
         return ret.build();
     }
 }
index 3bd51ec7d8b68dabe567857101a098cf2d2f4928..7fb05806df36f1925a936fb49615212f64339a8d 100644 (file)
@@ -1,50 +1,59 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.opendaylight.controller</groupId>
-    <artifactId>sal-parent</artifactId>
-    <version>1.0-SNAPSHOT</version>
-  </parent>
-  <artifactId>sal-common-impl</artifactId>
-  <packaging>bundle</packaging>
-  <scm>
-    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-  </scm>
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>sal-common-impl</artifactId>
+    <packaging>bundle</packaging>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
 
-  <dependencies>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-api</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.xtend</groupId>
-      <artifactId>org.eclipse.xtend.lib</artifactId>
-    </dependency>
-  </dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+    </dependencies>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Export-Package>
-                org.opendaylight.controller.md.sal.common.impl,
-                org.opendaylight.controller.md.sal.common.impl.*
-            </Export-Package>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.opendaylight.controller.md.sal.common.impl,
+                            org.opendaylight.controller.md.sal.common.impl.*
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
index c335b75e15981989078fa862ad31b88dd70d4e04..c9e1d6e330e38324f21e26b510cb548f5298a562 100644 (file)
@@ -1,8 +1,8 @@
 package org.opendaylight.controller.md.sal.common.impl;
 
+import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW;
+
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -10,9 +10,6 @@ import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.yangtools.concepts.Path;
-
-import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW;
 
 public abstract class AbstractDataModification<P /* extends Path<P> */, D> implements DataModification<P, D> {
 
@@ -86,7 +83,7 @@ public abstract class AbstractDataModification<P /* extends Path<P> */, D> imple
 
     @Override
     public final void putRuntimeData(P path, D data) {
-        putRuntimeData(path, data);
+        putOperationalData(path, data);
     }
 
     @Override
index f83c61f8049205977e998c61295072fe84176624..d6b3c5334aa1c4d02563d51cef0a0d27d8939c61 100644 (file)
@@ -35,7 +35,7 @@ public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements Da
     @Override
     public D readOperationalData(P path) {
         FluentIterable<D> dataBits = FluentIterable //
-                .from(getReaders(configReaders, path)).transform(operationalRead(path));
+                .from(getReaders(operationalReaders, path)).transform(operationalRead(path));
         return merge(path,dataBits);
 
     }
@@ -75,7 +75,7 @@ public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements Da
         return new Function<DataReader<P, D>, D>() {
             @Override
             public D apply(DataReader<P, D> input) {
-                return input.readConfigurationData(path);
+                return input.readOperationalData(path);
             }
         };
     }
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend
new file mode 100644 (file)
index 0000000..b878071
--- /dev/null
@@ -0,0 +1,259 @@
+package org.opendaylight.controller.md.sal.common.impl.service
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
+import org.opendaylight.yangtools.concepts.ListenerRegistration
+import com.google.common.collect.Multimap
+import static com.google.common.base.Preconditions.*;
+import java.util.List
+import com.google.common.collect.HashMultimap
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Callable
+import org.opendaylight.yangtools.yang.common.RpcResult
+import java.util.Collections
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
+import java.util.ArrayList
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration
+import java.util.Arrays
+import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService
+import org.opendaylight.controller.md.sal.common.api.data.DataModificationTransactionFactory
+import org.opendaylight.controller.md.sal.common.api.data.DataChangePublisher
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener
+import org.opendaylight.controller.sal.common.util.Rpcs
+import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification
+import java.util.concurrent.Future
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
+import org.opendaylight.yangtools.concepts.Path
+import org.slf4j.LoggerFactory
+
+abstract class AbstractDataBroker<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> implements 
+DataModificationTransactionFactory<P, D>, //
+DataReader<P, D>, //
+DataChangePublisher<P, D, DCL>, //
+DataProvisionService<P,D> {
+
+    @Property
+    var ExecutorService executor;
+
+    @Property
+    var AbstractDataReadRouter<P,D> dataReadRouter;
+
+    Multimap<P, DataChangeListenerRegistration<P,D,DCL>> listeners = HashMultimap.create();
+    Multimap<P, DataCommitHandlerRegistration<P,D>> commitHandlers = HashMultimap.create();
+
+
+    public new() {
+        
+    }
+
+    override final readConfigurationData(P path) {
+        return dataReadRouter.readConfigurationData(path);
+    }
+
+    override final readOperationalData(P path) {
+        return dataReadRouter.readOperationalData(path);
+    }
+
+    override final registerCommitHandler(P path,
+        DataCommitHandler<P, D> commitHandler) {
+            val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
+            commitHandlers.put(path,registration)
+            return registration;
+    }
+
+    override final def registerDataChangeListener(P path, DCL listener) {
+        val reg = new DataChangeListenerRegistration(path, listener, this);
+        listeners.put(path, reg);
+        return reg;
+    }
+
+     final def registerDataReader(P path,DataReader<P,D> reader) {
+        
+        val confReg = dataReadRouter.registerConfigurationReader(path,reader);
+        val dataReg = dataReadRouter.registerOperationalReader(path,reader);
+        
+        return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg));
+    }
+
+    protected  final def removeListener(DataChangeListenerRegistration<P,D,DCL> registration) {
+        listeners.remove(registration.path, registration);
+    }
+
+    protected  final def removeCommitHandler(DataCommitHandlerRegistration<P,D> registration) {
+        commitHandlers.remove(registration.path, registration);
+    }
+    
+    protected  final def getActiveCommitHandlers() {
+        return commitHandlers.entries.map[ value.instance].toSet
+    }
+
+    package final def Future<RpcResult<TransactionStatus>>  commit(AbstractDataTransaction<P,D> transaction) {
+        checkNotNull(transaction);
+        transaction.changeStatus(TransactionStatus.SUBMITED);
+        val task = new TwoPhaseCommit(transaction, this);
+        return executor.submit(task);
+    }
+
+}
+
+package class DataChangeListenerRegistration<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> extends AbstractObjectRegistration<DCL> implements ListenerRegistration<DCL> {
+
+    AbstractDataBroker<P,D,DCL> dataBroker;
+
+    @Property
+    val P path;
+
+    new(P path, DCL instance, AbstractDataBroker<P,D,DCL> broker) {
+        super(instance)
+        dataBroker = broker;
+        _path = path;
+    }
+
+    override protected removeRegistration() {
+        dataBroker.removeListener(this);
+        dataBroker = null;
+    }
+
+}
+
+package class DataCommitHandlerRegistration<P extends Path<P>,D>
+extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
+
+    AbstractDataBroker<P,D,?> dataBroker;
+
+    @Property
+    val P path;
+
+    new(P path, DataCommitHandler<P, D> instance,
+        AbstractDataBroker<P,D,?> broker) {
+        super(instance)
+        dataBroker = broker;
+        _path = path;
+    }
+
+    override protected removeRegistration() {
+        dataBroker.removeCommitHandler(this);
+        dataBroker = null;
+    }
+
+}
+
+package class TwoPhaseCommit<P extends Path<P>,D> implements Callable<RpcResult<TransactionStatus>> {
+    
+    private static val log = LoggerFactory.getLogger(TwoPhaseCommit);
+
+    val AbstractDataTransaction<P,D> transaction;
+    val AbstractDataBroker<P,D,?> dataBroker;
+
+    new(AbstractDataTransaction<P,D> transaction, AbstractDataBroker<P,D,?> broker) {
+        this.transaction = transaction;
+        this.dataBroker = broker;
+    }
+
+    override call() throws Exception {
+
+        val Iterable<DataCommitHandler<P, D>> commitHandlers = dataBroker.activeCommitHandlers;
+
+        // requesting commits
+        val List<DataCommitTransaction<P, D>> handlerTransactions = new ArrayList();
+        try {
+            for (handler : commitHandlers) {
+                handlerTransactions.add(handler.requestCommit(transaction));
+            }
+        } catch (Exception e) {
+            log.error("Request Commit failded",e);
+            return rollback(handlerTransactions,e);
+        }
+        val List<RpcResult<Void>> results = new ArrayList();
+        try {
+            for (subtransaction : handlerTransactions) {
+                results.add(subtransaction.finish());
+            }
+        } catch (Exception e) {
+            log.error("Finish Commit failed",e);
+            return rollback(handlerTransactions,e);
+        }
+
+        return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
+    }
+
+    def rollback(List<DataCommitTransaction<P, D>> transactions,Exception e) {
+        for (transaction : transactions) {
+            transaction.rollback()
+        }
+        // FIXME return encountered error.
+        return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
+    }
+}
+
+public abstract class AbstractDataTransaction<P extends Path<P>, D> extends AbstractDataModification<P, D> {
+
+    @Property
+    private val Object identifier;
+
+    
+    var TransactionStatus status;
+    
+    
+    var AbstractDataBroker<P, D, ?> broker;
+
+    protected new (AbstractDataBroker<P,D,?> dataBroker) {
+        super(dataBroker);
+        _identifier = new Object();
+        broker = dataBroker;
+        status = TransactionStatus.NEW;
+        //listeners = new ListenerRegistry<>();
+    }
+
+    override  commit() {
+        return broker.commit(this);
+    }
+
+    override readConfigurationData(P path) {
+        return broker.readConfigurationData(path);
+    }
+
+    override readOperationalData(P path) {
+        return broker.readOperationalData(path);
+    }
+
+    override hashCode() {
+        return identifier.hashCode;
+    }
+
+    override equals(Object obj) {
+        if (this === obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        val other = (obj as AbstractDataTransaction<P,D>) ;
+        if (broker == null) {
+            if (other.broker != null)
+                return false;
+        } else if (!broker.equals(other.broker))
+            return false;
+        if (identifier == null) {
+            if (other.identifier != null)
+                return false;
+        } else if (!identifier.equals(other.identifier))
+            return false;
+        return true;
+    }
+
+    override TransactionStatus getStatus() {
+        return status;
+    }
+
+    
+    protected abstract def void onStatusChange(TransactionStatus status);
+    
+    public def changeStatus(TransactionStatus status) {
+        this.status = status;
+        onStatusChange(status);
+    }
+    
+}
index 52f60b3cc28728a7dce4a2435bfe1e97bb6a2e0c..b34c8d4c001b505a3a8e0f4b82d9122d5b6be5ce 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.sal.core.api.model;
 
 import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -39,4 +40,6 @@ public interface SchemaService extends BrokerService {
      * @return
      */
     SchemaContext getGlobalContext();
+    
+    ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener);
 }
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java
new file mode 100644 (file)
index 0000000..d76fd4d
--- /dev/null
@@ -0,0 +1,12 @@
+package org.opendaylight.controller.sal.core.api.model;
+
+import java.util.EventListener;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public interface SchemaServiceListener extends EventListener {
+
+    
+    void onGlobalContextUpdated(SchemaContext context);
+    
+}
index 8f6a5d0a90cb4fed609fb94a997c44ebe42ae02a..92542bc3455e497a6082fe64cf6607a290b30723 100644 (file)
@@ -1,8 +1,13 @@
 package org.opendaylight.controller.sal.core.api.mount;
 
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
 import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
 
-public interface MountProvisionInstance extends MountInstance, NotificationPublishService, RpcProvisionRegistry {
+public interface MountProvisionInstance extends //
+        MountInstance,//
+        NotificationPublishService, //
+        RpcProvisionRegistry,//
+        DataProviderService {
 
 }
index 530b02b733a0ea945ddad4018a2d29e4f8050705..3180271c935311a64bb69a66b7264ab1ef72cb2a 100644 (file)
@@ -7,10 +7,11 @@
  */
 package org.opendaylight.controller.sal.core.api.mount;
 
+import org.opendaylight.controller.sal.core.api.BrokerService;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
 
-public interface MountService {
+public interface MountService extends BrokerService {
 
     MountInstance getMountPoint(InstanceIdentifier path);
 }
index 9383a9e2ff50ee2149d1ce034ed6f195dfb0e7e6..62dbe16e4135de42001f6fde721799128b8dbebd 100644 (file)
@@ -1,79 +1,95 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
-    <modelVersion>4.0.0</modelVersion>\r
-    <parent>\r
-        <groupId>org.opendaylight.controller</groupId>\r
-        <artifactId>sal-parent</artifactId>\r
-        <version>1.0-SNAPSHOT</version>\r
-    </parent>\r
-    <artifactId>sal-broker-impl</artifactId>\r
-    <packaging>bundle</packaging>\r
-    <scm>\r
-        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
-        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
-        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
-    </scm>\r
-\r
-    <dependencies>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-core-api</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-util</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-                <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-impl</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-impl</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-core-spi</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.slf4j</groupId>\r
-            <artifactId>slf4j-api</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>com.google.guava</groupId>\r
-            <artifactId>guava</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.eclipse.xtend</groupId>\r
-            <artifactId>org.eclipse.xtend.lib</artifactId>\r
-        </dependency>\r
-    </dependencies>\r
-\r
-    <build>\r
-        <plugins>\r
-            <plugin>\r
-                <groupId>org.apache.felix</groupId>\r
-                <artifactId>maven-bundle-plugin</artifactId>\r
-                <extensions>true</extensions>\r
-                <configuration>\r
-                    <instructions>\r
-                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>\r
-                        <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>\r
-                        <Private-Package>\r
-                            org.opendaylight.controller.sal.dom.broker.*\r
-                        </Private-Package>\r
-                    </instructions>\r
-                </configuration>\r
-            </plugin>\r
-            <plugin>\r
-                <groupId>org.eclipse.xtend</groupId>\r
-                <artifactId>xtend-maven-plugin</artifactId>\r
-            </plugin>\r
-        </plugins>\r
-    </build>\r
-</project>\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>sal-broker-impl</artifactId>
+    <packaging>bundle</packaging>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-spi</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+            <version>0.2.3-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>
+                        <Private-Package>
+                            org.opendaylight.controller.sal.dom.broker.*
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
index e3f5e4b4cd15309d85825da7e01ed9e31084a018..3af645a2b8a48753b79659f58877c1044ff83394 100644 (file)
@@ -3,25 +3,70 @@ package org.opendaylight.controller.sal.dom.broker;
 import java.util.Hashtable;
 
 import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
 public class BrokerActivator implements BundleActivator {
 
+    private static final InstanceIdentifier ROOT = InstanceIdentifier.builder().toInstance();
     BrokerImpl broker;
     private ServiceRegistration<Broker> brokerReg;
-    
+    private ServiceRegistration<SchemaService> schemaReg;
+    private ServiceRegistration<DataBrokerService> dataReg;
+    private ServiceRegistration<DataProviderService> dataProviderReg;
+    private SchemaServiceImpl schemaService;
+    private DataBrokerImpl dataService;
+    private MountPointManagerImpl mountService;
+    private ServiceRegistration<MountService> mountReg;
+    private ServiceRegistration<MountProvisionService> mountProviderReg;
+    private HashMapDataStore hashMapStore;
+
     @Override
     public void start(BundleContext context) throws Exception {
+        Hashtable<String, String> emptyProperties = new Hashtable<String, String>();
         broker = new BrokerImpl();
         broker.setBundleContext(context);
-        brokerReg = context.registerService(Broker.class, broker, new Hashtable<String,String>());
+        
+
+        schemaService = new SchemaServiceImpl();
+        schemaService.setContext(context);
+        schemaService.setParser(new YangParserImpl());
+        schemaService.start();
+        schemaReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String, String>());
+        
+        dataService = new DataBrokerImpl();
+        dataService.setExecutor(broker.getExecutor());
+        
+        dataReg = context.registerService(DataBrokerService.class, dataService, emptyProperties);
+        dataProviderReg = context.registerService(DataProviderService.class, dataService, emptyProperties);
+        
+        hashMapStore = new HashMapDataStore();
+        
+        dataService.registerConfigurationReader(ROOT, hashMapStore);
+        dataService.registerCommitHandler(ROOT, hashMapStore);
+        dataService.registerOperationalReader(ROOT, hashMapStore);
+        
+        mountService = new MountPointManagerImpl();
+        mountService.setDataBroker(dataService);
+        
+        mountReg = context.registerService(MountService.class, mountService, emptyProperties);
+        mountProviderReg =  context.registerService(MountProvisionService.class, mountService, emptyProperties);
+        
+        brokerReg = context.registerService(Broker.class, broker, emptyProperties);
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        if(brokerReg != null) {
+        if (brokerReg != null) {
             brokerReg.unregister();
         }
     }
index 855ad9bd328d19c79b30e09ba4e485e0d1918044..26fecef688d3cfc748bc1367a5a1e4e5a9d40ac1 100644 (file)
@@ -37,16 +37,13 @@ public class BrokerImpl implements Broker {
     private val Set<ConsumerContextImpl> sessions = Collections.synchronizedSet(new HashSet<ConsumerContextImpl>());
     private val Set<ProviderContextImpl> providerSessions = Collections.synchronizedSet(
         new HashSet<ProviderContextImpl>());
-    private val Set<BrokerModule> modules = Collections.synchronizedSet(new HashSet<BrokerModule>());
-    private val Map<Class<? extends BrokerService>, BrokerModule> serviceProviders = Collections.
-        synchronizedMap(new HashMap<Class<? extends BrokerService>, BrokerModule>());
 
     // Implementation specific
     @Property
     private var ExecutorService executor = Executors.newFixedThreadPool(5);
     @Property
     private var BundleContext bundleContext;
-    
+
     @Property
     private var RpcRouter router;
 
@@ -68,29 +65,6 @@ public class BrokerImpl implements Broker {
         return session;
     }
 
-    public def addModule(BrokerModule module) {
-        log.info("Registering broker module " + module);
-        if(modules.contains(module)) {
-            log.error("Module already registered");
-            throw new IllegalArgumentException("Module already exists.");
-        }
-
-        val provServices = module.getProvidedServices();
-        for (Class<? extends BrokerService> serviceType : provServices) {
-            log.info("  Registering session service implementation: " + serviceType.getCanonicalName());
-            serviceProviders.put(serviceType, module);
-        }
-    }
-
-    public def <T extends BrokerService> T serviceFor(Class<T> service, ConsumerContextImpl session) {
-        val prov = serviceProviders.get(service);
-        if(prov == null) {
-            log.warn("Service " + service.toString() + " is not supported");
-            return null;
-        }
-        return prov.getServiceForSession(service, session);
-    }
-
     protected def Future<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
         val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
         return result;
@@ -98,20 +72,20 @@ public class BrokerImpl implements Broker {
 
     // Validation
     private def void checkPredicates(Provider prov) {
-        if(prov == null)
+        if (prov == null)
             throw new IllegalArgumentException("Provider should not be null.");
         for (ProviderContextImpl session : providerSessions) {
-            if(prov.equals(session.getProvider()))
+            if (prov.equals(session.getProvider()))
                 throw new IllegalStateException("Provider already registered");
         }
 
     }
 
     private def void checkPredicates(Consumer cons) {
-        if(cons == null)
+        if (cons == null)
             throw new IllegalArgumentException("Consumer should not be null.");
         for (ConsumerContextImpl session : sessions) {
-            if(cons.equals(session.getConsumer()))
+            if (cons.equals(session.getConsumer()))
                 throw new IllegalStateException("Consumer already registered");
         }
     }
index 6d57a4e2247392089f4a0895b439e8f2d3c84b76..9f21823e3efb33c56e841fc1ad2af52ba481ad7f 100644 (file)
@@ -1,13 +1,15 @@
 package org.opendaylight.controller.sal.dom.broker
 
-import java.util.Collections
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import java.util.HashMap
 import org.opendaylight.controller.sal.core.api.BrokerService
 import org.opendaylight.controller.sal.core.api.Consumer
 import org.osgi.framework.BundleContext
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy
+import com.google.common.collect.ClassToInstanceMap
+import com.google.common.collect.MutableClassToInstanceMap
+import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory
 
 class ConsumerContextImpl implements ConsumerSession {
 
@@ -17,8 +19,7 @@ class ConsumerContextImpl implements ConsumerSession {
     @Property
     private var BrokerImpl broker;
 
-    private val instantiatedServices = Collections.synchronizedMap(
-        new HashMap<Class<? extends BrokerService>, BrokerService>());
+    private val ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap.create();
     private boolean closed = false;
 
     private BundleContext context;
@@ -33,14 +34,20 @@ class ConsumerContextImpl implements ConsumerSession {
     }
 
     override <T extends BrokerService> T getService(Class<T> service) {
-        val potential = instantiatedServices.get(service);
-        if(potential != null) {
-            val ret = potential as T;
-            return ret;
+        val localProxy = instantiatedServices.getInstance(service);
+        if(localProxy != null) {
+            return localProxy;
         }
-        val ret = broker.serviceFor(service, this);
+        val serviceRef = context.getServiceReference(service);
+        if(serviceRef == null) {
+            return null;
+        }
+        val serviceImpl = context.getService(serviceRef);
+        
+        
+        val ret = ProxyFactory.createProxy(serviceRef,serviceImpl);
         if(ret != null) {
-            instantiatedServices.put(service, ret);
+            instantiatedServices.putInstance(service, ret);
         }
         return ret;
     }
@@ -49,7 +56,9 @@ class ConsumerContextImpl implements ConsumerSession {
         val toStop = instantiatedServices.values();
         this.closed = true;
         for (BrokerService brokerService : toStop) {
-            //brokerService.closeSession();
+            if(brokerService instanceof AbstractBrokerServiceProxy<?>) {
+                (brokerService as AutoCloseable).close();
+            } 
         }
         broker.consumerSessionClosed(this);
     }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java
new file mode 100644 (file)
index 0000000..d95fdcc
--- /dev/null
@@ -0,0 +1,66 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier, CompositeNode, DataChangeListener> implements
+        DataProviderService {
+
+    public DataBrokerImpl() {
+        setDataReadRouter(new DataReaderRouter());
+    }
+
+    @Override
+    public DataTransactionImpl beginTransaction() {
+        return new DataTransactionImpl(this);
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return getDataReadRouter().registerConfigurationReader(path, reader);
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return getDataReadRouter().registerOperationalReader(path, reader);
+    }
+
+    @Deprecated
+    @Override
+    public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Deprecated
+    @Override
+    public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Deprecated
+    @Override
+    public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Deprecated
+    @Override
+    public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataConsumerServiceImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataConsumerServiceImpl.xtend
deleted file mode 100644 (file)
index 3bccc4e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.opendaylight.controller.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.common.DataStoreIdentifier
-import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener
-
-class DataConsumerServiceImpl implements DataBrokerService {
-    
-    override beginTransaction() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-
-    override readConfigurationData(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-    
-    override readOperationalData(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-    
-    override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java
new file mode 100644 (file)
index 0000000..5cb01c9
--- /dev/null
@@ -0,0 +1,31 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DataTransactionImpl extends AbstractDataTransaction<InstanceIdentifier, CompositeNode> 
+    implements DataModificationTransaction {
+    private final ListenerRegistry<DataTransactionListener> listeners = new ListenerRegistry<DataTransactionListener>();
+    
+    
+    
+    public DataTransactionImpl(DataBrokerImpl dataBroker) {
+        super(dataBroker);
+    }
+
+    @Override
+    public ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener) {
+        return listeners.register(listener);
+    }
+
+    protected void onStatusChange(TransactionStatus status) {
+        for (ListenerRegistration<DataTransactionListener> listenerRegistration : listeners) {
+            listenerRegistration.getInstance().onStatusUpdated(this, status);
+        }
+    }
+}
\ No newline at end of file
index 7037b46ce978dea4d717692498e526c8706cb7a8..eafc402ddcea6987b82980b5a2d92ffec5443108 100644 (file)
@@ -1,15 +1,19 @@
 package org.opendaylight.controller.sal.dom.broker;
 
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Future;
 
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
 import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
 import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter;
@@ -23,17 +27,33 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 
 public class MountPointImpl implements MountProvisionInstance {
 
-    final RpcRouter rpcs;
-    final DataReaderRouter dataReader;
-    final NotificationRouter notificationRouter;
+    private final RpcRouter rpcs;
+    private final DataReaderRouter dataReader;
+    private final NotificationRouter notificationRouter;
+    private final DataReader<InstanceIdentifier,CompositeNode> readWrapper;
+    
+    
+    private final InstanceIdentifier mountPath;
 
     public MountPointImpl(InstanceIdentifier path) {
+        this.mountPath = path;
         rpcs = new RpcRouterImpl("");
         dataReader = new DataReaderRouter();
         notificationRouter = new NotificationRouterImpl();
+        readWrapper = new ReadWrapper();
+    }
+
+    public InstanceIdentifier getMountPath() {
+        return mountPath;
+    }
+
+    public DataReader<InstanceIdentifier, CompositeNode> getReadWrapper() {
+        return readWrapper;
     }
 
     @Override
@@ -113,6 +133,62 @@ public class MountPointImpl implements MountProvisionInstance {
     @Override
     public void sendNotification(CompositeNode notification) {
         publish(notification);
+    }
+    
+    @Override
+    public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
+            InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+    
+    @Override
+    public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+     // NOOP
+    }
+    
+    @Override
+    public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+     // NOOP
+    }
+    
+    @Override
+    public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+     // NOOP
+    }
+    @Override
+    public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+        // NOOP
+    }
+    
+    class ReadWrapper implements DataReader<InstanceIdentifier, CompositeNode> {
+        
+        
+        private InstanceIdentifier shortenPath(InstanceIdentifier path) {
+            InstanceIdentifier ret = null;
+            if(mountPath.contains(path)) {
+                List<PathArgument> newArgs = path.getPath().subList(mountPath.getPath().size(), path.getPath().size());
+                ret = new InstanceIdentifier(newArgs);
+            }
+            return ret;
+        }
+        
+        @Override
+        public CompositeNode readConfigurationData(InstanceIdentifier path) {
+            InstanceIdentifier newPath = shortenPath(path);
+            if(newPath == null) {
+                return null;
+            }
+            return MountPointImpl.this.readConfigurationData(newPath);
+        }
         
+        @Override
+        public CompositeNode readOperationalData(InstanceIdentifier path) {
+            InstanceIdentifier newPath = shortenPath(path);
+            if(newPath == null) {
+                return null;
+            }
+            return MountPointImpl.this.readOperationalData(newPath);
+        }
     }
 }
index c64d1e56dd9638d28d9dee0d1d508aaead85e030..19634d79c2203fafe5aaa0156c41bf45a62f905f 100644 (file)
@@ -6,15 +6,27 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import java.util.concurrent.ConcurrentMap
 import java.util.concurrent.ConcurrentHashMap
 import static com.google.common.base.Preconditions.*;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
 
 class MountPointManagerImpl implements MountProvisionService {
     
+    @Property
+    DataProviderService dataBroker;
+    
     ConcurrentMap<InstanceIdentifier,MountPointImpl> mounts = new ConcurrentHashMap();
     
     override createMountPoint(InstanceIdentifier path) {
         checkState(!mounts.containsKey(path),"Mount already created");
         val mount = new MountPointImpl(path);
+        registerMountPoint(mount);
         mounts.put(path,mount);
+        return mount;
+    }
+    
+    def registerMountPoint(MountPointImpl impl) {
+        dataBroker?.registerConfigurationReader(impl.mountPath,impl.readWrapper);
+        dataBroker?.registerOperationalReader(impl.mountPath,impl.readWrapper);
+        
     }
     
     
@@ -30,6 +42,4 @@ class MountPointManagerImpl implements MountProvisionService {
     override getMountPoint(InstanceIdentifier path) {
         mounts.get(path);
     }
-    
-    
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java
new file mode 100644 (file)
index 0000000..ba558c5
--- /dev/null
@@ -0,0 +1,281 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.Checksum;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.*;
+
+public class SchemaServiceImpl implements SchemaService, AutoCloseable {
+    private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class);
+
+    private ListenerRegistry<SchemaServiceListener> listeners;
+    private YangModelParser parser;
+
+    private BundleContext context;
+    private BundleScanner scanner = new BundleScanner();
+
+    /**
+     * Map of currently problematic yang files that should get fixed eventually
+     * after all events are received.
+     */
+    private final Multimap<Bundle, URL> inconsistentBundlesToYangURLs = HashMultimap.create();
+    private final Multimap<Bundle, URL> consistentBundlesToYangURLs = HashMultimap.create();
+    private BundleTracker<Object> bundleTracker;
+    private final YangStoreCache cache = new YangStoreCache();
+
+    public ListenerRegistry<SchemaServiceListener> getListeners() {
+        return listeners;
+    }
+
+    public void setListeners(ListenerRegistry<SchemaServiceListener> listeners) {
+        this.listeners = listeners;
+    }
+
+    public YangModelParser getParser() {
+        return parser;
+    }
+
+    public void setParser(YangModelParser parser) {
+        this.parser = parser;
+    }
+
+    public BundleContext getContext() {
+        return context;
+    }
+
+    public void setContext(BundleContext context) {
+        this.context = context;
+    }
+
+    public void start() {
+        checkState(parser != null);
+        checkState(context != null);
+        if (listeners == null) {
+            listeners = new ListenerRegistry<>();
+        }
+
+        bundleTracker = new BundleTracker<Object>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
+        bundleTracker.open();
+    }
+
+    public SchemaContext getGlobalContext() {
+        return getSchemaContextSnapshot();
+    }
+
+    public synchronized SchemaContext getSchemaContextSnapshot() {
+        Optional<SchemaContext> yangStoreOpt = cache.getCachedSchemaContext(consistentBundlesToYangURLs);
+        if (yangStoreOpt.isPresent()) {
+            return yangStoreOpt.get();
+        }
+        SchemaContext snapshot = createSnapshot(parser, consistentBundlesToYangURLs);
+        updateCache(snapshot);
+        return snapshot;
+    }
+
+    @Override
+    public void addModule(Module module) {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public SchemaContext getSessionContext() {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void removeModule(Module module) {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    
+    @Override
+    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+        return listeners.register(listener);
+    }
+    
+    @Override
+    public void close() throws Exception {
+        bundleTracker.close();
+        // FIXME: Add listeners.close();
+
+    }
+
+    private synchronized boolean tryToUpdateState(Collection<URL> changedURLs, Multimap<Bundle, URL> proposedNewState,
+            boolean adding) {
+        Preconditions.checkArgument(changedURLs.size() > 0, "No change can occur when no URLs are changed");
+
+        try {
+            // consistent state
+            // merge into
+            SchemaContext snapshot = createSnapshot(parser, proposedNewState);
+            consistentBundlesToYangURLs.clear();
+            consistentBundlesToYangURLs.putAll(proposedNewState);
+            inconsistentBundlesToYangURLs.clear();
+            // update cache
+            updateCache(snapshot);
+            logger.info("SchemaService updated to new consistent state");
+            logger.trace("SchemaService  updated to new consistent state containing {}", consistentBundlesToYangURLs);
+
+            // notifyListeners(changedURLs, adding);
+            return true;
+        } catch (Exception e) {
+            // inconsistent state
+            logger.debug(
+                    "SchemaService is falling back on last consistent state containing {}, inconsistent yang files {}, reason {}",
+                    consistentBundlesToYangURLs, inconsistentBundlesToYangURLs, e.toString());
+            return false;
+        }
+    }
+
+    private static Collection<InputStream> fromUrlsToInputStreams(Multimap<Bundle, URL> multimap) {
+        return Collections2.transform(multimap.values(), new Function<URL, InputStream>() {
+
+            @Override
+            public InputStream apply(URL url) {
+                try {
+                    return url.openStream();
+                } catch (IOException e) {
+                    logger.warn("Unable to open stream from {}", url);
+                    throw new IllegalStateException("Unable to open stream from " + url, e);
+                }
+            }
+        });
+    }
+
+    private static SchemaContext createSnapshot(YangModelParser parser, Multimap<Bundle, URL> multimap) {
+        List<InputStream> models = new ArrayList<>(fromUrlsToInputStreams(multimap));
+        Set<Module> modules = parser.parseYangModelsFromStreams(models);
+        SchemaContext yangStoreSnapshot = parser.resolveSchemaContext(modules);
+        return yangStoreSnapshot;
+    }
+
+    private void updateCache(SchemaContext snapshot) {
+        cache.cacheYangStore(consistentBundlesToYangURLs, snapshot);
+        for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+            try {
+                listener.getInstance().onGlobalContextUpdated(snapshot);
+            } catch (Exception e) {
+                logger.error("Exception occured during invoking listener",e);
+            }
+        }
+    }
+
+    private class BundleScanner implements BundleTrackerCustomizer<Object> {
+        @Override
+        public Object addingBundle(Bundle bundle, BundleEvent event) {
+
+            // Ignore system bundle:
+            // system bundle might have config-api on classpath &&
+            // config-api contains yang files =>
+            // system bundle might contain yang files from that bundle
+            if (bundle.getBundleId() == 0)
+                return bundle;
+
+            Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
+            if (enumeration != null && enumeration.hasMoreElements()) {
+                synchronized (this) {
+                    List<URL> addedURLs = new ArrayList<>();
+                    while (enumeration.hasMoreElements()) {
+                        URL url = enumeration.nextElement();
+                        addedURLs.add(url);
+                    }
+                    logger.trace("Bundle {} has event {}, bundle state {}, URLs {}", bundle, event, bundle.getState(),
+                            addedURLs);
+                    // test that yang store is consistent
+                    Multimap<Bundle, URL> proposedNewState = HashMultimap.create(consistentBundlesToYangURLs);
+                    proposedNewState.putAll(inconsistentBundlesToYangURLs);
+                    proposedNewState.putAll(bundle, addedURLs);
+                    boolean adding = true;
+                    if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) {
+                        inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
+                    }
+                }
+            }
+            return bundle;
+        }
+
+        @Override
+        public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+            logger.debug("Modified bundle {} {} {}", bundle, event, object);
+        }
+
+        /**
+         * If removing YANG files makes yang store inconsistent, method
+         * {@link #getYangStoreSnapshot()} will throw exception. There is no
+         * rollback.
+         */
+
+        @Override
+        public synchronized void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+            inconsistentBundlesToYangURLs.removeAll(bundle);
+            Collection<URL> consistentURLsToBeRemoved = consistentBundlesToYangURLs.removeAll(bundle);
+
+            if (consistentURLsToBeRemoved.isEmpty()) {
+                return; // no change
+            }
+            boolean adding = false;
+            // notifyListeners(consistentURLsToBeRemoved, adding);
+        }
+    }
+
+    private static final class YangStoreCache {
+
+        Set<URL> cachedUrls;
+        SchemaContext cachedContextSnapshot;
+
+        Optional<SchemaContext> getCachedSchemaContext(Multimap<Bundle, URL> bundlesToYangURLs) {
+            Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
+            if (cachedUrls != null && cachedUrls.equals(urls)) {
+                Preconditions.checkState(cachedContextSnapshot != null);
+                return Optional.of(cachedContextSnapshot);
+            }
+            return Optional.absent();
+        }
+
+        private static Set<URL> setFromMultimapValues(Multimap<Bundle, URL> bundlesToYangURLs) {
+            Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
+            Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
+            return urls;
+        }
+
+        void cacheYangStore(Multimap<Bundle, URL> urls, SchemaContext ctx) {
+            this.cachedUrls = setFromMultimapValues(urls);
+            this.cachedContextSnapshot = ctx;
+        }
+
+    }
+}
index 1e0f3385ccf78bdf418261c15077d2d056fad1f1..fbed2ca113621c728dd00a5fa4b9ae932344d7db 100644 (file)
@@ -3,11 +3,16 @@ package org.opendaylight.controller.sal.dom.broker.impl
 import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
 
 class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
 
     override protected merge(InstanceIdentifier path, Iterable<CompositeNode> data) {
-        return data.iterator.next
+        val iterator = data.iterator;
+        if(iterator.hasNext) {
+            return data.iterator.next
+        }
+        return null;
     }
 
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend
new file mode 100644 (file)
index 0000000..1a2f947
--- /dev/null
@@ -0,0 +1,50 @@
+package org.opendaylight.controller.sal.dom.broker.impl
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import java.util.Map
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import java.util.Map.Entry
+import java.util.HashSet
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+
+class DataUtils {
+
+    static def CompositeNode read(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
+        val root = map.get(path);
+        val childs = map.getChilds(path);
+        if(root === null && childs.empty) {
+            return null;
+        }
+        
+        return merge(path, root, childs);
+    }
+
+    static def CompositeNode merge(InstanceIdentifier path, CompositeNode node,
+        HashSet<Entry<InstanceIdentifier, CompositeNode>> entries) {
+        val it = new ArrayList<Node<?>>();
+        val qname = path.path.last.nodeType;
+        if (node != null) {
+            addAll(node.children);
+        }
+        for (entry : entries) {
+            val nesting = entry.key.path.size - path.path.size;
+            if (nesting === 1) {
+                add(entry.value);
+            }
+        }
+        return new CompositeNodeTOImpl(qname, null, it);
+    }
+
+    static def getChilds(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
+        val it = new HashSet<Entry<InstanceIdentifier, CompositeNode>>();
+        for (entry : map.entrySet) {
+            if (path.contains(entry.key)) {
+                add(entry);
+            }
+        }
+        return it;
+    }
+
+}
@@ -1,10 +1,7 @@
-package org.opendaylight.controller.sal.binding.impl
+package org.opendaylight.controller.sal.dom.broker.impl
 
 import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.controller.md.sal.common.api.data.DataModification
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
 import org.opendaylight.yangtools.yang.common.RpcResult
@@ -12,58 +9,62 @@ import java.util.Map
 import java.util.concurrent.ConcurrentHashMap
 import org.opendaylight.controller.sal.common.util.Rpcs
 import java.util.Collections
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import static extension org.opendaylight.controller.sal.dom.broker.impl.DataUtils.*;
 
 class HashMapDataStore //
 implements //
-RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+DataReader<InstanceIdentifier, CompositeNode>, DataCommitHandler<InstanceIdentifier, CompositeNode> {
 
-    val Map<InstanceIdentifier<? extends DataObject>,DataObject> configuration = new ConcurrentHashMap();
-    val Map<InstanceIdentifier<? extends DataObject>,DataObject> operational = new ConcurrentHashMap();
+    val Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap();
+    val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
 
-
-    override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
-        configuration.get(path);
+    override readConfigurationData(InstanceIdentifier path) {
+        configuration.read(path);
     }
 
-    override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
-        operational.get(path);
+    override readOperationalData(InstanceIdentifier path) {
+        operational.read(path);
     }
+    
+
 
-    override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-        return new HashMapDataStoreTransaction(modification,this);
+
+    override requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
+        return new HashMapDataStoreTransaction(modification, this);
     }
-    
+
     def RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
-        return Rpcs.getRpcResult(true,null,Collections.emptySet);
+        return Rpcs.getRpcResult(true, null, Collections.emptySet);
     }
-    
+
     def RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
         val modification = transaction.modification;
         configuration.putAll(modification.updatedConfigurationData);
         operational.putAll(modification.updatedOperationalData);
-        
-        for(removal : modification.removedConfigurationData) {
+
+        for (removal : modification.removedConfigurationData) {
             configuration.remove(removal);
         }
-        for(removal : modification.removedOperationalData) {
+        for (removal : modification.removedOperationalData) {
             operational.remove(removal);
         }
-        return Rpcs.getRpcResult(true,null,Collections.emptySet);
+        return Rpcs.getRpcResult(true, null, Collections.emptySet);
     }
 
 }
 
 class HashMapDataStoreTransaction implements // 
-DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+DataCommitTransaction<InstanceIdentifier, CompositeNode> {
     @Property
-    val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification
+    val DataModification<InstanceIdentifier, CompositeNode> modification
 
     @Property
     val HashMapDataStore datastore;
-    
-    
+
     new(
-        DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modify,
+        DataModification<InstanceIdentifier, CompositeNode> modify,
         HashMapDataStore store
     ) {
         _modification = modify;
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java
new file mode 100644 (file)
index 0000000..7e3d9be
--- /dev/null
@@ -0,0 +1,68 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.osgi.framework.ServiceReference;
+import static com.google.common.base.Preconditions.*;
+
+public abstract class AbstractBrokerServiceProxy<T extends BrokerService> implements AutoCloseable, BrokerService {
+
+    private T delegate;
+    private final ServiceReference<T> reference;
+
+    public AbstractBrokerServiceProxy(ServiceReference<T> ref, T delegate) {
+        this.delegate = checkNotNull(delegate, "Delegate should not be null.");
+        this.reference = checkNotNull(ref, "Reference should not be null.");
+    }
+
+    protected final T getDelegate() {
+        checkState(delegate != null, "Proxy was closed and unregistered.");
+        return delegate;
+    }
+
+    protected final ServiceReference<T> getReference() {
+        return reference;
+    }
+
+    private Set<Registration<?>> registrations = Collections.synchronizedSet(new HashSet<Registration<?>>());
+
+    protected <R extends Registration<?>> R addRegistration(R registration) {
+        if (registration != null) {
+            registrations.add(registration);
+        }
+        return registration;
+    }
+
+    protected void closeBeforeUnregistrations() {
+        // NOOP
+    }
+
+    protected void closeAfterUnregistrations() {
+        // NOOP
+    }
+
+    @Override
+    public void close() {
+        if (delegate != null) {
+            delegate = null;
+            RuntimeException potentialException = new RuntimeException(
+                    "Uncaught exceptions occured during unregistration");
+            boolean hasSuppressed = false;
+            for (Registration<?> registration : registrations) {
+                try {
+                    registration.close();
+                } catch (Exception e) {
+                    potentialException.addSuppressed(e);
+                    hasSuppressed = true;
+                }
+            }
+            if (hasSuppressed) {
+                throw potentialException;
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java
new file mode 100644 (file)
index 0000000..3eb7e22
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataBrokerServiceProxy extends AbstractBrokerServiceProxy<DataBrokerService> implements DataBrokerService {
+
+    public DataBrokerServiceProxy(ServiceReference<DataBrokerService> ref, DataBrokerService delegate) {
+        super(ref, delegate);
+    }
+
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+            DataChangeListener listener) {
+        return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+    }
+
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        return getDelegate().readConfigurationData(path);
+    }
+
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        return getDelegate().readOperationalData(path);
+    }
+
+    public DataModificationTransaction beginTransaction() {
+        return getDelegate().beginTransaction();
+    }
+    
+    
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java
new file mode 100644 (file)
index 0000000..2fded87
--- /dev/null
@@ -0,0 +1,77 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataProviderServiceProxy extends AbstractBrokerServiceProxy<DataProviderService> implements
+        DataProviderService {
+
+    public DataProviderServiceProxy(ServiceReference<DataProviderService> ref, DataProviderService delegate) {
+        super(ref, delegate);
+    }
+
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+            DataChangeListener listener) {
+        return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+    }
+
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        return getDelegate().readConfigurationData(path);
+    }
+
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        return getDelegate().readOperationalData(path);
+    }
+
+    public DataModificationTransaction beginTransaction() {
+        return getDelegate().beginTransaction();
+    }
+
+    @Override
+    public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        getDelegate().addRefresher(store, refresher);
+    }
+
+    @Override
+    public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+        getDelegate().addValidator(store, validator);
+    }
+
+    @Override
+    public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
+            InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+        return addRegistration(getDelegate().registerCommitHandler(path, commitHandler));
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return addRegistration(getDelegate().registerConfigurationReader(path, reader));
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return addRegistration(getDelegate().registerOperationalReader(path, reader));
+    }
+
+    @Override
+    public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        getDelegate().removeRefresher(store, refresher);
+    }
+
+    @Override
+    public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+        getDelegate().removeValidator(store, validator);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/MountProviderServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/MountProviderServiceProxy.java
new file mode 100644 (file)
index 0000000..0d18cb3
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class MountProviderServiceProxy extends AbstractBrokerServiceProxy<MountProvisionService> implements MountProvisionService{
+
+    
+    public MountProviderServiceProxy(ServiceReference<MountProvisionService> ref, MountProvisionService delegate) {
+        super(ref, delegate);
+    }
+
+    public MountProvisionInstance getMountPoint(InstanceIdentifier path) {
+        return getDelegate().getMountPoint(path);
+    }
+
+    public MountProvisionInstance createMountPoint(InstanceIdentifier path) {
+        return getDelegate().createMountPoint(path);
+    }
+
+    public MountProvisionInstance createOrGetMountPoint(InstanceIdentifier path) {
+        return getDelegate().createOrGetMountPoint(path);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java
new file mode 100644 (file)
index 0000000..170517b
--- /dev/null
@@ -0,0 +1,29 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationPublishServiceProxy extends AbstractBrokerServiceProxy<NotificationPublishService> implements NotificationPublishService {
+
+    public NotificationPublishServiceProxy(ServiceReference<NotificationPublishService> ref,
+            NotificationPublishService delegate) {
+        super(ref, delegate);
+    }
+
+    public void sendNotification(CompositeNode notification) {
+        getDelegate().sendNotification(notification);
+    }
+
+    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+        return addRegistration(getDelegate().addNotificationListener(notification, listener));
+
+    }
+
+    public void publish(CompositeNode notification) {
+        getDelegate().publish(notification);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java
new file mode 100644 (file)
index 0000000..d685370
--- /dev/null
@@ -0,0 +1,20 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationServiceProxy extends AbstractBrokerServiceProxy<NotificationService> implements
+        NotificationService {
+
+    public NotificationServiceProxy(ServiceReference<NotificationService> ref, NotificationService delegate) {
+        super(ref, delegate);
+    }
+
+    @Override
+    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+        return addRegistration(getDelegate().addNotificationListener(notification, listener));
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend
new file mode 100644 (file)
index 0000000..938808f
--- /dev/null
@@ -0,0 +1,47 @@
+package org.opendaylight.controller.sal.dom.broker.osgi
+
+import org.opendaylight.controller.sal.core.api.BrokerService
+import org.osgi.framework.ServiceReference
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService
+import org.opendaylight.controller.sal.core.api.notify.NotificationService
+import org.opendaylight.controller.sal.core.api.model.SchemaService
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
+
+class ProxyFactory {
+
+    static def <T extends BrokerService> T createProxy(ServiceReference<T> serviceRef, T service) {
+        return createProxyImpl(serviceRef, service) as T;
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, DataBrokerService service) {
+        new DataBrokerServiceProxy(ref as ServiceReference<DataBrokerService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, DataProviderService service) {
+        new DataProviderServiceProxy(ref as ServiceReference<DataProviderService>, service);
+    }
+    
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationPublishService service) {
+        new NotificationPublishServiceProxy(ref as ServiceReference<NotificationPublishService>, service);
+    }
+    
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationService service) {
+        new NotificationServiceProxy(ref as ServiceReference<NotificationService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, MountProvisionService service) {
+        new MountProviderServiceProxy(ref as ServiceReference<MountProvisionService>, service);
+    }
+
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, SchemaService service) {
+        new SchemaServiceProxy(ref as ServiceReference<SchemaService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> reference, BrokerService service) {
+        throw new IllegalArgumentException("Not supported class");
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java
new file mode 100644 (file)
index 0000000..8938bf2
--- /dev/null
@@ -0,0 +1,45 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.framework.ServiceReference;
+
+public class SchemaServiceProxy extends AbstractBrokerServiceProxy<SchemaService> implements SchemaService {
+
+    public SchemaServiceProxy(ServiceReference<SchemaService> ref, SchemaService delegate) {
+        super(ref, delegate);
+    }
+
+    @Override
+    public void addModule(Module module) {
+        getDelegate().addModule(module);
+    }
+
+    @Override
+    public void removeModule(Module module) {
+        getDelegate().removeModule(module);
+    }
+
+    @Override
+    public SchemaContext getSessionContext() {
+        return null;
+    }
+
+    @Override
+    public SchemaContext getGlobalContext() {
+        return getDelegate().getGlobalContext();
+    }
+
+    @Override
+    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+        ListenerRegistration<SchemaServiceListener> registration = getDelegate().registerSchemaServiceListener(listener);
+        addRegistration(registration);
+        return registration;
+    }
+
+    
+    
+}
index 57e4d858c196beee2c9bf5a5d6ac04a7ed0d6d78..6ef5780c8a577c1bc93c97bd95420a50d608f5fc 100644 (file)
@@ -7,7 +7,7 @@
         <version>1.0-SNAPSHOT</version>
     </parent>
     <properties>
-        <netconf.version>0.2.2-SNAPSHOT</netconf.version>
+        <netconf.version>0.2.3-SNAPSHOT</netconf.version>
     </properties>
     <artifactId>sal-netconf-connector</artifactId>
     <scm>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netconf-client</artifactId>
-            <version>0.2.2-SNAPSHOT</version>
+            <version>${netconf.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-impl</artifactId>
             <version>0.5.9-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+            <type>jar</type>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
     </dependencies>
 
     <packaging>bundle</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.opendaylight.controller.sal.connect.netconf.NetconfProvider</Bundle-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/InventoryUtils.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/InventoryUtils.java
new file mode 100644 (file)
index 0000000..8350e39
--- /dev/null
@@ -0,0 +1,39 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.net.URI;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class InventoryUtils {
+
+    private static final URI INVENTORY_NAMESPACE = URI.create("urn:opendaylight:inventory");
+    private static final Date INVENTORY_REVISION = date();
+    public static final QName INVENTORY_NODES = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "nodes");
+    public static final QName INVENTORY_NODE = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "node");
+    public static final QName INVENTORY_ID = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "id");
+
+    public static final InstanceIdentifier INVENTORY_PATH = InstanceIdentifier.builder().node(INVENTORY_NODES)
+            .toInstance();
+    public static final QName NETCONF_INVENTORY_MOUNT = null;
+    
+    
+    
+    private static Date date() {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            return formatter.parse("2013-08-19");
+        } catch (ParseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    
+    
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.xtend b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.xtend
new file mode 100644 (file)
index 0000000..0171c1f
--- /dev/null
@@ -0,0 +1,95 @@
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.netconf.client.NetconfClient
+import org.opendaylight.controller.sal.core.api.RpcImplementation
+import static extension org.opendaylight.controller.sal.connect.netconf.NetconfMapping.*
+import java.net.InetSocketAddress
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import org.opendaylight.yangtools.yang.common.QName
+import java.util.Collections
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
+import org.opendaylight.yangtools.concepts.Registration
+
+class NetconfDevice implements DataReader<InstanceIdentifier, CompositeNode>, RpcImplementation {
+
+    var NetconfClient client;
+
+    @Property
+    var InetSocketAddress socketAddress;
+
+    @Property
+    val MountProvisionInstance mountInstance;
+
+    @Property
+    val InstanceIdentifier path;
+    
+    Registration<DataReader<InstanceIdentifier,CompositeNode>> operReaderReg
+    
+    Registration<DataReader<InstanceIdentifier,CompositeNode>> confReaderReg
+    
+    public new(MountProvisionInstance mount,InstanceIdentifier path) {
+        _mountInstance = mount;
+        _path = path;
+    }
+
+    def start(NetconfClientDispatcher dispatcher) {
+        client = new NetconfClient("sal-netconf-connector", socketAddress, dispatcher);
+        
+        confReaderReg = mountInstance.registerConfigurationReader(path,this);
+        operReaderReg = mountInstance.registerOperationalReader(path,this);
+    }
+
+    override readConfigurationData(InstanceIdentifier path) {
+        val result = invokeRpc(NETCONF_GET_CONFIG_QNAME, wrap(NETCONF_GET_CONFIG_QNAME, path.toFilterStructure()));
+        val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
+        return data?.findNode(path) as CompositeNode;
+    }
+
+    override readOperationalData(InstanceIdentifier path) {
+        val result = invokeRpc(NETCONF_GET_QNAME, wrap(NETCONF_GET_QNAME, path.toFilterStructure()));
+        val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
+        return data?.findNode(path) as CompositeNode;
+    }
+
+    override getSupportedRpcs() {
+        Collections.emptySet;
+    }
+
+    override invokeRpc(QName rpc, CompositeNode input) {
+        val message = rpc.toRpcMessage(input);
+        val result = client.sendMessage(message);
+        return result.toRpcResult();
+    }
+
+    def Node<?> findNode(CompositeNode node, InstanceIdentifier identifier) {
+
+        var Node<?> current = node;
+        for (arg : identifier.path) {
+            if (current instanceof SimpleNode<?>) {
+                return null;
+            } else if (current instanceof CompositeNode) {
+                val currentComposite = (current as CompositeNode);
+
+                current = currentComposite.getFirstCompositeByName(arg.nodeType);
+                if (current == null) {
+                    current = currentComposite.getFirstSimpleByName(arg.nodeType);
+                }
+                if (current == null) {
+                    return null;
+                }
+            }
+        }
+        return current;
+    }
+    
+    public def stop() {
+        confReaderReg?.close()
+        operReaderReg?.close()
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend
new file mode 100644 (file)
index 0000000..2fe145e
--- /dev/null
@@ -0,0 +1,84 @@
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
+import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.QName
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*;
+import static extension org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils.*;
+
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent
+import java.util.Map
+import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
+import java.io.OptionalDataException
+import com.google.common.base.Optional
+import java.net.SocketAddress
+import java.net.InetSocketAddress
+
+class NetconfDeviceManager {
+
+    val Map<InstanceIdentifier, NetconfDevice> devices = new ConcurrentHashMap;
+
+    var ProviderSession session;
+
+    @Property
+    var DataProviderService dataService;
+    
+    @Property
+    var MountProvisionService mountService;
+    
+    val nodeUpdateListener = new NetconfInventoryListener(this);
+
+
+    @Property
+    var NetconfClientDispatcher dispatcher;
+
+    def void start() {
+        dataService?.registerDataChangeListener(INVENTORY_PATH, nodeUpdateListener);
+        if(dispatcher == null) {
+        dispatcher = new NetconfClientDispatcher(Optional.absent);
+        }
+    }
+
+    def netconfNodeAdded(InstanceIdentifier path, CompositeNode node) {
+        val address = node.endpointAddress;
+        val port = Integer.parseInt(node.endpointPort);
+        netconfNodeAdded(path,new InetSocketAddress(address,port))
+
+    }
+    
+    def netconfNodeAdded(InstanceIdentifier path, InetSocketAddress address) {
+    
+        val mountPointPath = path;
+        val mountPoint = mountService.createOrGetMountPoint(mountPointPath);
+        val localPath = InstanceIdentifier.builder().toInstance;
+        val netconfDevice = new NetconfDevice(mountPoint,localPath);
+        netconfDevice.setSocketAddress(address);
+        netconfDevice.start(dispatcher);
+    }
+
+    def netconfNodeRemoved(InstanceIdentifier path) {
+    
+    }
+
+}
+
+class NetconfInventoryListener implements DataChangeListener {
+
+    val NetconfDeviceManager manager;
+
+    new(NetconfDeviceManager manager) {
+        this.manager = manager;
+    }
+
+    override onDataChanged(DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
+        
+        //manager.netconfNodeAdded(path, change);
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfInventoryUtils.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfInventoryUtils.java
new file mode 100644 (file)
index 0000000..a69f670
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public class NetconfInventoryUtils {
+
+    
+    public static final QName NETCONF_MOUNT = null;
+    public static final QName NETCONF_ENDPOINT = null;
+    public static final QName NETCONF_ENDPOINT_ADDRESS = null;
+    public static final QName NETCONF_ENDPOINT_PORT = null;
+
+
+    public static String getEndpointAddress(CompositeNode node) {
+        return node.getCompositesByName(NETCONF_ENDPOINT).get(0).getFirstSimpleByName(NETCONF_ENDPOINT_ADDRESS).getValue().toString();
+    }
+    
+    public static String getEndpointPort(CompositeNode node) {
+        return node.getCompositesByName(NETCONF_ENDPOINT).get(0).getFirstSimpleByName(NETCONF_ENDPOINT_PORT).getValue().toString();
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend
new file mode 100644 (file)
index 0000000..d23ec1c
--- /dev/null
@@ -0,0 +1,95 @@
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.netconf.api.NetconfMessage
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.common.RpcResult
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import java.net.URI
+import java.util.Collections
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.NodeUtils
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import java.util.concurrent.atomic.AtomicInteger
+import org.w3c.dom.Document
+import org.w3c.dom.Element
+import org.opendaylight.controller.sal.common.util.Rpcs
+
+class NetconfMapping {
+
+    public static val NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
+    public static val NETCONF_QNAME = new QName(NETCONF_URI,null,"netconf");
+    public static val NETCONF_RPC_QNAME = new QName(NETCONF_QNAME,"rpc");
+    public static val NETCONF_GET_QNAME = new QName(NETCONF_QNAME,"get");
+    public static val NETCONF_GET_CONFIG_QNAME = new QName(NETCONF_QNAME,"get-config");
+    public static val NETCONF_RPC_REPLY_QNAME = new QName(NETCONF_QNAME,"rpc-reply");
+    public static val NETCONF_OK_QNAME = new QName(NETCONF_QNAME,"ok");
+    public static val NETCONF_DATA_QNAME = new QName(NETCONF_QNAME,"data");
+    
+
+    static val messageId = new AtomicInteger(0);
+
+
+
+    static def Node<?> toFilterStructure(InstanceIdentifier identifier) {
+        var Node<?> previous = null;
+        for (component : identifier.path.reverse) {
+            val Node<?> current = component.toNode(previous);
+            previous = current;
+        }
+        return previous;
+    }
+    
+    static def dispatch Node<?> toNode(NodeIdentifierWithPredicates argument, Node<?> node) {
+        val list = new ArrayList<Node<?>>();
+        for( arg : argument.keyValues.entrySet) {
+            list.add = new SimpleNodeTOImpl(arg.key,null,arg.value);
+        }
+        return new CompositeNodeTOImpl(argument.nodeType,null,list)
+    }
+    
+    static def dispatch Node<?> toNode(PathArgument argument, Node<?> node) {
+        if(node != null) {
+            return new CompositeNodeTOImpl(argument.nodeType,null,Collections.singletonList(node));
+        } else {
+            return new SimpleNodeTOImpl(argument.nodeType,null,null);
+        }
+    }
+
+    static def CompositeNode toCompositeNode(NetconfMessage message) {
+        return message.toRpcResult().result;
+    }
+
+    static def NetconfMessage toRpcMessage(QName rpc, CompositeNode node) {
+        val rpcPayload = wrap(NETCONF_RPC_QNAME,node);
+        val w3cPayload = NodeUtils.buildShadowDomTree(rpcPayload);
+        w3cPayload.documentElement.setAttribute("message-id","m-"+ messageId.andIncrement);
+        return new NetconfMessage(w3cPayload);
+    }
+
+    static def RpcResult<CompositeNode> toRpcResult(NetconfMessage message) {
+        val rawRpc = message.document.toCompositeNode() as CompositeNode;
+        //rawRpc.
+        
+        return Rpcs.getRpcResult(true,rawRpc,Collections.emptySet());
+    }
+    
+    
+    static def wrap(QName name,Node<?> node) {
+        if(node != null) {
+            return new CompositeNodeTOImpl(name,null,Collections.singletonList(node));
+        }
+        else {
+            return new CompositeNodeTOImpl(name,null,Collections.emptyList());
+        }
+    }
+    
+    
+    public static def Node<?> toCompositeNode(Document document) {
+        return XmlDocumentUtils.toCompositeNode(document) as Node<?>
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java
new file mode 100644 (file)
index 0000000..8cf5f02
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.util.Hashtable;
+
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.osgi.framework.BundleContext;
+
+public class NetconfProvider extends AbstractProvider {
+
+    private NetconfDeviceManager netconfDeviceManager;
+
+    @Override
+    protected void startImpl(BundleContext context) {
+        netconfDeviceManager = new NetconfDeviceManager();
+        context.registerService(NetconfDeviceManager.class, netconfDeviceManager, new Hashtable<String,String>());
+    }
+    
+    
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+        MountProvisionService mountService = session.getService(MountProvisionService.class);
+        
+        
+        netconfDeviceManager.setMountService(mountService);
+        netconfDeviceManager.start();
+    }
+
+    @Override
+    protected void stopImpl(BundleContext context) {
+        
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/XmlDocumentUtils.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/XmlDocumentUtils.java
new file mode 100644 (file)
index 0000000..3f6b4e1
--- /dev/null
@@ -0,0 +1,54 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class XmlDocumentUtils {
+
+    public static CompositeNode toCompositeNode(Document doc) {
+        return (CompositeNode) toCompositeNode(doc.getDocumentElement());
+    }
+
+    private static Node<?> toCompositeNode(Element element) {
+        String orgNamespace = element.getNamespaceURI();
+        URI biNamespace = null;
+        if (orgNamespace != null) {
+            biNamespace = URI.create(orgNamespace);
+        }
+        QName qname = new QName(biNamespace, element.getLocalName());
+
+        List<Node<?>> values = new ArrayList<>();
+        NodeList nodes = element.getChildNodes();
+        boolean isSimpleObject = false;
+        String value = null;
+        for (int i = 0; i < nodes.getLength(); i++) {
+            org.w3c.dom.Node child = nodes.item(i);
+            if (child instanceof Element) {
+                isSimpleObject = false;
+                values.add(toCompositeNode((Element) child));
+            }
+            if (!isSimpleObject && child instanceof org.w3c.dom.Text) {
+                value = element.getTextContent();
+                if (value.matches(".*\\w.*")) {
+                    isSimpleObject = true;
+                    break;
+                }
+            }
+        }
+
+        if (isSimpleObject) {
+            return new SimpleNodeTOImpl<>(qname, null, value);
+        }
+        return new CompositeNodeTOImpl(qname, null, values);
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java
new file mode 100644 (file)
index 0000000..4abf0e1
--- /dev/null
@@ -0,0 +1,197 @@
+package org.opendaylight.controller.sal.connector.netconf.test;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+import io.netty.channel.ChannelFuture;
+import io.netty.util.HashedWheelTimer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLContext;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.yang.store.api.YangStoreException;
+import org.opendaylight.controller.config.yang.store.impl.HardcodedYangStoreService;
+import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.client.NetconfClient;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
+import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
+import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
+import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl;
+import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+public class MountTest extends AbstractConfigTest {
+
+    private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
+    private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
+    private static final URI NETCONF_MONITORING_NS = URI.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring");
+    
+    private static final QName NETCONF_MONITORING = new QName(NETCONF_MONITORING_NS, new Date(2010,10,04), "ietf-netconf-monitoring");
+    private static final QName NETCONF_MONITORING_STATE = new QName(NETCONF_MONITORING,"netconf-state");
+    
+
+    private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession;
+    private DefaultCommitNotificationProducer commitNot;
+    private NetconfServerDispatcher dispatch;
+    private DataProviderService dataBroker;
+    private MountPointManagerImpl mountManager;
+    private NetconfDeviceManager netconfManager;
+
+    private static QName CONFIG_MODULES = new QName(
+            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+    private static QName CONFIG_SERVICES = new QName(
+            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+
+    private NetconfClient createSession(final InetSocketAddress address, NetconfClientDispatcher dispatcher) throws InterruptedException {
+        final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, dispatcher);
+        return netconfClient;
+    }
+    
+    @Before
+    public void setUp() throws Exception {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
+                new ModuleFactory[0])));
+
+        loadMessages();
+
+        NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
+
+        commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
+
+        dispatch = createDispatcher(Optional.<SSLContext> absent(), factoriesListener);
+        ChannelFuture s = dispatch.createServer(tcpAddress);
+        s.await();
+
+        dataBroker = new DataBrokerImpl();
+        mountManager = new MountPointManagerImpl();
+        mountManager.setDataBroker(dataBroker);
+        netconfManager = new NetconfDeviceManager();
+
+        netconfManager.setMountService(mountManager);
+        netconfManager.setDataService(dataBroker);
+        netconfManager.start();
+
+        try (NetconfClient netconfClient = createSession(tcpAddress, netconfManager.getDispatcher())) {
+            // send edit_config.xml
+            final Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
+            assertNotNull(rpcReply);
+        }
+    }
+
+
+    protected List<ModuleFactory> getModuleFactories() {
+        return getModuleFactoriesS();
+    }
+
+    static List<ModuleFactory> getModuleFactoriesS() {
+        return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(),
+                new NetconfTestImplModuleFactory());
+    }
+
+    private void loadMessages() throws IOException, SAXException, ParserConfigurationException {
+        this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
+        this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
+        this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
+        this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
+    }
+
+    private NetconfServerDispatcher createDispatcher(Optional<SSLContext> sslC,
+            NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+        SessionIdProvider idProvider = new SessionIdProvider();
+        NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
+                new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
+
+        NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
+                factoriesListener, commitNot, idProvider);
+
+        return new NetconfServerDispatcher(sslC, serverNegotiatorFactory, listenerFactory);
+    }
+
+    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
+        final Collection<InputStream> yangDependencies = getBasicYangs();
+        return new HardcodedYangStoreService(yangDependencies);
+    }
+
+    private Collection<InputStream> getBasicYangs() throws IOException {
+        List<String> paths = Arrays.asList("/META-INF/yang/config.yang", "/META-INF/yang/rpc-context.yang",
+                "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang",
+                "/META-INF/yang/ietf-inet-types.yang");
+        final Collection<InputStream> yangDependencies = new ArrayList<>();
+        for (String path : paths) {
+            final InputStream is = Preconditions
+                    .checkNotNull(getClass().getResourceAsStream(path), path + " not found");
+            yangDependencies.add(is);
+        }
+        return yangDependencies;
+    }
+
+    @Test
+    public void test() {
+        // MountProvisionInstance mount =
+        // Mockito.mock(MountProvisionInstance.class);
+        InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
+                .node(InventoryUtils.INVENTORY_NODE).toInstance();
+        netconfManager.netconfNodeAdded(path, tcpAddress);
+        InstanceIdentifier mountPointPath = path;
+        MountProvisionInstance mountPoint = mountManager.getMountPoint(mountPointPath);
+
+        CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
+                .toInstance());
+        assertNotNull(data);
+        assertEquals(CONFIG_MODULES, data.getNodeType());
+
+        CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
+        assertNotNull(data2);
+
+        InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
+
+        CompositeNode data3 = dataBroker.readOperationalData(fullPath);
+        assertNotNull(data3);
+        assertEquals(CONFIG_MODULES, data.getNodeType());
+    }
+
+}
index 8cc46dda9f12b4156ef0662d280a99349e9cf0b1..bdcb0bdd2bce239d65eac72f83432c1cff036a0e 100644 (file)
               org.eclipse.xtend.lib,
               org.eclipse.xtext.xbase.*
             </Private-Package>
+            <Import-Package>
+            *,
+            com.sun.jersey.spi.container.servlet
+            </Import-Package>
+            <Bundle-Activator>org.opendaylight.controller.sal.rest.impl.RestconfProvider</Bundle-Activator>
+            <Web-ContextPath>/restconf</Web-ContextPath>
           </instructions>
         </configuration>
       </plugin>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java
new file mode 100644 (file)
index 0000000..70b2cf5
--- /dev/null
@@ -0,0 +1,17 @@
+package org.opendaylight.controller.sal.rest.api;
+
+public class Draft02 {
+    public static class MediaTypes {
+        public static final String API = "application/yang.api";
+        public static final String DATASTORE = "application/yang.datastore";
+        public static final String DATA = "application/yang.data";
+        public static final String OPERATION = "application/yang.operation";
+        public static final String PATCH = "application/yang.patch";
+        public static final String PATCH_STATUS = "application/yang.patch-status";
+        public static final String STREAM = "application/yang.stream";
+    }
+    
+    public static class Paths {
+        
+    }
+}
index 0f566f5df72e36bd9e401ec8613585cafc460e13..c36a79c5d901093ad3bf79d1a4a354ebcf161209 100644 (file)
@@ -16,7 +16,9 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 /**
@@ -25,7 +27,9 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
  *  Section 5 for details on each URI.
  *    <ul>
  *    <li><b>/restconf</b> - {@link #getRoot()}
- *     <ul><li><b>/datastore</b> - {@link #readAllData()}
+ *     <ul><li><b>/config</b> 
+ *         <li><b>/operational</b> - {@link #readAllData()} - Added in Draft02
+ *         <li><b>/datastore</b> - {@link #readAllData()}
  *         <ul>
  *            <li>/(top-level-data-nodes) (config=true or false)
  *         </ul>
@@ -44,8 +48,8 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
  *         <li>/version (field)
  *     </ul>
  */
-@Path("restconf")
-public interface RestconfService {
+@Path("/")
+public interface RestconfService extends RestconfServiceLegacy {
 
     public static final String XML = "+xml";
     public static final String JSON = "+json";
@@ -53,33 +57,49 @@ public interface RestconfService {
     @GET
     public Object getRoot();
 
+
     @GET
-    @Path("/datastore")
+    @Path("/modules")
     @Produces({API+JSON,API+XML})
-    public Object readAllData();
+    public StructuredData getModules();
 
+    @POST
+    @Path("/operations/{identifier}")
+    @Produces({Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML,API+JSON,API+XML})
+    public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+    
+    
     @GET
-    @Path("/datastore/{identifier}")
-    @Produces({API+JSON,API+XML})
-    public StructuredData readData(@PathParam("identifier") String identifier);
+    @Path("/config/{identifier:.+}")
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+    public StructuredData readConfigurationData(@PathParam("identifier") String identifier);
 
+    
+    
     @PUT
-    @Path("/datastore/{identifier}")
+    @Path("/config/{identifier:.+}")
     @Produces({API+JSON,API+XML})
-    public Object createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public RpcResult<TransactionStatus> createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @POST
-    @Path("/datastore/{identifier}")
+    @Path("/config/{identifier:.+}")
     @Produces({API+JSON,API+XML})
-    public Object updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public RpcResult<TransactionStatus> updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @GET
-    @Path("/modules")
+    @Path("/operational/{identifier:.+}")
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+    public StructuredData readOperationalData(@PathParam("identifier") String identifier);
+
+    @PUT
+    @Path("/operational/{identifier:.+}")
     @Produces({API+JSON,API+XML})
-    public Object getModules();
+    public RpcResult<TransactionStatus> createOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @POST
-    @Path("/operations/{identifier}")
+    @Path("/operational/{identifier:.+}")
     @Produces({API+JSON,API+XML})
-    public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+    public RpcResult<TransactionStatus> updateOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
+
+    
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java
new file mode 100644 (file)
index 0000000..6683fd1
--- /dev/null
@@ -0,0 +1,46 @@
+package org.opendaylight.controller.sal.rest.api;
+
+import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface RestconfServiceLegacy {
+
+    public static final String XML = "+xml";
+    public static final String JSON = "+json";
+    
+    @Deprecated
+    @GET
+    @Path("/datastore")
+    @Produces({API+JSON,API+XML})
+    public StructuredData readAllData();
+
+    @Deprecated
+    @GET
+    @Path("/datastore/{identifier:.+}")
+    @Produces({API+JSON,API+XML})
+    public StructuredData readData(@PathParam("identifier") String identifier);
+
+    @Deprecated
+    @PUT
+    @Path("/datastore/{identifier:.+}")
+    @Produces({API+JSON,API+XML})
+    public RpcResult<TransactionStatus> createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
+
+    @Deprecated
+    @POST
+    @Path("/datastore/{identifier:.+}")
+    @Produces({API+JSON,API+XML})
+    public RpcResult<TransactionStatus> updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
new file mode 100644 (file)
index 0000000..55751e5
--- /dev/null
@@ -0,0 +1,190 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+
+import com.google.gson.stream.JsonWriter;
+
+class JsonMapper {
+    
+    private final Set<LeafListSchemaNode> foundLeafLists = new HashSet<>();
+    private final Set<ListSchemaNode> foundLists = new HashSet<>();
+    
+    public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException {
+        writer.beginObject();
+        writeChildrenOfParent(writer, data, schema);
+        writer.endObject();
+        foundLeafLists.clear();
+        foundLists.clear();
+    }
+
+    private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema) throws IOException {
+        checkNotNull(parent);
+        checkNotNull(parentSchema);
+        
+        for (Node<?> child : parent.getChildren()) {
+            DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
+            if (childSchema instanceof ContainerSchemaNode) {
+                writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
+            } else if (childSchema instanceof ListSchemaNode) {
+                if (!foundLists.contains(childSchema)) {
+                    foundLists.add((ListSchemaNode) childSchema);
+                    writeList(writer, (CompositeNode) child, (ListSchemaNode) childSchema);
+                }
+            } else if (childSchema instanceof LeafListSchemaNode) {
+                if (!foundLeafLists.contains(childSchema)) {
+                    foundLeafLists.add((LeafListSchemaNode) childSchema);
+                    writeLeafList(writer, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
+                }
+            } else if (childSchema instanceof LeafSchemaNode) {
+                writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
+            }
+        }
+        
+        for (Node<?> child : parent.getChildren()) {
+            DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
+            if (childSchema instanceof LeafListSchemaNode) {
+                foundLeafLists.remove((LeafListSchemaNode) childSchema);
+            } else if (childSchema instanceof ListSchemaNode) {
+                foundLists.remove((ListSchemaNode) childSchema);
+            }
+        }
+    }
+    
+    private DataSchemaNode findSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
+        for (DataSchemaNode dsn : dataSchemaNode) {
+            if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
+                return dsn;
+            }
+        }
+        return null;
+    }
+    
+    private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException {
+        writer.name(node.getNodeType().getLocalName());
+        writer.beginObject();
+        writeChildrenOfParent(writer, node, schema);
+        writer.endObject();
+    }
+    
+    private void writeList(JsonWriter writer, CompositeNode node, ListSchemaNode schema) throws IOException {
+            writer.name(node.getNodeType().getLocalName());
+            writer.beginArray();
+            
+            if (node.getParent() != null) {
+                CompositeNode parent = node.getParent();
+                List<CompositeNode> nodeLists = parent.getCompositesByName(node.getNodeType());
+                for (CompositeNode nodeList : nodeLists) {
+                    writer.beginObject();
+                    writeChildrenOfParent(writer, nodeList, schema);
+                    writer.endObject();
+                }
+            } else {
+                writer.beginObject();
+                writeChildrenOfParent(writer, node, schema);
+                writer.endObject();
+            }
+            
+            writer.endArray();
+    }
+    
+    private void writeLeafList(JsonWriter writer, SimpleNode<?> node, LeafListSchemaNode schema) throws IOException {
+            writer.name(node.getNodeType().getLocalName());
+            writer.beginArray();
+            
+            CompositeNode parent = node.getParent();
+            List<SimpleNode<?>> nodeLeafLists = parent.getSimpleNodesByName(node.getNodeType());
+            for (SimpleNode<?> nodeLeafList : nodeLeafLists) {
+                writeValueOfNodeByType(writer, nodeLeafList, schema.getType());
+            }
+            
+            writer.endArray();
+    }
+    
+    private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
+        writer.name(node.getNodeType().getLocalName());
+        writeValueOfNodeByType(writer, node, schema.getType());
+    }
+    
+    private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type) throws IOException {
+        if (!(node.getValue() instanceof String)) {
+            throw new IllegalStateException("Value in SimpleNode should be type String");
+        }
+        
+        String value = (String) node.getValue();
+        // TODO check Leafref, InstanceIdentifierTypeDefinition, IdentityrefTypeDefinition, UnionTypeDefinition
+        if (type.getBaseType() != null) {
+            writeValueOfNodeByType(writer, node, type.getBaseType());
+        } else if (type instanceof InstanceIdentifierTypeDefinition) {
+            writer.value(((InstanceIdentifierTypeDefinition) type).getPathStatement().toString());
+        } else if (type instanceof DecimalTypeDefinition 
+                || type instanceof IntegerTypeDefinition
+                || type instanceof UnsignedIntegerTypeDefinition) {
+            writer.value(new NumberForJsonWriter(value));
+        } else if (type instanceof BooleanTypeDefinition) {
+            writer.value(Boolean.parseBoolean(value));
+        } else if (type instanceof EmptyTypeDefinition) {
+            writer.value("[null]");
+        } else {
+            writer.value(value);
+        }
+    }
+    
+    private static final class NumberForJsonWriter extends Number {
+        
+        private static final long serialVersionUID = -3147729419814417666L;
+        private final String value;
+        
+        public NumberForJsonWriter(String value) {
+            this.value = value;
+        }
+
+        @Override
+        public int intValue() {
+            throw new IllegalStateException("Should not be invoked");
+        }
+
+        @Override
+        public long longValue() {
+            throw new IllegalStateException("Should not be invoked");
+        }
+
+        @Override
+        public float floatValue() {
+            throw new IllegalStateException("Should not be invoked");
+        }
+
+        @Override
+        public double doubleValue() {
+            throw new IllegalStateException("Should not be invoked");
+        }
+
+        @Override
+        public String toString() {
+            return value;
+        }
+        
+    }
+
+}
index 97ad3ef69d887b6fcda025c12ffa95921fc70857..cc6d449523671cfdca429ea1bb31779726a57b9c 100644 (file)
@@ -24,8 +24,7 @@ public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNo
 
     @Override
     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
-        // TODO Auto-generated method stub
-        return false;
+        return true;
     }
 
     @Override
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java
new file mode 100644 (file)
index 0000000..35b751c
--- /dev/null
@@ -0,0 +1,41 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.osgi.framework.BundleContext;
+
+public class RestconfProvider extends AbstractProvider {
+
+    private ListenerRegistration<SchemaServiceListener> listenerRegistration;
+
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+        DataBrokerService dataService = session.getService(DataBrokerService.class);
+
+        BrokerFacade.getInstance().setContext(session);
+        BrokerFacade.getInstance().setDataService(dataService);
+
+        SchemaService schemaService = session.getService(SchemaService.class);
+        listenerRegistration = schemaService.registerSchemaServiceListener(ControllerContext.getInstance());
+        ControllerContext.getInstance().setSchemas(schemaService.getGlobalContext());
+    }
+
+    @Override
+    protected void stopImpl(BundleContext context) {
+        super.stopImpl(context);
+        if (listenerRegistration != null) {
+            try {
+                listenerRegistration.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
index 608cdcd94341f5d8a37fc1ec520f2667b4b62028..b0e1e03c6c2715c0b99f271619d387f721d39884 100644 (file)
@@ -7,8 +7,6 @@ import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
-import java.util.List;
-import java.util.Set;
 
 import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
@@ -19,18 +17,7 @@ import javax.ws.rs.ext.Provider;
 
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
 
 import com.google.gson.stream.JsonWriter;
 
@@ -41,8 +28,7 @@ public enum StructuredDataToJsonProvider implements MessageBodyWriter<Structured
     
     @Override
     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
-        // TODO Auto-generated method stub
-        return false;
+        return true;
     }
 
     @Override
@@ -56,81 +42,9 @@ public enum StructuredDataToJsonProvider implements MessageBodyWriter<Structured
             throws IOException, WebApplicationException {
         JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, "UTF-8"));
         writer.setIndent("    ");
-        writer.beginObject();
-        convertNodeToJsonAccordingToSchema(writer, t.getData(), t.getSchema());
-        writer.endObject();
+        JsonMapper jsonMapper = new JsonMapper();
+        jsonMapper.write(writer, t.getData(), (DataNodeContainer) t.getSchema());
+        writer.flush();
     }
-
-    private void convertNodeToJsonAccordingToSchema(JsonWriter writer, Node<?> node, DataSchemaNode dataSchemaNode) throws IOException {
-        if (node instanceof CompositeNode) {
-            if (!(dataSchemaNode instanceof DataNodeContainer)) {
-                throw new IllegalStateException("CompositeNode should be represented as DataNodeContainer");
-            }
-            if (dataSchemaNode instanceof ContainerSchemaNode) {
-                writer.name(node.getNodeType().getLocalName());
-                writer.beginObject();
-                String listName = "";
-                for (Node<?> n : ((CompositeNode) node).getChildren()) {
-                    DataSchemaNode foundDataSchemaNode = findSchemaForNode(n, ((DataNodeContainer) dataSchemaNode).getChildNodes());
-                    if (foundDataSchemaNode instanceof ListSchemaNode) {
-                        if (listName.equals(n.getNodeType().getLocalName())) {
-                            continue;
-                        }
-                        listName = n.getNodeType().getLocalName();
-                    }
-                    convertNodeToJsonAccordingToSchema(writer, n, foundDataSchemaNode);
-                }
-                writer.endObject();
-            } else if (dataSchemaNode instanceof ListSchemaNode) {
-                writer.name(node.getNodeType().getLocalName());
-                writer.beginArray();
-                List<Node<?>> nodeSiblings = node.getParent().getChildren();
-                for (Node<?> nodeSibling : nodeSiblings) {
-                    if (nodeSibling.getNodeType().getLocalName().equals(node.getNodeType().getLocalName())) {
-                        DataSchemaNode schemaForNodeSibling = findSchemaForNode(nodeSibling,
-                                ((DataNodeContainer) dataSchemaNode.getParent()).getChildNodes());
-                        writer.beginObject();
-                        for (Node<?> child : ((CompositeNode) nodeSibling).getChildren()) {
-                            DataSchemaNode schemaForChild = findSchemaForNode(child,
-                                    ((DataNodeContainer) schemaForNodeSibling).getChildNodes());
-                            convertNodeToJsonAccordingToSchema(writer, child, schemaForChild);
-                        }
-                        writer.endObject();
-                    }
-                }
-                writer.endArray();
-            }
-        } else if (node instanceof SimpleNode<?>) {
-            if (!(dataSchemaNode instanceof LeafSchemaNode)) {
-                throw new IllegalStateException("SimpleNode should should be represented as LeafSchemaNode");
-            }
-            writeLeaf(writer, (LeafSchemaNode) dataSchemaNode, (SimpleNode<?>) node);
-        }
-    }
-
-    private DataSchemaNode findSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
-        for (DataSchemaNode dsn : dataSchemaNode) {
-            if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
-                return dsn;
-            }
-        }
-        return null;
-    }
-
-    private void writeLeaf(JsonWriter writer, LeafSchemaNode leafSchemaNode, SimpleNode<?> data) throws IOException {
-        TypeDefinition<?> type = leafSchemaNode.getType();
-
-        writer.name(data.getNodeType().getLocalName());
-
-        if (type instanceof DecimalTypeDefinition) {
-            writer.value((Double.valueOf((String) data.getValue())).doubleValue());
-        } else if (type instanceof IntegerTypeDefinition) {
-            writer.value((Integer.valueOf((String) data.getValue())).intValue());
-        } else if (type instanceof EmptyTypeDefinition) {
-            writer.value("[null]");
-        } else {
-            writer.value(String.valueOf(data.getValue()));
-        }
-    }
-
+    
 }
index 8e18661db6ecdfcc65d822dff5bf1e4c115c0b96..3c31c5a313ec0b45a9a8390729638331d4a7a7a0 100644 (file)
@@ -42,15 +42,15 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
         return future.get;
     }
 
-    def commitConfigurationDataUpdate(InstanceIdentifier path, CompositeNode payload) {
+    def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) {
         val transaction = dataService.beginTransaction;
         transaction.putConfigurationData(path, payload);
         return transaction.commit()
     }
 
-    def commitConfigurationDataCreate(InstanceIdentifier path, CompositeNode payload) {
+    def commitOperationalDataPut(InstanceIdentifier path, CompositeNode payload) {
         val transaction = dataService.beginTransaction;
-        transaction.putConfigurationData(path, payload);
+        transaction.putOperationalData(path, payload);
         return transaction.commit()
     }
     
index 5057413a7a0710b8261e359340fca5b0820e4f2f..400850103d7be35f72beeb39088a1618a23feff5 100644 (file)
@@ -24,18 +24,23 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
 
 import static com.google.common.base.Preconditions.*
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+import java.util.concurrent.ConcurrentHashMap
+
+class ControllerContext implements SchemaServiceListener {
 
-class ControllerContext {
-    
     val static ControllerContext INSTANCE = new ControllerContext
-    
+
     val static NULL_VALUE = "null"
-    
+
     @Property
     SchemaContext schemas;
 
     private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
     private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
+    private val Map<QName,RpcDefinition> qnameToRpc = new ConcurrentHashMap();
+    
 
     private new() {
         if (INSTANCE != null) {
@@ -208,6 +213,7 @@ class ControllerContext {
         if (targetNode instanceof ListSchemaNode) {
             val listNode = targetNode as ListSchemaNode;
             val keysSize = listNode.keyDefinition.size
+
             // every key has to be filled
             if ((strings.length - consumed) < keysSize) {
                 return null;
@@ -217,6 +223,7 @@ class ControllerContext {
             var i = 0;
             for (key : listNode.keyDefinition) {
                 val uriKeyValue = uriKeyValues.get(i);
+
                 // key value cannot be NULL
                 if (uriKeyValue.equals(NULL_VALUE)) {
                     return null
@@ -227,6 +234,7 @@ class ControllerContext {
             consumed = consumed + i;
             builder.nodeWithKey(targetNode.QName, keyValues);
         } else {
+
             // Only one instance of node is allowed
             builder.node(targetNode.QName);
         }
@@ -268,6 +276,23 @@ class ControllerContext {
         }
     }
 
-    public def QName toRpcQName(String name) {
+    public def QName toQName(String name) {
+        val module = name.toModuleName;
+        val node = name.toNodeName;
+        val namespace = moduleNameToUri.get(module);
+        return new QName(namespace,null,node);
+    }
+
+    override onGlobalContextUpdated(SchemaContext context) {
+        this.schemas = context;
+        for(operation : context.operations) {
+            val qname = new QName(operation.QName.namespace,null,operation.QName.localName);
+            qnameToRpc.put(qname,operation);
+        }
+    }
+    
+    def ContainerSchemaNode getRpcOutputSchema(QName name) {
+        qnameToRpc.get(name)?.output;
     }
+
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/JsonMapper.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/JsonMapper.xtend
deleted file mode 100644 (file)
index 7584b64..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.opendaylight.controller.sal.restconf.impl
-
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-
-class JsonMapper {
-    
-    @Property
-    ControllerContext controllerContext
-    
-    def convert(DataSchemaNode schema, CompositeNode data) {
-        return ""
-    }
-    
-}
\ No newline at end of file
index fc0dd1017fea6fbb9e77cd5f3b5a84d616b9e58f..31fbe8ec876876b0d677ffaa90df95fddbdfa91a 100644 (file)
@@ -25,7 +25,7 @@ class RestconfImpl implements RestconfService {
 
     override readAllData() {
 //        return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        throw new UnsupportedOperationException("Reading all data is currently not supported.")
     }
 
     override getModules() {
@@ -33,8 +33,7 @@ class RestconfImpl implements RestconfService {
     }
 
     override getRoot() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-
+        return null;
     }
 
     override readData(String identifier) {
@@ -44,18 +43,50 @@ class RestconfImpl implements RestconfService {
     }
 
     override createConfigurationData(String identifier, CompositeNode payload) {
-//        return broker.commitConfigurationDataCreate(identifier.toInstanceIdentifier.getInstanceIdentifier, payload);
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
     }
 
     override updateConfigurationData(String identifier, CompositeNode payload) {
-//        return broker.commitConfigurationDataCreate(identifier.toInstanceIdentifier.getInstanceIdentifier, payload);
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
     }
 
     override invokeRpc(String identifier, CompositeNode payload) {
-        val rpcResult = broker.invokeRpc(identifier.toRpcQName, payload);
-        return new StructuredData(rpcResult.result, identifier.toInstanceIdentifier.getSchemaNode)
+        val rpc = identifier.toQName;
+        val rpcResult = broker.invokeRpc(rpc, payload);
+        val schema = controllerContext.getRpcOutputSchema(rpc);
+        return new StructuredData(rpcResult.result, schema);
+    }
+    
+    override readConfigurationData(String identifier) {
+        val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+        val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+        return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+    }
+    
+    override readOperationalData(String identifier) {
+        val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+        val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+        return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+    }
+    
+    override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
+        updateConfigurationData(identifier,payload);
+    }
+    
+    override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
+        createConfigurationData(identifier,payload);
+    }
+    
+    override createOperationalData(String identifier, CompositeNode payload) {
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
+    }
+    
+    override updateOperationalData(String identifier, CompositeNode payload) {
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
     }
 
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/resources/WEB-INF/web.xml b/opendaylight/md-sal/sal-rest-connector/src/main/resources/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..eb2b516
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+    version="3.0">
+
+    <servlet>
+        <servlet-name>JAXRSRestconf</servlet-name>
+        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+        <init-param>
+            <param-name>javax.ws.rs.Application</param-name>
+            <param-value>org.opendaylight.controller.sal.rest.impl.RestconfApplication</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>JAXRSRestconf</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+
+    <filter>
+        <filter-name>CorsFilter</filter-name>
+        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
+        <init-param>
+            <param-name>cors.allowed.origins</param-name>
+            <param-value>*</param-value>
+        </init-param>
+        <init-param>
+            <param-name>cors.allowed.methods</param-name>
+            <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
+        </init-param>
+        <init-param>
+            <param-name>cors.allowed.headers</param-name>
+            <param-value>Content-Type,X-Requested-With,accept,authorization, 
+        origin,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
+        </init-param>
+        <init-param>
+            <param-name>cors.exposed.headers</param-name>
+            <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
+        </init-param>
+        <init-param>
+            <param-name>cors.support.credentials</param-name>
+            <param-value>true</param-value>
+        </init-param>
+        <init-param>
+            <param-name>cors.preflight.maxage</param-name>
+            <param-value>10</param-value>
+        </init-param>
+    </filter>
+    <filter-mapping>
+        <filter-name>CorsFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</url-pattern>
+            <http-method>POST</http-method>
+            <http-method>GET</http-method>
+            <http-method>PUT</http-method>
+            <http-method>PATCH</http-method>
+            <http-method>DELETE</http-method>
+            <http-method>HEAD</http-method>
+        </web-resource-collection>
+    </security-constraint>
+
+</web-app>
index b4cf6c985b6aa8a9995ccb43ed4c27fe6f494166..c6296eb7ea14ce82726dcd080b548dc375e26940 100644 (file)
@@ -1,15 +1,14 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.*;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+import javax.ws.rs.WebApplicationException;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -18,12 +17,13 @@ import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.*;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.slf4j.Logger;
@@ -114,5 +114,135 @@ final class TestUtils {
         }
 
     }
+    
+    static String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+        String jsonResult = null;
+        Set<Module> modules = null;
+
+        try {
+            modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("modules can't be null.", modules);
+
+        InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+        CompositeNode compositeNode = null;
+        try {
+            compositeNode = TestUtils.loadCompositeNode(xmlStream);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("Composite node can't be null", compositeNode);
+
+        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+        for (Module module : modules) {
+            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+                try {
+                    structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+                } catch (WebApplicationException | IOException e) {
+                    e.printStackTrace();
+                }
+                assertFalse(
+                        "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+                        byteArrayOS.toString().isEmpty());
+                jsonResult = byteArrayOS.toString();
+                try {
+                    outputToFile(byteArrayOS);
+                } catch (IOException e) {
+                    System.out.println("Output file wasn't cloased sucessfuly.");
+                }
+            }
+        }
+        return jsonResult;
+    }
+    
+    static void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+        FileOutputStream fileOS = null;
+        try {
+            String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+            File outFile = new File(path + "/data.json");
+            fileOS = new FileOutputStream(outFile);
+            try {
+                fileOS.write(outputStream.toByteArray());
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            fileOS.close();
+        } catch (FileNotFoundException e1) {
+            e1.printStackTrace();
+        }
+    }    
+    
+    static String readJsonFromFile(String path,boolean removeWhiteChars) {
+        FileReader fileReader = getFileReader(path);
+
+        StringBuilder strBuilder = new StringBuilder();
+        char[] buffer = new char[1000];
+
+        while (true) {
+            int loadedCharNum;
+            try {
+                loadedCharNum = fileReader.read(buffer);
+            } catch (IOException e) {
+                break;
+            }
+            if (loadedCharNum == -1) {
+                break;
+            }
+            strBuilder.append(buffer, 0, loadedCharNum);
+        }
+        try {
+            fileReader.close();
+        } catch (IOException e) {
+            System.out.println("The file wasn't closed");
+        }
+        String rawStr = strBuilder.toString();
+        if (removeWhiteChars) {        
+            rawStr = rawStr.replace("\n", "");
+            rawStr = rawStr.replace("\r", "");
+            rawStr = rawStr.replace("\t", "");
+            rawStr = removeSpaces(rawStr);
+        }
+
+        return rawStr;
+    }
+    
+    private static FileReader getFileReader(String path) {
+        String fullPath = YangAndXmlToJsonConversionJsonReaderTest.class.getResource(path).getPath();
+        assertNotNull("Path to file can't be null.", fullPath);
+        File file = new File(fullPath);
+        assertNotNull("File can't be null", file);
+        FileReader fileReader = null;
+        try {
+            fileReader = new FileReader(file);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("File reader can't be null.", fileReader);
+        return fileReader;
+    }
+
+    private static String removeSpaces(String rawStr) {
+        StringBuilder strBuilder = new StringBuilder();
+        int i = 0;
+        int quoteCount = 0;
+        while (i < rawStr.length()) {
+            if (rawStr.substring(i, i + 1).equals("\"")) {
+                quoteCount++;
+            }
+
+            if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
+                strBuilder.append(rawStr.charAt(i));
+            }
+            i++;
+        }
+
+        return strBuilder.toString();
+    }    
+    
+    
 
 }
index 3020824d3d97367374d53dd41c1242431a152090..0b8b5d48de1d6fe40bafaa5e82b61e854162fed6 100644 (file)
@@ -84,7 +84,7 @@ public class XmlProvidersTest extends JerseyTest {
     public void testStructuredDataToXmlProvider() throws FileNotFoundException {
         URI uri = null;
         try {
-            uri = new URI("/restconf/datastore/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+            uri = new URI("/datastore/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
         } catch (UnsupportedEncodingException | URISyntaxException e) {
             e.printStackTrace();
         }
@@ -101,7 +101,7 @@ public class XmlProvidersTest extends JerseyTest {
     public void testXmlToCompositeNodeProvider() throws ParserConfigurationException, SAXException, IOException {
         URI uri = null;
         try {
-            uri = new URI("/restconf/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+            uri = new URI("/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
         } catch (UnsupportedEncodingException | URISyntaxException e) {
             e.printStackTrace();
         }
@@ -138,7 +138,7 @@ public class XmlProvidersTest extends JerseyTest {
     public void testXmlToCompositeNodeProviderExceptions() {
         URI uri = null;
         try {
-            uri = new URI("/restconf/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+            uri = new URI("/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
         } catch (UnsupportedEncodingException | URISyntaxException e) {
             e.printStackTrace();
         }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionJsonReaderTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionJsonReaderTest.java
new file mode 100644 (file)
index 0000000..0f39088
--- /dev/null
@@ -0,0 +1,243 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.Test;
+
+import com.google.gson.stream.JsonReader;
+
+public class YangAndXmlToJsonConversionJsonReaderTest {
+
+    @Test
+    public void simpleYangTypesWithJsonReaderTest() {
+        String jsonOutput;
+        jsonOutput = TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",
+                false);
+
+//        jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+//                "/yang-to-json-conversion/simple-yang-types");
+        
+        StringReader strReader = new StringReader(jsonOutput);
+        JsonReader jReader = new JsonReader(strReader);
+        try {
+            checkCont1(jReader);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void checkCont1(JsonReader jReader) throws IOException {
+        jReader.beginObject();
+        assertNotNull("cont1 is missing.", jReader.hasNext());
+        jReader.nextName();
+        checkCont1Elements(jReader, prepareInputData(jReader), "cont1/");
+        jReader.endObject();
+
+    }
+
+    private Map<String, String> prepareInputData(JsonReader jReader) {
+        Map<String, String> dataMap = new HashMap<>();
+        dataMap.put("cont1/lf11", "lf");
+        dataMap.put("cont1/lflst11.1", "55");
+        dataMap.put("cont1/lflst11.2", "56");
+        dataMap.put("cont1/lflst11.3", "57");
+        dataMap.put("cont1/lflst12.1", "lflst12 str1");
+        dataMap.put("cont1/lflst12.2", "lflst12 str2");
+        dataMap.put("cont1/lflst12.3", "lflst12 str3");
+
+        dataMap.put("cont1/lst11.1/lf111", "140");
+        dataMap.put("cont1/lst11.1/lf112", "lf112 str");
+        dataMap.put("cont1/lst11.1/cont111/lf1111", "lf1111 str");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.1", "2048");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.2", "1024");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.3", "4096");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111A", "lf1111A str11");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111B", "4");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111A", "lf1111A str12");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111B", "7");
+        dataMap.put("cont1/lst11.1/lst111.1/lf1111", "65");
+        dataMap.put("cont1/lst11.1/lst112.1/lf1121", "lf1121 str11");
+
+        dataMap.put("cont1/lst11.2/lf111", "141");
+        dataMap.put("cont1/lst11.2/lf112", "lf112 str2");
+        dataMap.put("cont1/lst11.2/cont111/lf1111", "lf1111 str2");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.1", "2049");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.2", "1025");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.3", "4097");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111A", "lf1111A str21");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111B", "5");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111A", "lf1111A str22");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111B", "8");
+        dataMap.put("cont1/lst11.2/lst111.1/lf1111", "55");
+        dataMap.put("cont1/lst11.2/lst111.2/lf1111", "56");
+        dataMap.put("cont1/lst11.2/lst112.1/lf1121", "lf1121 str21");
+        dataMap.put("cont1/lst11.2/lst112.2/lf1121", "lf1121 str22");
+
+        return dataMap;
+
+    }
+
+    private void checkCont1Elements(JsonReader jReader, Map<String, String> dataMap, String pthPref) throws IOException {
+        Set<String> keys = new HashSet<>();
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf11")) {
+                assertEquals("Key " + keyName + " has incorrect value.", dataMap.get(pthPref + keyName),
+                        jReader.nextString());
+                keys.add(keyName);
+            } else if (keyName.equals("lflst11")) {
+                checkLflstValues(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else if (keyName.equals("lflst12")) {
+                checkLflstValues(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else if (keyName.equals("lst11")) {
+                checkLst11(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else {
+                assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+            }
+        }
+        jReader.endObject();
+        assertEquals("Incorrect number of keys in cont1", 4, keys.size());
+
+    }
+
+    private void checkLst11(JsonReader jReader, String pthPref, Map<String, String> dataMap) throws IOException {
+        jReader.beginArray();
+
+        int arrayLength = 0;
+        while (jReader.hasNext()) {
+            checkLst11Elements(jReader, pthPref + "." + ++arrayLength + "/", dataMap);
+        }
+        jReader.endArray();
+        assertEquals("Incorrect number of items in lst11 array.", 2, arrayLength);
+    }
+
+    private void checkLst11Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf111")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("lf112")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("cont111")) {
+                checkCont111(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst111")) {
+                checkLst111(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst112")) {
+                checkLst112(jReader, pthPref + keyName, data);
+            } else {
+                assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+            }
+        }
+        jReader.endObject();
+    }
+
+    private void checkLst112(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst112Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst112Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        if (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+        }
+        jReader.endObject();
+
+    }
+
+    private void checkLst111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        if (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+        }
+        jReader.endObject();
+    }
+
+    private void checkCont111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        checkCont111Elements(jReader, pthPref + "/", data);
+        jReader.endObject();
+    }
+
+    private void checkCont111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf1111")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("lflst1111")) {
+                checkLflstValues(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst1111")) {
+                checkLst1111(jReader, pthPref + keyName, data);
+            }
+        }
+
+    }
+
+    private void checkLst1111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst1111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst1111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf1111A")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+
+            } else if (keyName.equals("lf1111B")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            }
+        }
+        jReader.endObject();
+    }
+
+    private void checkLflstValues(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 1;
+        String keyValue = null;
+        List<String> searchedValues = new ArrayList<>();
+        while ((keyValue = data.get(pthPref + "." + arrayIndex++)) != null) {
+            searchedValues.add(keyValue);
+        }
+
+        while (jReader.hasNext()) {
+            String value = jReader.nextString();
+            assertTrue("Value " + value + " of lflst " + pthPref + " wasn't found", searchedValues.contains(value));
+        }
+
+        jReader.endArray();
+    }
+
+
+
+}
@@ -1,22 +1,14 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
-import java.io.*;
-import java.util.Set;
-import java.util.regex.*;
+import java.util.regex.Pattern;
 
-import javax.ws.rs.WebApplicationException;
+import org.junit.Test;
 
-import org.junit.*;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.model.api.*;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+public class YangAndXmlToJsonConversionRegExTest {
 
-public class YangAndXmlToJsonConversion {
-
-    @Ignore
     @Test
     /**
      * Test for simple yang types (leaf, list, leaf-list, container and various combination of them)
@@ -25,15 +17,14 @@ public class YangAndXmlToJsonConversion {
     public void simpleYangTypesTest() {
         String jsonOutput = null;
 
-        jsonOutput = convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
-                "/yang-to-json-conversion/simple-yang-types");
+//        jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+//                "/yang-to-json-conversion/simple-yang-types");
 
-//         jsonOutput =
-//         readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/output.json");
+         jsonOutput =
+         TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",true);
 
         verifyJsonOutputForSimpleYangTypes(jsonOutput);
-
-    }
+    }    
 
     private void verifyJsonOutputForSimpleYangTypes(String jsonOutput) {
 
@@ -149,125 +140,69 @@ public class YangAndXmlToJsonConversion {
         return null;
     }
 
-    private String readJsonFromFile(String path) {
-        String fullPath = YangAndXmlToJsonConversion.class.getResource(path).getPath();
-        assertNotNull("Path to file can't be null.", fullPath);
-        File file = new File(fullPath);
-        assertNotNull("File can't be null", file);
-        FileReader fileReader = null;
-        try {
-            fileReader = new FileReader(file);
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("File reader can't be null.", fileReader);
-
-        StringBuilder strBuilder = new StringBuilder();
-        char[] buffer = new char[1000];
-
-        while (true) {
-            int loadedCharNum;
-            try {
-                loadedCharNum = fileReader.read(buffer);
-            } catch (IOException e) {
-                break;
-            }
-            if (loadedCharNum == -1) {
-                break;
-            }
-            strBuilder.append(buffer, 0, loadedCharNum);
-        }
-        try {
-            fileReader.close();
-        } catch (IOException e) {
-            System.out.println("The file wasn't closed");
-            ;
-        }
-        String rawStr = strBuilder.toString();
-        rawStr = rawStr.replace("\n", "");
-        rawStr = rawStr.replace("\r", "");
-        rawStr = rawStr.replace("\t", "");
-        rawStr = removeSpaces(rawStr);
-
-        return rawStr;
-    }
-
-    private String removeSpaces(String rawStr) {
-        StringBuilder strBuilder = new StringBuilder();
-        int i = 0;
-        int quoteCount = 0;
-        while (i < rawStr.length()) {
-            if (rawStr.substring(i, i + 1).equals("\"")) {
-                quoteCount++;
-            }
 
-            if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
-                strBuilder.append(rawStr.charAt(i));
-            }
-            i++;
-        }
-
-        return strBuilder.toString();
-    }
 
-    private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
-        String jsonResult = null;
-        Set<Module> modules = null;
 
-        try {
-            modules = TestUtils.loadModules(YangAndXmlToJsonConversion.class.getResource(yangPath).getPath());
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("modules can't be null.", modules);
-
-        InputStream xmlStream = YangAndXmlToJsonConversion.class.getResourceAsStream(xmlDataPath);
-        CompositeNode compositeNode = null;
-        try {
-            compositeNode = TestUtils.loadCompositeNode(xmlStream);
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("Composite node can't be null", compositeNode);
+//    private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+//        String jsonResult = null;
+//        Set<Module> modules = null;
+//
+//        try {
+//            modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+//        } catch (FileNotFoundException e) {
+//            e.printStackTrace();
+//        }
+//        assertNotNull("modules can't be null.", modules);
+//
+//        InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+//        CompositeNode compositeNode = null;
+//        try {
+//            compositeNode = TestUtils.loadCompositeNode(xmlStream);
+//        } catch (FileNotFoundException e) {
+//            e.printStackTrace();
+//        }
+//        assertNotNull("Composite node can't be null", compositeNode);
+//
+//        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+//        for (Module module : modules) {
+//            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+//                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+//                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+//                try {
+//                    structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+//                } catch (WebApplicationException | IOException e) {
+//                    e.printStackTrace();
+//                }
+//                assertFalse(
+//                        "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+//                        byteArrayOS.toString().isEmpty());
+//                jsonResult = byteArrayOS.toString();
+//                try {
+//                    outputToFile(byteArrayOS);
+//                } catch (IOException e) {
+//                    System.out.println("Output file wasn't cloased sucessfuly.");
+//                }
+//            }
+//        }
+//        return jsonResult;
+//    }
+//
+//    private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+//        FileOutputStream fileOS = null;
+//        try {
+//            String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+//            File outFile = new File(path + "/data.json");
+//            fileOS = new FileOutputStream(outFile);
+//            try {
+//                fileOS.write(outputStream.toByteArray());
+//            } catch (IOException e) {
+//                e.printStackTrace();
+//            }
+//            fileOS.close();
+//        } catch (FileNotFoundException e1) {
+//            e1.printStackTrace();
+//        }
+//    }
+    
 
-        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
-        for (Module module : modules) {
-            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
-                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
-                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
-                try {
-                    structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
-                } catch (WebApplicationException | IOException e) {
-                    e.printStackTrace();
-                }
-                assertFalse(
-                        "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
-                        byteArrayOS.toString().isEmpty());
-                jsonResult = byteArrayOS.toString();
-                try {
-                    outputToFile(byteArrayOS);
-                } catch (IOException e) {
-                    System.out.println("Output file wasn't cloased sucessfuly.");
-                }
-            }
-        }
-        return jsonResult;
-    }
-
-    private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
-        FileOutputStream fileOS = null;
-        try {
-            String path = YangAndXmlToJsonConversion.class.getResource("/yang-to-json-conversion/xml").getPath();
-            File outFile = new File(path + "/data.json");
-            fileOS = new FileOutputStream(outFile);
-            try {
-                fileOS.write(outputStream.toByteArray());
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            fileOS.close();
-        } catch (FileNotFoundException e1) {
-            e1.printStackTrace();
-        }
-    }
 }
index e76e7bd9ef4f20c5405ef8a71046fcd504047d18..a0e5f2f0f2b804d182b9b1f1c310f61e150e9718 100644 (file)
                         "lf1111B": 7
                     }
                     ]
-                }
+                },
+                "lst111" : [
+                {
+                       "lf1111" : 65
+                       }
+                       ],
+                       "lst112" : [
+                       {
+                       "lf1121" : "lf1121 str11"
+                       }
+                       ]
+                
             },
             {
                 "lf111":141,
                         "lf1111B": 8
                     }
                     ]
-                }
+                },
+                "lst111" : [
+                {
+                       "lf1111" : 55
+                       },
+                {
+                       "lf1111" : 56
+                       }
+                       ],
             }        
         ]
+                       "lst112" : [
+                       {
+                       "lf1121" : "lf1121 str21"
+                       },
+                       {
+                       "lf1121" : "lf1121 str22"
+                       }
+                       ]
+            }
+            ]
     }
 }
\ No newline at end of file
index 3db4a65840dd6e1f4356cee52075878796da6d6f..72e49be4de49899f111aeb55ffe65426b0eb3d1e 100644 (file)
 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-parent</artifactId>
-        <version>1.0-SNAPSHOT</version>
-    </parent>
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>sal-parent</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
 
+  <artifactId>sal-zeromq-connector</artifactId>
+  <packaging>bundle</packaging>
 
-    <artifactId>sal-zeromq-connector</artifactId>
-    <packaging>bundle</packaging>
+  <properties>
+    <scala.version>2.10.3</scala.version>
+  </properties>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <version>${bundle.plugin.version}</version>
-                <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                        <Import-Package>
-                        org.opendaylight.controller.sal.connector.api,
-                        org.opendaylight.controller.sal.core.api,
-                        org.opendaylight.yangtools.concepts;version="[0.1,1)",
-                        org.opendaylight.yangtools.yang.common;version="[0.5,1)",
-                        org.opendaylight.yangtools.yang.data.api;version="[0.5,1)",
-                        org.zeromq;version="[0.3,1)"
-                        </Import-Package>
-                        <Bundle-Activator>org.opendaylight.controller.sal.connector.zeromq.Activator</Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <dependencies>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>containermanager</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>commons.northbound</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-binding</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-common</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-connector-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-util</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>${bundle.plugin.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>
+              org.opendaylight.controller.sal.connector.api,
+              org.opendaylight.controller.sal.core.api,
+              org.opendaylight.yangtools.concepts;version="[0.1,1)",
+              org.opendaylight.yangtools.yang.common;version="[0.5,1)",
+              org.opendaylight.yangtools.yang.data.api;version="[0.5,1)",
+              org.zeromq;version="[0.3,1)"
+            </Import-Package>
+            <Bundle-Activator>org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Activator</Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
 
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jeromq</groupId>
-            <artifactId>jeromq</artifactId>
-            <version>0.3.0-SNAPSHOT</version>
-        </dependency>
+      <plugin>
+        <groupId>net.alchim31.maven</groupId>
+        <artifactId>scala-maven-plugin</artifactId>
+        <version>3.1.6</version>
+        <configuration>
+          <recompileMode>incremental</recompileMode>
+          <args>
+            <arg>-target:jvm-1.7</arg>
+          </args>
+          <javacArgs>
+            <javacArg>-source</javacArg><javacArg>1.7</javacArg>
+            <javacArg>-target</javacArg><javacArg>1.7</javacArg>
+          </javacArgs>
+        </configuration>
+        <executions>
+          <execution>
+            <id>scala-compile</id>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>scala-test-compile</id>
+            <goals>
+              <goal>testCompile</goal>
+            </goals>
+          </execution>
+        </executions>
 
-    </dependencies>
-    <repositories>
-        <repository>
-            <id>sonatype-nexus-snapshots</id>
-            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
-            <releases>
-                <enabled>false</enabled>
-            </releases>
-            <snapshots>
-                <enabled>true</enabled>
-            </snapshots>
-        </repository>
-    </repositories>
+      </plugin>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>default-compile</id>
+            <phase>none</phase>
+          </execution>
+          <execution>
+            <id>default-testCompile</id>
+            <phase>none</phase>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.scala-lang</groupId>
+      <artifactId>scala-library</artifactId>
+      <version>${scala.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-binding</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-connector-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-util</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jeromq</groupId>
+      <artifactId>jeromq</artifactId>
+      <version>0.3.0-SNAPSHOT</version>
+    </dependency>
+
+  </dependencies>
+  <repositories>
+    <repository>
+      <id>sonatype-nexus-snapshots</id>
+      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+      <snapshots>
+        <enabled>true</enabled>
+      </snapshots>
+    </repository>
+  </repositories>
 
 </project>
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChange.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChange.java
new file mode 100644 (file)
index 0000000..ba90f37
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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
+ */
+package org.opendaylight.controller.sal.connector.remoterpc.api;
+
+import java.util.Map;
+import java.util.Set;
+
+public interface RouteChange<I, R> {
+
+  Map<I, Set<R>> getRemovals();
+  Map<I, Set<R>> getAnnouncements();
+}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java
new file mode 100644 (file)
index 0000000..701cfaf
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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
+ */
+package org.opendaylight.controller.sal.connector.remoterpc.api;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.util.EventListener;
+
+public interface RouteChangeListener extends EventListener {
+
+  public void onRouteChanged(RouteChange<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>  change);
+}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java
new file mode 100644 (file)
index 0000000..3c6c42e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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
+ */
+package org.opendaylight.controller.sal.connector.remoterpc.api;
+
+import java.util.Set;
+
+public interface RoutingTable<I,R> {
+
+  /**
+   * Adds a network address for the route. If address for route
+   * exists, appends the address to the list
+   *
+   * @param routeId route identifier
+   * @param route network address
+   */
+  public void addRoute(I routeId, R route);
+
+  /**
+   * Adds a network address for the route. If the route already exists,
+   * it throws. This method would be used when registering a global service.
+   *
+   * @param routeId route identifier
+   * @param route network address
+   * @throws DuplicateRouteException
+   */
+  public void addGlobalRoute(I routeId, R route) throws DuplicateRouteException;
+
+  /**
+   * Removes the network address for the route from routing table. If only
+   * one network address existed, remove the route as well.
+   * @param routeId
+   * @param route
+   */
+  public void removeRoute(I routeId, R route);
+
+  /**
+   * Returns a set of network addresses associated with this route
+   * @param routeId
+   * @return
+   */
+  public Set<R> getRoutes(I routeId);
+
+  /**
+   * Returns only one address from the list of network addresses
+   * associated with the route. The algorithm to determine that
+   * one address is upto the implementer
+   * @param route
+   * @return
+   */
+  public R getARoute(I routeId);
+
+  public void registerRouteChangeListener(RouteChangeListener listener);
+
+  public class DuplicateRouteException extends Exception {}
+}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Activator.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Activator.java
new file mode 100644 (file)
index 0000000..5b927a5
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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
+ */
+package org.opendaylight.controller.sal.connector.remoterpc.router.zeromq;
+
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.osgi.framework.BundleContext;
+
+public class Activator extends AbstractProvider {
+
+  ZeroMqRpcRouter router;
+
+  @Override
+  public void onSessionInitiated(ProviderSession session) {
+    router = ZeroMqRpcRouter.getInstance();
+    router.setBrokerSession(session);
+    router.start();
+  }
+
+  @Override
+  protected void stopImpl(BundleContext context) {
+    router.stop();
+  }
+
+}
@@ -1,16 +1,23 @@
-package org.opendaylight.controller.sal.connector.zeromq;
+/*
+ * 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
+ */
+
+package org.opendaylight.controller.sal.connector.remoterpc.router.zeromq;
 
 
 import org.codehaus.jackson.map.ObjectMapper;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 
 import java.io.*;
-import java.util.Arrays;
 
 public class Message implements Serializable {
 
- public enum MessageType {
-    ANNOUNCE((byte) 0),
+ public static enum MessageType {
+    ANNOUNCE((byte) 0),  //TODO: Remove announce, add rpc registration and deregistration
     HEARTBEAT((byte) 1),
     REQUEST((byte) 2),
     RESPONSE((byte) 3);
@@ -101,27 +108,15 @@ public class Message implements Serializable {
     return o.readObject();
   }
 
-  public static byte[] toJsonBytes(Message m){
+  public static byte[] toJsonBytes(Message m) throws IOException {
     ObjectMapper o = new ObjectMapper();
-    try {
-      System.out.println(o.writeValueAsString(m));
-      return o.writeValueAsBytes(m);
-    } catch (IOException e) {
-      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
-    }
-    return null;
+    return o.writeValueAsBytes(m);
   }
 
-  public static Message fromJsonBytes(byte [] bytes){
+  public static Message fromJsonBytes(byte [] bytes) throws IOException {
 
     ObjectMapper o = new ObjectMapper();
-    Message m = null;
-    try {
-      m = o.readValue(bytes, Message.class);
-    } catch (IOException e) {
-      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
-    }
-    return m;
+    return o.readValue(bytes, Message.class);
   }
 
   public static class Response extends Message implements RpcRouter.RpcReply {
@@ -146,5 +141,41 @@ public class Message implements Serializable {
     }
   }
 
+  /**
+   * Builds a {@link Message} object
+   */
+  public static class MessageBuilder{
+
+    private Message message;
+
+    public MessageBuilder(){
+      message = new Message();
+    }
+
+
+    public MessageBuilder type(MessageType type){
+      message.setType(type);
+      return this;
+    }
+
+    public MessageBuilder sender(String sender){
+      message.setSender(sender);
+      return this;
+    }
+
+    public MessageBuilder route(RpcRouter.RouteIdentifier route){
+      message.setRoute(route);
+      return this;
+    }
+
+    public MessageBuilder payload(Object obj){
+      message.setPayload(obj);
+      return this;
+    }
+
+    public Message build(){
+      return message;
+    }
+  }
 }
 
@@ -1,4 +1,11 @@
-package org.opendaylight.controller.sal.connector.zeromq;
+/*
+ * 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
+ */
+package org.opendaylight.controller.sal.connector.remoterpc.router.zeromq;
 
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -1,4 +1,11 @@
-package org.opendaylight.controller.sal.connector.zeromq;
+/*
+ * 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
+ */
+package org.opendaylight.controller.sal.connector.remoterpc.router.zeromq;
 
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -6,13 +13,6 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
 import java.io.Serializable;
 
-/**
- * Created with IntelliJ IDEA.
- * User: abhishk2
- * Date: 10/25/13
- * Time: 12:32 PM
- * To change this template use File | Settings | File Templates.
- */
 public class RpcRequestImpl implements RpcRouter.RpcRequest<QName, QName, InstanceIdentifier, Object>,Serializable {
 
   private RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier;
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/ZeroMqRpcRouter.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/ZeroMqRpcRouter.java
new file mode 100644 (file)
index 0000000..af94804
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+ * 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
+ */
+package org.opendaylight.controller.sal.connector.remoterpc.router.zeromq;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Message.MessageType;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+/**
+ * ZeroMq based implementation of RpcRouter
+ * TODO:
+ *    1. Make it multi VM aware
+ *    2. Make rpc request handling async and non-blocking. Note zmq socket is not thread safe
+ *    3. sendRpc() should use connection pooling
+ *    4. Read properties from config file using existing(?) ODL properties framework
+ */
+public class ZeroMqRpcRouter implements RpcRouter<QName, QName, InstanceIdentifier, Object> {
+
+  private ExecutorService serverPool;
+  private static ExecutorService handlersPool;
+
+  private Map<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
+
+  private ProviderSession brokerSession;
+
+  private ZMQ.Context context;
+  private ZMQ.Socket publisher;
+  private ZMQ.Socket subscriber;
+  private ZMQ.Socket replySocket;
+
+  private static ZeroMqRpcRouter _instance = new ZeroMqRpcRouter();
+
+  private final RpcFacade facade = new RpcFacade();
+  private final RpcListener listener = new RpcListener();
+
+  private final String localIp = getLocalIpAddress();
+
+  private String pubPort = System.getProperty("pub.port");// port on which announcements are sent
+  private String subPort = System.getProperty("sub.port");// other controller's pub port
+  private String pubIp = System.getProperty("pub.ip"); // other controller's ip
+  private String rpcPort = System.getProperty("rpc.port");// port on which RPC messages are received
+
+  private Logger _logger = LoggerFactory.getLogger(ZeroMqRpcRouter.class);
+
+  //Prevent instantiation
+  private ZeroMqRpcRouter() {
+  }
+
+  public static ZeroMqRpcRouter getInstance() {
+    return _instance;
+  }
+
+  public void start() {
+    context = ZMQ.context(2);
+    publisher = context.socket(ZMQ.PUB);
+    int ret = publisher.bind("tcp://*:" + pubPort);
+    // serverPool = Executors.newSingleThreadExecutor();
+    serverPool = Executors.newCachedThreadPool();
+    handlersPool = Executors.newCachedThreadPool();
+    routingTable = new ConcurrentHashMap<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
+
+    // Start listening for announce and rpc messages
+    serverPool.execute(receive());
+
+    brokerSession.addRpcRegistrationListener(listener);
+
+    Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
+    for (QName rpc : currentlySupported) {
+      listener.onRpcImplementationAdded(rpc);
+    }
+
+  }
+
+  public void stop() {
+    if (handlersPool != null)
+      handlersPool.shutdown();
+    if (serverPool != null)
+      serverPool.shutdown();
+    if (publisher != null) {
+      publisher.setLinger(0);
+      publisher.close();
+    }
+    if (replySocket != null) {
+      replySocket.setLinger(0);
+      replySocket.close();
+    }
+    if (subscriber != null) {
+      subscriber.setLinger(0);
+      subscriber.close();
+    }
+    if (context != null)
+      context.term();
+
+  }
+
+  private Runnable receive() {
+    return new Runnable() {
+      public void run() {
+        try {
+          // Bind to RPC reply socket
+          replySocket = context.socket(ZMQ.REP);
+          replySocket.bind("tcp://*:" + rpcPort);
+
+          // Bind to publishing controller
+          subscriber = context.socket(ZMQ.SUB);
+          String pubAddress = "tcp://" + pubIp + ":" + subPort;
+          subscriber.connect(pubAddress);
+          _logger.debug("{} Subscribing at[{}]", Thread.currentThread().getName(), pubAddress);
+
+          //subscribe for announcements
+          //TODO: Message type would be changed. Update this
+          subscriber.subscribe(Message.serialize(Message.MessageType.ANNOUNCE));
+
+          // Poller enables listening on multiple sockets using a single thread
+          ZMQ.Poller poller = new ZMQ.Poller(2);
+          poller.register(replySocket, ZMQ.Poller.POLLIN);
+          poller.register(subscriber, ZMQ.Poller.POLLIN);
+
+          //TODO: Add code to restart the thread after exception
+          while (!Thread.currentThread().isInterrupted()) {
+
+            poller.poll();
+
+            if (poller.pollin(0)) {
+              handleRpcCall();
+            }
+            if (poller.pollin(1)) {
+              handleAnnouncement();
+            }
+          }
+        } catch (Exception e) {
+          e.printStackTrace();
+        }
+        replySocket.setLinger(0);
+        replySocket.close();
+        subscriber.setLinger(0);
+        subscriber.close();
+      }
+    };
+  }
+
+  /**
+   * @throws IOException
+   * @throws ClassNotFoundException
+   */
+  private void handleAnnouncement() throws IOException, ClassNotFoundException {
+
+    _logger.info("Announcement received");
+    Message.MessageType topic = (MessageType) Message.deserialize(subscriber.recv());
+
+    if (subscriber.hasReceiveMore()) {
+      try {
+        Message m = (Message) Message.deserialize(subscriber.recv());
+        _logger.debug("Announcement message [{}]", m);
+
+        // TODO: check on msg type or topic. Both
+        // should be same. Need to normalize.
+        if (Message.MessageType.ANNOUNCE == m.getType())
+          updateRoutingTable(m);
+      } catch (IOException | ClassNotFoundException e) {
+        e.printStackTrace();
+      }
+    }
+
+  }
+
+  /**
+   * @throws InterruptedException
+   * @throws ExecutionException
+   */
+  private void handleRpcCall() throws InterruptedException, ExecutionException {
+    try {
+      Message request = parseMessage(replySocket);
+
+      _logger.debug("Received rpc request [{}]", request);
+
+      // Call broker to process the message then reply
+      Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc(
+          (QName) request.getRoute().getType(), (CompositeNode) request.getPayload());
+
+      RpcResult<CompositeNode> result = rpc.get();
+
+      Message response = new Message.MessageBuilder()
+          .type(MessageType.RESPONSE)
+          .sender(localIp + ":" + rpcPort)
+          .route(request.getRoute())
+          //.payload(result)    TODO: enable and test
+          .build();
+
+      replySocket.send(Message.serialize(response));
+
+      _logger.debug("Sent rpc response [{}]", response);
+
+    } catch (IOException ex) {
+      //TODO: handle exception and send error codes to caller
+      ex.printStackTrace();
+    }
+  }
+
+
+  @Override
+  public Future<RpcReply<Object>> sendRpc(
+      final RpcRequest<QName, QName, InstanceIdentifier, Object> input) {
+
+    return handlersPool.submit(new Callable<RpcReply<Object>>() {
+
+      @Override
+      public RpcReply<Object> call() {
+        ZMQ.Socket requestSocket = context.socket(ZMQ.REQ);
+
+        // TODO pick the ip and port from routing table based on routing identifier
+        requestSocket.connect("tcp://" + pubIp + ":5554");
+
+        Message requestMessage = new Message.MessageBuilder()
+            .type(MessageType.REQUEST)
+            .sender(localIp + ":" + rpcPort)
+            .route(input.getRoutingInformation())
+            .payload(input.getPayload())
+            .build();
+
+        _logger.debug("Sending rpc request [{}]", requestMessage);
+
+        RpcReply<Object> reply = null;
+
+        try {
+
+          requestSocket.send(Message.serialize(requestMessage));
+          final Message response = parseMessage(requestSocket);
+
+          _logger.debug("Received response [{}]", response);
+
+          reply = new RpcReply<Object>() {
+
+            @Override
+            public Object getPayload() {
+              return response.getPayload();
+            }
+          };
+        } catch (IOException ex) {
+          // TODO: Pass exception back to the caller
+          ex.printStackTrace();
+        }
+
+        return reply;
+      }
+    });
+  }
+
+  /**
+   * TODO: Remove this implementation and use RoutingTable implementation to send announcements
+   * Publishes a notice to other controllers in the cluster
+   *
+   * @param notice
+   */
+  public void publish(final Message notice) {
+    Runnable task = new Runnable() {
+      public void run() {
+
+        try {
+
+          publisher.sendMore(Message.serialize(Message.MessageType.ANNOUNCE));
+          publisher.send(Message.serialize(notice));
+          _logger.debug("Announcement sent [{}]", notice);
+        } catch (IOException ex) {
+          _logger.error("Error in sending announcement [{}]", notice);
+          ex.printStackTrace();
+        }
+      }
+    };
+    handlersPool.execute(task);
+  }
+
+  /**
+   * Finds IPv4 address of the local VM
+   * TODO: This method is non-deterministic. There may be more than one IPv4 address. Cant say which
+   * address will be returned. Read IP from a property file or enhance the code to make it deterministic.
+   * Should we use IP or hostname?
+   *
+   * @return
+   */
+  private String getLocalIpAddress() {
+    String hostAddress = null;
+    Enumeration e = null;
+    try {
+      e = NetworkInterface.getNetworkInterfaces();
+    } catch (SocketException e1) {
+      e1.printStackTrace();
+    }
+    while (e.hasMoreElements()) {
+
+      NetworkInterface n = (NetworkInterface) e.nextElement();
+
+      Enumeration ee = n.getInetAddresses();
+      while (ee.hasMoreElements()) {
+        InetAddress i = (InetAddress) ee.nextElement();
+        if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
+          hostAddress = i.getHostAddress();
+      }
+    }
+    return hostAddress;
+
+  }
+
+  /**
+   * TODO: Change to use external routing table implementation
+   *
+   * @param msg
+   */
+  private void updateRoutingTable(Message msg) {
+    routingTable.put(msg.getRoute(), msg.getSender());
+    RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> route = msg.getRoute();
+
+    // Currently only registers rpc implementation.
+    // TODO: do registration for instance based routing
+    QName rpcType = route.getType();
+    RpcRegistration registration = brokerSession.addRpcImplementation(rpcType, facade);
+    _logger.debug("Routing table updated");
+  }
+
+  /**
+   * @param socket
+   * @return
+   */
+  private Message parseMessage(ZMQ.Socket socket) {
+
+    Message msg = null;
+    try {
+      byte[] bytes = socket.recv();
+      _logger.debug("Received bytes:[{}]", bytes.length);
+      msg = (Message) Message.deserialize(bytes);
+    } catch (Throwable t) {
+      t.printStackTrace();
+    }
+    return msg;
+  }
+
+  private class RpcFacade implements RpcImplementation {
+
+    @Override
+    public Set<QName> getSupportedRpcs() {
+      return Collections.emptySet();
+    }
+
+    @Override
+    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+
+      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+      routeId.setType(rpc);
+
+      RpcRequestImpl request = new RpcRequestImpl();
+      request.setRouteIdentifier(routeId);
+      request.setPayload(input);
+
+      final Future<RpcReply<Object>> ret = sendRpc(request);
+
+      //TODO: Review result handling
+      RpcResult<CompositeNode> result = new RpcResult<CompositeNode>() {
+        @Override
+        public boolean isSuccessful() {
+          try {
+            ret.get();
+          } catch (InterruptedException | ExecutionException e) {
+            e.printStackTrace();
+            return false;
+          }
+          return true;
+        }
+
+        @Override
+        public CompositeNode getResult() {
+          return null;
+        }
+
+        @Override
+        public Collection<RpcError> getErrors() {
+          return Collections.EMPTY_LIST;
+        }
+      };
+      return result;
+    }
+  }
+
+  /**
+   * Listener for rpc registrations
+   */
+  private class RpcListener implements RpcRegistrationListener {
+
+    @Override
+    public void onRpcImplementationAdded(QName name) {
+
+      _logger.debug("Announcing registration for [{}]", name);
+      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+      routeId.setType(name);
+
+      //TODO: Make notice immutable and change message type
+      Message notice = new Message.MessageBuilder()
+          .type(MessageType.ANNOUNCE)
+          .sender("tcp://" + localIp + ":" + rpcPort)
+          .route(routeId)
+          .build();
+
+      publish(notice);
+    }
+
+    @Override
+    public void onRpcImplementationRemoved(QName name) {
+      // TODO: send a rpc-deregistrtation notice
+
+    }
+  }
+
+  public void setBrokerSession(ProviderSession session) {
+    this.brokerSession = session;
+
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Activator.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Activator.java
deleted file mode 100644 (file)
index b8933ec..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.opendaylight.controller.sal.connector.zeromq;
-
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.osgi.framework.BundleContext;
-
-public class Activator extends AbstractProvider {
-    
-    ZeroMqRpcRouter router;
-    
-    @Override
-    public void onSessionInitiated(ProviderSession session) {
-        router = ZeroMqRpcRouter.getInstance();
-        router.setBrokerSession(session);
-        router.start();
-    }
-    
-    @Override
-    protected void stopImpl(BundleContext context) {
-       router.stop();
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcReplyImpl.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcReplyImpl.java
deleted file mode 100644 (file)
index 66ff714..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.opendaylight.controller.sal.connector.zeromq;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-
-import java.io.Serializable;
-
-/**
- * Created with IntelliJ IDEA.
- * User: abhishk2
- * Date: 10/24/13
- * Time: 4:25 PM
- * To change this template use File | Settings | File Templates.
- */
-public class RpcReplyImpl implements RpcRouter.RpcReply<Object>,Serializable {
-
-  private Object payload;
-
-  @Override
-  public Object getPayload() {
-    return payload;  //To change body of implemented methods use File | Settings | File Templates.
-  }
-
-  public void setPayload(Object payload){
-    this.payload = payload;
-  }
-}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/ZeroMqRpcRouter.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/ZeroMqRpcRouter.java
deleted file mode 100644 (file)
index 7e5efda..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-package org.opendaylight.controller.sal.connector.zeromq;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.zeromq.ZMQ;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.*;
-import java.util.concurrent.*;
-
-public class ZeroMqRpcRouter implements RpcRouter<QName, QName, InstanceIdentifier, Object> {
-
-  private ExecutorService serverPool;
-  private static ExecutorService handlersPool;
-
-  private Map<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
-
-  private ProviderSession brokerSession;
-
-  private ZMQ.Context context;
-  private ZMQ.Socket publisher;
-  private ZMQ.Socket subscriber;
-  private ZMQ.Socket replySocket;
-
-  private static ZeroMqRpcRouter _instance = new ZeroMqRpcRouter();
-
-  private final RpcFacade facade = new RpcFacade();
-  private final RpcListener listener = new RpcListener();
-
-  private String pubPort = System.getProperty("pub.port");//port on which announcements are sent
-  private String subPort = System.getProperty("sub.port");//other controller's pub port
-  private String pubIp = System.getProperty("pub.ip");    //other controller's ip
-  private String rpcPort = System.getProperty("rpc.port");//port on which RPC messages are received
-
-
-  private ZeroMqRpcRouter() {
-  }
-
-  public static ZeroMqRpcRouter getInstance() {
-    return _instance;
-  }
-
-  public void start() {
-    context = ZMQ.context(2);
-    serverPool = Executors.newSingleThreadExecutor();
-    handlersPool = Executors.newCachedThreadPool();
-    routingTable = new ConcurrentHashMap<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
-
-    // Start listening for announce and rpc messages
-    serverPool.execute(receive());
-
-    
-    brokerSession.addRpcRegistrationListener(listener);
-    Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
-    for(QName rpc : currentlySupported) {
-        listener.onRpcImplementationAdded(rpc);
-    }
-
-
-  }
-
-  public void stop() {
-    if (handlersPool != null) handlersPool.shutdown();
-    if (serverPool != null) serverPool.shutdown();
-    if (publisher != null) {
-      publisher.setLinger(0);
-      publisher.close();
-    }
-    if (replySocket != null) {
-      replySocket.setLinger(0);
-      replySocket.close();
-    }
-    if (subscriber != null) {
-      subscriber.setLinger(0);
-      subscriber.close();
-    }
-    if (context != null) context.term();
-
-
-  }
-
-  private Runnable receive() {
-    return new Runnable() {
-      public void run() {
-        try {
-          // Bind to RPC reply socket
-          replySocket = context.socket(ZMQ.REP);
-          replySocket.bind("tcp://*:" + rpcPort);
-
-          // Bind to publishing controller
-          subscriber = context.socket(ZMQ.SUB);
-          subscriber.connect("tcp://" + pubIp + ":" + subPort);
-          System.out.println("Subscribing at[" + "tcp://" + pubIp + ":" + subPort + "]");
-
-          subscriber.subscribe(Message.serialize(Message.MessageType.ANNOUNCE));
-
-          // Initialize poll set
-          ZMQ.Poller poller = new ZMQ.Poller(2);
-          poller.register(replySocket, ZMQ.Poller.POLLIN);
-          poller.register(subscriber, ZMQ.Poller.POLLIN);
-
-          while (!Thread.currentThread().isInterrupted()) {
-
-            poller.poll(250);
-            //TODO: Fix this
-            if (poller.pollin(0)) {
-              //receive rpc request and reply
-              try {
-                Message req = parseMessage(replySocket);
-                Message resp = new Message();
-                //Call broker to process the message then reply
-                Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc((QName) req.getRoute().getType(), (CompositeNode) req.getPayload());
-                RpcResult<CompositeNode> result = rpc.get();
-                resp.setType(Message.MessageType.RESPONSE);
-                resp.setSender(getLocalIpAddress() + ":" + rpcPort);
-                resp.setRoute(req.getRoute());
-                resp.setPayload(result.isSuccessful());
-                replySocket.send(Message.serialize(resp));
-
-              } catch (IOException ex) {// | ClassNotFoundException ex) {
-                System.out.println("Rpc request could not be handled" + ex);
-              }
-            }
-            if (poller.pollin(1)) {
-              //get subscription and update routing table
-              //try {
-              Message.MessageType topic = (Message.MessageType)Message.deserialize(subscriber.recv());
-              System.out.println("Topic:[" + topic + "]");
-
-              if (subscriber.hasReceiveMore()) {
-                try {
-                  Message m = (Message) Message.deserialize(subscriber.recv());
-                  System.out.println(m);
-                  //TODO: check on msg type or topic. Both should be same. Need to normalize.
-                  if (Message.MessageType.ANNOUNCE == m.getType()) updateRoutingTable(m);
-                } catch (IOException | ClassNotFoundException e) {
-                  e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
-                }
-              }
-//
-            }
-          }
-        } catch (Exception e) {
-          e.printStackTrace();
-        }
-        replySocket.setLinger(0);
-        replySocket.close();
-        subscriber.setLinger(0);
-        subscriber.close();
-      }
-    };
-  }
-
-  private void updateRoutingTable(Message msg) {
-    routingTable.put(msg.getRoute(), msg.getSender());
-    RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> route = msg.getRoute();
-    QName rpcType = route.getType();
-    System.out.println("Routing Table\n" + routingTable);
-
-    RpcRegistration registration = brokerSession.addRpcImplementation(rpcType, facade);
-  }
-
-  private Message parseMessage(ZMQ.Socket socket) {
-    //Message m = new Message();
-    //socket.setReceiveBufferSize(40000);
-    Message msg = null;
-    try {
-      byte[] bytes = socket.recv();
-      System.out.println("Received bytes:[" + bytes.length + "]");
-      msg = (Message) Message.deserialize(bytes);
-    } catch (Throwable t) {
-      System.out.println("Caught exception");
-      t.printStackTrace();
-    }
-    return msg;
-    /*m.setType((Message.MessageType) Message.deserialize(socket.recv()));
-
-    if (socket.hasReceiveMore()) {
-      m.setSender((String) Message.deserialize(socket.recv()));
-    }
-    if (socket.hasReceiveMore()) {
-      m.setRoute((RouteIdentifier) Message.deserialize(socket.recv()));
-    }
-    if (socket.hasReceiveMore()) {
-      m.setPayload(Message.deserialize(socket.recv()));
-    }
-    return m;*/
-  }
-
-  @Override
-  public Future<RpcReply<Object>> sendRpc(final RpcRequest<QName, QName, InstanceIdentifier, Object> input) {
-
-    return handlersPool.submit(new Callable<RpcReply<Object>>() {
-
-      @Override
-      public RpcReply<Object> call() {
-        ZMQ.Socket requestSocket = context.socket(ZMQ.REQ);
-        Message req = new Message();
-        Message resp = null;
-        RpcReplyImpl reply = new RpcReplyImpl();
-        requestSocket.connect((String) routingTable.get(input.getRoutingInformation().getRoute()));
-
-        req.setType(Message.MessageType.REQUEST);
-        req.setSender(getLocalIpAddress() + ":" + rpcPort);
-        req.setRoute(input.getRoutingInformation());
-        req.setPayload(input.getPayload());
-        try {
-          requestSocket.send(Message.serialize(req));
-          resp = parseMessage(requestSocket);
-          reply.setPayload(resp.getPayload());
-        } catch (IOException ex) {//| ClassNotFoundException ex) {
-          //Log and ignore
-          System.out.println("Error in RPC send. Input could not be serialized[" + input + "]");
-        }
-
-        return reply;
-      }
-    });
-  }
-
-  public void publish(final Message message) {
-    Runnable task = new Runnable() {
-      public void run() {
-        // Bind to publishing port
-        publisher = context.socket(ZMQ.PUB);
-        publisher.bind("tcp://*:" + pubPort);
-        System.out.println("Publisher started at port[" + pubPort + "]");
-        try {
-          Message outMessage =  new Message();
-          outMessage.setType(Message.MessageType.ANNOUNCE);
-          outMessage.setSender("tcp://" + getLocalIpAddress() + ":" + rpcPort);
-          outMessage.setRoute(message.getRoute());
-
-          System.out.println("Sending announcement[" + outMessage + "]");
-          publisher.sendMore(Message.serialize(Message.MessageType.ANNOUNCE));
-          publisher.send(Message.serialize(outMessage));
-
-        } catch (IOException ex) {
-          //Log and ignore
-          System.out.println("Error in publishing");
-          ex.printStackTrace();
-        }
-        System.out.println("Published message[" + message + "]");
-        publisher.close();
-      }
-    };
-    handlersPool.execute(task);
-  }
-
-  private String getLocalIpAddress() {
-    String hostAddress = null;
-    Enumeration e = null;
-    try {
-      e = NetworkInterface.getNetworkInterfaces();
-    } catch (SocketException e1) {
-      e1.printStackTrace();
-    }
-    while (e.hasMoreElements()) {
-
-      NetworkInterface n = (NetworkInterface) e.nextElement();
-      Enumeration ee = n.getInetAddresses();
-      while (ee.hasMoreElements()) {
-        InetAddress i = (InetAddress) ee.nextElement();
-        if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
-          hostAddress = i.getHostAddress();
-      }
-    }
-
-    return hostAddress;
-
-
-  }
-
-
-  private class RpcFacade implements RpcImplementation {
-
-
-    @Override
-    public Set<QName> getSupportedRpcs() {
-      return Collections.emptySet();
-    }
-
-    @Override
-    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
-
-      RpcRequestImpl request = new RpcRequestImpl();
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
-      routeId.setContext(null);
-      routeId.setRoute(null);
-      routeId.setType(rpc);
-
-      request.setRouteIdentifier(routeId);
-      request.setPayload(input);
-      // Create message
-
-      Future<org.opendaylight.controller.sal.connector.api.RpcRouter.RpcReply<Object>> ret = sendRpc(request);
-
-      return null;
-    }
-  }
-
-  private class RpcListener implements RpcRegistrationListener {
-
-    @Override
-    public void onRpcImplementationAdded(QName name) {
-
-      Message msg = new Message();
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
-      routeId.setType(name);
-      msg.setRoute(routeId);
-      publish(msg);
-    }
-
-    @Override
-    public void onRpcImplementationRemoved(QName name) {
-      // TODO Auto-generated method stub
-
-    }
-  }
-
-  public void setBrokerSession(ProviderSession session) {
-    this.brokerSession = session;
-
-  }
-
-}
index f66bfd4b74aafecec742cf803ee58688edc70eb1..a1925a53b505a616b1dc3cd6b6d99146a7fe97f7 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-manager</artifactId>
-            <version>0.2.2-SNAPSHOT</version>
+            <version>0.2.3-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>equinoxSDK381</groupId>
             <artifactId>logback-classic</artifactId>
             <version>1.0.9</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+            <version>4.0</version>
+        </dependency>
     </dependencies>
 </project>
index 7cd4fa52c6318eb620b28aa94fa86838a9a8867f..f42cd01cf78e5bda4e3b0e4b37e9346d076ba565 100644 (file)
@@ -17,12 +17,17 @@ import static org.ops4j.pax.exam.CoreOptions.junitBundles;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.options;
 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import org.ops4j.pax.exam.util.PathUtils;
 
 @RunWith(PaxExam.class)
 public class ToasterTest {
 
     public static final String ODL = "org.opendaylight.controller";
     public static final String YANG = "org.opendaylight.yangtools";
+    public static final String CONTROLLER = "org.opendaylight.controller";
+    public static final String YANGTOOLS = "org.opendaylight.yangtools";
+    
+    
     public static final String SAMPLE = "org.opendaylight.controller.samples";
 
     @Test
@@ -46,13 +51,13 @@ public class ToasterTest {
     @Configuration
     public Option[] config() {
         return options(systemProperty("osgi.console").value("2401"), 
+                systemProperty("logback.configurationFile").value(
+                    "file:" + PathUtils.getBaseDir()
+                    + "/src/test/resources/logback.xml"),
                 mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
                 mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
                 mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
                 mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
-                mavenBundle(ODL, "sal-binding-api").versionAsInProject(), //
-                mavenBundle(ODL, "sal-binding-config").versionAsInProject(), 
-                mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject(), //
                 
                 mavenBundle(ODL, "sal-common").versionAsInProject(), //
                 mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
@@ -62,7 +67,37 @@ public class ToasterTest {
                 mavenBundle(ODL, "config-api").versionAsInProject(), //
                 mavenBundle(ODL, "config-manager").versionAsInProject(), //
                 mavenBundle("commons-io", "commons-io").versionAsInProject(),
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
                 
+                mavenBundle(CONTROLLER, "sal-binding-api").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(),
+                mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), //
+                mavenBundle("org.javassist", "javassist").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), //
+        
+                mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                
+                
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
+                
+                
+                mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
+                
+                mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
                 
                 mavenBundle(SAMPLE, "sample-toaster").versionAsInProject(), //
                 mavenBundle(SAMPLE, "sample-toaster-consumer").versionAsInProject(), //
similarity index 99%
rename from opendaylight/clustering/services_implementation/src/test/resources/logback.xml
rename to opendaylight/md-sal/samples/toaster-it/src/test/resources/logback.xml
index 6d9dfda9a365f9a08f9d4ba5b7733f2cb6340ba6..2d63ce57448f88b77a39b1bcb0525b9721c08370 100644 (file)
@@ -1,4 +1,5 @@
 <configuration scan="true">
+
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>
       <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/pom.xml b/opendaylight/md-sal/test/sal-rest-connector-it/pom.xml
new file mode 100644 (file)
index 0000000..8569783
--- /dev/null
@@ -0,0 +1,728 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>sal-test-parent</artifactId>
+        <groupId>org.opendaylight.controller.tests</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>sal-rest-connector-it</artifactId>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+
+    <properties>
+        <exam.version>3.0.0</exam.version>
+        <url.version>1.5.0</url.version>
+        <geminiweb.version>2.2.0.RELEASE</geminiweb.version>
+        <virgo.version>3.6.0.RELEASE</virgo.version>
+        <spring.version>3.1.3.RELEASE</spring.version>
+        <jersey.version>1.17</jersey.version>
+        <spring-security.version>3.1.3.RELEASE</spring-security.version>
+        <netconf.version>0.2.2-SNAPSHOT</netconf.version>
+        <config.version>0.2.2-SNAPSHOT</config.version>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.ops4j.pax.exam</groupId>
+                <artifactId>maven-paxexam-plugin</artifactId>
+                <version>1.2.4</version>
+                <executions>
+                    <execution>
+                        <id>generate-config</id>
+                        <goals>
+                            <goal>generate-depends-file</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+                <!--This plugin's configuration is used to store Eclipse 
+                    m2e settings only. It has no influence on the Maven build itself. -->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            org.ops4j.pax.exam
+                                        </groupId>
+                                        <artifactId>
+                                            maven-paxexam-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [1.2.4,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>
+                                                generate-depends-file
+                                            </goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>logging.bridge</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>xtend-lib-osgi</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>bundlescanner.implementation</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-rest-connector</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-netconf-connector</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-it</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+        <groupId>org.opendaylight.controller.thirdparty</groupId>
+        <artifactId>exificient</artifactId>
+        <version>0.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-native</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+            <version>4.0.10.Final</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.osgi</artifactId>
+            <version>3.8.1.v20120830-144521</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+            <version>1.7.2</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-service</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-manager</artifactId>
+            <version>0.2.2-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-management</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+            <version>4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>commons.northbound</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+            <version>1.7.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+            <version>1.7.2</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.8</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>javax.servlet</artifactId>
+            <version>3.0.0.v201112011016</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>javax.servlet.jsp</artifactId>
+            <version>2.2.0.v201112011158</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.equinox.ds</artifactId>
+            <version>1.4.0.v20120522-1841</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.equinox.util</artifactId>
+            <version>1.0.400.v20120522-2049</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.osgi.services</artifactId>
+            <version>3.3.100.v20120522-1822</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.osgi</artifactId>
+            <version>3.8.1.v20120830-144521</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.apache.felix.gogo.command</artifactId>
+            <version>0.8.0.v201108120515</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.apache.felix.gogo.runtime</artifactId>
+            <version>0.8.0.v201108120515</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.apache.felix.gogo.shell</artifactId>
+            <version>0.8.0.v201110170705</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.equinox.cm</artifactId>
+            <version>1.0.400.v20120522-1841</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.equinox.console</artifactId>
+            <version>1.0.0.v20120522-1841</version>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.equinox.launcher</artifactId>
+            <version>1.3.0.v20120522-1813</version>
+        </dependency>
+        <!-- Gemini Web -->
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.gemini.web.core</artifactId>
+            <version>${geminiweb.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.gemini.web.extender</artifactId>
+            <version>${geminiweb.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.gemini.web.tomcat</artifactId>
+            <version>${geminiweb.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.virgo.kernel.equinox.extensions</artifactId>
+            <version>${virgo.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.virgo.util.common</artifactId>
+            <version>${virgo.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.virgo.util.io</artifactId>
+            <version>${virgo.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.virgo.util.math</artifactId>
+            <version>${virgo.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.virgo.util.osgi</artifactId>
+            <version>${virgo.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.virgo.util.osgi.manifest</artifactId>
+            <version>${virgo.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>geminiweb</groupId>
+            <artifactId>org.eclipse.virgo.util.parser.manifest</artifactId>
+            <version>${virgo.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.dependencymanager</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
+            <version>3.0.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.transaction</groupId>
+            <artifactId>jboss-transaction-api_1.1_spec</artifactId>
+            <version>1.0.1.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.fileinstall</artifactId>
+            <version>3.1.6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>virgomirror</groupId>
+            <artifactId>org.eclipse.jdt.core.compiler.batch</artifactId>
+            <version>3.8.0.I20120518-2145</version>
+        </dependency>
+        <dependency>
+            <groupId>eclipselink</groupId>
+            <artifactId>javax.persistence</artifactId>
+            <version>2.0.4.v201112161009</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>javax.activation</artifactId>
+            <version>1.1.0.v201211130549</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>javax.annotation</artifactId>
+            <version>1.1.0.v201209060031</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>javax.ejb</artifactId>
+            <version>3.1.1.v201204261316</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>javax.el</artifactId>
+            <version>2.2.0.v201108011116</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>javax.mail.glassfish</artifactId>
+            <version>1.4.1.v201108011116</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>javax.xml.rpc</artifactId>
+            <version>1.1.0.v201005080400</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.catalina</artifactId>
+            <version>7.0.32.v201211201336</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.catalina.ha</artifactId>
+            <version>7.0.32.v201211201952</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.catalina.tribes</artifactId>
+            <version>7.0.32.v201211201952</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.coyote</artifactId>
+            <version>7.0.32.v201211201952</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.el</artifactId>
+            <version>7.0.32.v201211081135</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.jasper</artifactId>
+            <version>7.0.32.v201211201952</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.juli.extras</artifactId>
+            <version>7.0.32.v201211081135</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.tomcat.api</artifactId>
+            <version>7.0.32.v201211081135</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>org.apache.tomcat.util</artifactId>
+            <version>7.0.32.v201211201952</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>javax.servlet.jsp.jstl</artifactId>
+            <version>1.2.0.v201105211821</version>
+        </dependency>
+        <dependency>
+            <groupId>orbit</groupId>
+            <artifactId>javax.servlet.jsp.jstl.impl</artifactId>
+            <version>1.2.0.v201210211230</version>
+        </dependency>
+        <!-- Add Pax Exam -->
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-native</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.url</groupId>
+            <artifactId>pax-url-aether</artifactId>
+            <version>${url.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ow2.asm</groupId>
+            <artifactId>asm-all</artifactId>
+            <version>4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.asm</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.aop</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.context</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.context.support</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.core</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.beans</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.expression</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.web</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.aopalliance</groupId>
+            <artifactId>com.springsource.org.aopalliance</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.web.servlet</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <!-- Spring security -->
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-config</artifactId>
+            <version>${spring-security.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-core</artifactId>
+            <version>${spring-security.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-web</artifactId>
+            <version>${spring-security.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-taglibs</artifactId>
+            <version>${spring-security.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>org.springframework.transaction</artifactId>
+            <version>${spring-security.version}</version>
+        </dependency>
+        <!-- Visual VM hook -->
+        <dependency>
+            <groupId>org.ow2.chameleon.management</groupId>
+            <artifactId>chameleon-mbeans</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <!-- Jersey for JAXRS -->
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-core</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <!-- <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-servlet</artifactId> 
+            <version>${jersey.version}</version> </dependency> -->
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-server</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-client</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-json</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>eclipselink</groupId>
+            <artifactId>javax.resource</artifactId>
+            <version>1.5.0.v200906010428</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.thirdparty</groupId>
+            <artifactId>com.sun.jersey.jersey-servlet</artifactId>
+            <version>1.17</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.thirdparty</groupId>
+            <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+            <version>7.0.42</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-manager</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-util</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-jmx-generator</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-store-api</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-store-impl</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>logback-config</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-persister-api</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-persister-file-adapter</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-api</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-impl</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-util</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-client</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-mapping-api</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-netconf-connector</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-persister-impl</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java
new file mode 100644 (file)
index 0000000..23ba8aa
--- /dev/null
@@ -0,0 +1,329 @@
+package org.opendaylight.controller.test.restconf.it;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemPackages;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import static org.ops4j.pax.exam.CoreOptions.maven;
+
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
+import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.test.sal.binding.it.TestHelper;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.util.PathUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.*;
+
+@RunWith(PaxExam.class)
+public class ServiceProviderController {
+
+    public static final String ODL = "org.opendaylight.controller";
+    public static final String YANG = "org.opendaylight.yangtools";
+    public static final String SAMPLE = "org.opendaylight.controller.samples";
+
+    private static QName CONFIG_MODULES = new QName(
+            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+    private static QName CONFIG_SERVICES = new QName(
+            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+    @Inject
+    BundleContext context;
+
+    @Inject
+    MountProvisionService mountService;
+
+    @Inject
+    DataBrokerService dataBroker;
+
+    @Inject
+    NetconfDeviceManager netconfManager;
+
+    @Test
+    public void properInitialized() throws Exception {
+
+        Map<QName, String> arg = Collections.singletonMap(InventoryUtils.INVENTORY_ID, "foo");
+
+        InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
+                .nodeWithKey(InventoryUtils.INVENTORY_NODE, InventoryUtils.INVENTORY_ID, "foo").toInstance();
+
+        netconfManager.netconfNodeAdded(path, new InetSocketAddress("127.0.0.1", 8383));
+
+        
+        InstanceIdentifier mountPointPath = path;
+        
+        /** We retrive a mountpoint **/
+        MountProvisionInstance mountPoint = mountService.getMountPoint(mountPointPath);
+        CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
+                .toInstance());
+        assertNotNull(data);
+        assertEquals(CONFIG_MODULES, data.getNodeType());
+
+        CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
+        assertNotNull(data2);
+
+        InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
+
+        CompositeNode data3 = dataBroker.readOperationalData(fullPath);
+        assertNotNull(data3);
+        assertEquals(CONFIG_MODULES, data.getNodeType());
+
+        //Thread.sleep(30 * 60 * 1000); // Waiting for services to get wired.
+        //assertTrue(true);
+        // assertTrue(consumer.createToast(WhiteBread.class, 5));
+    }
+
+    @Configuration
+    public Option[] config() {
+        return options(
+                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
+                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
+                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
+                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
+
+                mdSalCoreBundles(),
+                baseModelBundles(),
+                flowCapableModelBundles(),
+                configMinumumBundles(),
+
+                // mavenBundle(ODL,
+                // "sal-binding-broker-impl").versionAsInProject().update(), //
+                mavenBundle(ODL, "sal-common").versionAsInProject(), //
+                mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
+                mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
+                mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
+
+                mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
+
+                mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
+                // mavenBundle(SAMPLE,
+                // "zeromq-test-provider").versionAsInProject(), //
+                mavenBundle(ODL, "sal-rest-connector").versionAsInProject(), //
+                mavenBundle(ODL, "sal-netconf-connector").versionAsInProject(), //
+
+                mavenBundle(YANG, "concepts").versionAsInProject(),
+                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
+                mavenBundle(YANG, "yang-common").versionAsInProject(), //
+                mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANG, "yang-data-impl").versionAsInProject(), //
+                mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
+                mavenBundle(YANG, "yang-parser-api").versionAsInProject(),
+                mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
+
+                mavenBundle(YANG + ".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
+                mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
+                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
+
+                // systemProperty("logback.configurationFile").value(
+                // "file:" + PathUtils.getBaseDir() +
+                // "/src/test/resources/logback.xml"),
+                // To start OSGi console for inspection remotely
+                systemProperty("osgi.console").value("2401"),
+                systemProperty("org.eclipse.gemini.web.tomcat.config.path").value(
+                        PathUtils.getBaseDir() + "/src/test/resources/tomcat-server.xml"),
+
+                // setting default level. Jersey bundles will need to be started
+                // earlier.
+                systemProperty("osgi.bundles.defaultStartLevel").value("4"),
+
+                systemProperty("netconf.tcp.address").value("127.0.0.1"),
+                systemProperty("netconf.tcp.port").value("8383"),
+
+                // Set the systemPackages (used by clustering)
+                systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
+
+                mavenBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.xerces", "2.11.0_1"),
+                mavenBundle("org.eclipse.birt.runtime.3_7_1", "org.apache.xml.resolver", "1.2.0"),
+
+                mavenBundle("org.slf4j", "jcl-over-slf4j").versionAsInProject(),
+                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
+                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
+                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
+                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
+                mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "clustering.services").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "containermanager").versionAsInProject(),
+                // List all the opendaylight modules
+                mavenBundle("org.opendaylight.controller", "configuration").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "sal").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "switchmanager").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "usermanager").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "logging.bridge").versionAsInProject(),
+                // mavenBundle("org.opendaylight.controller",
+                // "clustering.test").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "bundlescanner").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "bundlescanner.implementation").versionAsInProject(),
+
+                // Northbound bundles
+                mavenBundle("org.opendaylight.controller", "commons.northbound").versionAsInProject(),
+                mavenBundle("org.codehaus.jackson", "jackson-mapper-asl").versionAsInProject(),
+                mavenBundle("org.codehaus.jackson", "jackson-core-asl").versionAsInProject(),
+                mavenBundle("org.codehaus.jackson", "jackson-jaxrs").versionAsInProject(),
+                mavenBundle("org.codehaus.jackson", "jackson-xc").versionAsInProject(),
+                mavenBundle("org.codehaus.jettison", "jettison").versionAsInProject(),
+
+                mavenBundle("commons-io", "commons-io").versionAsInProject(),
+
+                // mavenBundle("commons-fileupload",
+                // "commons-fileupload").versionAsInProject(),
+
+                mavenBundle("io.netty", "netty-handler").versionAsInProject(),
+                mavenBundle("io.netty", "netty-codec").versionAsInProject(),
+                mavenBundle("io.netty", "netty-buffer").versionAsInProject(),
+                mavenBundle("io.netty", "netty-transport").versionAsInProject(),
+                mavenBundle("io.netty", "netty-common").versionAsInProject(),
+
+                mavenBundle(ODL, "config-api").versionAsInProject(),
+                mavenBundle(ODL, "config-manager").versionAsInProject(),
+                mavenBundle(ODL, "config-util").versionAsInProject(),
+                mavenBundle(ODL, "yang-jmx-generator").versionAsInProject(),
+                mavenBundle(ODL, "yang-store-api").versionAsInProject(),
+                mavenBundle(ODL, "yang-store-impl").versionAsInProject(),
+                mavenBundle(ODL, "logback-config").versionAsInProject(),
+                mavenBundle(ODL, "config-persister-api").versionAsInProject(),
+                // mavenBundle(ODL,"config-persister-file-adapter").versionAsInProject(),
+                mavenBundle(ODL, "netconf-api").versionAsInProject(),
+                mavenBundle(ODL, "netconf-impl").versionAsInProject(),
+                mavenBundle(ODL, "netconf-client").versionAsInProject(),
+                mavenBundle(ODL, "netconf-util").versionAsInProject(),
+                mavenBundle(ODL + ".thirdparty", "ganymed", "1.0-SNAPSHOT"),
+                mavenBundle(ODL, "netconf-mapping-api").versionAsInProject(),
+                mavenBundle(ODL, "config-netconf-connector").versionAsInProject(),
+                mavenBundle(ODL, "config-persister-impl").versionAsInProject(),
+
+                mavenBundle("org.opendaylight.bgpcep", "framework").versionAsInProject(),
+                mavenBundle("org.opendaylight.bgpcep", "util").versionAsInProject(),
+                mavenBundle(YANG, "binding-generator-spi").versionAsInProject(), //
+                mavenBundle(YANG, "binding-model-api").versionAsInProject(), //
+                mavenBundle(YANG, "binding-generator-util").versionAsInProject(),
+                mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
+                mavenBundle(YANG, "binding-type-provider").versionAsInProject(),
+
+                mavenBundle("org.opendaylight.controller.thirdparty", "exificient", "0.9.2"),
+
+                mavenBundle("equinoxSDK381", "javax.servlet").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "javax.servlet.jsp").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
+                mavenBundle("orbit", "javax.xml.rpc").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.eclipse.osgi.services").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.eclipse.equinox.cm").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
+                mavenBundle("equinoxSDK381", "org.eclipse.equinox.launcher").versionAsInProject(),
+
+                mavenBundle("geminiweb", "org.eclipse.gemini.web.core").versionAsInProject(),
+                mavenBundle("geminiweb", "org.eclipse.gemini.web.extender").versionAsInProject(),
+                mavenBundle("geminiweb", "org.eclipse.gemini.web.tomcat").versionAsInProject(),
+                mavenBundle("geminiweb", "org.eclipse.virgo.kernel.equinox.extensions").versionAsInProject().noStart(),
+                mavenBundle("geminiweb", "org.eclipse.virgo.util.common").versionAsInProject(),
+                mavenBundle("geminiweb", "org.eclipse.virgo.util.io").versionAsInProject(),
+                mavenBundle("geminiweb", "org.eclipse.virgo.util.math").versionAsInProject(),
+                mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi").versionAsInProject(),
+                mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi.manifest").versionAsInProject(),
+                mavenBundle("geminiweb", "org.eclipse.virgo.util.parser.manifest").versionAsInProject(),
+
+                mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
+                mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager.shell").versionAsInProject(),
+
+                mavenBundle("com.google.code.gson", "gson").versionAsInProject(),
+                mavenBundle("org.jboss.spec.javax.transaction", "jboss-transaction-api_1.1_spec").versionAsInProject(),
+                mavenBundle("org.apache.felix", "org.apache.felix.fileinstall").versionAsInProject(),
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
+                mavenBundle("commons-codec", "commons-codec").versionAsInProject(),
+                mavenBundle("virgomirror", "org.eclipse.jdt.core.compiler.batch").versionAsInProject(),
+                mavenBundle("eclipselink", "javax.persistence").versionAsInProject(),
+                mavenBundle("eclipselink", "javax.resource").versionAsInProject(),
+
+                mavenBundle("orbit", "javax.activation").versionAsInProject(),
+                mavenBundle("orbit", "javax.annotation").versionAsInProject(),
+                mavenBundle("orbit", "javax.ejb").versionAsInProject(),
+                mavenBundle("orbit", "javax.el").versionAsInProject(),
+                mavenBundle("orbit", "javax.mail.glassfish").versionAsInProject(),
+                mavenBundle("orbit", "javax.xml.rpc").versionAsInProject(),
+                mavenBundle("orbit", "org.apache.catalina").versionAsInProject(),
+                // these are bundle fragments that can't be started on its own
+                mavenBundle("orbit", "org.apache.catalina.ha").versionAsInProject().noStart(),
+                mavenBundle("orbit", "org.apache.catalina.tribes").versionAsInProject().noStart(),
+                mavenBundle("orbit", "org.apache.coyote").versionAsInProject().noStart(),
+                mavenBundle("orbit", "org.apache.jasper").versionAsInProject().noStart(),
+
+                mavenBundle("orbit", "org.apache.el").versionAsInProject(),
+                mavenBundle("orbit", "org.apache.juli.extras").versionAsInProject(),
+                mavenBundle("orbit", "org.apache.tomcat.api").versionAsInProject(),
+                mavenBundle("orbit", "org.apache.tomcat.util").versionAsInProject().noStart(),
+                mavenBundle("orbit", "javax.servlet.jsp.jstl").versionAsInProject(),
+                mavenBundle("orbit", "javax.servlet.jsp.jstl.impl").versionAsInProject(),
+
+                mavenBundle("org.ops4j.pax.exam", "pax-exam-container-native").versionAsInProject(),
+                mavenBundle("org.ops4j.pax.exam", "pax-exam-junit4").versionAsInProject(),
+                mavenBundle("org.ops4j.pax.exam", "pax-exam-link-mvn").versionAsInProject(),
+                mavenBundle("org.ops4j.pax.url", "pax-url-aether").versionAsInProject(),
+
+                mavenBundle("org.ow2.asm", "asm-all").versionAsInProject(),
+
+                mavenBundle("org.springframework", "org.springframework.asm").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.aop").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.context").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.context.support").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.core").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.beans").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.expression").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.web").versionAsInProject(),
+
+                mavenBundle("org.aopalliance", "com.springsource.org.aopalliance").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.web.servlet").versionAsInProject(),
+                mavenBundle("org.springframework.security", "spring-security-config").versionAsInProject(),
+                mavenBundle("org.springframework.security", "spring-security-core").versionAsInProject(),
+                mavenBundle("org.springframework.security", "spring-security-web").versionAsInProject(),
+                mavenBundle("org.springframework.security", "spring-security-taglibs").versionAsInProject(),
+                mavenBundle("org.springframework", "org.springframework.transaction").versionAsInProject(),
+
+                mavenBundle("org.ow2.chameleon.management", "chameleon-mbeans").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller.thirdparty", "com.sun.jersey.jersey-servlet")
+                        .versionAsInProject().startLevel(2),
+                mavenBundle("org.opendaylight.controller.thirdparty", "org.apache.catalina.filters.CorsFilter")
+                        .versionAsInProject().noStart(),
+
+                // Jersey needs to be started before the northbound application
+                // bundles, using a lower start level
+                mavenBundle("com.sun.jersey", "jersey-client").versionAsInProject(),
+                mavenBundle("com.sun.jersey", "jersey-server").versionAsInProject().startLevel(2),
+                mavenBundle("com.sun.jersey", "jersey-core").versionAsInProject().startLevel(2),
+                mavenBundle("com.sun.jersey", "jersey-json").versionAsInProject().startLevel(2),
+
+                junitBundles());
+    }
+
+}
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/exam.properties b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/exam.properties
new file mode 100644 (file)
index 0000000..d5f9ae1
--- /dev/null
@@ -0,0 +1,4 @@
+#pax.exam.system = default
+pax.exam.logging = none
+pax.exam.service.timeout = 5000
+
similarity index 96%
rename from opendaylight/switchmanager/implementation/src/test/resources/logback.xml
rename to opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/logback.xml
index 5fa21fecfcc67ba743dd5c3b21eda6108a77de10..2d63ce57448f88b77a39b1bcb0525b9721c08370 100644 (file)
@@ -1,13 +1,13 @@
-<configuration scan="true">\r
-\r
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
-    <encoder>\r
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
-      </pattern>\r
-    </encoder>\r
-  </appender>\r
-\r
-  <root level="error">\r
-    <appender-ref ref="STDOUT" />\r
-  </root>\r
-</configuration>\r
+<configuration scan="true">
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+      </pattern>
+    </encoder>
+  </appender>
+
+  <root level="error">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/tomcat-server.xml b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/tomcat-server.xml
new file mode 100644 (file)
index 0000000..d6ef6ed
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+    license agreements. See the NOTICE file distributed with this work for additional 
+    information regarding copyright ownership. The ASF licenses this file to 
+    You under the Apache License, Version 2.0 (the "License"); you may not use 
+    this file except in compliance with the License. You may obtain a copy of 
+    the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+    by applicable law or agreed to in writing, software distributed under the 
+    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+    OF ANY KIND, either express or implied. See the License for the specific 
+    language governing permissions and limitations under the License. -->
+<Server>
+    <!--APR library loader. Documentation at /docs/apr.html -->
+    <Listener className="org.apache.catalina.core.AprLifecycleListener"
+        SSLEngine="on" />
+    <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
+    <Listener className="org.apache.catalina.core.JasperListener" />
+    <!-- Prevent memory leaks due to use of particular java/javax APIs -->
+    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
+    <Listener
+        className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
+    <Listener
+        className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
+
+    <Service name="Catalina">
+        <Connector port="8080" protocol="HTTP/1.1"
+            connectionTimeout="20000" redirectPort="8443" />
+
+        <!-- Please remove the comments around the following Connector tag 
+            to enable HTTPS Authentication support. Remember to add a valid keystore 
+            in the configuration folder. More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration -->
+
+        <!-- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
+            maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" 
+            keystoreFile="configuration/keystore" keystorePass="changeit"/> -->
+
+        <Engine name="Catalina" defaultHost="localhost">
+            <Host name="localhost" appBase="" unpackWARs="false"
+                autoDeploy="false" deployOnStartup="false" createDirs="false">
+                <!-- Realm
+                    className="org.opendaylight.controller.security.ControllerCustomRealm" /> -->
+                <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
+
+                <Valve className="org.apache.catalina.valves.AccessLogValve"
+                    directory="logs" prefix="web_access_log_" suffix=".txt"
+                    resolveHosts="false" rotatable="true"
+                    fileDateFormat="yyyy-MM"
+                    pattern="%{yyyy-MM-dd HH:mm:ss.SSS z}t - [%a] - %r" />
+
+            </Host>
+        </Engine>
+    </Service>
+</Server>
index 989bd9e676464b669b1ba96c1c2a1a0511879328..d855f1554125764c16170b84c26457bd0976fa04 100755 (executable)
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>netconf-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
     <artifactId>config-netconf-connector</artifactId>
     <name>${project.artifactId}</name>
             <version>${bgpcep.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>commons.logback_settings</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
index 8497edbd2674ebef735f95e17f6d115ab303048c..ce0036f9afa6024d18282e5e2cfe559b2744cd4a 100644 (file)
@@ -8,8 +8,11 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
 import org.opendaylight.controller.config.yang.store.api.YangStoreService;
@@ -22,10 +25,8 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 /**
  * Manages life cycle of {@link YangStoreSnapshot}.
index fe2fc1c5da9b43ff673fd7e8e780ea5285edd69d..d404a964686596c0428a63d9f060219f4d44e3af 100644 (file)
@@ -441,8 +441,6 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
         Element response = get();
 
-        System.err.println(XmlUtil.toString(response));
-
         assertEquals(2, getElementsSize(response, "instance"));
         assertEquals(2, getElementsSize(response, "asdf"));
         assertEquals(5, getElementsSize(response, "inner-running-data"));
index 603f40b020eed1858397374b49890061c815b75f..85592e5aa209a717f32c1144a839e8c23eed4e47 100644 (file)
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>netconf-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
     <artifactId>config-persister-impl</artifactId>
     <name>${project.artifactId}</name>
@@ -72,7 +72,6 @@
                             javax.management,
                             javax.xml.parsers,
                             org.opendaylight.controller.config.persist.api,
-                            org.opendaylight.controller.config.stat,
                             org.opendaylight.controller.config.persist.api.storage,
                             org.opendaylight.controller.netconf.api,
                             org.opendaylight.controller.netconf.api.jmx,
index 08b0d1a511012803b665ea909a98610be7247a83..cd604312f4d0318fa2f55ed637e00c01b392e206 100644 (file)
@@ -10,7 +10,7 @@ package org.opendaylight.controller.netconf.persist.impl;
 
 import com.google.common.base.Optional;
 import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -20,8 +20,8 @@ public class NoOpStorageAdapter implements StorageAdapter {
     private static final Logger logger = LoggerFactory.getLogger(NoOpStorageAdapter.class);
 
     @Override
-    public void setProperties(ConfigProvider configProvider) {
-        logger.debug("setProperties called with {}", configProvider);
+    public void setProperties(BundleContext bundleContext) {
+        logger.debug("setProperties called with {}", bundleContext);
     }
 
     @Override
index 03892f0da74dfafa1476eea5ac7c7d8ec85b0331..e06968e86844f1e65148e1a9e06bc08092ff8d68 100644 (file)
@@ -12,7 +12,7 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
 
 import java.io.IOException;
 
@@ -36,8 +36,8 @@ public final class PersisterImpl implements Persister {
         this.storage = storage;
     }
 
-    public static Optional<PersisterImpl> createFromProperties(ConfigProvider configProvider) {
-        String storageAdapterClass = configProvider.getProperty(STORAGE_ADAPTER_CLASS_PROP);
+    public static Optional<PersisterImpl> createFromProperties(BundleContext bundleContext) {
+        String storageAdapterClass = bundleContext.getProperty(STORAGE_ADAPTER_CLASS_PROP);
         StorageAdapter storage;
         if (storageAdapterClass == null || storageAdapterClass.equals("")) {
             return Optional.absent();
@@ -45,7 +45,7 @@ public final class PersisterImpl implements Persister {
 
         try {
             storage = StorageAdapter.class.cast(resolveClass(storageAdapterClass, StorageAdapter.class).newInstance());
-            storage.setProperties(configProvider);
+            storage.setProperties(bundleContext);
 
         } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
             throw new IllegalArgumentException("Unable to instantiate storage adapter from " + storageAdapterClass, e);
index cf1b0af454905d8aa6091085f3f3d538d3dd9029..ae6c95312c9143d29f384571ffe9182b227aa862 100644 (file)
@@ -12,7 +12,6 @@ import com.google.common.base.Optional;
 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
 import org.opendaylight.controller.netconf.persist.impl.NoOpStorageAdapter;
 import org.opendaylight.controller.netconf.persist.impl.PersisterImpl;
-import org.opendaylight.controller.config.stat.ConfigProvider;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil.TLSConfiguration;
 import org.osgi.framework.BundleActivator;
@@ -38,16 +37,15 @@ public class ConfigPersisterActivator implements BundleActivator {
     public void start(BundleContext context) throws Exception {
         logger.debug("ConfigPersister activator started");
 
-        ConfigProvider configProvider = new ConfigProvider.ConfigProviderImpl(context);
-        Optional<PersisterImpl> maybePersister = PersisterImpl.createFromProperties(configProvider);
+        Optional<PersisterImpl> maybePersister = PersisterImpl.createFromProperties(context);
         if (maybePersister.isPresent() == false) {
             throw new IllegalStateException("No persister is defined in " + PersisterImpl.STORAGE_ADAPTER_CLASS_PROP
                     + " property. For noop persister use " + NoOpStorageAdapter.class.getCanonicalName()
                     + " . Persister is not operational");
         }
 
-        Optional<TLSConfiguration> maybeTLSConfiguration = NetconfConfigUtil.extractTLSConfiguration(configProvider);
-        Optional<InetSocketAddress> maybeTCPAddress = NetconfConfigUtil.extractTCPNetconfAddress(configProvider);
+        Optional<TLSConfiguration> maybeTLSConfiguration = NetconfConfigUtil.extractTLSConfiguration(context);
+        Optional<InetSocketAddress> maybeTCPAddress = NetconfConfigUtil.extractTCPNetconfAddress(context);
 
         InetSocketAddress address;
         if (maybeTLSConfiguration.isPresent()) {
index df6b1db97a6fe6ed9016fbd0d4149f53584940a9..44b3b610434038aba7cfb68a20c763e97f2f7cff 100644 (file)
@@ -16,7 +16,7 @@ import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
 import org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
 
 import java.io.File;
 import java.io.IOException;
@@ -34,7 +34,7 @@ import static org.mockito.Mockito.verify;
 
 public class PersisterImplTest {
     @Mock
-    ConfigProvider mockedConfigProvider;
+    BundleContext mockedContext;
 
     @Before
     public void setUpMocks() {
@@ -43,10 +43,10 @@ public class PersisterImplTest {
 
     @Test
     public void testFromProperties() throws Exception {
-        doReturn(MockAdapter.class.getName()).when(mockedConfigProvider).getProperty(
+        doReturn(MockAdapter.class.getName()).when(mockedContext).getProperty(
                 PersisterImpl.STORAGE_ADAPTER_CLASS_PROP);
 
-        PersisterImpl persisterImpl = PersisterImpl.createFromProperties(mockedConfigProvider).get();
+        PersisterImpl persisterImpl = PersisterImpl.createFromProperties(mockedContext).get();
         persisterImpl.persistConfig(null);
         persisterImpl.loadLastConfig();
         persisterImpl.persistConfig(null);
@@ -59,29 +59,29 @@ public class PersisterImplTest {
 
     @Test
     public void testFromProperties2() throws Exception {
-        mockedConfigProvider = mock(ConfigProvider.class);
-        doReturn(FileStorageAdapter.class.getName()).when(mockedConfigProvider).getProperty(
+        mockedContext = mock(BundleContext.class);
+        doReturn(FileStorageAdapter.class.getName()).when(mockedContext).getProperty(
                 PersisterImpl.STORAGE_ADAPTER_CLASS_PROP);
         doReturn("target" + File.separator + "generated-test-sources" + File.separator + "testFile").when(
-                mockedConfigProvider).getProperty(FileStorageAdapter.FILE_STORAGE_PROP);
-        doReturn("mockedConfigProvider").when(mockedConfigProvider).toString();
-        doReturn(null).when(mockedConfigProvider).getProperty("numberOfBackups");
+                mockedContext).getProperty(FileStorageAdapter.FILE_STORAGE_PROP);
+        doReturn("mockedContext").when(mockedContext).toString();
+        doReturn(null).when(mockedContext).getProperty("numberOfBackups");
 
-        PersisterImpl persisterImpl = PersisterImpl.createFromProperties(mockedConfigProvider).get();
+        PersisterImpl persisterImpl = PersisterImpl.createFromProperties(mockedContext).get();
         assertTrue(persisterImpl.getStorage() instanceof FileStorageAdapter);
     }
 
     @Test
     public void testFromProperties3() throws Exception {
-        mockedConfigProvider = mock(ConfigProvider.class);
-        doReturn(FileStorageAdapter.class.getName()).when(mockedConfigProvider).getProperty(
+        mockedContext = mock(BundleContext.class);
+        doReturn(FileStorageAdapter.class.getName()).when(mockedContext).getProperty(
                 PersisterImpl.STORAGE_ADAPTER_CLASS_PROP);
         doReturn("target" + File.separator + "generated-test-sources" + File.separator + "testFile").when(
-                mockedConfigProvider).getProperty(FileStorageAdapter.FILE_STORAGE_PROP);
-        doReturn("mockedConfigProvider").when(mockedConfigProvider).toString();
-        doReturn("0").when(mockedConfigProvider).getProperty("numberOfBackups");
+                mockedContext).getProperty(FileStorageAdapter.FILE_STORAGE_PROP);
+        doReturn("mockedContext").when(mockedContext).toString();
+        doReturn("0").when(mockedContext).getProperty("numberOfBackups");
         try {
-            PersisterImpl.createFromProperties(mockedConfigProvider).get();
+            PersisterImpl.createFromProperties(mockedContext).get();
             fail();
         } catch (RuntimeException e) {
             assertThat(
@@ -123,7 +123,7 @@ public class PersisterImplTest {
         static int props = 0;
 
         @Override
-        public void setProperties(ConfigProvider configProvider) {
+        public void setProperties(BundleContext configProvider) {
             props++;
         }
 
index 3c6209485de9499a07a8e077956ccf1e8bae6a3f..0e9b421229873365a9fe08785f41f1b93ff6834e 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>netconf-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>netconf-api</artifactId>
                             javax.management,
                             org.opendaylight.controller.config.api.jmx,
                             org.opendaylight.protocol.framework,
-                            org.w3c.dom
+                            io.netty.channel,
+                            io.netty.util.concurrent,
+                            org.w3c.dom,
+                            org.slf4j
                         </Import-Package>
                         <Export-Package>
                             org.opendaylight.controller.netconf.api,
@@ -46,7 +49,7 @@
                         </Export-Package>
                     </instructions>
                 </configuration>
-            </plugin>
+             </plugin>
         </plugins>
     </build>
 
index 49ca0c010681b6f451d7bb19348b323b84affe21..e2a2d832c779e37f3e26c2d86efc37fb27d1b345 100644 (file)
@@ -12,7 +12,8 @@ import org.w3c.dom.Document;
 
 public interface NetconfOperationRouter extends AutoCloseable {
 
-    Document onNetconfMessage(Document message) throws NetconfDocumentedException;
+    Document onNetconfMessage(Document message, NetconfSession session)
+            throws NetconfDocumentedException;
 
     @Override
     void close();
index a61d6938f6a91ed12c1f3597aad9ec3cac6ce7e9..8b761a85b23b423314a39f8718492a2f5d1f8de0 100644 (file)
  * 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.netconf.api;
 
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+
+import java.io.IOException;
+import java.util.Map;
+
 import org.opendaylight.protocol.framework.AbstractProtocolSession;
+import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
+import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
+import org.opendaylight.protocol.framework.SessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class NetconfSession extends AbstractProtocolSession<NetconfMessage> {
 
-    public abstract void sendMessage(NetconfMessage netconfMessage);
+    private ChannelHandler exiEncoder;
+    private String exiEncoderName;
+    private String removeAfterMessageSentname;
+    private String pmeName,pmdName;
+    private final  Channel channel;
+    private final  SessionListener sessionListener;
+    private final long sessionId;
+    private boolean up = false;
+    private static final Logger logger = LoggerFactory.getLogger(NetconfSession.class);
+    private static final int T = 0;
+
+    protected NetconfSession(SessionListener sessionListener, Channel channel, long sessionId) {
+        this.sessionListener = sessionListener;
+        this.channel = channel;
+        this.sessionId = sessionId;
+        logger.debug("Session {} created", toString());
+
+        ChannelHandler pmd = channel.pipeline().get(ProtocolMessageDecoder.class);
+        ChannelHandler pme = channel.pipeline().get(ProtocolMessageEncoder.class);
+
+        for (Map.Entry<String, ChannelHandler> entry:channel.pipeline().toMap().entrySet()){
+            if (entry.getValue().equals(pmd)){
+                pmdName = entry.getKey();
+            }
+            if (entry.getValue().equals(pme)){
+                pmeName = entry.getKey();
+            }
+        }
+    }
+    @Override
+    public void close() {
+        channel.close();
+        sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Session closed"));
+    }
+
+    @Override
+    protected void handleMessage(NetconfMessage netconfMessage) {
+        logger.debug("handlign incomming message");
+        sessionListener.onMessage(this, netconfMessage);
+    }
+
+    public void sendMessage(NetconfMessage netconfMessage) {
+        channel.writeAndFlush(netconfMessage);
+        if (exiEncoder!=null){
+            if (channel.pipeline().get(exiEncoderName)== null){
+                channel.pipeline().addBefore(pmeName, exiEncoderName, exiEncoder);
+            }
+        }
+        if (removeAfterMessageSentname!=null){
+            channel.pipeline().remove(removeAfterMessageSentname);
+            removeAfterMessageSentname = null;
+        }
+    }
+
+    @Override
+    protected void endOfInput() {
+        logger.debug("Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
+                : "initialized");
+        if (isUp()) {
+            this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
+        }
+    }
+
+    @Override
+    protected void sessionUp() {
+        logger.debug("Session {} up", toString());
+        sessionListener.onSessionUp(this);
+        this.up = true;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuffer sb = new StringBuffer("ServerNetconfSession{");
+        sb.append("sessionId=").append(sessionId);
+        sb.append('}');
+        return sb.toString();
+    }
+
+    public boolean isUp() {
+        return up;
+    }
+
+    public long getSessionId() {
+        return sessionId;
+    }
+
+    public <T extends ChannelHandler> T remove(Class<T> handlerType) {
+        return channel.pipeline().remove(handlerType);
+    }
+
+    public <T extends ChannelHandler> T getHandler(Class<T> handlerType) {
+        return channel.pipeline().get(handlerType);
+   }
+
+    public void addFirst(ChannelHandler handler, String name){
+        channel.pipeline().addFirst(name, handler);
+    }
+    public void addLast(ChannelHandler handler, String name){
+        channel.pipeline().addLast(name, handler);
+    }
+
+    public void addExiDecoder(String name,ChannelHandler handler){
+        if (channel.pipeline().get(name)== null){
+            channel.pipeline().addBefore(pmdName, name, handler);
+        }
+    }
+    public void addExiEncoderAfterMessageSent(String name, ChannelHandler handler){
+        this.exiEncoder = handler;
+        this.exiEncoderName = name;
+    }
+
+    public void addExiEncoder(String name, ChannelHandler handler){
+        channel.pipeline().addBefore(pmeName, name, handler);
+    }
+
+    public void removeAfterMessageSent(String handlerName){
+        this.removeAfterMessageSentname = handlerName;
+    }
+
 }
+
index 0864a52356e63aa59a6b4ccc4397e9ba3e98e1f6..ffd46e882c60f4a86b47470159d18139863ffff9 100644 (file)
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>netconf-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
     <artifactId>netconf-client</artifactId>
     <name>${project.artifactId}</name>
index cc8d987a68f5d1aa314b8ec412f78e49d700e9f3..61a9a9b9548bc6eeb771dcf952c61e08e4a669f3 100644 (file)
@@ -8,16 +8,8 @@
 
 package org.opendaylight.controller.netconf.client;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GlobalEventExecutor;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import org.opendaylight.protocol.framework.ReconnectStrategy;
-import org.opendaylight.protocol.framework.TimedReconnectStrategy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -26,6 +18,16 @@ import java.util.Set;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.TimedReconnectStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+
 public class NetconfClient implements Closeable {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
@@ -121,4 +123,8 @@ public class NetconfClient implements Closeable {
         Preconditions.checkState(clientSession != null, "Client was not initialized successfully");
         return Sets.newHashSet(clientSession.getServerCapabilities());
     }
+
+    public NetconfClientSession getClientSession() {
+        return clientSession;
+    }
 }
index f0180cf78d74a8c47a9697f91480c474601a9759..11c7f3061f9e9b28f34926b482c60a8bbe51a26a 100644 (file)
@@ -9,87 +9,28 @@
 package org.opendaylight.controller.netconf.client;
 
 import io.netty.channel.Channel;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
+
+import java.util.Collection;
+
 import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.SessionListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.util.Collection;
-
 public class NetconfClientSession extends NetconfSession {
 
-    private final SessionListener sessionListener;
-    private final long sessionId;
-    private final Channel channel;
-
     private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class);
     private final Collection<String> capabilities;
-    private boolean up;
 
     public NetconfClientSession(SessionListener sessionListener, Channel channel, long sessionId,
             Collection<String> capabilities) {
-        this.sessionListener = sessionListener;
-        this.channel = channel;
-        this.sessionId = sessionId;
+        super(sessionListener,channel,sessionId);
         this.capabilities = capabilities;
         logger.debug("Client Session {} created", toString());
     }
 
-    @Override
-    public void close() {
-        channel.close();
-        sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Client Session closed"));
-    }
-
-    @Override
-    protected void handleMessage(NetconfMessage netconfMessage) {
-        logger.debug("Client Session {} received message {}", toString(),
-                XmlUtil.toString(netconfMessage.getDocument()));
-        sessionListener.onMessage(this, netconfMessage);
-    }
-
-    @Override
-    public void sendMessage(NetconfMessage netconfMessage) {
-        channel.writeAndFlush(netconfMessage);
-    }
-
-    @Override
-    protected void endOfInput() {
-        logger.debug("Client Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
-                : "initialized");
-        if (isUp()) {
-            this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
-        }
-    }
-
-    @Override
-    protected void sessionUp() {
-        logger.debug("Client Session {} up", toString());
-        sessionListener.onSessionUp(this);
-        this.up = true;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuffer sb = new StringBuffer("ClientNetconfSession{");
-        sb.append("sessionId=").append(sessionId);
-        sb.append('}');
-        return sb.toString();
-    }
-
-    public boolean isUp() {
-        return up;
-    }
-
-    public long getSessionId() {
-        return sessionId;
-    }
-
     public Collection<String> getServerCapabilities() {
         return capabilities;
     }
+
 }
index 1d85b688e5cd51fde186c473791d81a54b057e8f..221953e56e51053af95bc32bd866f2d51b99f05a 100644 (file)
@@ -1,5 +1,6 @@
 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <capabilities>
         <capability>urn:ietf:params:netconf:base:1.0</capability>
+        <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
     </capabilities>
 </hello>
\ No newline at end of file
index c355cb0638f2cb02a102e13e5aa1b09c9946783a..33fa675a926677245ae6583acc5106c9327f179c 100644 (file)
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>netconf-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>netconf-impl</artifactId>
@@ -54,7 +54,6 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
-
         <!-- test dependencies -->
         <dependency>
             <groupId>org.opendaylight.bgpcep</groupId>
             <artifactId>netconf-client</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>commons.logback_settings</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
                             io.netty.channel.socket,
                             io.netty.util,
                             io.netty.util.concurrent,
+                            io.netty.buffer,
+                            io.netty.handler.codec,
                             javax.management,
                             javax.net.ssl,
                             javax.xml.namespace,
                             org.opendaylight.controller.netconf.util.mapping,
                             org.opendaylight.controller.netconf.util.osgi,
                             org.opendaylight.controller.netconf.util.xml,
+                            org.opendaylight.controller.netconf.util.handler,
                             org.opendaylight.protocol.framework,
                             org.osgi.framework,
                             org.osgi.util.tracker,
                             org.w3c.dom,
                             org.xml.sax,
                             org.opendaylight.controller.netconf.util.messages,
-                            org.opendaylight.controller.config.stat
+                            com.siemens.ct.exi.exceptions
                         </Import-Package>
                     </instructions>
                 </configuration>
index 1ae3fabbb9a31bf5275b63f1bc27da15e8a72d88..a4d7e747234ce07804a1405ff4f96ff31ecd35e5 100644 (file)
@@ -9,77 +9,18 @@
 package org.opendaylight.controller.netconf.impl;
 
 import io.netty.channel.Channel;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
+
 import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.SessionListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-
 public class NetconfServerSession extends NetconfSession {
 
-    private final SessionListener sessionListener;
-    private final Channel channel;
-
     private static final Logger logger = LoggerFactory.getLogger(NetconfServerSession.class);
-    private final long sessionId;
-    private boolean up = false;
 
     public NetconfServerSession(SessionListener sessionListener, Channel channel, long sessionId) {
-        this.sessionListener = sessionListener;
-        this.channel = channel;
-        this.sessionId = sessionId;
+        super(sessionListener,channel,sessionId);
         logger.debug("Session {} created", toString());
     }
-
-    @Override
-    public void close() {
-        channel.close();
-        sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Session closed"));
-    }
-
-    @Override
-    protected void handleMessage(NetconfMessage netconfMessage) {
-        logger.debug("Session {} received message {}", toString(), XmlUtil.toString(netconfMessage.getDocument()));
-        sessionListener.onMessage(this, netconfMessage);
-    }
-
-    public void sendMessage(NetconfMessage netconfMessage) {
-        channel.writeAndFlush(netconfMessage);
-    }
-
-    @Override
-    protected void endOfInput() {
-        logger.debug("Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
-                : "initialized");
-        if (isUp()) {
-            this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
-        }
-    }
-
-    @Override
-    protected void sessionUp() {
-        logger.debug("Session {} up", toString());
-        sessionListener.onSessionUp(this);
-        this.up = true;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuffer sb = new StringBuffer("ServerNetconfSession{");
-        sb.append("sessionId=").append(sessionId);
-        sb.append('}');
-        return sb.toString();
-    }
-
-    public boolean isUp() {
-        return up;
-    }
-
-    public long getSessionId() {
-        return sessionId;
-    }
 }
index 4f71ab9bb55f207f72418338e49b4b4d7c1cfe02..686adcad8550a3401809235cc0bda6e660782738 100644 (file)
@@ -8,10 +8,11 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
+import static com.google.common.base.Preconditions.checkState;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
 import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil;
@@ -24,7 +25,8 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 
-import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
 
 public class NetconfServerSessionListener implements
         SessionListener<NetconfMessage, NetconfServerSession, NetconfTerminationReason> {
@@ -66,7 +68,8 @@ public class NetconfServerSessionListener implements
             Preconditions.checkState(operationRouter != null, "Cannot handle message, session up was not yet received");
             // FIXME: there is no validation since the document may contain yang
             // schemas
-            final NetconfMessage message = processDocument(netconfMessage);
+            final NetconfMessage message = processDocument(netconfMessage,
+                    session);
             logger.debug("Respondign with message {}", XmlUtil.toString(message.getDocument()));
             session.sendMessage(message);
 
@@ -89,16 +92,18 @@ public class NetconfServerSessionListener implements
         logger.info("Session {} closed successfully", session.getSessionId());
     }
 
-    private NetconfMessage processDocument(final NetconfMessage netconfMessage) throws NetconfDocumentedException {
+    private NetconfMessage processDocument(final NetconfMessage netconfMessage,
+            NetconfSession session) throws NetconfDocumentedException {
 
         final Document incommingDocument = netconfMessage.getDocument();
         final Node rootNode = incommingDocument.getDocumentElement();
 
-        if (rootNode.getNodeName().equals(XmlNetconfConstants.RPC_KEY)) {
+        if (rootNode.getLocalName().equals(XmlNetconfConstants.RPC_KEY)) {
             final String messageId = rootNode.getAttributes().getNamedItem(MESSAGE_ID).getTextContent();
             checkState(messageId != null);
             final Document responseDocument = XmlUtil.newDocument();
-            Document rpcReply = operationRouter.onNetconfMessage(incommingDocument);
+            Document rpcReply = operationRouter.onNetconfMessage(
+                    incommingDocument, session);
             responseDocument.appendChild(responseDocument.importNode(rpcReply.getDocumentElement(), true));
             return new NetconfMessage(responseDocument);
         } else {
index eea6dc19dae9be8897078a7798fd90c3ed7197e1..70ddf299fd5dd0d7ff8c091598c0644a88278342 100644 (file)
@@ -23,7 +23,8 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto
     private final SessionIdProvider idProvider;
 
     public NetconfServerSessionListenerFactory(NetconfOperationServiceFactoryListener factoriesListener,
-            DefaultCommitNotificationProducer commitNotifier, SessionIdProvider idProvider) {
+            DefaultCommitNotificationProducer commitNotifier,
+            SessionIdProvider idProvider) {
         this.factoriesListener = factoriesListener;
         this.commitNotifier = commitNotifier;
         this.idProvider = idProvider;
@@ -36,8 +37,9 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto
 
         CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot);
 
-        NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot,
-                capabilityProvider, commitNotifier);
+        NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(
+                netconfOperationServiceSnapshot, capabilityProvider,
+                commitNotifier);
 
         return new NetconfServerSessionListener(operationRouter);
     }
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java
new file mode 100644 (file)
index 0000000..721c0c2
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.codec.ByteToMessageDecoder;\r
+\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class ExiDecoderHandler extends ByteToMessageDecoder {\r
+\r
+    public static final String HANDLER_NAME;\r
+\r
+    static {\r
+        HANDLER_NAME = "exiDecoder";\r
+    }\r
+\r
+    private final static Logger logger = LoggerFactory\r
+            .getLogger(ExiDecoderHandler.class);\r
+\r
+    private ExiParameters parameters;\r
+\r
+    public ExiDecoderHandler(ExiParameters parameters) {\r
+        this.parameters = parameters;\r
+    }\r
+\r
+    @Override\r
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in,\r
+            List<Object> out) {\r
+        try {\r
+            ExiUtil.decode(in, out, this.parameters);\r
+        } catch (Exception e) {\r
+            throw new IllegalStateException("Unable to decode exi message.");\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java
new file mode 100644 (file)
index 0000000..e7a5917
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.codec.MessageToByteEncoder;\r
+\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+\r
+public class ExiEncoderHandler extends MessageToByteEncoder<Object> {\r
+\r
+    public static final String HANDLER_NAME;\r
+    static {\r
+        HANDLER_NAME = "exiEncoder";\r
+    }\r
+\r
+    private ExiParameters parameters;\r
+\r
+    public ExiEncoderHandler(ExiParameters parameters) {\r
+        this.parameters = parameters;\r
+    }\r
+\r
+    @Override\r
+    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)\r
+            throws Exception {\r
+        try {\r
+            ExiUtil.encode(msg, out, this.parameters);\r
+        } catch (Exception e) {\r
+            throw new IllegalStateException("Unable to encode exi message.");\r
+        }\r
+    }\r
+}\r
index 1438515f040e41c547a8742010aec37b6ab2471b..3623ef50325378b1c710d005248be520479c6763 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.controller.netconf.impl.mapping.operations;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.api.NetconfSession;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -17,8 +19,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-public class DefaultCloseSession extends AbstractNetconfOperation {
+public class DefaultCloseSession extends AbstractNetconfOperation implements DefaultNetconfOperation {
     public static final String CLOSE_SESSION = "close-session";
+    private NetconfSession netconfSession;
 
     public DefaultCloseSession(String netconfSessionIdForReporting) {
         super(netconfSessionIdForReporting);
@@ -45,4 +48,13 @@ public class DefaultCloseSession extends AbstractNetconfOperation {
         opRouter.close();
         return document.createElement(XmlNetconfConstants.OK);
     }
+
+    @Override
+    public void setNetconfSession(NetconfSession s) {
+        this.netconfSession = s;
+    }
+
+    public NetconfSession getNetconfSession() {
+        return netconfSession;
+    }
 }
index 8637c0dd7444ca816360bac9beb322bc57108293..9069e87a935784419e0c573f8721d8e31c1b3af8 100644 (file)
@@ -8,7 +8,9 @@
 
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
-import com.google.common.collect.Maps;
+import java.io.InputStream;
+import java.util.Map;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
@@ -24,8 +26,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.io.InputStream;
-import java.util.Map;
+import com.google.common.collect.Maps;
 
 public class DefaultCommit implements NetconfOperationFilter {
 
@@ -78,13 +79,13 @@ public class DefaultCommit implements NetconfOperationFilter {
     }
 
     @Override
-    public int getSoringOrder() {
+    public int getSortingOrder() {
         return 0;
     }
 
     @Override
     public int compareTo(NetconfOperationFilter o) {
-        return Integer.compare(getSoringOrder(), o.getSoringOrder());
+        return Integer.compare(getSortingOrder(), o.getSortingOrder());
     }
 
     private boolean canHandle(OperationNameAndNamespace operationNameAndNamespace) {
@@ -117,7 +118,8 @@ public class DefaultCommit implements NetconfOperationFilter {
     }
 
     private Element getConfigSnapshot(NetconfOperationRouter opRouter) throws NetconfDocumentedException {
-        final Document responseDocument = opRouter.onNetconfMessage(getConfigMessage);
+        final Document responseDocument = opRouter.onNetconfMessage(
+                getConfigMessage, null);
 
         XmlElement dataElement;
         try {
index 3e65ed8842f5a0d58fd7d46d7f47f13fbd9b8230..77042855e6525673a69fcce76344d5ea757b4061 100644 (file)
@@ -8,11 +8,14 @@
 
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -23,12 +26,13 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.util.HashMap;
-import java.util.Map;
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
 
-public final class DefaultGetSchema extends AbstractNetconfOperation {
+public final class DefaultGetSchema extends AbstractNetconfOperation implements DefaultNetconfOperation {
 
     private final CapabilityProvider cap;
+    private NetconfSession netconfSession;
 
     private static final Logger logger = LoggerFactory.getLogger(DefaultGetSchema.class);
 
@@ -116,4 +120,12 @@ public final class DefaultGetSchema extends AbstractNetconfOperation {
 
         }
     }
+
+    public void setNetconfSession(NetconfSession s) {
+        this.netconfSession = s;
+    }
+
+    public NetconfSession getNetconfSession() {
+        return netconfSession;
+    }
 }
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java
new file mode 100644 (file)
index 0000000..8f08688
--- /dev/null
@@ -0,0 +1,92 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping.operations;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;\r
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+\r
+public class DefaultStartExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+\r
+    public static final String START_EXI = "start-exi";\r
+\r
+    private static NetconfSession netconfSession;\r
+\r
+    private static final Logger logger = LoggerFactory.getLogger(DefaultStartExi.class);\r
+\r
+    public DefaultStartExi(String netconfSessionIdForReporting) {\r
+        super(netconfSessionIdForReporting);\r
+    }\r
+\r
+    @Override\r
+    protected HandlingPriority canHandle(String operationName,\r
+            String netconfOperationNamespace) {\r
+        if (operationName.equals(START_EXI) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+        if (netconfOperationNamespace\r
+                .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+\r
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+    }\r
+\r
+    @Override\r
+    protected Element handle(Document document, XmlElement operationElement,\r
+            NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+\r
+\r
+        Element getSchemaResult = document\r
+                .createElement(XmlNetconfConstants.OK);\r
+        XmlUtil.addNamespaceAttr(getSchemaResult,\r
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);\r
+\r
+\r
+        try {\r
+            ExiParameters exiParams = new ExiParameters();\r
+            exiParams.setParametersFromXmlElement(operationElement);\r
+\r
+            netconfSession.addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams));\r
+            netconfSession.addExiEncoderAfterMessageSent(ExiEncoderHandler.HANDLER_NAME,new ExiEncoderHandler(exiParams));\r
+\r
+        } catch (EXIException e) {\r
+            getSchemaResult = document\r
+                    .createElement(XmlNetconfConstants.RPC_ERROR);\r
+        }\r
+\r
+        logger.info("{} operation successful", START_EXI);\r
+        logger.debug("received start-exi message {} ", XmlUtil.toString(document));\r
+        return getSchemaResult;\r
+\r
+    }\r
+\r
+    @Override\r
+    public void setNetconfSession(NetconfSession s) {\r
+        netconfSession = s;\r
+    }\r
+\r
+    public NetconfSession getNetconfSession() {\r
+        return netconfSession;\r
+    }\r
+\r
+\r
+}\r
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java
new file mode 100644 (file)
index 0000000..98a7205
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping.operations;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;\r
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+public class DefaultStopExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+\r
+    public static final String STOP_EXI = "stop-exi";\r
+    private NetconfSession netconfSession;\r
+\r
+    private static final Logger logger = LoggerFactory\r
+            .getLogger(DefaultStartExi.class);\r
+\r
+    public DefaultStopExi(String netconfSessionIdForReporting) {\r
+        super(netconfSessionIdForReporting);\r
+    }\r
+\r
+    @Override\r
+    protected HandlingPriority canHandle(String operationName,\r
+            String netconfOperationNamespace) {\r
+        if (operationName.equals(STOP_EXI) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+        if (netconfOperationNamespace\r
+                .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+\r
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+    }\r
+\r
+    @Override\r
+    protected Element handle(Document document, XmlElement operationElement,\r
+            NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+\r
+        netconfSession.remove(ExiDecoderHandler.class);\r
+        netconfSession.removeAfterMessageSent(ExiEncoderHandler.HANDLER_NAME);\r
+\r
+        Element getSchemaResult = document.createElement(XmlNetconfConstants.OK);\r
+        XmlUtil.addNamespaceAttr(getSchemaResult,\r
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);\r
+        logger.info("{} operation successful", STOP_EXI);\r
+        logger.debug("received stop-exi message {} ", XmlUtil.toString(document));\r
+        return getSchemaResult;\r
+    }\r
+\r
+    @Override\r
+    public void setNetconfSession(NetconfSession s) {\r
+        this.netconfSession = s;\r
+    }\r
+\r
+    public NetconfSession getNetconfSession() {\r
+        return netconfSession;\r
+    }\r
+}
\ No newline at end of file
index 824518a5efc8d48062443266ba0473de45c6c9cc..fc240f91c9d168397a82c82f42577310aeb5b408 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.controller.netconf.impl.osgi;
 
 import com.google.common.base.Optional;
 import io.netty.util.HashedWheelTimer;
-import org.opendaylight.controller.config.stat.ConfigProvider;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
 import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
@@ -39,9 +38,8 @@ public class NetconfImplActivator implements BundleActivator {
 
     @Override
     public void start(final BundleContext context) throws Exception {
-        final ConfigProvider configProvider = new ConfigProvider.ConfigProviderImpl(context);
-        maybeTCPAddress = NetconfConfigUtil.extractTCPNetconfAddress(configProvider);
-        maybeTLSConfiguration = NetconfConfigUtil.extractTLSConfiguration(configProvider);
+        maybeTCPAddress = NetconfConfigUtil.extractTCPNetconfAddress(context);
+        maybeTLSConfiguration = NetconfConfigUtil.extractTLSConfiguration(context);
         if (maybeTCPAddress.isPresent() == false && maybeTLSConfiguration.isPresent() == false) {
             throw new IllegalStateException("TCP nor TLS is configured, netconf not available.");
         }
index a9bea344c9471853bc1654f708f8f9d99a61e619..3dd6e6803bda9662b7e54a95849db368931a8452 100644 (file)
@@ -7,16 +7,25 @@
  */
 package org.opendaylight.controller.netconf.impl.osgi;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
@@ -27,13 +36,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
@@ -46,8 +51,10 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
     private final CapabilityProvider capabilityProvider;
 
+
     public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
-            CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
+            CapabilityProvider capabilityProvider,
+            DefaultCommitNotificationProducer commitNotifier) {
 
         this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
 
@@ -58,6 +65,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
                 .getNetconfSessionIdForReporting()));
         defaultNetconfOperations.add(new DefaultCloseSession(netconfOperationServiceSnapshot
                 .getNetconfSessionIdForReporting()));
+        defaultNetconfOperations.add(new DefaultStartExi(
+                netconfOperationServiceSnapshot
+                        .getNetconfSessionIdForReporting()));
+        defaultNetconfOperations.add(new DefaultStopExi(
+                netconfOperationServiceSnapshot
+                        .getNetconfSessionIdForReporting()));
 
         allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
 
@@ -101,8 +114,10 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
     }
 
     @Override
-    public synchronized Document onNetconfMessage(Document message) throws NetconfDocumentedException {
-        NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(message);
+    public synchronized Document onNetconfMessage(Document message,
+            NetconfSession session) throws NetconfDocumentedException {
+        NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(
+                message, session);
         logger.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message),
                 netconfOperationExecution.operationWithHighestPriority);
 
@@ -125,10 +140,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return chain.getFirst().execute(message, this);
     }
 
-    private NetconfOperationExecution getNetconfOperationWithHighestPriority(Document message) {
+    private NetconfOperationExecution getNetconfOperationWithHighestPriority(
+            Document message, NetconfSession session) {
 
         // TODO test
-        TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(message);
+        TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(
+                message, session);
 
         Preconditions.checkState(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
                 NetconfOperation.class.getName(), XmlUtil.toString(message));
@@ -143,12 +160,16 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
     }
 
-    private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(Document message) {
+    private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(
+            Document message, NetconfSession session) {
         TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
 
         for (NetconfOperation netconfOperation : allNetconfOperations) {
             final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
-
+            if (netconfOperation instanceof DefaultNetconfOperation) {
+                ((DefaultNetconfOperation) netconfOperation)
+                        .setNetconfSession(session);
+            }
             if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
                 Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
                 netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
@@ -197,4 +218,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot
                 + '}';
     }
+
+
+
 }
index 6a3f911cd4e0ed5958700b05344ccdb3162b03b2..eb4b4b9225b4e8a56f92de3714513d0fcb91a295 100644 (file)
@@ -2,6 +2,7 @@
 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <capabilities>
         <capability>urn:ietf:params:netconf:base:1.0</capability>
+        <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
     </capabilities>
     <session-id>1</session-id>
 </hello>
diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java
new file mode 100644 (file)
index 0000000..6b0316b
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.controller.netconf.impl;\r
+\r
+import static junit.framework.Assert.assertNotNull;\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.buffer.Unpooled;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.junit.Test;\r
+import org.opendaylight.controller.netconf.api.NetconfMessage;\r
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+\r
+\r
+\r
+public class ExiEncodeDecodeTest  {\r
+    @Test\r
+    public void encodeExi() throws Exception{\r
+\r
+        String startExiString = XmlFileLoader.xmlFileToString("netconfMessages/startExi.xml");\r
+        assertNotNull(startExiString);\r
+\r
+        NetconfMessage startExiMessage = XmlFileLoader.xmlFileToNetconfMessage(("netconfMessages/startExi.xml"));\r
+        assertNotNull(startExiMessage);\r
+\r
+        ExiParameters exiParams = new ExiParameters();\r
+        exiParams.setParametersFromXmlElement(XmlElement.fromDomElement(startExiMessage.getDocument().getDocumentElement()));\r
+        assertNotNull(exiParams);\r
+\r
+        ByteBuf encodedBuf = Unpooled.buffer();\r
+        ByteBuf sourceBuf = Unpooled.copiedBuffer(startExiString.getBytes());\r
+        ExiUtil.encode(sourceBuf, encodedBuf, exiParams);\r
+\r
+        List<Object> newOut = new ArrayList<Object>();\r
+        ExiUtil.decode(encodedBuf, newOut, exiParams);\r
+\r
+        ByteBuf decodedBuf = (ByteBuf)newOut.get(0);\r
+        String decodedString = new String(decodedBuf.array(),"UTF-8");\r
+        assertNotNull(decodedString);\r
+    }\r
+}\r
index 6facfa8fba7d6da08d291abec853164ffb586832..13b0a1e570b122ae04a94e5b626b27e7c93f7b88 100644 (file)
@@ -7,7 +7,7 @@
     <parent>
         <artifactId>netconf-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
 
     <artifactId>netconf-it</artifactId>
             <artifactId>mockito-configuration</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>commons.logback_settings</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
index 1512d54105af31cf02437ce4f88c4298095d19ce..e9fe857bcac571501900dc2111edc2d4567bbe80 100644 (file)
@@ -44,9 +44,12 @@ import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
 import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
@@ -80,9 +83,11 @@ public class NetconfITTest extends AbstractConfigTest {
     // private static final Logger logger =
     // LoggerFactory.getLogger(NetconfITTest.class);
     //
+
     private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
 
-    private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession;
+    private NetconfMessage getConfig, getConfigCandidate, editConfig,
+            closeSession, startExi, stopExi;
     private DefaultCommitNotificationProducer commitNot;
     private NetconfServerDispatcher dispatch;
 
@@ -132,6 +137,10 @@ public class NetconfITTest extends AbstractConfigTest {
         this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
         this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
         this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
+        this.startExi = XmlFileLoader
+                .xmlFileToNetconfMessage("netconfMessages/startExi.xml");
+        this.stopExi = XmlFileLoader
+                .xmlFileToNetconfMessage("netconfMessages/stopExi.xml");
         this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
     }
 
@@ -270,6 +279,7 @@ public class NetconfITTest extends AbstractConfigTest {
             final Element rpcReply = message.getDocument().getDocumentElement();
             final XmlElement resultElement = XmlElement.fromDomElement(rpcReply).getOnlyChildElement();
             assertEquals("result", resultElement.getName());
+
             final String namespace = resultElement.getNamespaceAttribute();
             assertEquals(expectedNamespace, namespace);
         }
@@ -298,15 +308,44 @@ public class NetconfITTest extends AbstractConfigTest {
         });
     }
 
+    @Test
+//    @Ignore
+    public void testStartExi() throws Exception {
+        try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
+
+
+            Document rpcReply = netconfClient.sendMessage(this.startExi)
+                    .getDocument();
+            assertIsOK(rpcReply);
+
+            ExiParameters exiParams = new ExiParameters();
+            exiParams.setParametersFromXmlElement(XmlElement.fromDomDocument(this.startExi.getDocument()));
+
+            netconfClient.getClientSession().addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams));
+            netconfClient.getClientSession().addExiEncoder(ExiEncoderHandler.HANDLER_NAME, new ExiEncoderHandler(exiParams));
+
+            rpcReply = netconfClient.sendMessage(this.editConfig)
+                    .getDocument();
+            assertIsOK(rpcReply);
+
+            rpcReply = netconfClient.sendMessage(this.stopExi)
+                    .getDocument();
+            assertIsOK(rpcReply);
+
+        }
+    }
+
     @Test
     public void testCloseSession() throws Exception {
         try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
 
             // edit config
-            Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
+            Document rpcReply = netconfClient.sendMessage(this.editConfig)
+                    .getDocument();
             assertIsOK(rpcReply);
 
-            rpcReply = netconfClient.sendMessage(this.closeSession).getDocument();
+            rpcReply = netconfClient.sendMessage(this.closeSession)
+                    .getDocument();
 
             assertIsOK(rpcReply);
         }
@@ -336,7 +375,7 @@ public class NetconfITTest extends AbstractConfigTest {
     }
 
     private void assertIsOK(final Document rpcReply) {
-        assertEquals("rpc-reply", rpcReply.getDocumentElement().getTagName());
+        assertEquals("rpc-reply", rpcReply.getDocumentElement().getLocalName());
         assertEquals("ok", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName());
     }
 
@@ -398,9 +437,7 @@ public class NetconfITTest extends AbstractConfigTest {
 
     private NetconfClient createSession(final InetSocketAddress address, final String expected) throws Exception {
         final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, NETCONF_CLIENT_DISPATCHER);
-
         assertEquals(expected, Long.toString(netconfClient.getSessionId()));
-
         return netconfClient;
     }
 
index 9fb820695adbf18216afe20886e47133e70457ea..d7775d156d3ab8e830d9c8e1220ec02caed626ac 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>netconf-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>netconf-mapping-api</artifactId>
diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java
new file mode 100644 (file)
index 0000000..f6f05f6
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.netconf.mapping.api;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+\r
+public interface DefaultNetconfOperation {\r
+    void setNetconfSession(NetconfSession s);\r
+}\r
index 22a730726d60b5ffdef95b0431059a72b466c592..c9e04e3dcd281d1fb8ca45046a42eda0c1d5e4ef 100644 (file)
@@ -21,6 +21,6 @@ public interface NetconfOperationFilter extends Comparable<NetconfOperationFilte
     Document doFilter(Document message, NetconfOperationRouter operationRouter, NetconfOperationFilterChain filterChain)
             throws NetconfDocumentedException;
 
-    int getSoringOrder();
+    int getSortingOrder();
 
 }
index d6bf62413a569949da0ca09de44d5678f3c9a4da..c19506b236a2d8b9cacdc7e03cc263f20a131bfb 100644 (file)
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>netconf-subsystem</artifactId>
         <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.2-SNAPSHOT</version>
+        <version>0.2.3-SNAPSHOT</version>
     </parent>
     <artifactId>netconf-util</artifactId>
     <name>${project.artifactId}</name>
             <artifactId>netty-handler</artifactId>
             <version>${netconf.netty.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.siemens.ct.exi</groupId>
+            <artifactId>exificient</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.thirdparty</groupId>
             <artifactId>ganymed</artifactId>
@@ -71,9 +75,9 @@
                             org.opendaylight.controller.netconf.util.osgi,
                             org.opendaylight.controller.netconf.util.mapping,
                             org.opendaylight.controller.netconf.util.messages,
+                            org.opendaylight.controller.netconf.util.handler,
                         </Export-Package>
                         <Import-Package>
-                            org.opendaylight.controller.config.stat,
                             com.google.common.base,
                             com.google.common.collect,
                             ch.ethz.ssh2,
@@ -93,6 +97,7 @@
                             javax.xml.transform.stream,
                             javax.xml.validation,
                             javax.xml.xpath,
+                            javax.xml.transform.sax,
                             org.opendaylight.controller.netconf.api,
                             org.opendaylight.controller.netconf.mapping.api,
                             org.opendaylight.protocol.framework,
                             org.slf4j,
                             org.w3c.dom,
                             org.xml.sax,
+                            com.siemens.ct.exi,
+                            com.siemens.ct.exi.api.sax,
+                            com.siemens.ct.exi.grammars,
+                            com.siemens.ct.exi.helpers,
+                            com.siemens.ct.exi.exceptions,
+                            com.siemens.ct.exi.api.dom,
+                            org.xml.sax.helpers,
                         </Import-Package>
                     </instructions>
                 </configuration>
index 868ddbd99c37a07a6fd31198cd81fe01c654e662..b67f48f5fcf3014b06f701c18a956bfed0a78e5b 100644 (file)
@@ -8,6 +8,10 @@
 
 package org.opendaylight.controller.netconf.util.handler;
 
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
 import java.util.List;
 
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
@@ -15,10 +19,6 @@ import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageDecoder;
-
 public class NetconfMessageAggregator extends ByteToMessageDecoder {
 
     private final static Logger logger = LoggerFactory.getLogger(NetconfMessageAggregator.class);
@@ -35,7 +35,7 @@ public class NetconfMessageAggregator extends ByteToMessageDecoder {
     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
         int index = indexOfSequence(in, eom);
         if (index == -1) {
-            logger.debug("Message is not complete, read agian.");
+            logger.debug("Message is not complete, read again.");
             ctx.read();
         } else {
             ByteBuf msg = in.readBytes(index);
index 5850e64a0591a4d58c320eb67330e1dc0aa55cae..86081b7f81d0f342669fdb1c7124b74dbff3157b 100644 (file)
@@ -8,8 +8,6 @@
 
 package org.opendaylight.controller.netconf.util.mapping;
 
-import java.util.Map;
-
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
@@ -20,6 +18,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.util.Map;
 
 public abstract class AbstractNetconfOperation implements NetconfOperation {
     private final String netconfSessionIdForReporting;
@@ -76,15 +77,23 @@ public abstract class AbstractNetconfOperation implements NetconfOperation {
         Map<String, Attr> attributes = requestElement.getAttributes();
 
         Element response = handle(document, operationElement, opRouter);
-
         Element rpcReply = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
                 XmlNetconfConstants.RPC_REPLY_KEY);
-        rpcReply.appendChild(response);
 
-        for (String attrName : attributes.keySet()) {
-            rpcReply.setAttribute(attrName, attributes.get(attrName).getNodeValue());
+        if(XmlElement.fromDomElement(response).hasNamespace()) {
+            rpcReply.appendChild(response);
+        } else {
+            Element responseNS = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, response.getNodeName());
+            NodeList list = response.getChildNodes();
+            while(list.getLength()!=0) {
+                responseNS.appendChild(list.item(0));
+            }
+            rpcReply.appendChild(responseNS);
         }
 
+        for (String attrName : attributes.keySet()) {
+            rpcReply.setAttributeNode((Attr) document.importNode(attributes.get(attrName), true));
+        }
         document.appendChild(rpcReply);
         return document;
     }
index 54041e6602c52adc996b3d06c29f6461b5e7e4b1..76068399c17f470b249c0ba35027f89d723b5d81 100644 (file)
@@ -8,21 +8,19 @@
 
 package org.opendaylight.controller.netconf.util.osgi;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Optional;
+import org.opendaylight.protocol.util.SSLUtil;
+import org.osgi.framework.BundleContext;
 
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
 import java.net.InetSocketAddress;
 
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-
-import org.opendaylight.controller.config.stat.ConfigProvider;
-import org.opendaylight.protocol.util.SSLUtil;
-
-import com.google.common.base.Optional;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 
 public class NetconfConfigUtil {
     private static final String PREFIX_PROP = "netconf.";
@@ -37,19 +35,19 @@ public class NetconfConfigUtil {
     private static final String NETCONF_TLS_KEYSTORE_PROP = PREFIX_PROP + InfixProp.tls + ".keystore";
     private static final String NETCONF_TLS_KEYSTORE_PASSWORD_PROP = NETCONF_TLS_KEYSTORE_PROP + ".password";
 
-    public static Optional<InetSocketAddress> extractTCPNetconfAddress(ConfigProvider configProvider) {
-        return extractSomeNetconfAddress(configProvider, InfixProp.tcp);
+    public static Optional<InetSocketAddress> extractTCPNetconfAddress(BundleContext context) {
+        return extractSomeNetconfAddress(context, InfixProp.tcp);
     }
 
-    public static Optional<TLSConfiguration> extractTLSConfiguration(ConfigProvider configProvider) {
-        Optional<InetSocketAddress> address = extractSomeNetconfAddress(configProvider, InfixProp.tls);
+    public static Optional<TLSConfiguration> extractTLSConfiguration(BundleContext context) {
+        Optional<InetSocketAddress> address = extractSomeNetconfAddress(context, InfixProp.tls);
         if (address.isPresent()) {
-            String keystoreFileName = configProvider.getProperty(NETCONF_TLS_KEYSTORE_PROP);
+            String keystoreFileName = context.getProperty(NETCONF_TLS_KEYSTORE_PROP);
             File keystoreFile = new File(keystoreFileName);
             checkState(keystoreFile.exists() && keystoreFile.isFile() && keystoreFile.canRead(),
                     "Keystore file %s does not exist or is not readable file", keystoreFileName);
             keystoreFile = keystoreFile.getAbsoluteFile();
-            String keystorePassword = configProvider.getProperty(NETCONF_TLS_KEYSTORE_PASSWORD_PROP);
+            String keystorePassword = context.getProperty(NETCONF_TLS_KEYSTORE_PASSWORD_PROP);
             checkNotNull(keystoreFileName, "Property %s must be defined for tls netconf server",
                     NETCONF_TLS_KEYSTORE_PROP);
             keystorePassword = keystorePassword != null ? keystorePassword : "";
@@ -98,7 +96,7 @@ public class NetconfConfigUtil {
     }
 
     /**
-     * @param configProvider
+     * @param context
      *            from which properties are being read.
      * @param infixProp
      *            either tcp or tls
@@ -107,14 +105,14 @@ public class NetconfConfigUtil {
      * @throws IllegalStateException
      *             if address or port are invalid
      */
-    private static Optional<InetSocketAddress> extractSomeNetconfAddress(ConfigProvider configProvider,
+    private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
             InfixProp infixProp) {
-        String address = configProvider.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
+        String address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
         if (address == null) {
             return Optional.absent();
         }
         String portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
-        String portString = configProvider.getProperty(portKey);
+        String portString = context.getProperty(portKey);
         checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey);
         try {
             int port = Integer.valueOf(portString);
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java
new file mode 100644 (file)
index 0000000..63dfcde
--- /dev/null
@@ -0,0 +1,128 @@
+package org.opendaylight.controller.netconf.util.xml;\r
+\r
+import com.siemens.ct.exi.CodingMode;\r
+import com.siemens.ct.exi.FidelityOptions;\r
+import com.siemens.ct.exi.GrammarFactory;\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+import com.siemens.ct.exi.grammars.Grammars;\r
+\r
+public class ExiParameters {\r
+\r
+    private static final String EXI_PARAMETER_ALIGNMENT = "alignment";\r
+    private static final String EXI_PARAMETER_BYTE_ALIGNED = "byte-aligned";\r
+    private static final String EXI_PARAMETER_COMPRESSED = "compressed";\r
+\r
+    private static final String EXI_PARAMETER_FIDELITY = "fidelity";\r
+    private static final String EXI_FIDELITY_DTD = "dtd";\r
+    private static final String EXI_FIDELITY_LEXICAL_VALUES = "lexical-values";\r
+    private static final String EXI_FIDELITY_COMMENTS = "comments";\r
+    private static final String EXI_FIDELITY_PIS = "pis";\r
+    private static final String EXI_FIDELITY_PREFIXES = "prefixes";\r
+\r
+    private static final String EXI_PARAMETER_SCHEMA = "schema";\r
+    private static final String EXI_PARAMETER_SCHEMA_NONE = "none";\r
+    private static final String EXI_PARAMETER_SCHEMA_BUILT_IN = "builtin";\r
+    private static final String EXI_PARAMETER_SCHEMA_BASE_1_1 = "base:1.1";\r
+\r
+    private static final String NETCONF_XSD_LOCATION = "";\r
+\r
+    private FidelityOptions fidelityOptions;\r
+    private Grammars grammars;\r
+    private CodingMode codingMode = CodingMode.BIT_PACKED;\r
+\r
+    public void setParametersFromXmlElement(XmlElement operationElement)\r
+            throws EXIException {\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_ALIGNMENT)\r
+                .getLength() > 0) {\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_BYTE_ALIGNED)\r
+                    .getLength() > 0) {\r
+                this.codingMode = CodingMode.BYTE_PACKED;\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_BYTE_ALIGNED).getLength() > 0) {\r
+                this.codingMode = CodingMode.BYTE_PACKED;\r
+            }\r
+            if (operationElement.getElementsByTagName(EXI_PARAMETER_COMPRESSED)\r
+                    .getLength() > 0) {\r
+                this.codingMode = CodingMode.COMPRESSION;\r
+            }\r
+        }\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_FIDELITY)\r
+                .getLength() > 0) {\r
+\r
+            this.fidelityOptions = FidelityOptions.createDefault();\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_DTD)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_DTD,\r
+                        true);\r
+            }\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_FIDELITY_LEXICAL_VALUES)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_LEXICAL_VALUE, true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_COMMENTS)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_COMMENT, true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_PIS)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_PI,\r
+                        true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_PREFIXES)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_PREFIX, true);\r
+            }\r
+\r
+        }\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_SCHEMA)\r
+                .getLength() > 0) {\r
+\r
+            GrammarFactory grammarFactory = GrammarFactory.newInstance();\r
+            if (operationElement\r
+                    .getElementsByTagName(EXI_PARAMETER_SCHEMA_NONE)\r
+                    .getLength() > 0) {\r
+                this.grammars = grammarFactory.createSchemaLessGrammars();\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_SCHEMA_BUILT_IN).getLength() > 0) {\r
+                this.grammars = grammarFactory.createXSDTypesOnlyGrammars();\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_SCHEMA_BASE_1_1).getLength() > 0) {\r
+                this.grammars = grammarFactory\r
+                        .createGrammars(NETCONF_XSD_LOCATION);\r
+            }\r
+\r
+        }\r
+    }\r
+\r
+    public FidelityOptions getFidelityOptions() {\r
+        return fidelityOptions;\r
+    }\r
+\r
+    public Grammars getGrammars() {\r
+        return grammars;\r
+    }\r
+\r
+    public CodingMode getCodingMode() {\r
+        return codingMode;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java
new file mode 100644 (file)
index 0000000..8baa68e
--- /dev/null
@@ -0,0 +1,91 @@
+package org.opendaylight.controller.netconf.util.xml;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.buffer.EmptyByteBuf;\r
+import io.netty.buffer.Unpooled;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import javax.xml.parsers.ParserConfigurationException;\r
+\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.xml.sax.SAXException;\r
+\r
+import com.siemens.ct.exi.EXIFactory;\r
+import com.siemens.ct.exi.api.dom.DOMBuilder;\r
+import com.siemens.ct.exi.api.dom.DOMWriter;\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+import com.siemens.ct.exi.helpers.DefaultEXIFactory;\r
+\r
+public class ExiUtil {\r
+\r
+    private final static Logger logger = LoggerFactory.getLogger(ExiUtil.class);\r
+\r
+\r
+\r
+    public static void encode(final Object msg, final ByteBuf out,\r
+            ExiParameters parameters)\r
+            throws EXIException, IOException, SAXException {\r
+        final byte[] bytes = toExi(msg, parameters);\r
+        out.writeBytes(bytes);\r
+    }\r
+\r
+    public static void decode(ByteBuf in, List<Object> out,\r
+            ExiParameters parameters) throws ParserConfigurationException, EXIException, IOException\r
+             {\r
+        if (in instanceof EmptyByteBuf){\r
+            return;\r
+        }\r
+\r
+        EXIFactory exiFactory = DefaultEXIFactory.newInstance();\r
+        if (parameters.getGrammars() != null) {\r
+            exiFactory.setGrammars(parameters.getGrammars());\r
+        }\r
+\r
+        if (parameters.getFidelityOptions() != null) {\r
+            exiFactory.setFidelityOptions(parameters.getFidelityOptions());\r
+        }\r
+\r
+        exiFactory.setCodingMode(parameters.getCodingMode());\r
+        try (ByteArrayInputStream exiIS = new ByteArrayInputStream(((ByteBuf)in).readBytes(((ByteBuf)in).readableBytes()).array())){\r
+            DOMBuilder domBuilder = new DOMBuilder(exiFactory);\r
+            ByteBuf result = Unpooled.copiedBuffer(XmlUtil.toString(domBuilder.parse(exiIS)).getBytes());\r
+            exiIS.close();\r
+            out.add(result);\r
+        }\r
+    }\r
+\r
+    private static byte[] toExi(Object msg, ExiParameters parameters) throws EXIException, IOException,\r
+            SAXException {\r
+\r
+        if (!(msg instanceof ByteBuf)){\r
+              return Unpooled.EMPTY_BUFFER.array();\r
+        }\r
+\r
+        EXIFactory exiFactory = DefaultEXIFactory.newInstance();\r
+        if (parameters.getGrammars() != null) {\r
+            exiFactory.setGrammars(parameters.getGrammars());\r
+        }\r
+\r
+        if (parameters.getFidelityOptions() != null) {\r
+            exiFactory.setFidelityOptions(parameters.getFidelityOptions());\r
+        }\r
+\r
+        Document doc = XmlUtil.readXmlToDocument(new String( ((ByteBuf)msg).readBytes(((ByteBuf)msg).readableBytes()).array(),"UTF-8"));\r
+        exiFactory.setCodingMode(parameters.getCodingMode());\r
+\r
+        try (ByteArrayOutputStream exiOS = new ByteArrayOutputStream()){\r
+            DOMWriter domWriter = new DOMWriter(exiFactory);\r
+            domWriter.setOutput(exiOS);\r
+            domWriter.encode(doc) ;\r
+            exiOS.close();\r
+            return exiOS.toByteArray();\r
+        }\r
+    }\r
+\r
+}\r
index 7cb0bb02859afd89418db41a69c60993671deeeb..c37b4abc6215906f1a1a98f5b088e63633f81e16 100644 (file)
@@ -103,6 +103,9 @@ public class XmlElement {
     }
 
     public String getName() {
+        if (element.getLocalName()!=null && !element.getLocalName().equals("")){
+            return element.getLocalName();
+        }
         return element.getTagName();
     }
 
@@ -114,6 +117,10 @@ public class XmlElement {
         return element.getAttributeNS(namespace, attributeName);
     }
 
+    public NodeList getElementsByTagName(String name) {
+        return element.getElementsByTagName(name);
+    }
+
     public void appendChild(Element element) {
         this.element.appendChild(element);
         // Element newElement = (Element) element.cloneNode(true);
@@ -273,8 +280,8 @@ public class XmlElement {
 
     public String getNamespaceAttribute() {
         String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY);
-        Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify a %s attribute",
-                toString(), XmlUtil.XMLNS_ATTRIBUTE_KEY);
+        Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify namespace",
+                toString());
         return attribute;
     }
 
@@ -369,6 +376,20 @@ public class XmlElement {
         return element.hashCode();
     }
 
+    public boolean hasNamespace() {
+        try {
+            getNamespaceAttribute();
+        } catch (IllegalStateException e) {
+            try {
+                getNamespace();
+            } catch (IllegalStateException e1) {
+                return false;
+            }
+            return true;
+        }
+        return true;
+    }
+
     private static interface ElementFilteringStrategy {
         boolean accept(Element e);
     }
index 0791812910f96067d5de3dadbcc73da12d1e9816..3e862faa7b34c96378002d17d79350fb0d4f45d7 100644 (file)
@@ -35,6 +35,7 @@ public class XmlNetconfConstants {
     //
     public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0";
     public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0";
+
     public static final String URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring";
     // TODO where to store namespace of config ?
     public static final String URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG = "urn:opendaylight:params:xml:ns:yang:controller:config";
index 298038996eddf08382ebcabcb929d6a15ff2e5a6..5e3a7ac54f49444ac8a2278f85ed82c20a052a7a 100644 (file)
@@ -8,11 +8,12 @@
 
 package org.opendaylight.controller.netconf.util.xml;
 
-import com.google.common.base.Charsets;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
 
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
@@ -32,12 +33,13 @@ import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Charsets;
 
 public class XmlUtil {
 
@@ -79,7 +81,6 @@ public class XmlUtil {
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         factory.setNamespaceAware(true);
         factory.setCoalescing(true);
-        // factory.setValidating(true);
         factory.setIgnoringElementContentWhitespace(true);
         factory.setIgnoringComments(true);
         return factory;
index 8b60719ebe2df0028166deab0d3a38011bb59d4b..28cb4d8194b6c6b67d8afe17790974a5584de4f2 100644 (file)
@@ -8,20 +8,22 @@
 
 package org.opendaylight.controller.netconf.util.test;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Preconditions;
-import com.google.common.io.CharStreams;
-import com.google.common.io.InputSupplier;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.io.CharStreams;
+import com.google.common.io.InputSupplier;
 
 public class XmlFileLoader {
 
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml
new file mode 100644 (file)
index 0000000..6b9e945
--- /dev/null
@@ -0,0 +1,9 @@
+<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" message-id="a">\r
+<start-exi>\r
+<alignment>pre-compression</alignment>\r
+<fidelity>\r
+<dtd/>\r
+<lexical-values/>\r
+</fidelity>\r
+</start-exi>\r
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml
new file mode 100644 (file)
index 0000000..4168d21
--- /dev/null
@@ -0,0 +1,3 @@
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+    <stop-exi/>\r
+</rpc>
\ No newline at end of file
index 5447f7f5d057c71eba0e08369986c46c31013903..b22732e630bf0b5263d1221c9684faf2e0a14f52 100644 (file)
@@ -9,7 +9,7 @@
         <relativePath>../commons/opendaylight</relativePath>
     </parent>
 
-    <version>0.2.2-SNAPSHOT</version>
+    <version>0.2.3-SNAPSHOT</version>
     <artifactId>netconf-subsystem</artifactId>
     <packaging>pom</packaging>
     <name>${project.artifactId}</name>
@@ -27,6 +27,7 @@
         <module>netconf-mapping-api</module>
         <module>netconf-client</module>
         <module>../../third-party/ganymed</module>
+        <module>../../third-party/com.siemens.ct.exi</module>
     </modules>
 
     <profiles>
@@ -46,6 +47,7 @@
         <maven.bundle.version>2.3.7</maven.bundle.version>
         <slf4j.version>1.7.2</slf4j.version>
         <netconf.netty.version>4.0.10.Final</netconf.netty.version>
+        <ct.exi.version>0.9.2</ct.exi.version>
     </properties>
 
     <dependencies>
                 <artifactId>logback-config</artifactId>
                 <version>${config.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.siemens.ct.exi</groupId>
+                <artifactId>exificient</artifactId>
+                <version>${ct.exi.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
index 7e5b093c072f20aa093014a56b873871977f9bd6..4202856774b81a19403a0de2f193c8aa24bf185e 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.util.Hashtable;\r
-import java.util.Dictionary;\r
-import org.apache.felix.dm.Component;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;\r
-\r
-public class Activator extends ComponentActivatorAbstractBase {\r
-    protected static final Logger logger = LoggerFactory\r
-    .getLogger(Activator.class);\r
-\r
-    /**\r
-     * Function called when the activator starts just after some\r
-     * initializations are done by the\r
-     * ComponentActivatorAbstractBase.\r
-     *\r
-     */\r
-    public void init() {\r
-\r
-    }\r
-\r
-    /**\r
-     * Function called when the activator stops just before the\r
-     * cleanup done by ComponentActivatorAbstractBase\r
-     *\r
-     */\r
-    public void destroy() {\r
-\r
-    }\r
-\r
-    /**\r
-     * Function that is used to communicate to dependency manager the\r
-     * list of known implementations for services inside a container\r
-     *\r
-     *\r
-     * @return An array containing all the CLASS objects that will be\r
-     * instantiated in order to get an fully working implementation\r
-     * Object\r
-     */\r
-    public Object[] getImplementations() {\r
-        Object[] res = { NeutronFloatingIPInterface.class,\r
-                NeutronRouterInterface.class,\r
-                NeutronPortInterface.class,\r
-                NeutronSubnetInterface.class,\r
-                NeutronNetworkInterface.class };\r
-        return res;\r
-    }\r
-\r
-    /**\r
-     * Function that is called when configuration of the dependencies\r
-     * is required.\r
-     *\r
-     * @param c dependency manager Component object, used for\r
-     * configuring the dependencies exported and imported\r
-     * @param imp Implementation class that is being configured,\r
-     * needed as long as the same routine can configure multiple\r
-     * implementations\r
-     * @param containerName The containerName being configured, this allow\r
-     * also optional per-container different behavior if needed, usually\r
-     * should not be the case though.\r
-     */\r
-    public void configureInstance(Component c, Object imp, String containerName) {\r
-        if (imp.equals(NeutronFloatingIPInterface.class)) {\r
-            // export the service\r
-            c.setInterface(\r
-                    new String[] { INeutronFloatingIPCRUD.class.getName() }, null);\r
-            Dictionary<String, String> props = new Hashtable<String, String>();\r
-            props.put("salListenerName", "neutron");\r
-            c.add(createContainerServiceDependency(containerName)\r
-                    .setService(IClusterContainerServices.class)\r
-                    .setCallbacks("setClusterContainerService",\r
-                    "unsetClusterContainerService").setRequired(true));\r
-        }\r
-        if (imp.equals(NeutronRouterInterface.class)) {\r
-            // export the service\r
-            c.setInterface(\r
-                    new String[] { INeutronRouterCRUD.class.getName() }, null);\r
-            Dictionary<String, String> props = new Hashtable<String, String>();\r
-            props.put("salListenerName", "neutron");\r
-            c.add(createContainerServiceDependency(containerName)\r
-                    .setService(IClusterContainerServices.class)\r
-                    .setCallbacks("setClusterContainerService",\r
-                    "unsetClusterContainerService").setRequired(true));\r
-        }\r
-        if (imp.equals(NeutronPortInterface.class)) {\r
-            // export the service\r
-            c.setInterface(\r
-                    new String[] { INeutronPortCRUD.class.getName() }, null);\r
-            Dictionary<String, String> props = new Hashtable<String, String>();\r
-            props.put("salListenerName", "neutron");\r
-            c.add(createContainerServiceDependency(containerName)\r
-                    .setService(IClusterContainerServices.class)\r
-                    .setCallbacks("setClusterContainerService",\r
-                    "unsetClusterContainerService").setRequired(true));\r
-        }\r
-        if (imp.equals(NeutronSubnetInterface.class)) {\r
-            // export the service\r
-            c.setInterface(\r
-                    new String[] { INeutronSubnetCRUD.class.getName() }, null);\r
-            Dictionary<String, String> props = new Hashtable<String, String>();\r
-            props.put("salListenerName", "neutron");\r
-            c.add(createContainerServiceDependency(containerName)\r
-                    .setService(IClusterContainerServices.class)\r
-                    .setCallbacks("setClusterContainerService",\r
-                    "unsetClusterContainerService").setRequired(true));\r
-        }\r
-        if (imp.equals(NeutronNetworkInterface.class)) {\r
-            // export the service\r
-            c.setInterface(\r
-                    new String[] { INeutronNetworkCRUD.class.getName() }, null);\r
-            Dictionary<String, String> props = new Hashtable<String, String>();\r
-            props.put("salListenerName", "neutron");\r
-            c.add(createContainerServiceDependency(containerName)\r
-                    .setService(IClusterContainerServices.class)\r
-                    .setCallbacks("setClusterContainerService",\r
-                    "unsetClusterContainerService").setRequired(true));\r
-        }\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.implementation;
+
+import java.util.Hashtable;
+import java.util.Dictionary;
+import org.apache.felix.dm.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+
+public class Activator extends ComponentActivatorAbstractBase {
+    protected static final Logger logger = LoggerFactory
+    .getLogger(Activator.class);
+
+    /**
+     * Function called when the activator starts just after some
+     * initializations are done by the
+     * ComponentActivatorAbstractBase.
+     *
+     */
+    public void init() {
+
+    }
+
+    /**
+     * Function called when the activator stops just before the
+     * cleanup done by ComponentActivatorAbstractBase
+     *
+     */
+    public void destroy() {
+
+    }
+
+    /**
+     * Function that is used to communicate to dependency manager the
+     * list of known implementations for services inside a container
+     *
+     *
+     * @return An array containing all the CLASS objects that will be
+     * instantiated in order to get an fully working implementation
+     * Object
+     */
+    public Object[] getImplementations() {
+        Object[] res = { NeutronFloatingIPInterface.class,
+                NeutronRouterInterface.class,
+                NeutronPortInterface.class,
+                NeutronSubnetInterface.class,
+                NeutronNetworkInterface.class };
+        return res;
+    }
+
+    /**
+     * Function that is called when configuration of the dependencies
+     * is required.
+     *
+     * @param c dependency manager Component object, used for
+     * configuring the dependencies exported and imported
+     * @param imp Implementation class that is being configured,
+     * needed as long as the same routine can configure multiple
+     * implementations
+     * @param containerName The containerName being configured, this allow
+     * also optional per-container different behavior if needed, usually
+     * should not be the case though.
+     */
+    public void configureInstance(Component c, Object imp, String containerName) {
+        if (imp.equals(NeutronFloatingIPInterface.class)) {
+            // export the service
+            c.setInterface(
+                    new String[] { INeutronFloatingIPCRUD.class.getName() }, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                    .setService(IClusterContainerServices.class)
+                    .setCallbacks("setClusterContainerService",
+                    "unsetClusterContainerService").setRequired(true));
+        }
+        if (imp.equals(NeutronRouterInterface.class)) {
+            // export the service
+            c.setInterface(
+                    new String[] { INeutronRouterCRUD.class.getName() }, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                    .setService(IClusterContainerServices.class)
+                    .setCallbacks("setClusterContainerService",
+                    "unsetClusterContainerService").setRequired(true));
+        }
+        if (imp.equals(NeutronPortInterface.class)) {
+            // export the service
+            c.setInterface(
+                    new String[] { INeutronPortCRUD.class.getName() }, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                    .setService(IClusterContainerServices.class)
+                    .setCallbacks("setClusterContainerService",
+                    "unsetClusterContainerService").setRequired(true));
+        }
+        if (imp.equals(NeutronSubnetInterface.class)) {
+            // export the service
+            c.setInterface(
+                    new String[] { INeutronSubnetCRUD.class.getName() }, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                    .setService(IClusterContainerServices.class)
+                    .setCallbacks("setClusterContainerService",
+                    "unsetClusterContainerService").setRequired(true));
+        }
+        if (imp.equals(NeutronNetworkInterface.class)) {
+            // export the service
+            c.setInterface(
+                    new String[] { INeutronNetworkCRUD.class.getName() }, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                    .setService(IClusterContainerServices.class)
+                    .setCallbacks("setClusterContainerService",
+                    "unsetClusterContainerService").setRequired(true));
+        }
+    }
+}
index 7b10756d1cd749f4d9b153b2d758e14cc6cd91ef..7d9a2e657675e767d78a774c484e07a39f81d7d9 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronFloatingIPInterface implements INeutronFloatingIPCRUD {\r
-    private static final Logger logger = LoggerFactory.getLogger(NeutronFloatingIPInterface.class);\r
-    private String containerName = null;\r
-\r
-    private IClusterContainerServices clusterContainerService = null;\r
-    private ConcurrentMap<String, NeutronFloatingIP> floatingIPDB;\r
-\r
-    // methods needed for creating caches\r
-\r
-    void setClusterContainerService(IClusterContainerServices s) {\r
-        logger.debug("Cluster Service set");\r
-        this.clusterContainerService = s;\r
-    }\r
-\r
-    void unsetClusterContainerService(IClusterContainerServices s) {\r
-        if (this.clusterContainerService == s) {\r
-            logger.debug("Cluster Service removed!");\r
-            this.clusterContainerService = null;\r
-        }\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void allocateCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't create cache");\r
-            return;\r
-        }\r
-        logger.debug("Creating Cache for Neutron FloatingIPs");\r
-        try {\r
-            // neutron caches\r
-            this.clusterContainerService.createCache("neutronFloatingIPs",\r
-                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
-        } catch (CacheConfigException cce) {\r
-            logger.error("Cache couldn't be created for Neutron -  check cache mode");\r
-        } catch (CacheExistException cce) {\r
-            logger.error("Cache for Neutron already exists, destroy and recreate");\r
-        }\r
-        logger.debug("Cache successfully created for NeutronFloatingIps");\r
-    }\r
-\r
-    @SuppressWarnings({ "unchecked", "deprecation" })\r
-    private void retrieveCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
-            return;\r
-        }\r
-\r
-        logger.debug("Retrieving cache for Neutron FloatingIPs");\r
-        floatingIPDB = (ConcurrentMap<String, NeutronFloatingIP>) this.clusterContainerService\r
-        .getCache("neutronFloatingIPs");\r
-        if (floatingIPDB == null) {\r
-            logger.error("Cache couldn't be retrieved for Neutron FloatingIPs");\r
-        }\r
-        logger.debug("Cache was successfully retrieved for Neutron FloatingIPs");\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void destroyCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterMger, can't destroy cache");\r
-            return;\r
-        }\r
-        logger.debug("Destroying Cache for HostTracker");\r
-        this.clusterContainerService.destroyCache("neutronFloatingIPs");\r
-    }\r
-\r
-    private void startUp() {\r
-        allocateCache();\r
-        retrieveCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when all the required\r
-     * dependencies are satisfied\r
-     *\r
-     */\r
-    void init(Component c) {\r
-        Dictionary<?, ?> props = c.getServiceProperties();\r
-        if (props != null) {\r
-            this.containerName = (String) props.get("containerName");\r
-            logger.debug("Running containerName: {}", this.containerName);\r
-        } else {\r
-            // In the Global instance case the containerName is empty\r
-            this.containerName = "";\r
-        }\r
-        startUp();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when at least one dependency\r
-     * become unsatisfied or when the component is shutting down because for\r
-     * example bundle is being stopped.\r
-     *\r
-     */\r
-    void destroy() {\r
-        destroyCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by dependency manager after "init ()" is called and after\r
-     * the services provided by the class are registered in the service registry\r
-     *\r
-     */\r
-    void start() {\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager before the services exported by\r
-     * the component are unregistered, this will be followed by a "destroy ()"\r
-     * calls\r
-     *\r
-     */\r
-    void stop() {\r
-    }\r
-\r
-    // this method uses reflection to update an object from it's delta.\r
-\r
-    private boolean overwrite(Object target, Object delta) {\r
-        Method[] methods = target.getClass().getMethods();\r
-\r
-        for(Method toMethod: methods){\r
-            if(toMethod.getDeclaringClass().equals(target.getClass())\r
-                    && toMethod.getName().startsWith("set")){\r
-\r
-                String toName = toMethod.getName();\r
-                String fromName = toName.replace("set", "get");\r
-\r
-                try {\r
-                    Method fromMethod = delta.getClass().getMethod(fromName);\r
-                    Object value = fromMethod.invoke(delta, (Object[])null);\r
-                    if(value != null){\r
-                        toMethod.invoke(target, value);\r
-                    }\r
-                } catch (Exception e) {\r
-                    e.printStackTrace();\r
-                    return false;\r
-                }\r
-            }\r
-        }\r
-        return true;\r
-    }\r
-\r
-    // IfNBFloatingIPCRUD interface methods\r
-\r
-    public boolean floatingIPExists(String uuid) {\r
-        return floatingIPDB.containsKey(uuid);\r
-    }\r
-\r
-    public NeutronFloatingIP getFloatingIP(String uuid) {\r
-        if (!floatingIPExists(uuid))\r
-            return null;\r
-        return floatingIPDB.get(uuid);\r
-    }\r
-\r
-    public List<NeutronFloatingIP> getAllFloatingIPs() {\r
-        Set<NeutronFloatingIP> allIPs = new HashSet<NeutronFloatingIP>();\r
-        for (Entry<String, NeutronFloatingIP> entry : floatingIPDB.entrySet()) {\r
-            NeutronFloatingIP floatingip = entry.getValue();\r
-            allIPs.add(floatingip);\r
-        }\r
-        logger.debug("Exiting getAllFloatingIPs, Found {} FloatingIPs", allIPs.size());\r
-        List<NeutronFloatingIP> ans = new ArrayList<NeutronFloatingIP>();\r
-        ans.addAll(allIPs);\r
-        return ans;\r
-    }\r
-\r
-    public boolean addFloatingIP(NeutronFloatingIP input) {\r
-        INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-        INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-\r
-        if (floatingIPExists(input.getID()))\r
-            return false;\r
-        //if floating_ip_address isn't there, allocate from the subnet pool\r
-        NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(input.getFloatingNetworkUUID()).getSubnets().get(0));\r
-        if (input.getFloatingIPAddress() == null)\r
-            input.setFloatingIPAddress(subnet.getLowAddr());\r
-        subnet.allocateIP(input.getFloatingIPAddress());\r
-\r
-        //if port_id is there, bind port to this floating ip\r
-        if (input.getPortUUID() != null) {\r
-            NeutronPort port = portCRUD.getPort(input.getPortUUID());\r
-            port.addFloatingIP(input.getFixedIPAddress(), input);\r
-        }\r
-\r
-        floatingIPDB.putIfAbsent(input.getID(), input);\r
-        return true;\r
-    }\r
-\r
-    public boolean removeFloatingIP(String uuid) {\r
-        INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-        INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-\r
-        if (!floatingIPExists(uuid))\r
-            return false;\r
-        NeutronFloatingIP floatIP = getFloatingIP(uuid);\r
-        //if floating_ip_address isn't there, allocate from the subnet pool\r
-        NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(floatIP.getFloatingNetworkUUID()).getSubnets().get(0));\r
-        subnet.releaseIP(floatIP.getFloatingIPAddress());\r
-        if (floatIP.getPortUUID() != null) {\r
-            NeutronPort port = portCRUD.getPort(floatIP.getPortUUID());\r
-            port.removeFloatingIP(floatIP.getFixedIPAddress());\r
-        }\r
-        floatingIPDB.remove(uuid);\r
-        return true;\r
-    }\r
-\r
-    public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta) {\r
-        INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-\r
-        if (!floatingIPExists(uuid))\r
-            return false;\r
-        NeutronFloatingIP target = floatingIPDB.get(uuid);\r
-        if (target.getPortUUID() != null) {\r
-            NeutronPort port = portCRUD.getPort(target.getPortUUID());\r
-            port.removeFloatingIP(target.getFixedIPAddress());\r
-        }\r
-\r
-        //if port_id is there, bind port to this floating ip\r
-        if (delta.getPortUUID() != null) {\r
-            NeutronPort port = portCRUD.getPort(delta.getPortUUID());\r
-            port.addFloatingIP(delta.getFixedIPAddress(), delta);\r
-        }\r
-\r
-        target.setPortUUID(delta.getPortUUID());\r
-        target.setFixedIPAddress(delta.getFixedIPAddress());\r
-        return true;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronFloatingIPInterface implements INeutronFloatingIPCRUD {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronFloatingIPInterface.class);
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private ConcurrentMap<String, NeutronFloatingIP> floatingIPDB;
+
+    // methods needed for creating caches
+
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        this.clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (this.clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            this.clusterContainerService = null;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron FloatingIPs");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronFloatingIPs",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for NeutronFloatingIps");
+    }
+
+    @SuppressWarnings({ "unchecked", "deprecation" })
+    private void retrieveCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron FloatingIPs");
+        floatingIPDB = (ConcurrentMap<String, NeutronFloatingIP>) this.clusterContainerService
+        .getCache("neutronFloatingIPs");
+        if (floatingIPDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron FloatingIPs");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron FloatingIPs");
+    }
+
+    @SuppressWarnings("deprecation")
+    private void destroyCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for HostTracker");
+        this.clusterContainerService.destroyCache("neutronFloatingIPs");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for(Method toMethod: methods){
+            if(toMethod.getDeclaringClass().equals(target.getClass())
+                    && toMethod.getName().startsWith("set")){
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    if(value != null){
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    // IfNBFloatingIPCRUD interface methods
+
+    public boolean floatingIPExists(String uuid) {
+        return floatingIPDB.containsKey(uuid);
+    }
+
+    public NeutronFloatingIP getFloatingIP(String uuid) {
+        if (!floatingIPExists(uuid))
+            return null;
+        return floatingIPDB.get(uuid);
+    }
+
+    public List<NeutronFloatingIP> getAllFloatingIPs() {
+        Set<NeutronFloatingIP> allIPs = new HashSet<NeutronFloatingIP>();
+        for (Entry<String, NeutronFloatingIP> entry : floatingIPDB.entrySet()) {
+            NeutronFloatingIP floatingip = entry.getValue();
+            allIPs.add(floatingip);
+        }
+        logger.debug("Exiting getAllFloatingIPs, Found {} FloatingIPs", allIPs.size());
+        List<NeutronFloatingIP> ans = new ArrayList<NeutronFloatingIP>();
+        ans.addAll(allIPs);
+        return ans;
+    }
+
+    public boolean addFloatingIP(NeutronFloatingIP input) {
+        INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+        INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+        INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+
+        if (floatingIPExists(input.getID()))
+            return false;
+        //if floating_ip_address isn't there, allocate from the subnet pool
+        NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(input.getFloatingNetworkUUID()).getSubnets().get(0));
+        if (input.getFloatingIPAddress() == null)
+            input.setFloatingIPAddress(subnet.getLowAddr());
+        subnet.allocateIP(input.getFloatingIPAddress());
+
+        //if port_id is there, bind port to this floating ip
+        if (input.getPortUUID() != null) {
+            NeutronPort port = portCRUD.getPort(input.getPortUUID());
+            port.addFloatingIP(input.getFixedIPAddress(), input);
+        }
+
+        floatingIPDB.putIfAbsent(input.getID(), input);
+        return true;
+    }
+
+    public boolean removeFloatingIP(String uuid) {
+        INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+        INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+        INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+
+        if (!floatingIPExists(uuid))
+            return false;
+        NeutronFloatingIP floatIP = getFloatingIP(uuid);
+        //if floating_ip_address isn't there, allocate from the subnet pool
+        NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(floatIP.getFloatingNetworkUUID()).getSubnets().get(0));
+        subnet.releaseIP(floatIP.getFloatingIPAddress());
+        if (floatIP.getPortUUID() != null) {
+            NeutronPort port = portCRUD.getPort(floatIP.getPortUUID());
+            port.removeFloatingIP(floatIP.getFixedIPAddress());
+        }
+        floatingIPDB.remove(uuid);
+        return true;
+    }
+
+    public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta) {
+        INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+
+        if (!floatingIPExists(uuid))
+            return false;
+        NeutronFloatingIP target = floatingIPDB.get(uuid);
+        if (target.getPortUUID() != null) {
+            NeutronPort port = portCRUD.getPort(target.getPortUUID());
+            port.removeFloatingIP(target.getFixedIPAddress());
+        }
+
+        //if port_id is there, bind port to this floating ip
+        if (delta.getPortUUID() != null) {
+            NeutronPort port = portCRUD.getPort(delta.getPortUUID());
+            port.addFloatingIP(delta.getFixedIPAddress(), delta);
+        }
+
+        target.setPortUUID(delta.getPortUUID());
+        target.setFixedIPAddress(delta.getFixedIPAddress());
+        return true;
+    }
+}
index a2454217a64327c2d8adfc707598c904c7d395ce..b1e382107adcb5e52b58da3e41a5f4b91e9881bf 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronNetworkInterface implements INeutronNetworkCRUD {\r
-    private static final Logger logger = LoggerFactory.getLogger(NeutronNetworkInterface.class);\r
-    private String containerName = null;\r
-\r
-    private ConcurrentMap<String, NeutronNetwork> networkDB;\r
-    private IClusterContainerServices clusterContainerService = null;\r
-\r
-    // methods needed for creating caches\r
-\r
-    void setClusterContainerService(IClusterContainerServices s) {\r
-        logger.debug("Cluster Service set");\r
-        this.clusterContainerService = s;\r
-    }\r
-\r
-    void unsetClusterContainerService(IClusterContainerServices s) {\r
-        if (this.clusterContainerService == s) {\r
-            logger.debug("Cluster Service removed!");\r
-            this.clusterContainerService = null;\r
-        }\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void allocateCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't create cache");\r
-            return;\r
-        }\r
-        logger.debug("Creating Cache for Neutron Networks");\r
-        try {\r
-            // neutron caches\r
-            this.clusterContainerService.createCache("neutronNetworks",\r
-                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
-        } catch (CacheConfigException cce) {\r
-            logger.error("Cache couldn't be created for Neutron Networks -  check cache mode");\r
-        } catch (CacheExistException cce) {\r
-            logger.error("Cache for Neutron Networks already exists, destroy and recreate");\r
-        }\r
-        logger.debug("Cache successfully created for Neutron Networks");\r
-    }\r
-\r
-    @SuppressWarnings({ "unchecked", "deprecation" })\r
-    private void retrieveCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
-            return;\r
-        }\r
-        logger.debug("Retrieving cache for Neutron Networks");\r
-        networkDB = (ConcurrentMap<String, NeutronNetwork>) this.clusterContainerService.getCache("neutronNetworks");\r
-        if (networkDB == null) {\r
-            logger.error("Cache couldn't be retrieved for Neutron Networks");\r
-        }\r
-        logger.debug("Cache was successfully retrieved for Neutron Networks");\r
-    }\r
-\r
-    private void startUp() {\r
-        allocateCache();\r
-        retrieveCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when all the required\r
-     * dependencies are satisfied\r
-     *\r
-     */\r
-    void init(Component c) {\r
-        Dictionary<?, ?> props = c.getServiceProperties();\r
-        if (props != null) {\r
-            this.containerName = (String) props.get("containerName");\r
-            logger.debug("Running containerName: {}", this.containerName);\r
-        } else {\r
-            // In the Global instance case the containerName is empty\r
-            this.containerName = "";\r
-        }\r
-        startUp();\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void destroyCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterMger, can't destroy cache");\r
-            return;\r
-        }\r
-        logger.debug("Destroying Cache for Neutron Networks");\r
-        this.clusterContainerService.destroyCache("Neutron Networks");\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when at least one dependency\r
-     * become unsatisfied or when the component is shutting down because for\r
-     * example bundle is being stopped.\r
-     *\r
-     */\r
-    void destroy() {\r
-        destroyCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by dependency manager after "init ()" is called and after\r
-     * the services provided by the class are registered in the service registry\r
-     *\r
-     */\r
-    void start() {\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager before the services exported by\r
-     * the component are unregistered, this will be followed by a "destroy ()"\r
-     * calls\r
-     *\r
-     */\r
-    void stop() {\r
-    }\r
-\r
-    // this method uses reflection to update an object from it's delta.\r
-\r
-    private boolean overwrite(Object target, Object delta) {\r
-        Method[] methods = target.getClass().getMethods();\r
-\r
-        for(Method toMethod: methods){\r
-            if(toMethod.getDeclaringClass().equals(target.getClass())\r
-                    && toMethod.getName().startsWith("set")){\r
-\r
-                String toName = toMethod.getName();\r
-                String fromName = toName.replace("set", "get");\r
-\r
-                try {\r
-                    Method fromMethod = delta.getClass().getMethod(fromName);\r
-                    Object value = fromMethod.invoke(delta, (Object[])null);\r
-                    if(value != null){\r
-                        toMethod.invoke(target, value);\r
-                    }\r
-                } catch (Exception e) {\r
-                    e.printStackTrace();\r
-                    return false;\r
-                }\r
-            }\r
-        }\r
-        return true;\r
-    }\r
-\r
-    // IfNBNetworkCRUD methods\r
-\r
-    public boolean networkExists(String uuid) {\r
-        return networkDB.containsKey(uuid);\r
-    }\r
-\r
-    public NeutronNetwork getNetwork(String uuid) {\r
-        if (!networkExists(uuid))\r
-            return null;\r
-        return networkDB.get(uuid);\r
-    }\r
-\r
-    public List<NeutronNetwork> getAllNetworks() {\r
-        Set<NeutronNetwork> allNetworks = new HashSet<NeutronNetwork>();\r
-        for (Entry<String, NeutronNetwork> entry : networkDB.entrySet()) {\r
-            NeutronNetwork network = entry.getValue();\r
-            allNetworks.add(network);\r
-        }\r
-        logger.debug("Exiting getAllNetworks, Found {} OpenStackNetworks", allNetworks.size());\r
-        List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();\r
-        ans.addAll(allNetworks);\r
-        return ans;\r
-    }\r
-\r
-    public boolean addNetwork(NeutronNetwork input) {\r
-        if (networkExists(input.getID()))\r
-            return false;\r
-        networkDB.putIfAbsent(input.getID(), input);\r
-      //TODO: add code to find INeutronNetworkAware services and call newtorkCreated on them\r
-        return true;\r
-    }\r
-\r
-    public boolean removeNetwork(String uuid) {\r
-        if (!networkExists(uuid))\r
-            return false;\r
-        networkDB.remove(uuid);\r
-      //TODO: add code to find INeutronNetworkAware services and call newtorkDeleted on them\r
-        return true;\r
-    }\r
-\r
-    public boolean updateNetwork(String uuid, NeutronNetwork delta) {\r
-        if (!networkExists(uuid))\r
-            return false;\r
-        NeutronNetwork target = networkDB.get(uuid);\r
-        return overwrite(target, delta);\r
-    }\r
-\r
-    public boolean networkInUse(String netUUID) {\r
-        if (!networkExists(netUUID))\r
-            return true;\r
-        NeutronNetwork target = networkDB.get(netUUID);\r
-        if (target.getPortsOnNetwork().size() > 0)\r
-            return true;\r
-        return false;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronNetworkInterface implements INeutronNetworkCRUD {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronNetworkInterface.class);
+    private String containerName = null;
+
+    private ConcurrentMap<String, NeutronNetwork> networkDB;
+    private IClusterContainerServices clusterContainerService = null;
+
+    // methods needed for creating caches
+
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        this.clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (this.clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            this.clusterContainerService = null;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron Networks");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronNetworks",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron Networks -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron Networks already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for Neutron Networks");
+    }
+
+    @SuppressWarnings({ "unchecked", "deprecation" })
+    private void retrieveCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+        logger.debug("Retrieving cache for Neutron Networks");
+        networkDB = (ConcurrentMap<String, NeutronNetwork>) this.clusterContainerService.getCache("neutronNetworks");
+        if (networkDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Networks");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Networks");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    @SuppressWarnings("deprecation")
+    private void destroyCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for Neutron Networks");
+        this.clusterContainerService.destroyCache("Neutron Networks");
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for(Method toMethod: methods){
+            if(toMethod.getDeclaringClass().equals(target.getClass())
+                    && toMethod.getName().startsWith("set")){
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    if(value != null){
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    // IfNBNetworkCRUD methods
+
+    public boolean networkExists(String uuid) {
+        return networkDB.containsKey(uuid);
+    }
+
+    public NeutronNetwork getNetwork(String uuid) {
+        if (!networkExists(uuid))
+            return null;
+        return networkDB.get(uuid);
+    }
+
+    public List<NeutronNetwork> getAllNetworks() {
+        Set<NeutronNetwork> allNetworks = new HashSet<NeutronNetwork>();
+        for (Entry<String, NeutronNetwork> entry : networkDB.entrySet()) {
+            NeutronNetwork network = entry.getValue();
+            allNetworks.add(network);
+        }
+        logger.debug("Exiting getAllNetworks, Found {} OpenStackNetworks", allNetworks.size());
+        List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();
+        ans.addAll(allNetworks);
+        return ans;
+    }
+
+    public boolean addNetwork(NeutronNetwork input) {
+        if (networkExists(input.getID()))
+            return false;
+        networkDB.putIfAbsent(input.getID(), input);
+      //TODO: add code to find INeutronNetworkAware services and call newtorkCreated on them
+        return true;
+    }
+
+    public boolean removeNetwork(String uuid) {
+        if (!networkExists(uuid))
+            return false;
+        networkDB.remove(uuid);
+      //TODO: add code to find INeutronNetworkAware services and call newtorkDeleted on them
+        return true;
+    }
+
+    public boolean updateNetwork(String uuid, NeutronNetwork delta) {
+        if (!networkExists(uuid))
+            return false;
+        NeutronNetwork target = networkDB.get(uuid);
+        return overwrite(target, delta);
+    }
+
+    public boolean networkInUse(String netUUID) {
+        if (!networkExists(netUUID))
+            return true;
+        NeutronNetwork target = networkDB.get(netUUID);
+        if (target.getPortsOnNetwork().size() > 0)
+            return true;
+        return false;
+    }
+}
index 273d4209533112d181f106e490a9b459e9477b2a..fd030e178bd021cb8ec4ccfcb14c1877d89b172a 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronPortInterface implements INeutronPortCRUD {\r
-    private static final Logger logger = LoggerFactory.getLogger(NeutronPortInterface.class);\r
-    private String containerName = null;\r
-\r
-    private IClusterContainerServices clusterContainerService = null;\r
-    private ConcurrentMap<String, NeutronPort> portDB;\r
-\r
-    // methods needed for creating caches\r
-\r
-    void setClusterContainerService(IClusterContainerServices s) {\r
-        logger.debug("Cluster Service set");\r
-        this.clusterContainerService = s;\r
-    }\r
-\r
-    void unsetClusterContainerService(IClusterContainerServices s) {\r
-        if (this.clusterContainerService == s) {\r
-            logger.debug("Cluster Service removed!");\r
-            this.clusterContainerService = null;\r
-        }\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void allocateCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't create cache");\r
-            return;\r
-        }\r
-        logger.debug("Creating Cache for OpenDOVE");\r
-        try {\r
-            // neutron caches\r
-            this.clusterContainerService.createCache("neutronPorts",\r
-                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
-        } catch (CacheConfigException cce) {\r
-            logger.error("Cache couldn't be created for OpenDOVE -  check cache mode");\r
-        } catch (CacheExistException cce) {\r
-            logger.error("Cache for OpenDOVE already exists, destroy and recreate");\r
-        }\r
-        logger.debug("Cache successfully created for OpenDOVE");\r
-    }\r
-\r
-    @SuppressWarnings({ "unchecked", "deprecation" })\r
-    private void retrieveCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
-            return;\r
-        }\r
-\r
-        logger.debug("Retrieving cache for Neutron Ports");\r
-        portDB = (ConcurrentMap<String, NeutronPort>) this.clusterContainerService\r
-        .getCache("neutronPorts");\r
-        if (portDB == null) {\r
-            logger.error("Cache couldn't be retrieved for Neutron Ports");\r
-        }\r
-        logger.debug("Cache was successfully retrieved for Neutron Ports");\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void destroyCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterMger, can't destroy cache");\r
-            return;\r
-        }\r
-        logger.debug("Destroying Cache for HostTracker");\r
-        this.clusterContainerService.destroyCache("neutronPorts");\r
-    }\r
-\r
-    private void startUp() {\r
-        allocateCache();\r
-        retrieveCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when all the required\r
-     * dependencies are satisfied\r
-     *\r
-     */\r
-    void init(Component c) {\r
-        Dictionary<?, ?> props = c.getServiceProperties();\r
-        if (props != null) {\r
-            this.containerName = (String) props.get("containerName");\r
-            logger.debug("Running containerName: {}", this.containerName);\r
-        } else {\r
-            // In the Global instance case the containerName is empty\r
-            this.containerName = "";\r
-        }\r
-        startUp();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when at least one dependency\r
-     * become unsatisfied or when the component is shutting down because for\r
-     * example bundle is being stopped.\r
-     *\r
-     */\r
-    void destroy() {\r
-        destroyCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by dependency manager after "init ()" is called and after\r
-     * the services provided by the class are registered in the service registry\r
-     *\r
-     */\r
-    void start() {\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager before the services exported by\r
-     * the component are unregistered, this will be followed by a "destroy ()"\r
-     * calls\r
-     *\r
-     */\r
-    void stop() {\r
-    }\r
-\r
-    // this method uses reflection to update an object from it's delta.\r
-\r
-    private boolean overwrite(Object target, Object delta) {\r
-        Method[] methods = target.getClass().getMethods();\r
-\r
-        for(Method toMethod: methods){\r
-            if(toMethod.getDeclaringClass().equals(target.getClass())\r
-                    && toMethod.getName().startsWith("set")){\r
-\r
-                String toName = toMethod.getName();\r
-                String fromName = toName.replace("set", "get");\r
-\r
-                try {\r
-                    Method fromMethod = delta.getClass().getMethod(fromName);\r
-                    Object value = fromMethod.invoke(delta, (Object[])null);\r
-                    if(value != null){\r
-                        toMethod.invoke(target, value);\r
-                    }\r
-                } catch (Exception e) {\r
-                    e.printStackTrace();\r
-                    return false;\r
-                }\r
-            }\r
-        }\r
-        return true;\r
-    }\r
-\r
-    // IfNBPortCRUD methods\r
-\r
-    public boolean portExists(String uuid) {\r
-        return portDB.containsKey(uuid);\r
-    }\r
-\r
-    public NeutronPort getPort(String uuid) {\r
-        if (!portExists(uuid))\r
-            return null;\r
-        return portDB.get(uuid);\r
-    }\r
-\r
-    public List<NeutronPort> getAllPorts() {\r
-        Set<NeutronPort> allPorts = new HashSet<NeutronPort>();\r
-        for (Entry<String, NeutronPort> entry : portDB.entrySet()) {\r
-            NeutronPort port = entry.getValue();\r
-            allPorts.add(port);\r
-        }\r
-        logger.debug("Exiting getAllPorts, Found {} OpenStackPorts", allPorts.size());\r
-        List<NeutronPort> ans = new ArrayList<NeutronPort>();\r
-        ans.addAll(allPorts);\r
-        return ans;\r
-    }\r
-\r
-    public boolean addPort(NeutronPort input) {\r
-        if (portExists(input.getID()))\r
-            return false;\r
-        portDB.putIfAbsent(input.getID(), input);\r
-        // if there are no fixed IPs, allocate one for each subnet in the network\r
-        INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        if (input.getFixedIPs().size() == 0) {\r
-            List<Neutron_IPs> list = input.getFixedIPs();\r
-            Iterator<NeutronSubnet> subnetIterator = systemCRUD.getAllSubnets().iterator();\r
-            while (subnetIterator.hasNext()) {\r
-                NeutronSubnet subnet = subnetIterator.next();\r
-                if (subnet.getNetworkUUID().equals(input.getNetworkUUID()))\r
-                    list.add(new Neutron_IPs(subnet.getID()));\r
-            }\r
-        }\r
-        Iterator<Neutron_IPs> fixedIPIterator = input.getFixedIPs().iterator();\r
-        while (fixedIPIterator.hasNext()) {\r
-            Neutron_IPs ip = fixedIPIterator.next();\r
-            NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
-            if (ip.getIpAddress() == null)\r
-                ip.setIpAddress(subnet.getLowAddr());\r
-            if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {\r
-                subnet.allocateIP(ip.getIpAddress());\r
-            }\r
-            else {\r
-                subnet.setGatewayIPAllocated();\r
-            }\r
-            subnet.addPort(input);\r
-        }\r
-        INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-\r
-        NeutronNetwork network = networkIf.getNetwork(input.getNetworkUUID());\r
-        network.addPort(input);\r
-        return true;\r
-    }\r
-\r
-    public boolean removePort(String uuid) {\r
-        if (!portExists(uuid))\r
-            return false;\r
-        NeutronPort port = getPort(uuid);\r
-        portDB.remove(uuid);\r
-        INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-        INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-\r
-        NeutronNetwork network = networkCRUD.getNetwork(port.getNetworkUUID());\r
-        network.removePort(port);\r
-        Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
-        while (fixedIPIterator.hasNext()) {\r
-            Neutron_IPs ip = fixedIPIterator.next();\r
-            NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
-            if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {\r
-                subnet.releaseIP(ip.getIpAddress());\r
-            }\r
-            else {\r
-                subnet.resetGatewayIPAllocated();\r
-            }\r
-            subnet.removePort(port);\r
-        }\r
-        return true;\r
-    }\r
-\r
-    public boolean updatePort(String uuid, NeutronPort delta) {\r
-        if (!portExists(uuid))\r
-            return false;\r
-        NeutronPort target = portDB.get(uuid);\r
-        // remove old Fixed_IPs\r
-        NeutronPort port = getPort(uuid);\r
-        INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
-        while (fixedIPIterator.hasNext()) {\r
-            Neutron_IPs ip = fixedIPIterator.next();\r
-            NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
-            subnet.releaseIP(ip.getIpAddress());\r
-        }\r
-\r
-        // allocate new Fixed_IPs\r
-        fixedIPIterator = delta.getFixedIPs().iterator();\r
-        while (fixedIPIterator.hasNext()) {\r
-            Neutron_IPs ip = fixedIPIterator.next();\r
-            NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
-            if (ip.getIpAddress() == null)\r
-                ip.setIpAddress(subnet.getLowAddr());\r
-            subnet.allocateIP(ip.getIpAddress());\r
-        }\r
-        return overwrite(target, delta);\r
-    }\r
-\r
-    public boolean macInUse(String macAddress) {\r
-        List<NeutronPort> ports = getAllPorts();\r
-        Iterator<NeutronPort> portIterator = ports.iterator();\r
-        while (portIterator.hasNext()) {\r
-            NeutronPort port = portIterator.next();\r
-            if (macAddress.equalsIgnoreCase(port.getMacAddress()))\r
-                return true;\r
-        }\r
-        return false;\r
-    }\r
-\r
-    public NeutronPort getGatewayPort(String subnetUUID) {\r
-        INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        NeutronSubnet subnet = systemCRUD.getSubnet(subnetUUID);\r
-        Iterator<NeutronPort> portIterator = getAllPorts().iterator();\r
-        while (portIterator.hasNext()) {\r
-            NeutronPort port = portIterator.next();\r
-            List<Neutron_IPs> fixedIPs = port.getFixedIPs();\r
-            if (fixedIPs.size() == 1) {\r
-                if (subnet.getGatewayIP().equals(fixedIPs.get(0).getIpAddress()))\r
-                    return port;\r
-            }\r
-        }\r
-        return null;\r
-    }\r
-\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronPortInterface implements INeutronPortCRUD {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronPortInterface.class);
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private ConcurrentMap<String, NeutronPort> portDB;
+
+    // methods needed for creating caches
+
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            clusterContainerService = null;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void allocateCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for OpenDOVE");
+        try {
+            // neutron caches
+            clusterContainerService.createCache("neutronPorts",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for OpenDOVE -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for OpenDOVE already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for OpenDOVE");
+    }
+
+    @SuppressWarnings({ "unchecked", "deprecation" })
+    private void retrieveCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron Ports");
+        portDB = (ConcurrentMap<String, NeutronPort>) clusterContainerService
+        .getCache("neutronPorts");
+        if (portDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Ports");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Ports");
+    }
+
+    @SuppressWarnings("deprecation")
+    private void destroyCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for HostTracker");
+        clusterContainerService.destroyCache("neutronPorts");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for(Method toMethod: methods){
+            if(toMethod.getDeclaringClass().equals(target.getClass())
+                    && toMethod.getName().startsWith("set")){
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    if(value != null){
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    // IfNBPortCRUD methods
+
+    @Override
+    public boolean portExists(String uuid) {
+        return portDB.containsKey(uuid);
+    }
+
+    @Override
+    public NeutronPort getPort(String uuid) {
+        if (!portExists(uuid)) {
+            return null;
+        }
+        return portDB.get(uuid);
+    }
+
+    @Override
+    public List<NeutronPort> getAllPorts() {
+        Set<NeutronPort> allPorts = new HashSet<NeutronPort>();
+        for (Entry<String, NeutronPort> entry : portDB.entrySet()) {
+            NeutronPort port = entry.getValue();
+            allPorts.add(port);
+        }
+        logger.debug("Exiting getAllPorts, Found {} OpenStackPorts", allPorts.size());
+        List<NeutronPort> ans = new ArrayList<NeutronPort>();
+        ans.addAll(allPorts);
+        return ans;
+    }
+
+    @Override
+    public boolean addPort(NeutronPort input) {
+        if (portExists(input.getID())) {
+            return false;
+        }
+        portDB.putIfAbsent(input.getID(), input);
+        // if there are no fixed IPs, allocate one for each subnet in the network
+        INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+        if (input.getFixedIPs().size() == 0) {
+            List<Neutron_IPs> list = input.getFixedIPs();
+            Iterator<NeutronSubnet> subnetIterator = systemCRUD.getAllSubnets().iterator();
+            while (subnetIterator.hasNext()) {
+                NeutronSubnet subnet = subnetIterator.next();
+                if (subnet.getNetworkUUID().equals(input.getNetworkUUID())) {
+                    list.add(new Neutron_IPs(subnet.getID()));
+                }
+            }
+        }
+        Iterator<Neutron_IPs> fixedIPIterator = input.getFixedIPs().iterator();
+        while (fixedIPIterator.hasNext()) {
+            Neutron_IPs ip = fixedIPIterator.next();
+            NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());
+            if (ip.getIpAddress() == null) {
+                ip.setIpAddress(subnet.getLowAddr());
+            }
+            if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {
+                subnet.allocateIP(ip.getIpAddress());
+            }
+            else {
+                subnet.setGatewayIPAllocated();
+            }
+            subnet.addPort(input);
+        }
+        INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+
+        NeutronNetwork network = networkIf.getNetwork(input.getNetworkUUID());
+        network.addPort(input);
+        return true;
+    }
+
+    @Override
+    public boolean removePort(String uuid) {
+        if (!portExists(uuid)) {
+            return false;
+        }
+        NeutronPort port = getPort(uuid);
+        portDB.remove(uuid);
+        INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+        INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+
+        NeutronNetwork network = networkCRUD.getNetwork(port.getNetworkUUID());
+        network.removePort(port);
+        Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();
+        while (fixedIPIterator.hasNext()) {
+            Neutron_IPs ip = fixedIPIterator.next();
+            NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());
+            if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {
+                subnet.releaseIP(ip.getIpAddress());
+            }
+            else {
+                subnet.resetGatewayIPAllocated();
+            }
+            subnet.removePort(port);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean updatePort(String uuid, NeutronPort delta) {
+        if (!portExists(uuid)) {
+            return false;
+        }
+        NeutronPort target = portDB.get(uuid);
+        // remove old Fixed_IPs
+        if (delta.getFixedIPs() != null) {
+            NeutronPort port = getPort(uuid);
+            INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+            for (Neutron_IPs ip: port.getFixedIPs()) {
+                NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());
+                subnet.releaseIP(ip.getIpAddress());
+            }
+
+            // allocate new Fixed_IPs
+            for (Neutron_IPs ip: delta.getFixedIPs()) {
+                NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());
+                if (ip.getIpAddress() == null) {
+                    ip.setIpAddress(subnet.getLowAddr());
+                }
+                subnet.allocateIP(ip.getIpAddress());
+            }
+        }
+        return overwrite(target, delta);
+    }
+
+    @Override
+    public boolean macInUse(String macAddress) {
+        List<NeutronPort> ports = getAllPorts();
+        Iterator<NeutronPort> portIterator = ports.iterator();
+        while (portIterator.hasNext()) {
+            NeutronPort port = portIterator.next();
+            if (macAddress.equalsIgnoreCase(port.getMacAddress())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public NeutronPort getGatewayPort(String subnetUUID) {
+        INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+        NeutronSubnet subnet = systemCRUD.getSubnet(subnetUUID);
+        Iterator<NeutronPort> portIterator = getAllPorts().iterator();
+        while (portIterator.hasNext()) {
+            NeutronPort port = portIterator.next();
+            List<Neutron_IPs> fixedIPs = port.getFixedIPs();
+            if (fixedIPs.size() == 1) {
+                if (subnet.getGatewayIP().equals(fixedIPs.get(0).getIpAddress())) {
+                    return port;
+                }
+            }
+        }
+        return null;
+    }
+
+}
index 0a7afa562c2d5365cb52dabc6dfd34f975aad678..0e64dc5a098284640bb9d242a68e3649e100cf5e 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronRouterInterface implements INeutronRouterCRUD {\r
-    private static final Logger logger = LoggerFactory.getLogger(NeutronRouterInterface.class);\r
-    private String containerName = null;\r
-\r
-    private IClusterContainerServices clusterContainerService = null;\r
-    private ConcurrentMap<String, NeutronRouter> routerDB;\r
-    // methods needed for creating caches\r
-\r
-    void setClusterContainerService(IClusterContainerServices s) {\r
-        logger.debug("Cluster Service set");\r
-        this.clusterContainerService = s;\r
-    }\r
-\r
-    void unsetClusterContainerService(IClusterContainerServices s) {\r
-        if (this.clusterContainerService == s) {\r
-            logger.debug("Cluster Service removed!");\r
-            this.clusterContainerService = null;\r
-        }\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void allocateCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't create cache");\r
-            return;\r
-        }\r
-        logger.debug("Creating Cache for Neutron Routers");\r
-        try {\r
-            // neutron caches\r
-            this.clusterContainerService.createCache("neutronRouters",\r
-                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
-        } catch (CacheConfigException cce) {\r
-            logger.error("Cache couldn't be created for Neutron Routers -  check cache mode");\r
-        } catch (CacheExistException cce) {\r
-            logger.error("Cache for Neutron Routers already exists, destroy and recreate");\r
-        }\r
-        logger.debug("Cache successfully created for Neutron Routers");\r
-    }\r
-\r
-    @SuppressWarnings({ "unchecked", "deprecation" })\r
-    private void retrieveCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
-            return;\r
-        }\r
-\r
-        logger.debug("Retrieving cache for Neutron Routers");\r
-        routerDB = (ConcurrentMap<String, NeutronRouter>) this.clusterContainerService\r
-        .getCache("neutronRouters");\r
-        if (routerDB == null) {\r
-            logger.error("Cache couldn't be retrieved for Neutron Routers");\r
-        }\r
-        logger.debug("Cache was successfully retrieved for Neutron Routers");\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void destroyCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterMger, can't destroy cache");\r
-            return;\r
-        }\r
-        logger.debug("Destroying Cache for HostTracker");\r
-        this.clusterContainerService.destroyCache("neutronRouters");\r
-    }\r
-\r
-    private void startUp() {\r
-        allocateCache();\r
-        retrieveCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when all the required\r
-     * dependencies are satisfied\r
-     *\r
-     */\r
-    void init(Component c) {\r
-        Dictionary<?, ?> props = c.getServiceProperties();\r
-        if (props != null) {\r
-            this.containerName = (String) props.get("containerName");\r
-            logger.debug("Running containerName: {}", this.containerName);\r
-        } else {\r
-            // In the Global instance case the containerName is empty\r
-            this.containerName = "";\r
-        }\r
-        startUp();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when at least one dependency\r
-     * become unsatisfied or when the component is shutting down because for\r
-     * example bundle is being stopped.\r
-     *\r
-     */\r
-    void destroy() {\r
-        destroyCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by dependency manager after "init ()" is called and after\r
-     * the services provided by the class are registered in the service registry\r
-     *\r
-     */\r
-    void start() {\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager before the services exported by\r
-     * the component are unregistered, this will be followed by a "destroy ()"\r
-     * calls\r
-     *\r
-     */\r
-    void stop() {\r
-    }\r
-\r
-    // this method uses reflection to update an object from it's delta.\r
-\r
-    private boolean overwrite(Object target, Object delta) {\r
-        Method[] methods = target.getClass().getMethods();\r
-\r
-        for(Method toMethod: methods){\r
-            if(toMethod.getDeclaringClass().equals(target.getClass())\r
-                    && toMethod.getName().startsWith("set")){\r
-\r
-                String toName = toMethod.getName();\r
-                String fromName = toName.replace("set", "get");\r
-\r
-                try {\r
-                    Method fromMethod = delta.getClass().getMethod(fromName);\r
-                    Object value = fromMethod.invoke(delta, (Object[])null);\r
-                    if(value != null){\r
-                        toMethod.invoke(target, value);\r
-                    }\r
-                } catch (Exception e) {\r
-                    e.printStackTrace();\r
-                    return false;\r
-                }\r
-            }\r
-        }\r
-        return true;\r
-    }\r
-\r
-\r
-    // IfNBRouterCRUD Interface methods\r
-\r
-    public boolean routerExists(String uuid) {\r
-        return routerDB.containsKey(uuid);\r
-    }\r
-\r
-    public NeutronRouter getRouter(String uuid) {\r
-        if (!routerExists(uuid))\r
-            return null;\r
-        return routerDB.get(uuid);\r
-    }\r
-\r
-    public List<NeutronRouter> getAllRouters() {\r
-        Set<NeutronRouter> allRouters = new HashSet<NeutronRouter>();\r
-        for (Entry<String, NeutronRouter> entry : routerDB.entrySet()) {\r
-            NeutronRouter router = entry.getValue();\r
-            allRouters.add(router);\r
-        }\r
-        logger.debug("Exiting getAllRouters, Found {} Routers", allRouters.size());\r
-        List<NeutronRouter> ans = new ArrayList<NeutronRouter>();\r
-        ans.addAll(allRouters);\r
-        return ans;\r
-    }\r
-\r
-    public boolean addRouter(NeutronRouter input) {\r
-        if (routerExists(input.getID()))\r
-            return false;\r
-        routerDB.putIfAbsent(input.getID(), input);\r
-        return true;\r
-    }\r
-\r
-    public boolean removeRouter(String uuid) {\r
-        if (!routerExists(uuid))\r
-            return false;\r
-        routerDB.remove(uuid);\r
-        return true;\r
-    }\r
-\r
-    public boolean updateRouter(String uuid, NeutronRouter delta) {\r
-        if (!routerExists(uuid))\r
-            return false;\r
-        NeutronRouter target = routerDB.get(uuid);\r
-        return overwrite(target, delta);\r
-    }\r
-\r
-    public boolean routerInUse(String routerUUID) {\r
-        if (!routerExists(routerUUID))\r
-            return true;\r
-        NeutronRouter target = routerDB.get(routerUUID);\r
-        return (target.getInterfaces().size() > 0);\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronRouterInterface implements INeutronRouterCRUD {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronRouterInterface.class);
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private ConcurrentMap<String, NeutronRouter> routerDB;
+    // methods needed for creating caches
+
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        this.clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (this.clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            this.clusterContainerService = null;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron Routers");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronRouters",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron Routers -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron Routers already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for Neutron Routers");
+    }
+
+    @SuppressWarnings({ "unchecked", "deprecation" })
+    private void retrieveCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron Routers");
+        routerDB = (ConcurrentMap<String, NeutronRouter>) this.clusterContainerService
+        .getCache("neutronRouters");
+        if (routerDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Routers");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Routers");
+    }
+
+    @SuppressWarnings("deprecation")
+    private void destroyCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for HostTracker");
+        this.clusterContainerService.destroyCache("neutronRouters");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for(Method toMethod: methods){
+            if(toMethod.getDeclaringClass().equals(target.getClass())
+                    && toMethod.getName().startsWith("set")){
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    if(value != null){
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+
+    // IfNBRouterCRUD Interface methods
+
+    public boolean routerExists(String uuid) {
+        return routerDB.containsKey(uuid);
+    }
+
+    public NeutronRouter getRouter(String uuid) {
+        if (!routerExists(uuid))
+            return null;
+        return routerDB.get(uuid);
+    }
+
+    public List<NeutronRouter> getAllRouters() {
+        Set<NeutronRouter> allRouters = new HashSet<NeutronRouter>();
+        for (Entry<String, NeutronRouter> entry : routerDB.entrySet()) {
+            NeutronRouter router = entry.getValue();
+            allRouters.add(router);
+        }
+        logger.debug("Exiting getAllRouters, Found {} Routers", allRouters.size());
+        List<NeutronRouter> ans = new ArrayList<NeutronRouter>();
+        ans.addAll(allRouters);
+        return ans;
+    }
+
+    public boolean addRouter(NeutronRouter input) {
+        if (routerExists(input.getID()))
+            return false;
+        routerDB.putIfAbsent(input.getID(), input);
+        return true;
+    }
+
+    public boolean removeRouter(String uuid) {
+        if (!routerExists(uuid))
+            return false;
+        routerDB.remove(uuid);
+        return true;
+    }
+
+    public boolean updateRouter(String uuid, NeutronRouter delta) {
+        if (!routerExists(uuid))
+            return false;
+        NeutronRouter target = routerDB.get(uuid);
+        return overwrite(target, delta);
+    }
+
+    public boolean routerInUse(String routerUUID) {
+        if (!routerExists(routerUUID))
+            return true;
+        NeutronRouter target = routerDB.get(routerUUID);
+        return (target.getInterfaces().size() > 0);
+    }
+}
index 0fc333723a61874f17c7d2409a80a928adc36c98..62ef64c74c705fe8d0fb0f92c913d750157ece9c 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronSubnetInterface implements INeutronSubnetCRUD {\r
-    private static final Logger logger = LoggerFactory.getLogger(NeutronSubnetInterface.class);\r
-    private String containerName = null;\r
-\r
-    private IClusterContainerServices clusterContainerService = null;\r
-    private ConcurrentMap<String, NeutronSubnet> subnetDB;\r
-\r
-    // methods needed for creating caches\r
-\r
-    void setClusterContainerService(IClusterContainerServices s) {\r
-        logger.debug("Cluster Service set");\r
-        this.clusterContainerService = s;\r
-    }\r
-\r
-    void unsetClusterContainerService(IClusterContainerServices s) {\r
-        if (this.clusterContainerService == s) {\r
-            logger.debug("Cluster Service removed!");\r
-            this.clusterContainerService = null;\r
-        }\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void allocateCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't create cache");\r
-            return;\r
-        }\r
-        logger.debug("Creating Cache for Neutron Subnets");\r
-        try {\r
-            // neutron caches\r
-            this.clusterContainerService.createCache("neutronSubnets",\r
-                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
-        } catch (CacheConfigException cce) {\r
-            logger.error("Cache couldn't be created for Neutron Subnets -  check cache mode");\r
-        } catch (CacheExistException cce) {\r
-            logger.error("Cache for Neutron Subnets already exists, destroy and recreate");\r
-        }\r
-        logger.debug("Cache successfully created for Neutron Subnets");\r
-    }\r
-\r
-    @SuppressWarnings({ "unchecked", "deprecation" })\r
-    private void retrieveCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
-            return;\r
-        }\r
-\r
-        logger.debug("Retrieving cache for Neutron Subnets");\r
-        subnetDB = (ConcurrentMap<String, NeutronSubnet>) this.clusterContainerService\r
-        .getCache("neutronSubnets");\r
-        if (subnetDB == null) {\r
-            logger.error("Cache couldn't be retrieved for Neutron Subnets");\r
-        }\r
-        logger.debug("Cache was successfully retrieved for Neutron Subnets");\r
-    }\r
-\r
-    @SuppressWarnings("deprecation")\r
-    private void destroyCache() {\r
-        if (this.clusterContainerService == null) {\r
-            logger.error("un-initialized clusterMger, can't destroy cache");\r
-            return;\r
-        }\r
-        logger.debug("Destroying Cache for HostTracker");\r
-        this.clusterContainerService.destroyCache("neutronSubnets");\r
-    }\r
-\r
-    private void startUp() {\r
-        allocateCache();\r
-        retrieveCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when all the required\r
-     * dependencies are satisfied\r
-     *\r
-     */\r
-    void init(Component c) {\r
-        Dictionary<?, ?> props = c.getServiceProperties();\r
-        if (props != null) {\r
-            this.containerName = (String) props.get("containerName");\r
-            logger.debug("Running containerName: {}", this.containerName);\r
-        } else {\r
-            // In the Global instance case the containerName is empty\r
-            this.containerName = "";\r
-        }\r
-        startUp();\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager when at least one dependency\r
-     * become unsatisfied or when the component is shutting down because for\r
-     * example bundle is being stopped.\r
-     *\r
-     */\r
-    void destroy() {\r
-        destroyCache();\r
-    }\r
-\r
-    /**\r
-     * Function called by dependency manager after "init ()" is called and after\r
-     * the services provided by the class are registered in the service registry\r
-     *\r
-     */\r
-    void start() {\r
-    }\r
-\r
-    /**\r
-     * Function called by the dependency manager before the services exported by\r
-     * the component are unregistered, this will be followed by a "destroy ()"\r
-     * calls\r
-     *\r
-     */\r
-    void stop() {\r
-    }\r
-\r
-    // this method uses reflection to update an object from it's delta.\r
-\r
-    private boolean overwrite(Object target, Object delta) {\r
-        Method[] methods = target.getClass().getMethods();\r
-\r
-        for(Method toMethod: methods){\r
-            if(toMethod.getDeclaringClass().equals(target.getClass())\r
-                    && toMethod.getName().startsWith("set")){\r
-\r
-                String toName = toMethod.getName();\r
-                String fromName = toName.replace("set", "get");\r
-\r
-                try {\r
-                    Method fromMethod = delta.getClass().getMethod(fromName);\r
-                    Object value = fromMethod.invoke(delta, (Object[])null);\r
-                    if(value != null){\r
-                        toMethod.invoke(target, value);\r
-                    }\r
-                } catch (Exception e) {\r
-                    e.printStackTrace();\r
-                    return false;\r
-                }\r
-            }\r
-        }\r
-        return true;\r
-    }\r
-\r
-\r
-    // IfNBSubnetCRUD methods\r
-\r
-    public boolean subnetExists(String uuid) {\r
-        return subnetDB.containsKey(uuid);\r
-    }\r
-\r
-    public NeutronSubnet getSubnet(String uuid) {\r
-        if (!subnetExists(uuid))\r
-            return null;\r
-        return subnetDB.get(uuid);\r
-    }\r
-\r
-    public List<NeutronSubnet> getAllSubnets() {\r
-        Set<NeutronSubnet> allSubnets = new HashSet<NeutronSubnet>();\r
-        for (Entry<String, NeutronSubnet> entry : subnetDB.entrySet()) {\r
-            NeutronSubnet subnet = entry.getValue();\r
-            allSubnets.add(subnet);\r
-        }\r
-        logger.debug("Exiting getAllSubnets, Found {} OpenStackSubnets", allSubnets.size());\r
-        List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();\r
-        ans.addAll(allSubnets);\r
-        return ans;\r
-    }\r
-\r
-    public boolean addSubnet(NeutronSubnet input) {\r
-        String id = input.getID();\r
-        if (subnetExists(id))\r
-            return false;\r
-        subnetDB.putIfAbsent(id, input);\r
-        INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-\r
-        NeutronNetwork targetNet = networkIf.getNetwork(input.getNetworkUUID());\r
-        targetNet.addSubnet(id);\r
-        return true;\r
-    }\r
-\r
-    public boolean removeSubnet(String uuid) {\r
-        if (!subnetExists(uuid))\r
-            return false;\r
-        NeutronSubnet target = subnetDB.get(uuid);\r
-        INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-\r
-        NeutronNetwork targetNet = networkIf.getNetwork(target.getNetworkUUID());\r
-        targetNet.removeSubnet(uuid);\r
-        subnetDB.remove(uuid);\r
-        return true;\r
-    }\r
-\r
-    public boolean updateSubnet(String uuid, NeutronSubnet delta) {\r
-        if (!subnetExists(uuid))\r
-            return false;\r
-        NeutronSubnet target = subnetDB.get(uuid);\r
-        return overwrite(target, delta);\r
-    }\r
-\r
-    public boolean subnetInUse(String subnetUUID) {\r
-        if (!subnetExists(subnetUUID))\r
-            return true;\r
-        NeutronSubnet target = subnetDB.get(subnetUUID);\r
-        return (target.getPortsInSubnet().size() > 0);\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronSubnetInterface implements INeutronSubnetCRUD {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronSubnetInterface.class);
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private ConcurrentMap<String, NeutronSubnet> subnetDB;
+
+    // methods needed for creating caches
+
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        this.clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (this.clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            this.clusterContainerService = null;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron Subnets");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronSubnets",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron Subnets -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron Subnets already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for Neutron Subnets");
+    }
+
+    @SuppressWarnings({ "unchecked", "deprecation" })
+    private void retrieveCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron Subnets");
+        subnetDB = (ConcurrentMap<String, NeutronSubnet>) this.clusterContainerService
+        .getCache("neutronSubnets");
+        if (subnetDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Subnets");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Subnets");
+    }
+
+    @SuppressWarnings("deprecation")
+    private void destroyCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for HostTracker");
+        this.clusterContainerService.destroyCache("neutronSubnets");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for(Method toMethod: methods){
+            if(toMethod.getDeclaringClass().equals(target.getClass())
+                    && toMethod.getName().startsWith("set")){
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    if(value != null){
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+
+    // IfNBSubnetCRUD methods
+
+    public boolean subnetExists(String uuid) {
+        return subnetDB.containsKey(uuid);
+    }
+
+    public NeutronSubnet getSubnet(String uuid) {
+        if (!subnetExists(uuid))
+            return null;
+        return subnetDB.get(uuid);
+    }
+
+    public List<NeutronSubnet> getAllSubnets() {
+        Set<NeutronSubnet> allSubnets = new HashSet<NeutronSubnet>();
+        for (Entry<String, NeutronSubnet> entry : subnetDB.entrySet()) {
+            NeutronSubnet subnet = entry.getValue();
+            allSubnets.add(subnet);
+        }
+        logger.debug("Exiting getAllSubnets, Found {} OpenStackSubnets", allSubnets.size());
+        List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();
+        ans.addAll(allSubnets);
+        return ans;
+    }
+
+    public boolean addSubnet(NeutronSubnet input) {
+        String id = input.getID();
+        if (subnetExists(id))
+            return false;
+        subnetDB.putIfAbsent(id, input);
+        INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+
+        NeutronNetwork targetNet = networkIf.getNetwork(input.getNetworkUUID());
+        targetNet.addSubnet(id);
+        return true;
+    }
+
+    public boolean removeSubnet(String uuid) {
+        if (!subnetExists(uuid))
+            return false;
+        NeutronSubnet target = subnetDB.get(uuid);
+        INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+
+        NeutronNetwork targetNet = networkIf.getNetwork(target.getNetworkUUID());
+        targetNet.removeSubnet(uuid);
+        subnetDB.remove(uuid);
+        return true;
+    }
+
+    public boolean updateSubnet(String uuid, NeutronSubnet delta) {
+        if (!subnetExists(uuid))
+            return false;
+        NeutronSubnet target = subnetDB.get(uuid);
+        return overwrite(target, delta);
+    }
+
+    public boolean subnetInUse(String subnetUUID) {
+        if (!subnetExists(subnetUUID))
+            return true;
+        NeutronSubnet target = subnetDB.get(subnetUUID);
+        return (target.getPortsInSubnet().size() > 0);
+    }
+}
index 05d50be818a8d2a50481d1f7f6e01e3d7dc2c8cf..43175d3236455e1d3f9f4a5df23b3e3e290e9ac0 100644 (file)
@@ -1,83 +1,83 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron FloatingIPs needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronFloatingIPAware {\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified floatingIP can be created\r
-     *\r
-     * @param floatingIP\r
-     *            instance of proposed new Neutron FloatingIP object\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the create operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canCreateFloatingIP(NeutronFloatingIP floatingIP);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a floatingIP has been created\r
-     *\r
-     * @param floatingIP\r
-     *            instance of new Neutron FloatingIP object\r
-     * @return void\r
-     */\r
-    public void neutronFloatingIPCreated(NeutronFloatingIP floatingIP);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified floatingIP can be changed using the specified\r
-     * delta\r
-     *\r
-     * @param delta\r
-     *            updates to the floatingIP object using patch semantics\r
-     * @param floatingIP\r
-     *            instance of the Neutron FloatingIP object to be updated\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the update operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canUpdateFloatingIP(NeutronFloatingIP delta, NeutronFloatingIP original);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a floatingIP has been updated\r
-     *\r
-     * @param floatingIP\r
-     *            instance of modified Neutron FloatingIP object\r
-     * @return void\r
-     */\r
-    public void neutronFloatingIPUpdated(NeutronFloatingIP floatingIP);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified floatingIP can be deleted\r
-     *\r
-     * @param floatingIP\r
-     *            instance of the Neutron FloatingIP object to be deleted\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the delete operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canDeleteFloatingIP(NeutronFloatingIP floatingIP);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a floatingIP has been deleted\r
-     *\r
-     * @param floatingIP\r
-     *            instance of deleted Neutron FloatingIP object\r
-     * @return void\r
-     */\r
-    public void neutronFloatingIPDeleted(NeutronFloatingIP floatingIP);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron FloatingIPs needs to implement
+ *
+ */
+
+public interface INeutronFloatingIPAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified floatingIP can be created
+     *
+     * @param floatingIP
+     *            instance of proposed new Neutron FloatingIP object
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the create operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canCreateFloatingIP(NeutronFloatingIP floatingIP);
+
+    /**
+     * Services provide this interface method for taking action after a floatingIP has been created
+     *
+     * @param floatingIP
+     *            instance of new Neutron FloatingIP object
+     * @return void
+     */
+    public void neutronFloatingIPCreated(NeutronFloatingIP floatingIP);
+
+    /**
+     * Services provide this interface method to indicate if the specified floatingIP can be changed using the specified
+     * delta
+     *
+     * @param delta
+     *            updates to the floatingIP object using patch semantics
+     * @param floatingIP
+     *            instance of the Neutron FloatingIP object to be updated
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the update operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canUpdateFloatingIP(NeutronFloatingIP delta, NeutronFloatingIP original);
+
+    /**
+     * Services provide this interface method for taking action after a floatingIP has been updated
+     *
+     * @param floatingIP
+     *            instance of modified Neutron FloatingIP object
+     * @return void
+     */
+    public void neutronFloatingIPUpdated(NeutronFloatingIP floatingIP);
+
+    /**
+     * Services provide this interface method to indicate if the specified floatingIP can be deleted
+     *
+     * @param floatingIP
+     *            instance of the Neutron FloatingIP object to be deleted
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the delete operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDeleteFloatingIP(NeutronFloatingIP floatingIP);
+
+    /**
+     * Services provide this interface method for taking action after a floatingIP has been deleted
+     *
+     * @param floatingIP
+     *            instance of deleted Neutron FloatingIP object
+     * @return void
+     */
+    public void neutronFloatingIPDeleted(NeutronFloatingIP floatingIP);
+}
index 7443deec6e9f97f19906574cd702b157918d3fc6..e416ee7d2f31efb450fc4c6795a687c95eb25591 100644 (file)
@@ -1,83 +1,83 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB FloatingIP objects\r
- *\r
- */\r
-\r
-public interface INeutronFloatingIPCRUD {\r
-    /**\r
-     * Applications call this interface method to determine if a particular\r
-     * FloatingIP object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the FloatingIP object\r
-     * @return boolean\r
-     */\r
-\r
-    public boolean floatingIPExists(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return if a particular\r
-     * FloatingIP object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the FloatingIP object\r
-     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP.OpenStackFloatingIPs}\r
-     *          OpenStack FloatingIP class\r
-     */\r
-\r
-    public NeutronFloatingIP getFloatingIP(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return all FloatingIP objects\r
-     *\r
-     * @return a Set of OpenStackFloatingIPs objects\r
-     */\r
-\r
-    public List<NeutronFloatingIP> getAllFloatingIPs();\r
-\r
-    /**\r
-     * Applications call this interface method to add a FloatingIP object to the\r
-     * concurrent map\r
-     *\r
-     * @param input\r
-     *            OpenStackFloatingIP object\r
-     * @return boolean on whether the object was added or not\r
-     */\r
-\r
-    public boolean addFloatingIP(NeutronFloatingIP input);\r
-\r
-    /**\r
-     * Applications call this interface method to remove a FloatingIP object to the\r
-     * concurrent map\r
-     *\r
-     * @param uuid\r
-     *            identifier for the FloatingIP object\r
-     * @return boolean on whether the object was removed or not\r
-     */\r
-\r
-    public boolean removeFloatingIP(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to edit a FloatingIP object\r
-     *\r
-     * @param uuid\r
-     *            identifier of the FloatingIP object\r
-     * @param delta\r
-     *            OpenStackFloatingIP object containing changes to apply\r
-     * @return boolean on whether the object was updated or not\r
-     */\r
-\r
-    public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB FloatingIP objects
+ *
+ */
+
+public interface INeutronFloatingIPCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     * FloatingIP object exists
+     *
+     * @param uuid
+     *            UUID of the FloatingIP object
+     * @return boolean
+     */
+
+    public boolean floatingIPExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * FloatingIP object exists
+     *
+     * @param uuid
+     *            UUID of the FloatingIP object
+     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP.OpenStackFloatingIPs}
+     *          OpenStack FloatingIP class
+     */
+
+    public NeutronFloatingIP getFloatingIP(String uuid);
+
+    /**
+     * Applications call this interface method to return all FloatingIP objects
+     *
+     * @return a Set of OpenStackFloatingIPs objects
+     */
+
+    public List<NeutronFloatingIP> getAllFloatingIPs();
+
+    /**
+     * Applications call this interface method to add a FloatingIP object to the
+     * concurrent map
+     *
+     * @param input
+     *            OpenStackFloatingIP object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addFloatingIP(NeutronFloatingIP input);
+
+    /**
+     * Applications call this interface method to remove a FloatingIP object to the
+     * concurrent map
+     *
+     * @param uuid
+     *            identifier for the FloatingIP object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeFloatingIP(String uuid);
+
+    /**
+     * Applications call this interface method to edit a FloatingIP object
+     *
+     * @param uuid
+     *            identifier of the FloatingIP object
+     * @param delta
+     *            OpenStackFloatingIP object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta);
+}
index dc6df25ab7dd3b4ed801acdc44f3916352389c30..88d3c1dc6e84726842361add116002fd035ebb24 100644 (file)
@@ -1,83 +1,83 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron Networks needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronNetworkAware {\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified network can be created\r
-     *\r
-     * @param network\r
-     *            instance of proposed new Neutron Network object\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the create operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canCreateNetwork(NeutronNetwork network);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a network has been created\r
-     *\r
-     * @param network\r
-     *            instance of new Neutron Network object\r
-     * @return void\r
-     */\r
-    public void neutronNetworkCreated(NeutronNetwork network);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified network can be changed using the specified\r
-     * delta\r
-     *\r
-     * @param delta\r
-     *            updates to the network object using patch semantics\r
-     * @param network\r
-     *            instance of the Neutron Network object to be updated\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the update operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canUpdateNetwork(NeutronNetwork delta, NeutronNetwork original);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a network has been updated\r
-     *\r
-     * @param network\r
-     *            instance of modified Neutron Network object\r
-     * @return void\r
-     */\r
-    public void neutronNetworkUpdated(NeutronNetwork network);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified network can be deleted\r
-     *\r
-     * @param network\r
-     *            instance of the Neutron Network object to be deleted\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the delete operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canDeleteNetwork(NeutronNetwork network);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a network has been deleted\r
-     *\r
-     * @param network\r
-     *            instance of deleted Neutron Network object\r
-     * @return void\r
-     */\r
-    public void neutronNetworkDeleted(NeutronNetwork network);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Networks needs to implement
+ *
+ */
+
+public interface INeutronNetworkAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified network can be created
+     *
+     * @param network
+     *            instance of proposed new Neutron Network object
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the create operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canCreateNetwork(NeutronNetwork network);
+
+    /**
+     * Services provide this interface method for taking action after a network has been created
+     *
+     * @param network
+     *            instance of new Neutron Network object
+     * @return void
+     */
+    public void neutronNetworkCreated(NeutronNetwork network);
+
+    /**
+     * Services provide this interface method to indicate if the specified network can be changed using the specified
+     * delta
+     *
+     * @param delta
+     *            updates to the network object using patch semantics
+     * @param network
+     *            instance of the Neutron Network object to be updated
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the update operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canUpdateNetwork(NeutronNetwork delta, NeutronNetwork original);
+
+    /**
+     * Services provide this interface method for taking action after a network has been updated
+     *
+     * @param network
+     *            instance of modified Neutron Network object
+     * @return void
+     */
+    public void neutronNetworkUpdated(NeutronNetwork network);
+
+    /**
+     * Services provide this interface method to indicate if the specified network can be deleted
+     *
+     * @param network
+     *            instance of the Neutron Network object to be deleted
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the delete operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDeleteNetwork(NeutronNetwork network);
+
+    /**
+     * Services provide this interface method for taking action after a network has been deleted
+     *
+     * @param network
+     *            instance of deleted Neutron Network object
+     * @return void
+     */
+    public void neutronNetworkDeleted(NeutronNetwork network);
+}
index 248153105c581ede84d083240664b7206694b212..bf900a618f1057c5fbc8babc12635cbec7045d37 100644 (file)
@@ -1,95 +1,95 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB network objects\r
- *\r
- */\r
-\r
-public interface INeutronNetworkCRUD {\r
-    /**\r
-     * Applications call this interface method to determine if a particular\r
-     * Network object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the Network object\r
-     * @return boolean\r
-     */\r
-\r
-    public boolean networkExists(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return if a particular\r
-     * Network object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the Network object\r
-     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronNetwork.OpenStackNetworks}\r
-     *          OpenStack Network class\r
-     */\r
-\r
-    public NeutronNetwork getNetwork(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return all Network objects\r
-     *\r
-     * @return List of OpenStackNetworks objects\r
-     */\r
-\r
-    public List<NeutronNetwork> getAllNetworks();\r
-\r
-    /**\r
-     * Applications call this interface method to add a Network object to the\r
-     * concurrent map\r
-     *\r
-     * @param input\r
-     *            OpenStackNetwork object\r
-     * @return boolean on whether the object was added or not\r
-     */\r
-\r
-    public boolean addNetwork(NeutronNetwork input);\r
-\r
-    /**\r
-     * Applications call this interface method to remove a Network object to the\r
-     * concurrent map\r
-     *\r
-     * @param uuid\r
-     *            identifier for the network object\r
-     * @return boolean on whether the object was removed or not\r
-     */\r
-\r
-    public boolean removeNetwork(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to edit a Network object\r
-     *\r
-     * @param uuid\r
-     *            identifier of the network object\r
-     * @param delta\r
-     *            OpenStackNetwork object containing changes to apply\r
-     * @return boolean on whether the object was updated or not\r
-     */\r
-\r
-    public boolean updateNetwork(String uuid, NeutronNetwork delta);\r
-\r
-    /**\r
-     * Applications call this interface method to determine if a Network object\r
-     * is use\r
-     *\r
-     * @param netUUID\r
-     *            identifier of the network object\r
-     *\r
-     * @return boolean on whether the network is in use or not\r
-     */\r
-\r
-    public boolean networkInUse(String netUUID);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB network objects
+ *
+ */
+
+public interface INeutronNetworkCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     * Network object exists
+     *
+     * @param uuid
+     *            UUID of the Network object
+     * @return boolean
+     */
+
+    public boolean networkExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * Network object exists
+     *
+     * @param uuid
+     *            UUID of the Network object
+     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronNetwork.OpenStackNetworks}
+     *          OpenStack Network class
+     */
+
+    public NeutronNetwork getNetwork(String uuid);
+
+    /**
+     * Applications call this interface method to return all Network objects
+     *
+     * @return List of OpenStackNetworks objects
+     */
+
+    public List<NeutronNetwork> getAllNetworks();
+
+    /**
+     * Applications call this interface method to add a Network object to the
+     * concurrent map
+     *
+     * @param input
+     *            OpenStackNetwork object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addNetwork(NeutronNetwork input);
+
+    /**
+     * Applications call this interface method to remove a Network object to the
+     * concurrent map
+     *
+     * @param uuid
+     *            identifier for the network object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeNetwork(String uuid);
+
+    /**
+     * Applications call this interface method to edit a Network object
+     *
+     * @param uuid
+     *            identifier of the network object
+     * @param delta
+     *            OpenStackNetwork object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateNetwork(String uuid, NeutronNetwork delta);
+
+    /**
+     * Applications call this interface method to determine if a Network object
+     * is use
+     *
+     * @param netUUID
+     *            identifier of the network object
+     *
+     * @return boolean on whether the network is in use or not
+     */
+
+    public boolean networkInUse(String netUUID);
+}
index 36ed4ffb39ec12f82bb0cf38e1ab1bb7f813532e..3f40ba3879a84a2b8aa517f0baad66e2cf0c1672 100644 (file)
@@ -1,83 +1,83 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron Ports needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronPortAware {\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified port can be created\r
-     *\r
-     * @param port\r
-     *            instance of proposed new Neutron Port object\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the create operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canCreatePort(NeutronPort port);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a port has been created\r
-     *\r
-     * @param port\r
-     *            instance of new Neutron Port object\r
-     * @return void\r
-     */\r
-    public void neutronPortCreated(NeutronPort port);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified port can be changed using the specified\r
-     * delta\r
-     *\r
-     * @param delta\r
-     *            updates to the port object using patch semantics\r
-     * @param port\r
-     *            instance of the Neutron Port object to be updated\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the update operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canUpdatePort(NeutronPort delta, NeutronPort original);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a port has been updated\r
-     *\r
-     * @param port\r
-     *            instance of modified Neutron Port object\r
-     * @return void\r
-     */\r
-    public void neutronPortUpdated(NeutronPort port);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified port can be deleted\r
-     *\r
-     * @param port\r
-     *            instance of the Neutron Port object to be deleted\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the delete operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canDeletePort(NeutronPort port);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a port has been deleted\r
-     *\r
-     * @param port\r
-     *            instance of deleted Port Network object\r
-     * @return void\r
-     */\r
-    public void neutronPortDeleted(NeutronPort port);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Ports needs to implement
+ *
+ */
+
+public interface INeutronPortAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified port can be created
+     *
+     * @param port
+     *            instance of proposed new Neutron Port object
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the create operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canCreatePort(NeutronPort port);
+
+    /**
+     * Services provide this interface method for taking action after a port has been created
+     *
+     * @param port
+     *            instance of new Neutron Port object
+     * @return void
+     */
+    public void neutronPortCreated(NeutronPort port);
+
+    /**
+     * Services provide this interface method to indicate if the specified port can be changed using the specified
+     * delta
+     *
+     * @param delta
+     *            updates to the port object using patch semantics
+     * @param port
+     *            instance of the Neutron Port object to be updated
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the update operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canUpdatePort(NeutronPort delta, NeutronPort original);
+
+    /**
+     * Services provide this interface method for taking action after a port has been updated
+     *
+     * @param port
+     *            instance of modified Neutron Port object
+     * @return void
+     */
+    public void neutronPortUpdated(NeutronPort port);
+
+    /**
+     * Services provide this interface method to indicate if the specified port can be deleted
+     *
+     * @param port
+     *            instance of the Neutron Port object to be deleted
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the delete operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDeletePort(NeutronPort port);
+
+    /**
+     * Services provide this interface method for taking action after a port has been deleted
+     *
+     * @param port
+     *            instance of deleted Port Network object
+     * @return void
+     */
+    public void neutronPortDeleted(NeutronPort port);
+}
index 681e9253772d605632eec56b462663e9cbed1198..ce30c6806eea294c57bc637e3fb532377c3b21b4 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB Port objects\r
- *\r
- */\r
-\r
-public interface INeutronPortCRUD {\r
-    /**\r
-     * Applications call this interface method to determine if a particular\r
-     * Port object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the Port object\r
-     * @return boolean\r
-     */\r
-\r
-    public boolean portExists(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return if a particular\r
-     * Port object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the Port object\r
-     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronPort.OpenStackPorts}\r
-     *          OpenStack Port class\r
-     */\r
-\r
-    public NeutronPort getPort(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return all Port objects\r
-     *\r
-     * @return List of OpenStackPorts objects\r
-     */\r
-\r
-    public List<NeutronPort> getAllPorts();\r
-\r
-    /**\r
-     * Applications call this interface method to add a Port object to the\r
-     * concurrent map\r
-     *\r
-     * @param input\r
-     *            OpenStackPort object\r
-     * @return boolean on whether the object was added or not\r
-     */\r
-\r
-    public boolean addPort(NeutronPort input);\r
-\r
-    /**\r
-     * Applications call this interface method to remove a Port object to the\r
-     * concurrent map\r
-     *\r
-     * @param uuid\r
-     *            identifier for the Port object\r
-     * @return boolean on whether the object was removed or not\r
-     */\r
-\r
-    public boolean removePort(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to edit a Port object\r
-     *\r
-     * @param uuid\r
-     *            identifier of the Port object\r
-     * @param delta\r
-     *            OpenStackPort object containing changes to apply\r
-     * @return boolean on whether the object was updated or not\r
-     */\r
-\r
-    public boolean updatePort(String uuid, NeutronPort delta);\r
-\r
-    /**\r
-     * Applications call this interface method to see if a MAC address is in use\r
-     *\r
-     * @param macAddress\r
-     *            mac Address to be tested\r
-     * @return boolean on whether the macAddress is already associated with a\r
-     * port or not\r
-     */\r
-\r
-    public boolean macInUse(String macAddress);\r
-\r
-    /**\r
-     * Applications call this interface method to retrieve the port associated with\r
-     * the gateway address of a subnet\r
-     *\r
-     * @param subnetUUID\r
-     *            identifier of the subnet\r
-     * @return OpenStackPorts object if the port exists and null if it does not\r
-     */\r
-\r
-    public NeutronPort getGatewayPort(String subnetUUID);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB Port objects
+ *
+ */
+
+public interface INeutronPortCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     * Port object exists
+     *
+     * @param uuid
+     *            UUID of the Port object
+     * @return boolean
+     */
+
+    public boolean portExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * Port object exists
+     *
+     * @param uuid
+     *            UUID of the Port object
+     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronPort.OpenStackPorts}
+     *          OpenStack Port class
+     */
+
+    public NeutronPort getPort(String uuid);
+
+    /**
+     * Applications call this interface method to return all Port objects
+     *
+     * @return List of OpenStackPorts objects
+     */
+
+    public List<NeutronPort> getAllPorts();
+
+    /**
+     * Applications call this interface method to add a Port object to the
+     * concurrent map
+     *
+     * @param input
+     *            OpenStackPort object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addPort(NeutronPort input);
+
+    /**
+     * Applications call this interface method to remove a Port object to the
+     * concurrent map
+     *
+     * @param uuid
+     *            identifier for the Port object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removePort(String uuid);
+
+    /**
+     * Applications call this interface method to edit a Port object
+     *
+     * @param uuid
+     *            identifier of the Port object
+     * @param delta
+     *            OpenStackPort object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updatePort(String uuid, NeutronPort delta);
+
+    /**
+     * Applications call this interface method to see if a MAC address is in use
+     *
+     * @param macAddress
+     *            mac Address to be tested
+     * @return boolean on whether the macAddress is already associated with a
+     * port or not
+     */
+
+    public boolean macInUse(String macAddress);
+
+    /**
+     * Applications call this interface method to retrieve the port associated with
+     * the gateway address of a subnet
+     *
+     * @param subnetUUID
+     *            identifier of the subnet
+     * @return OpenStackPorts object if the port exists and null if it does not
+     */
+
+    public NeutronPort getGatewayPort(String subnetUUID);
+}
index 040bdd87c4cdfd0fddbe39dae95dd67a4e956f04..3c9e83d490c0e0d561077f42ad3903b1c11e93b9 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron Routers needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronRouterAware {\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified router can be created\r
-     *\r
-     * @param router\r
-     *            instance of proposed new Neutron Router object\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the create operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canCreateRouter(NeutronRouter router);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a router has been created\r
-     *\r
-     * @param router\r
-     *            instance of new Neutron Router object\r
-     * @return void\r
-     */\r
-    public void neutronRouterCreated(NeutronRouter router);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified router can be changed using the specified\r
-     * delta\r
-     *\r
-     * @param delta\r
-     *            updates to the router object using patch semantics\r
-     * @param router\r
-     *            instance of the Neutron Router object to be updated\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the update operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canUpdateRouter(NeutronRouter delta, NeutronRouter original);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a router has been updated\r
-     *\r
-     * @param router\r
-     *            instance of modified Neutron Router object\r
-     * @return void\r
-     */\r
-    public void neutronRouterUpdated(NeutronRouter router);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified router can be deleted\r
-     *\r
-     * @param router\r
-     *            instance of the Neutron Router object to be deleted\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the delete operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canDeleteRouter(NeutronRouter router);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a router has been deleted\r
-     *\r
-     * @param router\r
-     *            instance of deleted Router Network object\r
-     * @return void\r
-     */\r
-    public void neutronRouterDeleted(NeutronRouter router);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified interface can be attached to the specified route\r
-     *\r
-     * @param router\r
-     *            instance of the base Neutron Router object\r
-     * @param routerInterface\r
-     *            instance of the NeutronRouter_Interface to be attached to the router\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the attach operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canAttachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after an interface has been added to a router\r
-     *\r
-     * @param router\r
-     *            instance of the base Neutron Router object\r
-     * @param routerInterface\r
-     *            instance of the NeutronRouter_Interface being attached to the router\r
-     * @return void\r
-     */\r
-    public void neutronRouterInterfaceAttached(NeutronRouter router, NeutronRouter_Interface routerInterface);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified interface can be detached from the specified router\r
-     *\r
-     * @param router\r
-     *            instance of the base Neutron Router object\r
-     * @param routerInterface\r
-     *            instance of the NeutronRouter_Interface to be detached to the router\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the detach operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canDetachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after an interface has been removed from a router\r
-     *\r
-     * @param router\r
-     *            instance of the base Neutron Router object\r
-     * @param routerInterface\r
-     *            instance of the NeutronRouter_Interface being detached from the router\r
-     * @return void\r
-     */\r
-    public void neutronRouterInterfaceDetached(NeutronRouter router, NeutronRouter_Interface routerInterface);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Routers needs to implement
+ *
+ */
+
+public interface INeutronRouterAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified router can be created
+     *
+     * @param router
+     *            instance of proposed new Neutron Router object
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the create operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canCreateRouter(NeutronRouter router);
+
+    /**
+     * Services provide this interface method for taking action after a router has been created
+     *
+     * @param router
+     *            instance of new Neutron Router object
+     * @return void
+     */
+    public void neutronRouterCreated(NeutronRouter router);
+
+    /**
+     * Services provide this interface method to indicate if the specified router can be changed using the specified
+     * delta
+     *
+     * @param delta
+     *            updates to the router object using patch semantics
+     * @param router
+     *            instance of the Neutron Router object to be updated
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the update operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canUpdateRouter(NeutronRouter delta, NeutronRouter original);
+
+    /**
+     * Services provide this interface method for taking action after a router has been updated
+     *
+     * @param router
+     *            instance of modified Neutron Router object
+     * @return void
+     */
+    public void neutronRouterUpdated(NeutronRouter router);
+
+    /**
+     * Services provide this interface method to indicate if the specified router can be deleted
+     *
+     * @param router
+     *            instance of the Neutron Router object to be deleted
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the delete operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDeleteRouter(NeutronRouter router);
+
+    /**
+     * Services provide this interface method for taking action after a router has been deleted
+     *
+     * @param router
+     *            instance of deleted Router Network object
+     * @return void
+     */
+    public void neutronRouterDeleted(NeutronRouter router);
+
+    /**
+     * Services provide this interface method to indicate if the specified interface can be attached to the specified route
+     *
+     * @param router
+     *            instance of the base Neutron Router object
+     * @param routerInterface
+     *            instance of the NeutronRouter_Interface to be attached to the router
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the attach operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canAttachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface);
+
+    /**
+     * Services provide this interface method for taking action after an interface has been added to a router
+     *
+     * @param router
+     *            instance of the base Neutron Router object
+     * @param routerInterface
+     *            instance of the NeutronRouter_Interface being attached to the router
+     * @return void
+     */
+    public void neutronRouterInterfaceAttached(NeutronRouter router, NeutronRouter_Interface routerInterface);
+
+    /**
+     * Services provide this interface method to indicate if the specified interface can be detached from the specified router
+     *
+     * @param router
+     *            instance of the base Neutron Router object
+     * @param routerInterface
+     *            instance of the NeutronRouter_Interface to be detached to the router
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the detach operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDetachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface);
+
+    /**
+     * Services provide this interface method for taking action after an interface has been removed from a router
+     *
+     * @param router
+     *            instance of the base Neutron Router object
+     * @param routerInterface
+     *            instance of the NeutronRouter_Interface being detached from the router
+     * @return void
+     */
+    public void neutronRouterInterfaceDetached(NeutronRouter router, NeutronRouter_Interface routerInterface);
+}
index 19be16d68e3a1cfba9b88f532c5248b5dd624cfb..b1a943fce1946e287271da2984206c84b3942bab 100644 (file)
@@ -1,93 +1,93 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB Router objects\r
- *\r
- */\r
-\r
-public interface INeutronRouterCRUD {\r
-    /**\r
-     * Applications call this interface method to determine if a particular\r
-     * Router object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the Router object\r
-     * @return boolean\r
-     */\r
-\r
-    public boolean routerExists(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return if a particular\r
-     * Router object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the Router object\r
-     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronRouter.OpenStackRouters}\r
-     *          OpenStack Router class\r
-     */\r
-\r
-    public NeutronRouter getRouter(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return all Router objects\r
-     *\r
-     * @return List of OpenStackRouters objects\r
-     */\r
-\r
-    public List<NeutronRouter> getAllRouters();\r
-\r
-    /**\r
-     * Applications call this interface method to add a Router object to the\r
-     * concurrent map\r
-     *\r
-     * @param input\r
-     *            OpenStackRouter object\r
-     * @return boolean on whether the object was added or not\r
-     */\r
-\r
-    public boolean addRouter(NeutronRouter input);\r
-\r
-    /**\r
-     * Applications call this interface method to remove a Router object to the\r
-     * concurrent map\r
-     *\r
-     * @param uuid\r
-     *            identifier for the Router object\r
-     * @return boolean on whether the object was removed or not\r
-     */\r
-\r
-    public boolean removeRouter(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to edit a Router object\r
-     *\r
-     * @param uuid\r
-     *            identifier of the Router object\r
-     * @param delta\r
-     *            OpenStackRouter object containing changes to apply\r
-     * @return boolean on whether the object was updated or not\r
-     */\r
-\r
-    public boolean updateRouter(String uuid, NeutronRouter delta);\r
-\r
-    /**\r
-     * Applications call this interface method to check if a router is in use\r
-     *\r
-     * @param uuid\r
-     *            identifier of the Router object\r
-     * @return boolean on whether the router is in use or not\r
-     */\r
-\r
-    public boolean routerInUse(String routerUUID);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB Router objects
+ *
+ */
+
+public interface INeutronRouterCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     * Router object exists
+     *
+     * @param uuid
+     *            UUID of the Router object
+     * @return boolean
+     */
+
+    public boolean routerExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * Router object exists
+     *
+     * @param uuid
+     *            UUID of the Router object
+     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronRouter.OpenStackRouters}
+     *          OpenStack Router class
+     */
+
+    public NeutronRouter getRouter(String uuid);
+
+    /**
+     * Applications call this interface method to return all Router objects
+     *
+     * @return List of OpenStackRouters objects
+     */
+
+    public List<NeutronRouter> getAllRouters();
+
+    /**
+     * Applications call this interface method to add a Router object to the
+     * concurrent map
+     *
+     * @param input
+     *            OpenStackRouter object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addRouter(NeutronRouter input);
+
+    /**
+     * Applications call this interface method to remove a Router object to the
+     * concurrent map
+     *
+     * @param uuid
+     *            identifier for the Router object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeRouter(String uuid);
+
+    /**
+     * Applications call this interface method to edit a Router object
+     *
+     * @param uuid
+     *            identifier of the Router object
+     * @param delta
+     *            OpenStackRouter object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateRouter(String uuid, NeutronRouter delta);
+
+    /**
+     * Applications call this interface method to check if a router is in use
+     *
+     * @param uuid
+     *            identifier of the Router object
+     * @return boolean on whether the router is in use or not
+     */
+
+    public boolean routerInUse(String routerUUID);
+}
index b7bafab04cf58fe6e7032377fe9faec17ad67d8c..fa0707698d6a88208693bfb9233fd523b512c6de 100644 (file)
@@ -1,84 +1,84 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron Subnets needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronSubnetAware {\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified subnet can be created\r
-     *\r
-     * @param subnet\r
-     *            instance of proposed new Neutron Subnet object\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the create operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canCreateSubnet(NeutronSubnet subnet);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a subnet has been created\r
-     *\r
-     * @param subnet\r
-     *            instance of new Neutron Subnet object\r
-     * @return void\r
-     */\r
-    public void neutronSubnetCreated(NeutronSubnet subnet);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified subnet can be changed using the specified\r
-     * delta\r
-     *\r
-     * @param delta\r
-     *            updates to the subnet object using patch semantics\r
-     * @param subnet\r
-     *            instance of the Neutron Subnet object to be updated\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the update operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canUpdateSubnet(NeutronSubnet delta, NeutronSubnet original);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a subnet has been updated\r
-     *\r
-     * @param subnet\r
-     *            instance of modified Neutron Subnet object\r
-     * @return void\r
-     */\r
-    public void neutronSubnetUpdated(NeutronSubnet subnet);\r
-\r
-    /**\r
-     * Services provide this interface method to indicate if the specified subnet can be deleted\r
-     *\r
-     * @param subnet\r
-     *            instance of the Subnet Router object to be deleted\r
-     * @return integer\r
-     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299\r
-     *            results in the delete operation being interrupted and the returned status value reflected in the\r
-     *            HTTP response.\r
-     */\r
-    public int canDeleteSubnet(NeutronSubnet subnet);\r
-\r
-    /**\r
-     * Services provide this interface method for taking action after a subnet has been deleted\r
-     *\r
-     * @param subnet\r
-     *            instance of deleted Router Subnet object\r
-     * @return void\r
-     */\r
-    public void neutronSubnetDeleted(NeutronSubnet subnet);\r
-\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Subnets needs to implement
+ *
+ */
+
+public interface INeutronSubnetAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified subnet can be created
+     *
+     * @param subnet
+     *            instance of proposed new Neutron Subnet object
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the create operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canCreateSubnet(NeutronSubnet subnet);
+
+    /**
+     * Services provide this interface method for taking action after a subnet has been created
+     *
+     * @param subnet
+     *            instance of new Neutron Subnet object
+     * @return void
+     */
+    public void neutronSubnetCreated(NeutronSubnet subnet);
+
+    /**
+     * Services provide this interface method to indicate if the specified subnet can be changed using the specified
+     * delta
+     *
+     * @param delta
+     *            updates to the subnet object using patch semantics
+     * @param subnet
+     *            instance of the Neutron Subnet object to be updated
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the update operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canUpdateSubnet(NeutronSubnet delta, NeutronSubnet original);
+
+    /**
+     * Services provide this interface method for taking action after a subnet has been updated
+     *
+     * @param subnet
+     *            instance of modified Neutron Subnet object
+     * @return void
+     */
+    public void neutronSubnetUpdated(NeutronSubnet subnet);
+
+    /**
+     * Services provide this interface method to indicate if the specified subnet can be deleted
+     *
+     * @param subnet
+     *            instance of the Subnet Router object to be deleted
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the delete operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDeleteSubnet(NeutronSubnet subnet);
+
+    /**
+     * Services provide this interface method for taking action after a subnet has been deleted
+     *
+     * @param subnet
+     *            instance of deleted Router Subnet object
+     * @return void
+     */
+    public void neutronSubnetDeleted(NeutronSubnet subnet);
+
+}
index 9c390467e5c49409e2ad3554848a8155ee174041..6f9a6ffb7b54850dce84b900ca08cadd57c00ce4 100644 (file)
@@ -1,95 +1,95 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB Subnet objects\r
- *\r
- */\r
-\r
-public interface INeutronSubnetCRUD {\r
-    /**\r
-     * Applications call this interface method to determine if a particular\r
-     * Subnet object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the Subnet object\r
-     * @return boolean\r
-     */\r
-\r
-    public boolean subnetExists(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return if a particular\r
-     * Subnet object exists\r
-     *\r
-     * @param uuid\r
-     *            UUID of the Subnet object\r
-     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSubnet.OpenStackSubnets}\r
-     *          OpenStack Subnet class\r
-     */\r
-\r
-    public NeutronSubnet getSubnet(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to return all Subnet objects\r
-     *\r
-     * @return List of OpenStackSubnets objects\r
-     */\r
-\r
-    public List<NeutronSubnet> getAllSubnets();\r
-\r
-    /**\r
-     * Applications call this interface method to add a Subnet object to the\r
-     * concurrent map\r
-     *\r
-     * @param input\r
-     *            OpenStackSubnet object\r
-     * @return boolean on whether the object was added or not\r
-     */\r
-\r
-    public boolean addSubnet(NeutronSubnet input);\r
-\r
-    /**\r
-     * Applications call this interface method to remove a Subnet object to the\r
-     * concurrent map\r
-     *\r
-     * @param uuid\r
-     *            identifier for the Subnet object\r
-     * @return boolean on whether the object was removed or not\r
-     */\r
-\r
-    public boolean removeSubnet(String uuid);\r
-\r
-    /**\r
-     * Applications call this interface method to edit a Subnet object\r
-     *\r
-     * @param uuid\r
-     *            identifier of the Subnet object\r
-     * @param delta\r
-     *            OpenStackSubnet object containing changes to apply\r
-     * @return boolean on whether the object was updated or not\r
-     */\r
-\r
-    public boolean updateSubnet(String uuid, NeutronSubnet delta);\r
-\r
-    /**\r
-     * Applications call this interface method to determine if a Subnet object\r
-     * is use\r
-     *\r
-     * @param subnetUUID\r
-     *            identifier of the subnet object\r
-     *\r
-     * @return boolean on whether the subnet is in use or not\r
-     */\r
-\r
-    public boolean subnetInUse(String subnetUUID);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB Subnet objects
+ *
+ */
+
+public interface INeutronSubnetCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     * Subnet object exists
+     *
+     * @param uuid
+     *            UUID of the Subnet object
+     * @return boolean
+     */
+
+    public boolean subnetExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * Subnet object exists
+     *
+     * @param uuid
+     *            UUID of the Subnet object
+     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSubnet.OpenStackSubnets}
+     *          OpenStack Subnet class
+     */
+
+    public NeutronSubnet getSubnet(String uuid);
+
+    /**
+     * Applications call this interface method to return all Subnet objects
+     *
+     * @return List of OpenStackSubnets objects
+     */
+
+    public List<NeutronSubnet> getAllSubnets();
+
+    /**
+     * Applications call this interface method to add a Subnet object to the
+     * concurrent map
+     *
+     * @param input
+     *            OpenStackSubnet object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addSubnet(NeutronSubnet input);
+
+    /**
+     * Applications call this interface method to remove a Subnet object to the
+     * concurrent map
+     *
+     * @param uuid
+     *            identifier for the Subnet object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeSubnet(String uuid);
+
+    /**
+     * Applications call this interface method to edit a Subnet object
+     *
+     * @param uuid
+     *            identifier of the Subnet object
+     * @param delta
+     *            OpenStackSubnet object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateSubnet(String uuid, NeutronSubnet delta);
+
+    /**
+     * Applications call this interface method to determine if a Subnet object
+     * is use
+     *
+     * @param subnetUUID
+     *            identifier of the subnet object
+     *
+     * @return boolean on whether the subnet is in use or not
+     */
+
+    public boolean subnetInUse(String subnetUUID);
+}
index 0becb475b8301d0ad5f57ec1a6d3f084e99a3841..aebecfa93e18884d243cfb58227124a98de6d429 100644 (file)
@@ -1,39 +1,39 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-public class NeutronCRUDInterfaces {\r
-\r
-    public static INeutronNetworkCRUD getINeutronNetworkCRUD(Object o) {\r
-        INeutronNetworkCRUD answer = (INeutronNetworkCRUD) ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, o);\r
-        return answer;\r
-    }\r
-\r
-    public static INeutronSubnetCRUD getINeutronSubnetCRUD(Object o) {\r
-        INeutronSubnetCRUD answer = (INeutronSubnetCRUD) ServiceHelper.getGlobalInstance(INeutronSubnetCRUD.class, o);\r
-        return answer;\r
-    }\r
-\r
-    public static INeutronPortCRUD getINeutronPortCRUD(Object o) {\r
-        INeutronPortCRUD answer = (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, o);\r
-        return answer;\r
-    }\r
-\r
-    public static INeutronRouterCRUD getINeutronRouterCRUD(Object o) {\r
-        INeutronRouterCRUD answer = (INeutronRouterCRUD) ServiceHelper.getGlobalInstance(INeutronRouterCRUD.class, o);\r
-        return answer;\r
-    }\r
-\r
-    public static INeutronFloatingIPCRUD getINeutronFloatingIPCRUD(Object o) {\r
-        INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getGlobalInstance(INeutronFloatingIPCRUD.class, o);\r
-        return answer;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+public class NeutronCRUDInterfaces {
+
+    public static INeutronNetworkCRUD getINeutronNetworkCRUD(Object o) {
+        INeutronNetworkCRUD answer = (INeutronNetworkCRUD) ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, o);
+        return answer;
+    }
+
+    public static INeutronSubnetCRUD getINeutronSubnetCRUD(Object o) {
+        INeutronSubnetCRUD answer = (INeutronSubnetCRUD) ServiceHelper.getGlobalInstance(INeutronSubnetCRUD.class, o);
+        return answer;
+    }
+
+    public static INeutronPortCRUD getINeutronPortCRUD(Object o) {
+        INeutronPortCRUD answer = (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, o);
+        return answer;
+    }
+
+    public static INeutronRouterCRUD getINeutronRouterCRUD(Object o) {
+        INeutronRouterCRUD answer = (INeutronRouterCRUD) ServiceHelper.getGlobalInstance(INeutronRouterCRUD.class, o);
+        return answer;
+    }
+
+    public static INeutronFloatingIPCRUD getINeutronFloatingIPCRUD(Object o) {
+        INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getGlobalInstance(INeutronFloatingIPCRUD.class, o);
+        return answer;
+    }
+}
index 906b4d4e76baef1afe79e47ca8ed37fbbd8beecb..4d029dccf31c642a7fd8ca790570e8764bcbebb2 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronFloatingIP {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement (name="id")\r
-    String floatingIPUUID;\r
-\r
-    @XmlElement (name="floating_network_id")\r
-    String floatingNetworkUUID;\r
-\r
-    @XmlElement (name="port_id")\r
-    String portUUID;\r
-\r
-    @XmlElement (name="fixed_ip_address")\r
-    String fixedIPAddress;\r
-\r
-    @XmlElement (name="floating_ip_address")\r
-    String floatingIPAddress;\r
-\r
-    @XmlElement (name="tenant_id")\r
-    String tenantUUID;\r
-\r
-    public NeutronFloatingIP() {\r
-    }\r
-\r
-    public String getID() { return floatingIPUUID; }\r
-\r
-    public String getFloatingIPUUID() {\r
-        return floatingIPUUID;\r
-    }\r
-\r
-    public void setFloatingIPUUID(String floatingIPUUID) {\r
-        this.floatingIPUUID = floatingIPUUID;\r
-    }\r
-\r
-    public String getFloatingNetworkUUID() {\r
-        return floatingNetworkUUID;\r
-    }\r
-\r
-    public void setFloatingNetworkUUID(String floatingNetworkUUID) {\r
-        this.floatingNetworkUUID = floatingNetworkUUID;\r
-    }\r
-\r
-    public String getPortUUID() {\r
-        return portUUID;\r
-    }\r
-\r
-    public void setPortUUID(String portUUID) {\r
-        this.portUUID = portUUID;\r
-    }\r
-\r
-    public String getFixedIPAddress() {\r
-        return fixedIPAddress;\r
-    }\r
-\r
-    public void setFixedIPAddress(String fixedIPAddress) {\r
-        this.fixedIPAddress = fixedIPAddress;\r
-    }\r
-\r
-    public String getFloatingIPAddress() {\r
-        return floatingIPAddress;\r
-    }\r
-\r
-    public void setFloatingIPAddress(String floatingIPAddress) {\r
-        this.floatingIPAddress = floatingIPAddress;\r
-    }\r
-\r
-    public String getTenantUUID() {\r
-        return tenantUUID;\r
-    }\r
-\r
-    public void setTenantUUID(String tenantUUID) {\r
-        this.tenantUUID = tenantUUID;\r
-    }\r
-\r
-    /**\r
-     * This method copies selected fields from the object and returns them\r
-     * as a new object, suitable for marshaling.\r
-     *\r
-     * @param fields\r
-     *            List of attributes to be extracted\r
-     * @return an OpenStackFloatingIPs object with only the selected fields\r
-     * populated\r
-     */\r
-\r
-    public NeutronFloatingIP extractFields(List<String> fields) {\r
-        NeutronFloatingIP ans = new NeutronFloatingIP();\r
-        Iterator<String> i = fields.iterator();\r
-        while (i.hasNext()) {\r
-            String s = i.next();\r
-            if (s.equals("id"))\r
-                ans.setFloatingIPUUID(this.getFloatingIPUUID());\r
-            if (s.equals("floating_network_id"))\r
-                ans.setFloatingNetworkUUID(this.getFloatingNetworkUUID());\r
-            if (s.equals("port_id"))\r
-                ans.setPortUUID(this.getPortUUID());\r
-            if (s.equals("fixed_ip_address"))\r
-                ans.setFixedIPAddress(this.getFixedIPAddress());\r
-            if (s.equals("floating_ip_address"))\r
-                ans.setFloatingIPAddress(this.getFloatingIPAddress());\r
-            if (s.equals("tenant_id"))\r
-                ans.setTenantUUID(this.getTenantUUID());\r
-        }\r
-        return ans;\r
-    }\r
-\r
-    public void initDefaults() {\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronFloatingIP {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement (name="id")
+    String floatingIPUUID;
+
+    @XmlElement (name="floating_network_id")
+    String floatingNetworkUUID;
+
+    @XmlElement (name="port_id")
+    String portUUID;
+
+    @XmlElement (name="fixed_ip_address")
+    String fixedIPAddress;
+
+    @XmlElement (name="floating_ip_address")
+    String floatingIPAddress;
+
+    @XmlElement (name="tenant_id")
+    String tenantUUID;
+
+    public NeutronFloatingIP() {
+    }
+
+    public String getID() { return floatingIPUUID; }
+
+    public String getFloatingIPUUID() {
+        return floatingIPUUID;
+    }
+
+    public void setFloatingIPUUID(String floatingIPUUID) {
+        this.floatingIPUUID = floatingIPUUID;
+    }
+
+    public String getFloatingNetworkUUID() {
+        return floatingNetworkUUID;
+    }
+
+    public void setFloatingNetworkUUID(String floatingNetworkUUID) {
+        this.floatingNetworkUUID = floatingNetworkUUID;
+    }
+
+    public String getPortUUID() {
+        return portUUID;
+    }
+
+    public void setPortUUID(String portUUID) {
+        this.portUUID = portUUID;
+    }
+
+    public String getFixedIPAddress() {
+        return fixedIPAddress;
+    }
+
+    public void setFixedIPAddress(String fixedIPAddress) {
+        this.fixedIPAddress = fixedIPAddress;
+    }
+
+    public String getFloatingIPAddress() {
+        return floatingIPAddress;
+    }
+
+    public void setFloatingIPAddress(String floatingIPAddress) {
+        this.floatingIPAddress = floatingIPAddress;
+    }
+
+    public String getTenantUUID() {
+        return tenantUUID;
+    }
+
+    public void setTenantUUID(String tenantUUID) {
+        this.tenantUUID = tenantUUID;
+    }
+
+    /**
+     * This method copies selected fields from the object and returns them
+     * as a new object, suitable for marshaling.
+     *
+     * @param fields
+     *            List of attributes to be extracted
+     * @return an OpenStackFloatingIPs object with only the selected fields
+     * populated
+     */
+
+    public NeutronFloatingIP extractFields(List<String> fields) {
+        NeutronFloatingIP ans = new NeutronFloatingIP();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setFloatingIPUUID(this.getFloatingIPUUID());
+            }
+            if (s.equals("floating_network_id")) {
+                ans.setFloatingNetworkUUID(this.getFloatingNetworkUUID());
+            }
+            if (s.equals("port_id")) {
+                ans.setPortUUID(this.getPortUUID());
+            }
+            if (s.equals("fixed_ip_address")) {
+                ans.setFixedIPAddress(this.getFixedIPAddress());
+            }
+            if (s.equals("floating_ip_address")) {
+                ans.setFloatingIPAddress(this.getFloatingIPAddress());
+            }
+            if (s.equals("tenant_id")) {
+                ans.setTenantUUID(this.getTenantUUID());
+            }
+        }
+        return ans;
+    }
+
+    public void initDefaults() {
+    }
+}
index eccbbcc3464a24a272d1e4371ee59b273884a5e9..f7f7982947467d11d13615c28f01638b32b8493c 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement(name = "network")\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronNetwork {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement (name="id")\r
-    String networkUUID;              // network UUID\r
-\r
-    @XmlElement (name="name")\r
-    String networkName;              // name\r
-\r
-    @XmlElement (defaultValue="true", name="admin_state_up")\r
-    Boolean adminStateUp;             // admin state up (true/false)\r
-\r
-    @XmlElement (defaultValue="false", name="shared")\r
-    Boolean shared;                   // shared network or not\r
-\r
-    @XmlElement (name="tenant_id")\r
-    String tenantID;                 // tenant for this network\r
-\r
-    @XmlElement (defaultValue="false", namespace="router", name="external")\r
-    Boolean routerExternal;           // network external or not\r
-\r
-    @XmlElement (defaultValue="flat", namespace="provider", name="network_type")\r
-    String providerNetworkType;      // provider network type (flat or vlan)\r
-\r
-    @XmlElement (namespace="provider", name="physical_network")\r
-    String providerPhysicalNetwork;  // provider physical network (name)\r
-\r
-    @XmlElement (namespace="provider", name="segmentation_id")\r
-    String providerSegmentationID;   // provide segmentation ID (vlan ID)\r
-\r
-    @XmlElement (name="status")\r
-    String status;                   // status (read-only)\r
-\r
-    @XmlElement (name="subnets")\r
-    List<String> subnets;            // subnets (read-only)\r
-\r
-    /* This attribute lists the ports associated with an instance\r
-     * which is needed for determining if that instance can be deleted\r
-     */\r
-\r
-    List<NeutronPort> myPorts;\r
-\r
-    public NeutronNetwork() {\r
-        myPorts = new ArrayList<NeutronPort>();\r
-    }\r
-\r
-    public void initDefaults() {\r
-        subnets = new ArrayList<String>();\r
-        if (this.status == null)\r
-            this.status = "ACTIVE";\r
-        if (this.adminStateUp == null)\r
-            this.adminStateUp = true;\r
-        if (this.shared == null)\r
-            this.shared = false;\r
-        if (this.routerExternal == null)\r
-            this.routerExternal = false;\r
-        if (this.providerNetworkType == null)\r
-            this.providerNetworkType = "flat";\r
-    }\r
-\r
-    public String getID() { return networkUUID; }\r
-\r
-    public String getNetworkUUID() {\r
-        return networkUUID;\r
-    }\r
-\r
-    public void setNetworkUUID(String networkUUID) {\r
-        this.networkUUID = networkUUID;\r
-    }\r
-\r
-    public String getNetworkName() {\r
-        return networkName;\r
-    }\r
-\r
-    public void setNetworkName(String networkName) {\r
-        this.networkName = networkName;\r
-    }\r
-\r
-    public boolean isAdminStateUp() {\r
-        return adminStateUp;\r
-    }\r
-\r
-    public Boolean getAdminStateUp() { return adminStateUp; }\r
-\r
-    public void setAdminStateUp(boolean newValue) {\r
-        this.adminStateUp = newValue;\r
-    }\r
-\r
-    public boolean isShared() { return shared; }\r
-\r
-    public Boolean getShared() { return shared; }\r
-\r
-    public void setShared(boolean newValue) {\r
-        this.shared = newValue;\r
-    }\r
-\r
-    public String getTenantID() {\r
-        return tenantID;\r
-    }\r
-\r
-    public void setTenantID(String tenantID) {\r
-        this.tenantID = tenantID;\r
-    }\r
-\r
-    public boolean isRouterExternal() { return routerExternal; }\r
-\r
-    public Boolean getRouterExternal() { return routerExternal; }\r
-\r
-    public void setRouterExternal(boolean newValue) {\r
-        this.routerExternal = newValue;\r
-    }\r
-\r
-    public String getProviderNetworkType() {\r
-        return providerNetworkType;\r
-    }\r
-\r
-    public void setProviderNetworkType(String providerNetworkType) {\r
-        this.providerNetworkType = providerNetworkType;\r
-    }\r
-\r
-    public String getProviderPhysicalNetwork() {\r
-        return providerPhysicalNetwork;\r
-    }\r
-\r
-    public void setProviderPhysicalNetwork(String providerPhysicalNetwork) {\r
-        this.providerPhysicalNetwork = providerPhysicalNetwork;\r
-    }\r
-\r
-    public String getProviderSegmentationID() {\r
-        return providerSegmentationID;\r
-    }\r
-\r
-    public void setProviderSegmentationID(String providerSegmentationID) {\r
-        this.providerSegmentationID = providerSegmentationID;\r
-    }\r
-\r
-    public String getStatus() {\r
-        return status;\r
-    }\r
-\r
-    public void setStatus(String status) {\r
-        this.status = status;\r
-    }\r
-\r
-    public List<String> getSubnets() {\r
-        return subnets;\r
-    }\r
-\r
-    public void setSubnets(List<String> subnets) {\r
-        this.subnets = subnets;\r
-    }\r
-\r
-    public void addSubnet(String uuid) {\r
-        this.subnets.add(uuid);\r
-    }\r
-\r
-    public void removeSubnet(String uuid) {\r
-        this.subnets.remove(uuid);\r
-    }\r
-\r
-    public List<NeutronPort> getPortsOnNetwork() {\r
-        return myPorts;\r
-    }\r
-\r
-    public void addPort(NeutronPort port) {\r
-        myPorts.add(port);\r
-    }\r
-\r
-    public void removePort(NeutronPort port) {\r
-        myPorts.remove(port);\r
-    }\r
-\r
-    /**\r
-     * This method copies selected fields from the object and returns them\r
-     * as a new object, suitable for marshaling.\r
-     *\r
-     * @param fields\r
-     *            List of attributes to be extracted\r
-     * @return an OpenStackNetworks object with only the selected fields\r
-     * populated\r
-     */\r
-\r
-    public NeutronNetwork extractFields(List<String> fields) {\r
-        NeutronNetwork ans = new NeutronNetwork();\r
-        Iterator<String> i = fields.iterator();\r
-        while (i.hasNext()) {\r
-            String s = i.next();\r
-            if (s.equals("id"))\r
-                ans.setNetworkUUID(this.getNetworkUUID());\r
-            if (s.equals("name"))\r
-                ans.setNetworkName(this.getNetworkName());\r
-            if (s.equals("admin_state_up"))\r
-                ans.setAdminStateUp(this.adminStateUp);\r
-            if (s.equals("status"))\r
-                ans.setStatus(this.getStatus());\r
-            if (s.equals("subnets")) {\r
-                List<String> subnetList = new ArrayList<String>();\r
-                subnetList.addAll(this.getSubnets());\r
-                ans.setSubnets(subnetList);\r
-            }\r
-            if (s.equals("shared"))\r
-                ans.setShared(this.shared);\r
-            if (s.equals("tenant_id"))\r
-                ans.setTenantID(this.getTenantID());\r
-        }\r
-        return ans;\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "network")
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronNetwork {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement (name="id")
+    String networkUUID;              // network UUID
+
+    @XmlElement (name="name")
+    String networkName;              // name
+
+    @XmlElement (defaultValue="true", name="admin_state_up")
+    Boolean adminStateUp;             // admin state up (true/false)
+
+    @XmlElement (defaultValue="false", name="shared")
+    Boolean shared;                   // shared network or not
+
+    @XmlElement (name="tenant_id")
+    String tenantID;                 // tenant for this network
+
+    @XmlElement (defaultValue="false", namespace="router", name="external")
+    Boolean routerExternal;           // network external or not
+
+    @XmlElement (defaultValue="flat", namespace="provider", name="network_type")
+    String providerNetworkType;      // provider network type (flat or vlan)
+
+    @XmlElement (namespace="provider", name="physical_network")
+    String providerPhysicalNetwork;  // provider physical network (name)
+
+    @XmlElement (namespace="provider", name="segmentation_id")
+    String providerSegmentationID;   // provide segmentation ID (vlan ID)
+
+    @XmlElement (name="status")
+    String status;                   // status (read-only)
+
+    @XmlElement (name="subnets")
+    List<String> subnets;            // subnets (read-only)
+
+    /* This attribute lists the ports associated with an instance
+     * which is needed for determining if that instance can be deleted
+     */
+
+    List<NeutronPort> myPorts;
+
+    public NeutronNetwork() {
+        myPorts = new ArrayList<NeutronPort>();
+    }
+
+    public void initDefaults() {
+        subnets = new ArrayList<String>();
+        if (status == null) {
+            status = "ACTIVE";
+        }
+        if (adminStateUp == null) {
+            adminStateUp = true;
+        }
+        if (shared == null) {
+            shared = false;
+        }
+        if (routerExternal == null) {
+            routerExternal = false;
+        }
+        if (providerNetworkType == null) {
+            providerNetworkType = "flat";
+        }
+    }
+
+    public String getID() { return networkUUID; }
+
+    public String getNetworkUUID() {
+        return networkUUID;
+    }
+
+    public void setNetworkUUID(String networkUUID) {
+        this.networkUUID = networkUUID;
+    }
+
+    public String getNetworkName() {
+        return networkName;
+    }
+
+    public void setNetworkName(String networkName) {
+        this.networkName = networkName;
+    }
+
+    public boolean isAdminStateUp() {
+        return adminStateUp;
+    }
+
+    public Boolean getAdminStateUp() { return adminStateUp; }
+
+    public void setAdminStateUp(boolean newValue) {
+        adminStateUp = newValue;
+    }
+
+    public boolean isShared() { return shared; }
+
+    public Boolean getShared() { return shared; }
+
+    public void setShared(boolean newValue) {
+        shared = newValue;
+    }
+
+    public String getTenantID() {
+        return tenantID;
+    }
+
+    public void setTenantID(String tenantID) {
+        this.tenantID = tenantID;
+    }
+
+    public boolean isRouterExternal() { return routerExternal; }
+
+    public Boolean getRouterExternal() { return routerExternal; }
+
+    public void setRouterExternal(boolean newValue) {
+        routerExternal = newValue;
+    }
+
+    public String getProviderNetworkType() {
+        return providerNetworkType;
+    }
+
+    public void setProviderNetworkType(String providerNetworkType) {
+        this.providerNetworkType = providerNetworkType;
+    }
+
+    public String getProviderPhysicalNetwork() {
+        return providerPhysicalNetwork;
+    }
+
+    public void setProviderPhysicalNetwork(String providerPhysicalNetwork) {
+        this.providerPhysicalNetwork = providerPhysicalNetwork;
+    }
+
+    public String getProviderSegmentationID() {
+        return providerSegmentationID;
+    }
+
+    public void setProviderSegmentationID(String providerSegmentationID) {
+        this.providerSegmentationID = providerSegmentationID;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public List<String> getSubnets() {
+        return subnets;
+    }
+
+    public void setSubnets(List<String> subnets) {
+        this.subnets = subnets;
+    }
+
+    public void addSubnet(String uuid) {
+        subnets.add(uuid);
+    }
+
+    public void removeSubnet(String uuid) {
+        subnets.remove(uuid);
+    }
+
+    public List<NeutronPort> getPortsOnNetwork() {
+        return myPorts;
+    }
+
+    public void addPort(NeutronPort port) {
+        myPorts.add(port);
+    }
+
+    public void removePort(NeutronPort port) {
+        myPorts.remove(port);
+    }
+
+    /**
+     * This method copies selected fields from the object and returns them
+     * as a new object, suitable for marshaling.
+     *
+     * @param fields
+     *            List of attributes to be extracted
+     * @return an OpenStackNetworks object with only the selected fields
+     * populated
+     */
+
+    public NeutronNetwork extractFields(List<String> fields) {
+        NeutronNetwork ans = new NeutronNetwork();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setNetworkUUID(this.getNetworkUUID());
+            }
+            if (s.equals("name")) {
+                ans.setNetworkName(this.getNetworkName());
+            }
+            if (s.equals("admin_state_up")) {
+                ans.setAdminStateUp(adminStateUp);
+            }
+            if (s.equals("status")) {
+                ans.setStatus(this.getStatus());
+            }
+            if (s.equals("subnets")) {
+                List<String> subnetList = new ArrayList<String>();
+                subnetList.addAll(this.getSubnets());
+                ans.setSubnets(subnetList);
+            }
+            if (s.equals("shared")) {
+                ans.setShared(shared);
+            }
+            if (s.equals("tenant_id")) {
+                ans.setTenantID(this.getTenantID());
+            }
+        }
+        return ans;
+    }
+
+}
+
index 7f7f712bed65c55ad8ceae7c11538435c29f7fb7..b585554bf873734da16cc9f6b4871174b4f3645d 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronPort {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement (name="id")\r
-    String portUUID;\r
-\r
-    @XmlElement (name="network_id")\r
-    String networkUUID;\r
-\r
-    @XmlElement (name="name")\r
-    String name;\r
-\r
-    @XmlElement (defaultValue="true", name="admin_state_up")\r
-    Boolean adminStateUp;\r
-\r
-    @XmlElement (name="status")\r
-    String status;\r
-\r
-    @XmlElement (name="mac_address")\r
-    String macAddress;\r
-\r
-    @XmlElement (name="fixed_ips")\r
-    List<Neutron_IPs> fixedIPs;\r
-\r
-    @XmlElement (name="device_id")\r
-    String deviceID;\r
-\r
-    @XmlElement (name="device_owner")\r
-    String deviceOwner;\r
-\r
-    @XmlElement (name="tenant_id")\r
-    String tenantID;\r
-\r
-    // TODO: add security groups\r
-    //        @XmlElement (name="security_groups")\r
-    //        List<String> securityGroups;\r
-\r
-    /* this attribute stores the floating IP address assigned to\r
-     * each fixed IP address\r
-     */\r
-\r
-    HashMap<String, NeutronFloatingIP> floatingIPMap;\r
-\r
-    public NeutronPort() {\r
-        floatingIPMap = new HashMap<String, NeutronFloatingIP>();\r
-    }\r
-\r
-    public String getID() { return portUUID; }\r
-\r
-    public String getPortUUID() {\r
-        return portUUID;\r
-    }\r
-\r
-    public void setPortUUID(String portUUID) {\r
-        this.portUUID = portUUID;\r
-    }\r
-\r
-    public String getNetworkUUID() {\r
-        return networkUUID;\r
-    }\r
-\r
-    public void setNetworkUUID(String networkUUID) {\r
-        this.networkUUID = networkUUID;\r
-    }\r
-\r
-    public String getName() {\r
-        return name;\r
-    }\r
-\r
-    public void setName(String name) {\r
-        this.name = name;\r
-    }\r
-\r
-    public boolean isAdminStateUp() {\r
-        if (adminStateUp == null)\r
-            return true;\r
-        return adminStateUp;\r
-    }\r
-\r
-    public Boolean getAdminStateUp() { return adminStateUp; }\r
-\r
-    public void setAdminStateUp(Boolean newValue) {\r
-            this.adminStateUp = newValue;\r
-    }\r
-\r
-    public String getStatus() {\r
-        return status;\r
-    }\r
-\r
-    public void setStatus(String status) {\r
-        this.status = status;\r
-    }\r
-\r
-    public String getMacAddress() {\r
-        return macAddress;\r
-    }\r
-\r
-    public void setMacAddress(String macAddress) {\r
-        this.macAddress = macAddress;\r
-    }\r
-\r
-    public List<Neutron_IPs> getFixedIPs() {\r
-        return fixedIPs;\r
-    }\r
-\r
-    public void setFixedIPs(List<Neutron_IPs> fixedIPs) {\r
-        this.fixedIPs = fixedIPs;\r
-    }\r
-\r
-    public String getDeviceID() {\r
-        return deviceID;\r
-    }\r
-\r
-    public void setDeviceID(String deviceID) {\r
-        this.deviceID = deviceID;\r
-    }\r
-\r
-    public String getDeviceOwner() {\r
-        return deviceOwner;\r
-    }\r
-\r
-    public void setDeviceOwner(String deviceOwner) {\r
-        this.deviceOwner = deviceOwner;\r
-    }\r
-\r
-    public String getTenantID() {\r
-        return tenantID;\r
-    }\r
-\r
-    public void setTenantID(String tenantID) {\r
-        this.tenantID = tenantID;\r
-    }\r
-\r
-    public NeutronFloatingIP getFloatingIP(String key) {\r
-        if (!floatingIPMap.containsKey(key))\r
-            return null;\r
-        return floatingIPMap.get(key);\r
-    }\r
-\r
-    public void removeFloatingIP(String key) {\r
-        floatingIPMap.remove(key);\r
-    }\r
-\r
-    public void addFloatingIP(String key, NeutronFloatingIP floatingIP) {\r
-        if (!floatingIPMap.containsKey(key))\r
-            floatingIPMap.put(key, floatingIP);\r
-    }\r
-\r
-    /**\r
-     * This method copies selected fields from the object and returns them\r
-     * as a new object, suitable for marshaling.\r
-     *\r
-     * @param fields\r
-     *            List of attributes to be extracted\r
-     * @return an OpenStackPorts object with only the selected fields\r
-     * populated\r
-     */\r
-\r
-    public NeutronPort extractFields(List<String> fields) {\r
-        NeutronPort ans = new NeutronPort();\r
-        Iterator<String> i = fields.iterator();\r
-        while (i.hasNext()) {\r
-            String s = i.next();\r
-            if (s.equals("id"))\r
-                ans.setPortUUID(this.getPortUUID());\r
-            if (s.equals("network_id"))\r
-                ans.setNetworkUUID(this.getNetworkUUID());\r
-            if (s.equals("name"))\r
-                ans.setName(this.getName());\r
-            if (s.equals("admin_state_up"))\r
-                ans.setAdminStateUp(this.getAdminStateUp());\r
-            if (s.equals("status"))\r
-                ans.setStatus(this.getStatus());\r
-            if (s.equals("mac_address"))\r
-                ans.setMacAddress(this.getMacAddress());\r
-            if (s.equals("fixed_ips")) {\r
-                List<Neutron_IPs> fixedIPs = new ArrayList<Neutron_IPs>();\r
-                fixedIPs.addAll(this.getFixedIPs());\r
-                ans.setFixedIPs(fixedIPs);\r
-            }\r
-            if (s.equals("device_id")) {\r
-                ans.setDeviceID(this.getDeviceID());\r
-            }\r
-            if (s.equals("device_owner")) {\r
-                ans.setDeviceOwner(this.getDeviceOwner());\r
-            }\r
-            if (s.equals("tenant_id"))\r
-                ans.setTenantID(this.getTenantID());\r
-        }\r
-        return ans;\r
-    }\r
-\r
-    public void initDefaults() {\r
-        adminStateUp = true;\r
-        if (status == null)\r
-            status = "ACTIVE";\r
-        if (fixedIPs == null)\r
-            fixedIPs = new ArrayList<Neutron_IPs>();\r
-    }\r
-\r
-    /**\r
-     * This method checks to see if the port has a floating IPv4 address\r
-     * associated with the supplied fixed IPv4 address\r
-     *\r
-     * @param fixedIP\r
-     *            fixed IPv4 address in dotted decimal format\r
-     * @return a boolean indicating if there is a floating IPv4 address bound\r
-     * to the fixed IPv4 address\r
-     */\r
-\r
-    public boolean isBoundToFloatingIP(String fixedIP) {\r
-        return floatingIPMap.containsKey(fixedIP);\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronPort {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement (name="id")
+    String portUUID;
+
+    @XmlElement (name="network_id")
+    String networkUUID;
+
+    @XmlElement (name="name")
+    String name;
+
+    @XmlElement (defaultValue="true", name="admin_state_up")
+    Boolean adminStateUp;
+
+    @XmlElement (name="status")
+    String status;
+
+    @XmlElement (name="mac_address")
+    String macAddress;
+
+    @XmlElement (name="fixed_ips")
+    List<Neutron_IPs> fixedIPs;
+
+    @XmlElement (name="device_id")
+    String deviceID;
+
+    @XmlElement (name="device_owner")
+    String deviceOwner;
+
+    @XmlElement (name="tenant_id")
+    String tenantID;
+
+    // TODO: add security groups
+    //        @XmlElement (name="security_groups")
+    //        List<String> securityGroups;
+
+    /* this attribute stores the floating IP address assigned to
+     * each fixed IP address
+     */
+
+    HashMap<String, NeutronFloatingIP> floatingIPMap;
+
+    public NeutronPort() {
+        floatingIPMap = new HashMap<String, NeutronFloatingIP>();
+    }
+
+    public String getID() { return portUUID; }
+
+    public String getPortUUID() {
+        return portUUID;
+    }
+
+    public void setPortUUID(String portUUID) {
+        this.portUUID = portUUID;
+    }
+
+    public String getNetworkUUID() {
+        return networkUUID;
+    }
+
+    public void setNetworkUUID(String networkUUID) {
+        this.networkUUID = networkUUID;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isAdminStateUp() {
+        if (adminStateUp == null) {
+            return true;
+        }
+        return adminStateUp;
+    }
+
+    public Boolean getAdminStateUp() { return adminStateUp; }
+
+    public void setAdminStateUp(Boolean newValue) {
+            adminStateUp = newValue;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getMacAddress() {
+        return macAddress;
+    }
+
+    public void setMacAddress(String macAddress) {
+        this.macAddress = macAddress;
+    }
+
+    public List<Neutron_IPs> getFixedIPs() {
+        return fixedIPs;
+    }
+
+    public void setFixedIPs(List<Neutron_IPs> fixedIPs) {
+        this.fixedIPs = fixedIPs;
+    }
+
+    public String getDeviceID() {
+        return deviceID;
+    }
+
+    public void setDeviceID(String deviceID) {
+        this.deviceID = deviceID;
+    }
+
+    public String getDeviceOwner() {
+        return deviceOwner;
+    }
+
+    public void setDeviceOwner(String deviceOwner) {
+        this.deviceOwner = deviceOwner;
+    }
+
+    public String getTenantID() {
+        return tenantID;
+    }
+
+    public void setTenantID(String tenantID) {
+        this.tenantID = tenantID;
+    }
+
+    public NeutronFloatingIP getFloatingIP(String key) {
+        if (!floatingIPMap.containsKey(key)) {
+            return null;
+        }
+        return floatingIPMap.get(key);
+    }
+
+    public void removeFloatingIP(String key) {
+        floatingIPMap.remove(key);
+    }
+
+    public void addFloatingIP(String key, NeutronFloatingIP floatingIP) {
+        if (!floatingIPMap.containsKey(key)) {
+            floatingIPMap.put(key, floatingIP);
+        }
+    }
+
+    /**
+     * This method copies selected fields from the object and returns them
+     * as a new object, suitable for marshaling.
+     *
+     * @param fields
+     *            List of attributes to be extracted
+     * @return an OpenStackPorts object with only the selected fields
+     * populated
+     */
+
+    public NeutronPort extractFields(List<String> fields) {
+        NeutronPort ans = new NeutronPort();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setPortUUID(this.getPortUUID());
+            }
+            if (s.equals("network_id")) {
+                ans.setNetworkUUID(this.getNetworkUUID());
+            }
+            if (s.equals("name")) {
+                ans.setName(this.getName());
+            }
+            if (s.equals("admin_state_up")) {
+                ans.setAdminStateUp(this.getAdminStateUp());
+            }
+            if (s.equals("status")) {
+                ans.setStatus(this.getStatus());
+            }
+            if (s.equals("mac_address")) {
+                ans.setMacAddress(this.getMacAddress());
+            }
+            if (s.equals("fixed_ips")) {
+                List<Neutron_IPs> fixedIPs = new ArrayList<Neutron_IPs>();
+                fixedIPs.addAll(this.getFixedIPs());
+                ans.setFixedIPs(fixedIPs);
+            }
+            if (s.equals("device_id")) {
+                ans.setDeviceID(this.getDeviceID());
+            }
+            if (s.equals("device_owner")) {
+                ans.setDeviceOwner(this.getDeviceOwner());
+            }
+            if (s.equals("tenant_id")) {
+                ans.setTenantID(this.getTenantID());
+            }
+        }
+        return ans;
+    }
+
+    public void initDefaults() {
+        adminStateUp = true;
+        if (status == null) {
+            status = "ACTIVE";
+        }
+        if (fixedIPs == null) {
+            fixedIPs = new ArrayList<Neutron_IPs>();
+        }
+    }
+
+    /**
+     * This method checks to see if the port has a floating IPv4 address
+     * associated with the supplied fixed IPv4 address
+     *
+     * @param fixedIP
+     *            fixed IPv4 address in dotted decimal format
+     * @return a boolean indicating if there is a floating IPv4 address bound
+     * to the fixed IPv4 address
+     */
+
+    public boolean isBoundToFloatingIP(String fixedIP) {
+        return floatingIPMap.containsKey(fixedIP);
+    }
+}
index 8329ffc58fdaf057d73aceeab4af2bfb5e81faee..1ef48bd95bfe2f4a378f497371f38db11b307e91 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronRouter {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-    @XmlElement (name="id")\r
-    String routerUUID;\r
-\r
-    @XmlElement (name="name")\r
-    String name;\r
-\r
-    @XmlElement (defaultValue="true", name="admin_state_up")\r
-    Boolean adminStateUp;\r
-\r
-    @XmlElement (name="status")\r
-    String status;\r
-\r
-    @XmlElement (name="tenant_id")\r
-    String tenantID;\r
-\r
-    @XmlElement (name="external_gateway_info")\r
-    NeutronRouter_NetworkReference externalGatewayInfo;\r
-\r
-    /* Holds a map of OpenStackRouterInterfaces by subnet UUID\r
-     * used for internal mapping to DOVE\r
-     */\r
-    HashMap<String, NeutronRouter_Interface> interfaces;\r
-\r
-    public NeutronRouter() {\r
-        interfaces = new HashMap<String, NeutronRouter_Interface>();\r
-    }\r
-\r
-    public String getID() { return routerUUID; }\r
-\r
-    public String getRouterUUID() {\r
-        return routerUUID;\r
-    }\r
-\r
-    public void setRouterUUID(String routerUUID) {\r
-        this.routerUUID = routerUUID;\r
-    }\r
-\r
-    public String getName() {\r
-        return name;\r
-    }\r
-\r
-    public void setName(String name) {\r
-        this.name = name;\r
-    }\r
-\r
-    public boolean isAdminStateUp() {\r
-        if (adminStateUp == null)\r
-            return true;\r
-        return adminStateUp;\r
-    }\r
-\r
-    public Boolean getAdminStateUp() { return adminStateUp; }\r
-\r
-    public void setAdminStateUp(Boolean newValue) {\r
-        this.adminStateUp = newValue;\r
-    }\r
-\r
-    public String getStatus() {\r
-        return status;\r
-    }\r
-\r
-    public void setStatus(String status) {\r
-        this.status = status;\r
-    }\r
-\r
-    public String getTenantID() {\r
-        return tenantID;\r
-    }\r
-\r
-    public void setTenantID(String tenantID) {\r
-        this.tenantID = tenantID;\r
-    }\r
-\r
-    public NeutronRouter_NetworkReference getExternalGatewayInfo() {\r
-        return externalGatewayInfo;\r
-    }\r
-\r
-    public void setExternalGatewayInfo(NeutronRouter_NetworkReference externalGatewayInfo) {\r
-        this.externalGatewayInfo = externalGatewayInfo;\r
-    }\r
-\r
-    /**\r
-     * This method copies selected fields from the object and returns them\r
-     * as a new object, suitable for marshaling.\r
-     *\r
-     * @param fields\r
-     *            List of attributes to be extracted\r
-     * @return an OpenStackRouters object with only the selected fields\r
-     * populated\r
-     */\r
-\r
-    public NeutronRouter extractFields(List<String> fields) {\r
-        NeutronRouter ans = new NeutronRouter();\r
-        Iterator<String> i = fields.iterator();\r
-        while (i.hasNext()) {\r
-            String s = i.next();\r
-            if (s.equals("id"))\r
-                ans.setRouterUUID(this.getRouterUUID());\r
-            if (s.equals("name"))\r
-                ans.setName(this.getName());\r
-            if (s.equals("admin_state_up"))\r
-                ans.setAdminStateUp(this.getAdminStateUp());\r
-            if (s.equals("status"))\r
-                ans.setStatus(this.getStatus());\r
-            if (s.equals("tenant_id"))\r
-                ans.setTenantID(this.getTenantID());\r
-            if (s.equals("external_gateway_info")) {\r
-                ans.setExternalGatewayInfo(this.getExternalGatewayInfo());\r
-            }\r
-        }\r
-        return ans;\r
-    }\r
-\r
-    public HashMap<String, NeutronRouter_Interface> getInterfaces() {\r
-        return interfaces;\r
-    }\r
-\r
-    public void addInterface(String s, NeutronRouter_Interface i) {\r
-        interfaces.put(s, i);\r
-    }\r
-\r
-    public void removeInterface(String s) {\r
-        interfaces.remove(s);\r
-    }\r
-\r
-    public void initDefaults() {\r
-        adminStateUp = true;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronRouter {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+    @XmlElement (name="id")
+    String routerUUID;
+
+    @XmlElement (name="name")
+    String name;
+
+    @XmlElement (defaultValue="true", name="admin_state_up")
+    Boolean adminStateUp;
+
+    @XmlElement (name="status")
+    String status;
+
+    @XmlElement (name="tenant_id")
+    String tenantID;
+
+    @XmlElement (name="external_gateway_info")
+    NeutronRouter_NetworkReference externalGatewayInfo;
+
+    /* Holds a map of OpenStackRouterInterfaces by subnet UUID
+     * used for internal mapping to DOVE
+     */
+    HashMap<String, NeutronRouter_Interface> interfaces;
+
+    public NeutronRouter() {
+        interfaces = new HashMap<String, NeutronRouter_Interface>();
+    }
+
+    public String getID() { return routerUUID; }
+
+    public String getRouterUUID() {
+        return routerUUID;
+    }
+
+    public void setRouterUUID(String routerUUID) {
+        this.routerUUID = routerUUID;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isAdminStateUp() {
+        if (adminStateUp == null) {
+            return true;
+        }
+        return adminStateUp;
+    }
+
+    public Boolean getAdminStateUp() { return adminStateUp; }
+
+    public void setAdminStateUp(Boolean newValue) {
+        adminStateUp = newValue;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getTenantID() {
+        return tenantID;
+    }
+
+    public void setTenantID(String tenantID) {
+        this.tenantID = tenantID;
+    }
+
+    public NeutronRouter_NetworkReference getExternalGatewayInfo() {
+        return externalGatewayInfo;
+    }
+
+    public void setExternalGatewayInfo(NeutronRouter_NetworkReference externalGatewayInfo) {
+        this.externalGatewayInfo = externalGatewayInfo;
+    }
+
+    /**
+     * This method copies selected fields from the object and returns them
+     * as a new object, suitable for marshaling.
+     *
+     * @param fields
+     *            List of attributes to be extracted
+     * @return an OpenStackRouters object with only the selected fields
+     * populated
+     */
+
+    public NeutronRouter extractFields(List<String> fields) {
+        NeutronRouter ans = new NeutronRouter();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setRouterUUID(this.getRouterUUID());
+            }
+            if (s.equals("name")) {
+                ans.setName(this.getName());
+            }
+            if (s.equals("admin_state_up")) {
+                ans.setAdminStateUp(this.getAdminStateUp());
+            }
+            if (s.equals("status")) {
+                ans.setStatus(this.getStatus());
+            }
+            if (s.equals("tenant_id")) {
+                ans.setTenantID(this.getTenantID());
+            }
+            if (s.equals("external_gateway_info")) {
+                ans.setExternalGatewayInfo(this.getExternalGatewayInfo());
+            }
+        }
+        return ans;
+    }
+
+    public HashMap<String, NeutronRouter_Interface> getInterfaces() {
+        return interfaces;
+    }
+
+    public void addInterface(String s, NeutronRouter_Interface i) {
+        interfaces.put(s, i);
+    }
+
+    public void removeInterface(String s) {
+        interfaces.remove(s);
+    }
+
+    public void initDefaults() {
+        adminStateUp = true;
+    }
+}
index 307789c8cf2433311dd5f435b34527baa01c2900..5b5e0ce9cc61de995360bb0172b14b7f13475676 100644 (file)
@@ -1,65 +1,65 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronRouter_Interface {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement (name="subnet_id")\r
-    String subnetUUID;\r
-\r
-    @XmlElement (name="port_id")\r
-    String portUUID;\r
-\r
-    @XmlElement (name="id")\r
-    String id;\r
-\r
-    @XmlElement (name="tenant_id")\r
-    String tenantID;\r
-\r
-    public NeutronRouter_Interface() {\r
-    }\r
-\r
-    public NeutronRouter_Interface(String subnetUUID, String portUUID) {\r
-        this.subnetUUID = subnetUUID;\r
-        this.portUUID = portUUID;\r
-    }\r
-\r
-    public String getSubnetUUID() {\r
-        return subnetUUID;\r
-    }\r
-\r
-    public void setSubnetUUID(String subnetUUID) {\r
-        this.subnetUUID = subnetUUID;\r
-    }\r
-\r
-    public String getPortUUID() {\r
-        return portUUID;\r
-    }\r
-\r
-    public void setPortUUID(String portUUID) {\r
-        this.portUUID = portUUID;\r
-    }\r
-\r
-    public void setID(String id) {\r
-        this.id = id;\r
-    }\r
-\r
-    public void setTenantID(String tenantID) {\r
-        this.tenantID = tenantID;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronRouter_Interface {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement (name="subnet_id")
+    String subnetUUID;
+
+    @XmlElement (name="port_id")
+    String portUUID;
+
+    @XmlElement (name="id")
+    String id;
+
+    @XmlElement (name="tenant_id")
+    String tenantID;
+
+    public NeutronRouter_Interface() {
+    }
+
+    public NeutronRouter_Interface(String subnetUUID, String portUUID) {
+        this.subnetUUID = subnetUUID;
+        this.portUUID = portUUID;
+    }
+
+    public String getSubnetUUID() {
+        return subnetUUID;
+    }
+
+    public void setSubnetUUID(String subnetUUID) {
+        this.subnetUUID = subnetUUID;
+    }
+
+    public String getPortUUID() {
+        return portUUID;
+    }
+
+    public void setPortUUID(String portUUID) {
+        this.portUUID = portUUID;
+    }
+
+    public void setID(String id) {
+        this.id = id;
+    }
+
+    public void setTenantID(String tenantID) {
+        this.tenantID = tenantID;
+    }
+}
index 012215c719342360f9cc2175f0b20b77b85852e4..07f165dc7e16b661c0f9c9e052af89c63c43cf2a 100644 (file)
@@ -1,36 +1,36 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronRouter_NetworkReference {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="network_id")\r
-    String networkID;\r
-\r
-    public NeutronRouter_NetworkReference() {\r
-    }\r
-\r
-    public String getNetworkID() {\r
-        return networkID;\r
-    }\r
-\r
-    public void setNetworkID(String networkID) {\r
-        this.networkID = networkID;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronRouter_NetworkReference {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="network_id")
+    String networkID;
+
+    public NeutronRouter_NetworkReference() {
+    }
+
+    public String getNetworkID() {
+        return networkID;
+    }
+
+    public void setNetworkID(String networkID) {
+        this.networkID = networkID;
+    }
+}
index 8b1a8d6af4bb50c13e8b2166bac245fe7d41f0ce..e53c3d4b1a9ddee674c231bdf400f0beed22a162 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.apache.commons.net.util.SubnetUtils;\r
-import org.apache.commons.net.util.SubnetUtils.SubnetInfo;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronSubnet {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement (name="id")\r
-    String subnetUUID;\r
-\r
-    @XmlElement (name="network_id")\r
-    String networkUUID;\r
-\r
-    @XmlElement (name="name")\r
-    String name;\r
-\r
-    @XmlElement (defaultValue="4", name="ip_version")\r
-    Integer ipVersion;\r
-\r
-    @XmlElement (name="cidr")\r
-    String cidr;\r
-\r
-    @XmlElement (name="gateway_ip")\r
-    String gatewayIP;\r
-\r
-    @XmlElement (name="dns_nameservers")\r
-    List<String> dnsNameservers;\r
-\r
-    @XmlElement (name="allocation_pools")\r
-    List<NeutronSubnet_IPAllocationPool> allocationPools;\r
-\r
-    @XmlElement (name="host_routes")\r
-    List<NeutronSubnet_HostRoute> hostRoutes;\r
-\r
-    @XmlElement (defaultValue="true", name="enable_dhcp")\r
-    Boolean enableDHCP;\r
-\r
-    @XmlElement (name="tenant_id")\r
-    String tenantID;\r
-\r
-    /* stores the OpenStackPorts associated with an instance\r
-     * used to determine if that instance can be deleted.\r
-     */\r
-    List<NeutronPort> myPorts;\r
-\r
-    boolean gatewayIPAssigned;\r
-\r
-    public NeutronSubnet() {\r
-        myPorts = new ArrayList<NeutronPort>();\r
-    }\r
-\r
-    public String getID() { return subnetUUID; }\r
-\r
-    public String getSubnetUUID() {\r
-        return subnetUUID;\r
-    }\r
-\r
-    public void setSubnetUUID(String subnetUUID) {\r
-        this.subnetUUID = subnetUUID;\r
-    }\r
-\r
-    public String getNetworkUUID() {\r
-        return networkUUID;\r
-    }\r
-\r
-    public void setNetworkUUID(String networkUUID) {\r
-        this.networkUUID = networkUUID;\r
-    }\r
-\r
-    public String getName() {\r
-        return name;\r
-    }\r
-\r
-    public void setName(String name) {\r
-        this.name = name;\r
-    }\r
-\r
-    public Integer getIpVersion() {\r
-        return ipVersion;\r
-    }\r
-\r
-    public void setIpVersion(Integer ipVersion) {\r
-        this.ipVersion = ipVersion;\r
-    }\r
-\r
-    public String getCidr() {\r
-        return cidr;\r
-    }\r
-\r
-    public void setCidr(String cidr) {\r
-        this.cidr = cidr;\r
-    }\r
-\r
-    public String getGatewayIP() {\r
-        return gatewayIP;\r
-    }\r
-\r
-    public void setGatewayIP(String gatewayIP) {\r
-        this.gatewayIP = gatewayIP;\r
-    }\r
-\r
-    public List<String> getDnsNameservers() {\r
-        return dnsNameservers;\r
-    }\r
-\r
-    public void setDnsNameservers(List<String> dnsNameservers) {\r
-        this.dnsNameservers = dnsNameservers;\r
-    }\r
-\r
-    public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {\r
-        return allocationPools;\r
-    }\r
-\r
-    public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {\r
-        this.allocationPools = allocationPools;\r
-    }\r
-\r
-    public List<NeutronSubnet_HostRoute> getHostRoutes() {\r
-        return hostRoutes;\r
-    }\r
-\r
-    public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {\r
-        this.hostRoutes = hostRoutes;\r
-    }\r
-\r
-    public boolean isEnableDHCP() {\r
-        if (enableDHCP == null) {\r
-            return true;\r
-        }\r
-        return enableDHCP;\r
-    }\r
-\r
-    public Boolean getEnableDHCP() { return enableDHCP; }\r
-\r
-    public void setEnableDHCP(Boolean newValue) {\r
-            enableDHCP = newValue;\r
-    }\r
-\r
-    public String getTenantID() {\r
-        return tenantID;\r
-    }\r
-\r
-    public void setTenantID(String tenantID) {\r
-        this.tenantID = tenantID;\r
-    }\r
-\r
-    /**\r
-     * This method copies selected fields from the object and returns them\r
-     * as a new object, suitable for marshaling.\r
-     *\r
-     * @param fields\r
-     *            List of attributes to be extracted\r
-     * @return an OpenStackSubnets object with only the selected fields\r
-     * populated\r
-     */\r
-\r
-    public NeutronSubnet extractFields(List<String> fields) {\r
-        NeutronSubnet ans = new NeutronSubnet();\r
-        Iterator<String> i = fields.iterator();\r
-        while (i.hasNext()) {\r
-            String s = i.next();\r
-            if (s.equals("id")) {\r
-                ans.setSubnetUUID(this.getSubnetUUID());\r
-            }\r
-            if (s.equals("network_id")) {\r
-                ans.setNetworkUUID(this.getNetworkUUID());\r
-            }\r
-            if (s.equals("name")) {\r
-                ans.setName(this.getName());\r
-            }\r
-            if (s.equals("ip_version")) {\r
-                ans.setIpVersion(this.getIpVersion());\r
-            }\r
-            if (s.equals("cidr")) {\r
-                ans.setCidr(this.getCidr());\r
-            }\r
-            if (s.equals("gateway_ip")) {\r
-                ans.setGatewayIP(this.getGatewayIP());\r
-            }\r
-            if (s.equals("dns_nameservers")) {\r
-                List<String> nsList = new ArrayList<String>();\r
-                nsList.addAll(this.getDnsNameservers());\r
-                ans.setDnsNameservers(nsList);\r
-            }\r
-            if (s.equals("allocation_pools")) {\r
-                List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
-                aPools.addAll(this.getAllocationPools());\r
-                ans.setAllocationPools(aPools);\r
-            }\r
-            if (s.equals("host_routes")) {\r
-                List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
-                hRoutes.addAll(this.getHostRoutes());\r
-                ans.setHostRoutes(hRoutes);\r
-            }\r
-            if (s.equals("enable_dhcp")) {\r
-                ans.setEnableDHCP(this.getEnableDHCP());\r
-            }\r
-            if (s.equals("tenant_id")) {\r
-                ans.setTenantID(this.getTenantID());\r
-            }\r
-        }\r
-        return ans;\r
-    }\r
-\r
-    /* test to see if the cidr address used to define this subnet\r
-     * is a valid network address (an necessary condition when creating\r
-     * a new subnet)\r
-     */\r
-    public boolean isValidCIDR() {\r
-        try {\r
-            SubnetUtils util = new SubnetUtils(cidr);\r
-            SubnetInfo info = util.getInfo();\r
-            if (!info.getNetworkAddress().equals(info.getAddress())) {\r
-                return false;\r
-            }\r
-        } catch (Exception e) {\r
-            return false;\r
-        }\r
-        return true;\r
-    }\r
-\r
-    /* test to see if the gateway IP specified overlaps with specified\r
-     * allocation pools (an error condition when creating a new subnet\r
-     * or assigning a gateway IP)\r
-     */\r
-    public boolean gatewayIP_Pool_overlap() {\r
-        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
-        while (i.hasNext()) {\r
-            NeutronSubnet_IPAllocationPool pool = i.next();\r
-            if (pool.contains(gatewayIP)) {\r
-                return true;\r
-            }\r
-        }\r
-        return false;\r
-    }\r
-\r
-    public boolean initDefaults() {\r
-        if (enableDHCP == null) {\r
-            enableDHCP = true;\r
-        }\r
-        if (ipVersion == null) {\r
-            ipVersion = 4;\r
-        }\r
-        gatewayIPAssigned = false;\r
-        dnsNameservers = new ArrayList<String>();\r
-        allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
-        hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
-        try {\r
-            SubnetUtils util = new SubnetUtils(cidr);\r
-            SubnetInfo info = util.getInfo();\r
-            if (gatewayIP == null) {\r
-                gatewayIP = info.getLowAddress();\r
-            }\r
-            if (allocationPools.size() < 1) {\r
-                NeutronSubnet_IPAllocationPool source =\r
-                    new NeutronSubnet_IPAllocationPool(info.getLowAddress(),\r
-                            info.getHighAddress());\r
-                allocationPools = source.splitPool(gatewayIP);\r
-            }\r
-        } catch (Exception e) {\r
-            return false;\r
-        }\r
-        return true;\r
-    }\r
-\r
-    public List<NeutronPort> getPortsInSubnet() {\r
-        return myPorts;\r
-    }\r
-\r
-    public void addPort(NeutronPort port) {\r
-        myPorts.add(port);\r
-    }\r
-\r
-    public void removePort(NeutronPort port) {\r
-        myPorts.remove(port);\r
-    }\r
-\r
-    /* this method tests to see if the supplied IPv4 address\r
-     * is valid for this subnet or not\r
-     */\r
-    public boolean isValidIP(String ipAddress) {\r
-        try {\r
-            SubnetUtils util = new SubnetUtils(cidr);\r
-            SubnetInfo info = util.getInfo();\r
-            return info.isInRange(ipAddress);\r
-        } catch (Exception e) {\r
-            return false;\r
-        }\r
-    }\r
-\r
-    /* test to see if the supplied IPv4 address is part of one of the\r
-     * available allocation pools or not\r
-     */\r
-    public boolean isIPInUse(String ipAddress) {\r
-        if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) {\r
-            return false;\r
-        }\r
-        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
-        while (i.hasNext()) {\r
-            NeutronSubnet_IPAllocationPool pool = i.next();\r
-            if (pool.contains(ipAddress)) {\r
-                return false;\r
-            }\r
-        }\r
-        return true;\r
-    }\r
-\r
-    /* method to get the lowest available address of the subnet.\r
-     * go through all the allocation pools and keep the lowest of their\r
-     * low addresses.\r
-     */\r
-    public String getLowAddr() {\r
-        String ans = null;\r
-        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
-        while (i.hasNext()) {\r
-            NeutronSubnet_IPAllocationPool pool = i.next();\r
-            if (ans == null) {\r
-                ans = pool.getPoolStart();\r
-            }\r
-            else\r
-                if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <\r
-                        NeutronSubnet_IPAllocationPool.convert(ans)) {\r
-                    ans = pool.getPoolStart();\r
-                }\r
-        }\r
-        return ans;\r
-    }\r
-\r
-    /*\r
-     * allocate the parameter address.  Because this uses an iterator to\r
-     * check the instance's list of allocation pools and we want to modify\r
-     * pools while the iterator is being used, it is necessary to\r
-     * build a new list of allocation pools and replace the list when\r
-     * finished (otherwise a split will cause undefined iterator behavior.\r
-     */\r
-    public void allocateIP(String ipAddress) {\r
-        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
-        List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>();    // we have to modify a separate list\r
-        while (i.hasNext()) {\r
-            NeutronSubnet_IPAllocationPool pool = i.next();\r
-            /* if the pool contains a single address element and we are allocating it\r
-             * then we don't need to copy the pool over.  Otherwise, we need to possibly\r
-             * split the pool and add both pieces to the new list\r
-             */\r
-            if (!(pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&\r
-                    pool.getPoolStart().equalsIgnoreCase(ipAddress))) {\r
-                if (pool.contains(ipAddress)) {\r
-                    List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);\r
-                    newList.addAll(pools);\r
-                } else {\r
-                    newList.add(pool);\r
-                }\r
-            }\r
-        }\r
-        allocationPools = newList;\r
-    }\r
-\r
-    /*\r
-     * release an IP address back to the subnet.  Although an iterator\r
-     * is used, the list is not modified until the iterator is complete, so\r
-     * an extra list is not necessary.\r
-     */\r
-    public void releaseIP(String ipAddress) {\r
-        NeutronSubnet_IPAllocationPool lPool = null;\r
-        NeutronSubnet_IPAllocationPool hPool = null;\r
-        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
-        long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);\r
-        //look for lPool where ipAddr - 1 is high address\r
-        //look for hPool where ipAddr + 1 is low address\r
-        while (i.hasNext()) {\r
-            NeutronSubnet_IPAllocationPool pool = i.next();\r
-            long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());\r
-            long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());\r
-            if (sIP+1 == lIP) {\r
-                hPool = pool;\r
-            }\r
-            if (sIP-1 == hIP) {\r
-                lPool = pool;\r
-            }\r
-        }\r
-        //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high\r
-        if (lPool == null && hPool == null) {\r
-            allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));\r
-        }\r
-        //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr\r
-        if (lPool == null && hPool != null) {\r
-            hPool.setPoolStart(ipAddress);\r
-        }\r
-        //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr\r
-        if (lPool != null && hPool == null) {\r
-            lPool.setPoolEnd(ipAddress);\r
-        }\r
-        //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool\r
-        //        where low address = lPool.low address and high address = hPool.high Address\r
-        if (lPool != null && hPool != null) {\r
-            allocationPools.remove(lPool);\r
-            allocationPools.remove(hPool);\r
-            allocationPools.add(new NeutronSubnet_IPAllocationPool(\r
-                    lPool.getPoolStart(), hPool.getPoolEnd()));\r
-        }\r
-    }\r
-\r
-    public void setGatewayIPAllocated() {\r
-        gatewayIPAssigned = true;\r
-    }\r
-\r
-    public void resetGatewayIPAllocated() {\r
-        gatewayIPAssigned = false;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSubnet {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement (name="id")
+    String subnetUUID;
+
+    @XmlElement (name="network_id")
+    String networkUUID;
+
+    @XmlElement (name="name")
+    String name;
+
+    @XmlElement (defaultValue="4", name="ip_version")
+    Integer ipVersion;
+
+    @XmlElement (name="cidr")
+    String cidr;
+
+    @XmlElement (name="gateway_ip")
+    String gatewayIP;
+
+    @XmlElement (name="dns_nameservers")
+    List<String> dnsNameservers;
+
+    @XmlElement (name="allocation_pools")
+    List<NeutronSubnet_IPAllocationPool> allocationPools;
+
+    @XmlElement (name="host_routes")
+    List<NeutronSubnet_HostRoute> hostRoutes;
+
+    @XmlElement (defaultValue="true", name="enable_dhcp")
+    Boolean enableDHCP;
+
+    @XmlElement (name="tenant_id")
+    String tenantID;
+
+    /* stores the OpenStackPorts associated with an instance
+     * used to determine if that instance can be deleted.
+     */
+    List<NeutronPort> myPorts;
+
+    boolean gatewayIPAssigned;
+
+    public NeutronSubnet() {
+        myPorts = new ArrayList<NeutronPort>();
+    }
+
+    public String getID() { return subnetUUID; }
+
+    public String getSubnetUUID() {
+        return subnetUUID;
+    }
+
+    public void setSubnetUUID(String subnetUUID) {
+        this.subnetUUID = subnetUUID;
+    }
+
+    public String getNetworkUUID() {
+        return networkUUID;
+    }
+
+    public void setNetworkUUID(String networkUUID) {
+        this.networkUUID = networkUUID;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getIpVersion() {
+        return ipVersion;
+    }
+
+    public void setIpVersion(Integer ipVersion) {
+        this.ipVersion = ipVersion;
+    }
+
+    public String getCidr() {
+        return cidr;
+    }
+
+    public void setCidr(String cidr) {
+        this.cidr = cidr;
+    }
+
+    public String getGatewayIP() {
+        return gatewayIP;
+    }
+
+    public void setGatewayIP(String gatewayIP) {
+        this.gatewayIP = gatewayIP;
+    }
+
+    public List<String> getDnsNameservers() {
+        return dnsNameservers;
+    }
+
+    public void setDnsNameservers(List<String> dnsNameservers) {
+        this.dnsNameservers = dnsNameservers;
+    }
+
+    public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {
+        return allocationPools;
+    }
+
+    public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {
+        this.allocationPools = allocationPools;
+    }
+
+    public List<NeutronSubnet_HostRoute> getHostRoutes() {
+        return hostRoutes;
+    }
+
+    public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {
+        this.hostRoutes = hostRoutes;
+    }
+
+    public boolean isEnableDHCP() {
+        if (enableDHCP == null) {
+            return true;
+        }
+        return enableDHCP;
+    }
+
+    public Boolean getEnableDHCP() { return enableDHCP; }
+
+    public void setEnableDHCP(Boolean newValue) {
+            enableDHCP = newValue;
+    }
+
+    public String getTenantID() {
+        return tenantID;
+    }
+
+    public void setTenantID(String tenantID) {
+        this.tenantID = tenantID;
+    }
+
+    /**
+     * This method copies selected fields from the object and returns them
+     * as a new object, suitable for marshaling.
+     *
+     * @param fields
+     *            List of attributes to be extracted
+     * @return an OpenStackSubnets object with only the selected fields
+     * populated
+     */
+
+    public NeutronSubnet extractFields(List<String> fields) {
+        NeutronSubnet ans = new NeutronSubnet();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setSubnetUUID(this.getSubnetUUID());
+            }
+            if (s.equals("network_id")) {
+                ans.setNetworkUUID(this.getNetworkUUID());
+            }
+            if (s.equals("name")) {
+                ans.setName(this.getName());
+            }
+            if (s.equals("ip_version")) {
+                ans.setIpVersion(this.getIpVersion());
+            }
+            if (s.equals("cidr")) {
+                ans.setCidr(this.getCidr());
+            }
+            if (s.equals("gateway_ip")) {
+                ans.setGatewayIP(this.getGatewayIP());
+            }
+            if (s.equals("dns_nameservers")) {
+                List<String> nsList = new ArrayList<String>();
+                nsList.addAll(this.getDnsNameservers());
+                ans.setDnsNameservers(nsList);
+            }
+            if (s.equals("allocation_pools")) {
+                List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
+                aPools.addAll(this.getAllocationPools());
+                ans.setAllocationPools(aPools);
+            }
+            if (s.equals("host_routes")) {
+                List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();
+                hRoutes.addAll(this.getHostRoutes());
+                ans.setHostRoutes(hRoutes);
+            }
+            if (s.equals("enable_dhcp")) {
+                ans.setEnableDHCP(this.getEnableDHCP());
+            }
+            if (s.equals("tenant_id")) {
+                ans.setTenantID(this.getTenantID());
+            }
+        }
+        return ans;
+    }
+
+    /* test to see if the cidr address used to define this subnet
+     * is a valid network address (an necessary condition when creating
+     * a new subnet)
+     */
+    public boolean isValidCIDR() {
+        try {
+            SubnetUtils util = new SubnetUtils(cidr);
+            SubnetInfo info = util.getInfo();
+            if (!info.getNetworkAddress().equals(info.getAddress())) {
+                return false;
+            }
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+    /* test to see if the gateway IP specified overlaps with specified
+     * allocation pools (an error condition when creating a new subnet
+     * or assigning a gateway IP)
+     */
+    public boolean gatewayIP_Pool_overlap() {
+        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+        while (i.hasNext()) {
+            NeutronSubnet_IPAllocationPool pool = i.next();
+            if (pool.contains(gatewayIP)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean initDefaults() {
+        if (enableDHCP == null) {
+            enableDHCP = true;
+        }
+        if (ipVersion == null) {
+            ipVersion = 4;
+        }
+        gatewayIPAssigned = false;
+        dnsNameservers = new ArrayList<String>();
+        allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
+        hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();
+        try {
+            SubnetUtils util = new SubnetUtils(cidr);
+            SubnetInfo info = util.getInfo();
+            if (gatewayIP == null) {
+                gatewayIP = info.getLowAddress();
+            }
+            if (allocationPools.size() < 1) {
+                NeutronSubnet_IPAllocationPool source =
+                    new NeutronSubnet_IPAllocationPool(info.getLowAddress(),
+                            info.getHighAddress());
+                allocationPools = source.splitPool(gatewayIP);
+            }
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+    public List<NeutronPort> getPortsInSubnet() {
+        return myPorts;
+    }
+
+    public void addPort(NeutronPort port) {
+        myPorts.add(port);
+    }
+
+    public void removePort(NeutronPort port) {
+        myPorts.remove(port);
+    }
+
+    /* this method tests to see if the supplied IPv4 address
+     * is valid for this subnet or not
+     */
+    public boolean isValidIP(String ipAddress) {
+        try {
+            SubnetUtils util = new SubnetUtils(cidr);
+            SubnetInfo info = util.getInfo();
+            return info.isInRange(ipAddress);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /* test to see if the supplied IPv4 address is part of one of the
+     * available allocation pools or not
+     */
+    public boolean isIPInUse(String ipAddress) {
+        if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) {
+            return false;
+        }
+        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+        while (i.hasNext()) {
+            NeutronSubnet_IPAllocationPool pool = i.next();
+            if (pool.contains(ipAddress)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /* method to get the lowest available address of the subnet.
+     * go through all the allocation pools and keep the lowest of their
+     * low addresses.
+     */
+    public String getLowAddr() {
+        String ans = null;
+        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+        while (i.hasNext()) {
+            NeutronSubnet_IPAllocationPool pool = i.next();
+            if (ans == null) {
+                ans = pool.getPoolStart();
+            }
+            else
+                if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <
+                        NeutronSubnet_IPAllocationPool.convert(ans)) {
+                    ans = pool.getPoolStart();
+                }
+        }
+        return ans;
+    }
+
+    /*
+     * allocate the parameter address.  Because this uses an iterator to
+     * check the instance's list of allocation pools and we want to modify
+     * pools while the iterator is being used, it is necessary to
+     * build a new list of allocation pools and replace the list when
+     * finished (otherwise a split will cause undefined iterator behavior.
+     */
+    public void allocateIP(String ipAddress) {
+        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+        List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>();    // we have to modify a separate list
+        while (i.hasNext()) {
+            NeutronSubnet_IPAllocationPool pool = i.next();
+            /* if the pool contains a single address element and we are allocating it
+             * then we don't need to copy the pool over.  Otherwise, we need to possibly
+             * split the pool and add both pieces to the new list
+             */
+            if (!(pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&
+                    pool.getPoolStart().equalsIgnoreCase(ipAddress))) {
+                if (pool.contains(ipAddress)) {
+                    List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);
+                    newList.addAll(pools);
+                } else {
+                    newList.add(pool);
+                }
+            }
+        }
+        allocationPools = newList;
+    }
+
+    /*
+     * release an IP address back to the subnet.  Although an iterator
+     * is used, the list is not modified until the iterator is complete, so
+     * an extra list is not necessary.
+     */
+    public void releaseIP(String ipAddress) {
+        NeutronSubnet_IPAllocationPool lPool = null;
+        NeutronSubnet_IPAllocationPool hPool = null;
+        Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+        long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);
+        //look for lPool where ipAddr - 1 is high address
+        //look for hPool where ipAddr + 1 is low address
+        while (i.hasNext()) {
+            NeutronSubnet_IPAllocationPool pool = i.next();
+            long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());
+            long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());
+            if (sIP+1 == lIP) {
+                hPool = pool;
+            }
+            if (sIP-1 == hIP) {
+                lPool = pool;
+            }
+        }
+        //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high
+        if (lPool == null && hPool == null) {
+            allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));
+        }
+        //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr
+        if (lPool == null && hPool != null) {
+            hPool.setPoolStart(ipAddress);
+        }
+        //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr
+        if (lPool != null && hPool == null) {
+            lPool.setPoolEnd(ipAddress);
+        }
+        //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool
+        //        where low address = lPool.low address and high address = hPool.high Address
+        if (lPool != null && hPool != null) {
+            allocationPools.remove(lPool);
+            allocationPools.remove(hPool);
+            allocationPools.add(new NeutronSubnet_IPAllocationPool(
+                    lPool.getPoolStart(), hPool.getPoolEnd()));
+        }
+    }
+
+    public void setGatewayIPAllocated() {
+        gatewayIPAssigned = true;
+    }
+
+    public void resetGatewayIPAllocated() {
+        gatewayIPAssigned = false;
+    }
+}
index c1084297ba0528526ba0b3f4b2b07fde529626fd..75238c1ad97956de49a0d77ab1b0f2ac76d255d8 100644 (file)
@@ -1,29 +1,29 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronSubnet_HostRoute {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="destination")\r
-    String destination;\r
-\r
-    @XmlElement(name="nexthop")\r
-    String nextHop;\r
-\r
-    public NeutronSubnet_HostRoute() { }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronSubnet_HostRoute {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="destination")
+    String destination;
+
+    @XmlElement(name="nexthop")
+    String nextHop;
+
+    public NeutronSubnet_HostRoute() { }
+}
index b4bbd11704c5f36f97bfa6ca89541022b93988f0..7829ba2199aac43b5e7ac99c2fa730d656436562 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronSubnet_IPAllocationPool {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="start")\r
-    String poolStart;\r
-\r
-    @XmlElement(name="end")\r
-    String poolEnd;\r
-\r
-    public NeutronSubnet_IPAllocationPool() { }\r
-\r
-    public NeutronSubnet_IPAllocationPool(String lowAddress, String highAddress) {\r
-        poolStart = lowAddress;\r
-        poolEnd = highAddress;\r
-    }\r
-\r
-    public String getPoolStart() {\r
-        return poolStart;\r
-    }\r
-\r
-    public void setPoolStart(String poolStart) {\r
-        this.poolStart = poolStart;\r
-    }\r
-\r
-    public String getPoolEnd() {\r
-        return poolEnd;\r
-    }\r
-\r
-    public void setPoolEnd(String poolEnd) {\r
-        this.poolEnd = poolEnd;\r
-    }\r
-\r
-    /**\r
-     * This method determines if this allocation pool contains the\r
-     * input IPv4 address\r
-     *\r
-     * @param inputString\r
-     *            IPv4 address in dotted decimal format\r
-     * @returns a boolean on whether the pool contains the address or not\r
-     */\r
-\r
-    public boolean contains(String inputString) {\r
-        long inputIP = convert(inputString);\r
-        long startIP = convert(poolStart);\r
-        long endIP = convert(poolEnd);\r
-        return (inputIP >= startIP && inputIP <= endIP);\r
-    }\r
-\r
-    /**\r
-     * This static method converts the supplied IPv4 address to a long\r
-     * integer for comparison\r
-     *\r
-     * @param inputString\r
-     *            IPv4 address in dotted decimal format\r
-     * @returns high-endian representation of the IPv4 address as a long\r
-     */\r
-\r
-    static long convert(String inputString) {\r
-        long ans = 0;\r
-        String[] parts = inputString.split("\\.");\r
-        for (String part: parts) {\r
-            ans <<= 8;\r
-            ans |= Integer.parseInt(part);\r
-        }\r
-        return ans;\r
-    }\r
-\r
-    /**\r
-     * This static method converts the supplied high-ending long back\r
-     * into a dotted decimal representation of an IPv4 address\r
-     *\r
-     * @param l\r
-     *            high-endian representation of the IPv4 address as a long\r
-     * @returns IPv4 address in dotted decimal format\r
-     */\r
-    static String longtoIP(long l) {\r
-        int i;\r
-        String[] parts = new String[4];\r
-        for (i=0; i<4; i++) {\r
-            parts[3-i] = String.valueOf(l & 255);\r
-            l >>= 8;\r
-        }\r
-        return join(parts,".");\r
-    }\r
-\r
-    /*\r
-     * helper routine used by longtoIP\r
-     */\r
-    public static String join(String r[],String d)\r
-    {\r
-        if (r.length == 0) return "";\r
-        StringBuilder sb = new StringBuilder();\r
-        int i;\r
-        for(i=0;i<r.length-1;i++) {\r
-            sb.append(r[i]+d);\r
-        }\r
-        return sb.toString()+r[i];\r
-    }\r
-\r
-    /*\r
-     * This method splits the current instance by removing the supplied\r
-     * parameter.\r
-     *\r
-     * If the parameter is either the low or high address,\r
-     * then that member is adjusted and a list containing just this instance\r
-     * is returned.\r
-     *\r
-     * If the parameter is in the middle of the pool, then\r
-     * create two new instances, one ranging from low to parameter-1\r
-     * the other ranging from parameter+1 to high\r
-     */\r
-    public List<NeutronSubnet_IPAllocationPool> splitPool(String ipAddress) {\r
-        List<NeutronSubnet_IPAllocationPool> ans = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
-        long gIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);\r
-        long sIP = NeutronSubnet_IPAllocationPool.convert(poolStart);\r
-        long eIP = NeutronSubnet_IPAllocationPool.convert(poolEnd);\r
-        long i;\r
-        NeutronSubnet_IPAllocationPool p = new NeutronSubnet_IPAllocationPool();\r
-        boolean poolStarted = false;\r
-        for (i=sIP; i<=eIP; i++) {\r
-            if (i == sIP) {\r
-                if (i != gIP) {\r
-                    p.setPoolStart(poolStart);\r
-                    poolStarted = true;\r
-                }\r
-            }\r
-            if (i == eIP) {\r
-                if (i != gIP) {\r
-                    p.setPoolEnd(poolEnd);\r
-                } else {\r
-                    p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1));\r
-                }\r
-                ans.add(p);\r
-            }\r
-            if (i != sIP && i != eIP) {\r
-                if (i != gIP) {\r
-                    if (!poolStarted) {\r
-                        p.setPoolStart(NeutronSubnet_IPAllocationPool.longtoIP(i));\r
-                        poolStarted = true;\r
-                    }\r
-                } else {\r
-                    p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1));\r
-                    poolStarted = false;\r
-                    ans.add(p);\r
-                    p = new NeutronSubnet_IPAllocationPool();\r
-                }\r
-            }\r
-        }\r
-        return ans;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronSubnet_IPAllocationPool {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="start")
+    String poolStart;
+
+    @XmlElement(name="end")
+    String poolEnd;
+
+    public NeutronSubnet_IPAllocationPool() { }
+
+    public NeutronSubnet_IPAllocationPool(String lowAddress, String highAddress) {
+        poolStart = lowAddress;
+        poolEnd = highAddress;
+    }
+
+    public String getPoolStart() {
+        return poolStart;
+    }
+
+    public void setPoolStart(String poolStart) {
+        this.poolStart = poolStart;
+    }
+
+    public String getPoolEnd() {
+        return poolEnd;
+    }
+
+    public void setPoolEnd(String poolEnd) {
+        this.poolEnd = poolEnd;
+    }
+
+    /**
+     * This method determines if this allocation pool contains the
+     * input IPv4 address
+     *
+     * @param inputString
+     *            IPv4 address in dotted decimal format
+     * @returns a boolean on whether the pool contains the address or not
+     */
+
+    public boolean contains(String inputString) {
+        long inputIP = convert(inputString);
+        long startIP = convert(poolStart);
+        long endIP = convert(poolEnd);
+        return (inputIP >= startIP && inputIP <= endIP);
+    }
+
+    /**
+     * This static method converts the supplied IPv4 address to a long
+     * integer for comparison
+     *
+     * @param inputString
+     *            IPv4 address in dotted decimal format
+     * @returns high-endian representation of the IPv4 address as a long
+     */
+
+    static long convert(String inputString) {
+        long ans = 0;
+        String[] parts = inputString.split("\\.");
+        for (String part: parts) {
+            ans <<= 8;
+            ans |= Integer.parseInt(part);
+        }
+        return ans;
+    }
+
+    /**
+     * This static method converts the supplied high-ending long back
+     * into a dotted decimal representation of an IPv4 address
+     *
+     * @param l
+     *            high-endian representation of the IPv4 address as a long
+     * @returns IPv4 address in dotted decimal format
+     */
+    static String longtoIP(long l) {
+        int i;
+        String[] parts = new String[4];
+        for (i=0; i<4; i++) {
+            parts[3-i] = String.valueOf(l & 255);
+            l >>= 8;
+        }
+        return join(parts,".");
+    }
+
+    /*
+     * helper routine used by longtoIP
+     */
+    public static String join(String r[],String d)
+    {
+        if (r.length == 0) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder();
+        int i;
+        for(i=0;i<r.length-1;i++) {
+            sb.append(r[i]+d);
+        }
+        return sb.toString()+r[i];
+    }
+
+    /*
+     * This method splits the current instance by removing the supplied
+     * parameter.
+     *
+     * If the parameter is either the low or high address,
+     * then that member is adjusted and a list containing just this instance
+     * is returned.
+     *
+     * If the parameter is in the middle of the pool, then
+     * create two new instances, one ranging from low to parameter-1
+     * the other ranging from parameter+1 to high
+     */
+    public List<NeutronSubnet_IPAllocationPool> splitPool(String ipAddress) {
+        List<NeutronSubnet_IPAllocationPool> ans = new ArrayList<NeutronSubnet_IPAllocationPool>();
+        long gIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);
+        long sIP = NeutronSubnet_IPAllocationPool.convert(poolStart);
+        long eIP = NeutronSubnet_IPAllocationPool.convert(poolEnd);
+        long i;
+        NeutronSubnet_IPAllocationPool p = new NeutronSubnet_IPAllocationPool();
+        boolean poolStarted = false;
+        for (i=sIP; i<=eIP; i++) {
+            if (i == sIP) {
+                if (i != gIP) {
+                    p.setPoolStart(poolStart);
+                    poolStarted = true;
+                }
+            }
+            if (i == eIP) {
+                if (i != gIP) {
+                    p.setPoolEnd(poolEnd);
+                } else {
+                    p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1));
+                }
+                ans.add(p);
+            }
+            if (i != sIP && i != eIP) {
+                if (i != gIP) {
+                    if (!poolStarted) {
+                        p.setPoolStart(NeutronSubnet_IPAllocationPool.longtoIP(i));
+                        poolStarted = true;
+                    }
+                } else {
+                    p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1));
+                    poolStarted = false;
+                    ans.add(p);
+                    p = new NeutronSubnet_IPAllocationPool();
+                }
+            }
+        }
+        return ans;
+    }
+}
index 73094793996aa393055bb8c3a7cf0aaf23c4a8c6..6fe7c529942f1cf524320b923282d3b0b60315cc 100644 (file)
@@ -1,49 +1,49 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class Neutron_IPs {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="ip_address")\r
-    String ipAddress;\r
-\r
-    @XmlElement(name="subnet_id")\r
-    String subnetUUID;\r
-\r
-    public Neutron_IPs() { }\r
-\r
-    public Neutron_IPs(String uuid) {\r
-        this.subnetUUID = uuid;\r
-    }\r
-\r
-    public String getIpAddress() {\r
-        return ipAddress;\r
-    }\r
-\r
-    public void setIpAddress(String ipAddress) {\r
-        this.ipAddress = ipAddress;\r
-    }\r
-\r
-    public String getSubnetUUID() {\r
-        return subnetUUID;\r
-    }\r
-\r
-    public void setSubnetUUID(String subnetUUID) {\r
-        this.subnetUUID = subnetUUID;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class Neutron_IPs {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="ip_address")
+    String ipAddress;
+
+    @XmlElement(name="subnet_id")
+    String subnetUUID;
+
+    public Neutron_IPs() { }
+
+    public Neutron_IPs(String uuid) {
+        subnetUUID = uuid;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public void setIpAddress(String ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    public String getSubnetUUID() {
+        return subnetUUID;
+    }
+
+    public void setSubnetUUID(String subnetUUID) {
+        this.subnetUUID = subnetUUID;
+    }
+}
index e0c7dcd2ac7a9e85bc293786b6fd8b1d606fa2cb..df56dbae360654b8252502c19ae3d433a6f5a854 100644 (file)
@@ -3,7 +3,7 @@
     xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
 
   <services>
-    <rest defaultRestSubcontext="/controller/nb/v2/host"/>
+    <rest defaultRestSubcontext="/controller/nb/v2/hosttracker"/>
   </services>
 
   <modules>
index 12a49f0996b2652123ce0eb810a5c685801dbf26..74c13d11f129943ba45e449411adfbc9f09d41e3 100644 (file)
@@ -394,8 +394,8 @@ public class HostTrackerNorthbound {
      * &#x20;&lt;nodeId&gt;00:00:00:00:00:00:00:01&lt;/nodeId&gt;
      * &#x20;&lt;nodeConnectorType&gt;OF&lt;/nodeConnectorType&gt;
      * &#x20;&lt;nodeConnectorId&gt;9&lt;/nodeConnectorId&gt;
-     * &#x20;&lt;vlan&gt;0&lt;/vlan&gt;
-     * &#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
+     * &#x20;&lt;vlan&gt;1&lt;/vlan&gt;
+     * &#x20;&lt;staticHost&gt;true&lt;/staticHost&gt;
      * &lt;/hostConfig&gt;
      *
      * Request body in JSON:
@@ -406,8 +406,8 @@ public class HostTrackerNorthbound {
      * &#x20;"nodeId":"00:00:00:00:00:00:00:01",
      * &#x20;"nodeConnectorType":"OF",
      * &#x20;"nodeConnectorId":"9",
-     * &#x20;"vlan":"0",
-     * &#x20;"staticHost":"false",
+     * &#x20;"vlan":"1",
+     * &#x20;"staticHost":"true",
      * &#x20;"networkAddress":"1.1.1.1"
      * }
      * </pre>
index 7bec2722bf96fd1e9b3b645203aa67c8a6b4f36c..602de9a1c6f28f8e195ed0aa00c78bd82f3da434 100644 (file)
@@ -310,7 +310,7 @@ public class NorthboundIT {
         JSONTokener jt = new JSONTokener(result);
         JSONObject json = new JSONObject(jt);
         JSONArray subnetConfigs = json.getJSONArray("subnetConfig");
-        Assert.assertEquals(subnetConfigs.length(), 0);
+        Assert.assertEquals(subnetConfigs.length(), 1); // should only get the default subnet
 
         // Test GET subnet1 expecting 404
         result = getJsonResult(baseURL + "default/subnet/" + name1);
index ca1389c724d90c36f8a23476daae064f24a998d5..efb86e0542e9b9fcec607b55bdc8fb9742cbf8bb 100644 (file)
@@ -1,52 +1,52 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronFloatingIPRequest {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="floatingip")\r
-    NeutronFloatingIP singletonFloatingIP;\r
-\r
-    @XmlElement(name="floatingips")\r
-    List<NeutronFloatingIP> bulkRequest;\r
-\r
-    NeutronFloatingIPRequest() {\r
-    }\r
-\r
-    NeutronFloatingIPRequest(List<NeutronFloatingIP> bulk) {\r
-        bulkRequest = bulk;\r
-        singletonFloatingIP = null;\r
-    }\r
-\r
-    NeutronFloatingIPRequest(NeutronFloatingIP singleton) {\r
-        bulkRequest = null;\r
-        singletonFloatingIP = singleton;\r
-    }\r
-\r
-    public NeutronFloatingIP getSingleton() {\r
-        return singletonFloatingIP;\r
-    }\r
-\r
-    public boolean isSingleton() {\r
-        return (singletonFloatingIP != null);\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronFloatingIPRequest {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="floatingip")
+    NeutronFloatingIP singletonFloatingIP;
+
+    @XmlElement(name="floatingips")
+    List<NeutronFloatingIP> bulkRequest;
+
+    NeutronFloatingIPRequest() {
+    }
+
+    NeutronFloatingIPRequest(List<NeutronFloatingIP> bulk) {
+        bulkRequest = bulk;
+        singletonFloatingIP = null;
+    }
+
+    NeutronFloatingIPRequest(NeutronFloatingIP singleton) {
+        bulkRequest = null;
+        singletonFloatingIP = singleton;
+    }
+
+    public NeutronFloatingIP getSingleton() {
+        return singletonFloatingIP;
+    }
+
+    public boolean isSingleton() {
+        return (singletonFloatingIP != null);
+    }
+}
index 2b0ad45629967ac7061d8961ff54c16155a17543..680b028f9adf6f4de276188745cbeb6ceb4092b9 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs.<br>\r
- * This class provides REST APIs for managing the open DOVE\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/floatingips")\r
-public class NeutronFloatingIPsNorthbound {\r
-\r
-    private NeutronFloatingIP extractFields(NeutronFloatingIP o, List<String> fields) {\r
-        return o.extractFields(fields);\r
-    }\r
-\r
-    /**\r
-     * Returns a list of all FloatingIPs */\r
-\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response listFloatingIPs(\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields,\r
-            // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
-            @QueryParam("id") String queryID,\r
-            @QueryParam("floating_network_id") String queryFloatingNetworkId,\r
-            @QueryParam("port_id") String queryPortId,\r
-            @QueryParam("fixed_ip_address") String queryFixedIPAddress,\r
-            @QueryParam("floating_ip_address") String queryFloatingIPAddress,\r
-            @QueryParam("tenant_id") String queryTenantID,\r
-            // pagination\r
-            @QueryParam("limit") String limit,\r
-            @QueryParam("marker") String marker,\r
-            @QueryParam("page_reverse") String pageReverse\r
-            // sorting not supported\r
-            ) {\r
-        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
-        if (floatingIPInterface == null) {\r
-            throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        List<NeutronFloatingIP> allFloatingIPs = floatingIPInterface.getAllFloatingIPs();\r
-        List<NeutronFloatingIP> ans = new ArrayList<NeutronFloatingIP>();\r
-        Iterator<NeutronFloatingIP> i = allFloatingIPs.iterator();\r
-        while (i.hasNext()) {\r
-            NeutronFloatingIP oSS = i.next();\r
-            //match filters: TODO provider extension and router extension\r
-            if ((queryID == null || queryID.equals(oSS.getID())) &&\r
-                    (queryFloatingNetworkId == null || queryFloatingNetworkId.equals(oSS.getFloatingNetworkUUID())) &&\r
-                    (queryPortId == null || queryPortId.equals(oSS.getPortUUID())) &&\r
-                    (queryFixedIPAddress == null || queryFixedIPAddress.equals(oSS.getFixedIPAddress())) &&\r
-                    (queryFloatingIPAddress == null || queryFloatingIPAddress.equals(oSS.getFloatingIPAddress())) &&\r
-                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantUUID()))) {\r
-                if (fields.size() > 0)\r
-                    ans.add(extractFields(oSS,fields));\r
-                else\r
-                    ans.add(oSS);\r
-            }\r
-        }\r
-        //TODO: apply pagination to results\r
-        return Response.status(200).entity(\r
-                new NeutronFloatingIPRequest(ans)).build();\r
-    }\r
-\r
-    /**\r
-     * Returns a specific FloatingIP */\r
-\r
-    @Path("{floatingipUUID}")\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response showFloatingIP(\r
-            @PathParam("floatingipUUID") String floatingipUUID,\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields ) {\r
-        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
-        if (floatingIPInterface == null) {\r
-            throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (!floatingIPInterface.floatingIPExists(floatingipUUID))\r
-            return Response.status(404).build();\r
-        if (fields.size() > 0) {\r
-            NeutronFloatingIP ans = floatingIPInterface.getFloatingIP(floatingipUUID);\r
-            return Response.status(200).entity(\r
-                    new NeutronFloatingIPRequest(extractFields(ans, fields))).build();\r
-        } else\r
-            return Response.status(200).entity(\r
-                    new NeutronFloatingIPRequest(floatingIPInterface.getFloatingIP(floatingipUUID))).build();\r
-\r
-    }\r
-\r
-    /**\r
-     * Creates new FloatingIPs */\r
-\r
-    @POST\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    @StatusCodes({\r
-        @ResponseCode(code = 201, condition = "Created"),\r
-        @ResponseCode(code = 400, condition = "Bad Request"),\r
-        @ResponseCode(code = 401, condition = "Unauthorized"),\r
-        @ResponseCode(code = 409, condition = "Conflict"),\r
-        @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response createFloatingIPs(final NeutronFloatingIPRequest input) {\r
-        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
-        if (floatingIPInterface == null) {\r
-            throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD( this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (input.isSingleton()) {\r
-            NeutronFloatingIP singleton = input.getSingleton();\r
-            // check existence of id in cache and return badrequest if exists\r
-            if (floatingIPInterface.floatingIPExists(singleton.getID()))\r
-                return Response.status(400).build();\r
-            // check if the external network is specified, exists, and is an external network\r
-            String externalNetworkUUID = singleton.getFloatingNetworkUUID();\r
-            if (externalNetworkUUID == null)\r
-                return Response.status(400).build();\r
-            if (!networkInterface.networkExists(externalNetworkUUID))\r
-                return Response.status(400).build();\r
-            NeutronNetwork externNetwork = networkInterface.getNetwork(externalNetworkUUID);\r
-            if (!externNetwork.isRouterExternal())\r
-                return Response.status(400).build();\r
-            // if floating IP is specified, make sure it can come from the network\r
-            String floatingIP = singleton.getFloatingIPAddress();\r
-            if (floatingIP != null) {\r
-                if (externNetwork.getSubnets().size() > 1)\r
-                    return Response.status(400).build();\r
-                NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));\r
-                if (!externSubnet.isValidIP(floatingIP))\r
-                    return Response.status(400).build();\r
-                if (externSubnet.isIPInUse(floatingIP))\r
-                    return Response.status(409).build();\r
-            }\r
-            // if port_id is specified, then check that the port exists and has at least one IP\r
-            String port_id = singleton.getPortUUID();\r
-            if (port_id != null) {\r
-                String fixedIP = null;        // used for the fixedIP calculation\r
-                if (!portInterface.portExists(port_id))\r
-                    return Response.status(404).build();\r
-                NeutronPort port = portInterface.getPort(port_id);\r
-                if (port.getFixedIPs().size() < 1)\r
-                    return Response.status(400).build();\r
-                // if there is more than one fixed IP then check for fixed_ip_address\r
-                // and that it is in the list of port addresses\r
-                if (port.getFixedIPs().size() > 1) {\r
-                    fixedIP = singleton.getFixedIPAddress();\r
-                    if (fixedIP == null)\r
-                        return Response.status(400).build();\r
-                    Iterator<Neutron_IPs> i = port.getFixedIPs().iterator();\r
-                    boolean validFixedIP = false;\r
-                    while (i.hasNext() && !validFixedIP) {\r
-                        Neutron_IPs ip = i.next();\r
-                        if (ip.getIpAddress().equals(fixedIP))\r
-                            validFixedIP = true;\r
-                    }\r
-                    if (!validFixedIP)\r
-                        return Response.status(400).build();\r
-                } else {\r
-                    fixedIP = port.getFixedIPs().get(0).getIpAddress();\r
-                    if (singleton.getFixedIPAddress() != null && !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress()))\r
-                        return Response.status(400).build();\r
-                }\r
-                //lastly check that this fixed IP address isn't already used\r
-                if (port.isBoundToFloatingIP(fixedIP))\r
-                    return Response.status(409).build();\r
-                singleton.setFixedIPAddress(fixedIP);\r
-            }\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
-                    int status = service.canCreateFloatingIP(singleton);\r
-                    if (status < 200 || status > 299)\r
-                        return Response.status(status).build();\r
-                }\r
-            }\r
-            floatingIPInterface.addFloatingIP(singleton);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
-                    service.neutronFloatingIPCreated(singleton);\r
-                }\r
-            }\r
-        } else {\r
-            return Response.status(400).build();\r
-        }\r
-        return Response.status(201).entity(input).build();\r
-    }\r
-\r
-    /**\r
-     * Updates a FloatingIP */\r
-\r
-    @Path("{floatingipUUID}")\r
-    @PUT\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Conflict"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response updateFloatingIP(\r
-            @PathParam("floatingipUUID") String floatingipUUID,\r
-            NeutronFloatingIPRequest input\r
-            ) {\r
-        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
-        if (floatingIPInterface == null) {\r
-            throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD( this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (!floatingIPInterface.floatingIPExists(floatingipUUID))\r
-            return Response.status(404).build();\r
-\r
-        NeutronFloatingIP sourceFloatingIP = floatingIPInterface.getFloatingIP(floatingipUUID);\r
-        if (!input.isSingleton())\r
-            return Response.status(400).build();\r
-        NeutronFloatingIP singleton = input.getSingleton();\r
-        if (singleton.getID() != null)\r
-            return Response.status(400).build();\r
-\r
-        NeutronNetwork externNetwork = networkInterface.getNetwork(\r
-                sourceFloatingIP.getFloatingNetworkUUID());\r
-\r
-        // if floating IP is specified, make sure it can come from the network\r
-        String floatingIP = singleton.getFloatingIPAddress();\r
-        if (floatingIP != null) {\r
-            if (externNetwork.getSubnets().size() > 1)\r
-                return Response.status(400).build();\r
-            NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));\r
-            if (!externSubnet.isValidIP(floatingIP))\r
-                return Response.status(400).build();\r
-            if (externSubnet.isIPInUse(floatingIP))\r
-                return Response.status(409).build();\r
-        }\r
-\r
-        // if port_id is specified, then check that the port exists and has at least one IP\r
-        String port_id = singleton.getPortUUID();\r
-        if (port_id != null) {\r
-            String fixedIP = null;        // used for the fixedIP calculation\r
-            if (!portInterface.portExists(port_id))\r
-                return Response.status(404).build();\r
-            NeutronPort port = portInterface.getPort(port_id);\r
-            if (port.getFixedIPs().size() < 1)\r
-                return Response.status(400).build();\r
-            // if there is more than one fixed IP then check for fixed_ip_address\r
-            // and that it is in the list of port addresses\r
-            if (port.getFixedIPs().size() > 1) {\r
-                fixedIP = singleton.getFixedIPAddress();\r
-                if (fixedIP == null)\r
-                    return Response.status(400).build();\r
-                Iterator<Neutron_IPs> i = port.getFixedIPs().iterator();\r
-                boolean validFixedIP = false;\r
-                while (i.hasNext() && !validFixedIP) {\r
-                    Neutron_IPs ip = i.next();\r
-                    if (ip.getIpAddress().equals(fixedIP))\r
-                        validFixedIP = true;\r
-                }\r
-                if (!validFixedIP)\r
-                    return Response.status(400).build();\r
-            } else {\r
-                fixedIP = port.getFixedIPs().get(0).getIpAddress();\r
-                if (singleton.getFixedIPAddress() != null &&\r
-                        !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress()))\r
-                    return Response.status(400).build();\r
-            }\r
-            //lastly check that this fixed IP address isn't already used\r
-            if (port.isBoundToFloatingIP(fixedIP))\r
-                return Response.status(409).build();\r
-            singleton.setFixedIPAddress(fixedIP);\r
-        }\r
-        NeutronFloatingIP target = floatingIPInterface.getFloatingIP(floatingipUUID);\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
-                int status = service.canUpdateFloatingIP(singleton, target);\r
-                if (status < 200 || status > 299)\r
-                    return Response.status(status).build();\r
-            }\r
-        }\r
-        floatingIPInterface.updateFloatingIP(floatingipUUID, singleton);\r
-        target = floatingIPInterface.getFloatingIP(floatingipUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
-                service.neutronFloatingIPUpdated(target);\r
-            }\r
-        }\r
-        return Response.status(200).entity(\r
-                new NeutronFloatingIPRequest(target)).build();\r
-\r
-    }\r
-\r
-    /**\r
-     * Deletes a FloatingIP */\r
-\r
-    @Path("{floatingipUUID}")\r
-    @DELETE\r
-    @StatusCodes({\r
-            @ResponseCode(code = 204, condition = "No Content"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response deleteFloatingIP(\r
-            @PathParam("floatingipUUID") String floatingipUUID) {\r
-        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
-        if (floatingIPInterface == null) {\r
-            throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (!floatingIPInterface.floatingIPExists(floatingipUUID))\r
-            return Response.status(404).build();\r
-        // TODO: need to undo port association if it exists\r
-        NeutronFloatingIP singleton = floatingIPInterface.getFloatingIP(floatingipUUID);\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
-                int status = service.canDeleteFloatingIP(singleton);\r
-                if (status < 200 || status > 299)\r
-                    return Response.status(status).build();\r
-            }\r
-        }\r
-        floatingIPInterface.removeFloatingIP(floatingipUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
-                service.neutronFloatingIPDeleted(singleton);\r
-            }\r
-        }\r
-        return Response.status(204).build();\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+/**
+ * Open DOVE Northbound REST APIs.<br>
+ * This class provides REST APIs for managing the open DOVE
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/floatingips")
+public class NeutronFloatingIPsNorthbound {
+
+    private NeutronFloatingIP extractFields(NeutronFloatingIP o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all FloatingIPs */
+
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response listFloatingIPs(
+            // return fields
+            @QueryParam("fields") List<String> fields,
+            // note: openstack isn't clear about filtering on lists, so we aren't handling them
+            @QueryParam("id") String queryID,
+            @QueryParam("floating_network_id") String queryFloatingNetworkId,
+            @QueryParam("port_id") String queryPortId,
+            @QueryParam("fixed_ip_address") String queryFixedIPAddress,
+            @QueryParam("floating_ip_address") String queryFloatingIPAddress,
+            @QueryParam("tenant_id") String queryTenantID,
+            // pagination
+            @QueryParam("limit") String limit,
+            @QueryParam("marker") String marker,
+            @QueryParam("page_reverse") String pageReverse
+            // sorting not supported
+            ) {
+        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+        if (floatingIPInterface == null) {
+            throw new ServiceUnavailableException("Floating IP CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronFloatingIP> allFloatingIPs = floatingIPInterface.getAllFloatingIPs();
+        List<NeutronFloatingIP> ans = new ArrayList<NeutronFloatingIP>();
+        Iterator<NeutronFloatingIP> i = allFloatingIPs.iterator();
+        while (i.hasNext()) {
+            NeutronFloatingIP oSS = i.next();
+            //match filters: TODO provider extension and router extension
+            if ((queryID == null || queryID.equals(oSS.getID())) &&
+                    (queryFloatingNetworkId == null || queryFloatingNetworkId.equals(oSS.getFloatingNetworkUUID())) &&
+                    (queryPortId == null || queryPortId.equals(oSS.getPortUUID())) &&
+                    (queryFixedIPAddress == null || queryFixedIPAddress.equals(oSS.getFixedIPAddress())) &&
+                    (queryFloatingIPAddress == null || queryFloatingIPAddress.equals(oSS.getFloatingIPAddress())) &&
+                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantUUID()))) {
+                if (fields.size() > 0)
+                    ans.add(extractFields(oSS,fields));
+                else
+                    ans.add(oSS);
+            }
+        }
+        //TODO: apply pagination to results
+        return Response.status(200).entity(
+                new NeutronFloatingIPRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific FloatingIP */
+
+    @Path("{floatingipUUID}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response showFloatingIP(
+            @PathParam("floatingipUUID") String floatingipUUID,
+            // return fields
+            @QueryParam("fields") List<String> fields ) {
+        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+        if (floatingIPInterface == null) {
+            throw new ServiceUnavailableException("Floating IP CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!floatingIPInterface.floatingIPExists(floatingipUUID))
+            return Response.status(404).build();
+        if (fields.size() > 0) {
+            NeutronFloatingIP ans = floatingIPInterface.getFloatingIP(floatingipUUID);
+            return Response.status(200).entity(
+                    new NeutronFloatingIPRequest(extractFields(ans, fields))).build();
+        } else
+            return Response.status(200).entity(
+                    new NeutronFloatingIPRequest(floatingIPInterface.getFloatingIP(floatingipUUID))).build();
+
+    }
+
+    /**
+     * Creates new FloatingIPs */
+
+    @POST
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+        @ResponseCode(code = 201, condition = "Created"),
+        @ResponseCode(code = 400, condition = "Bad Request"),
+        @ResponseCode(code = 401, condition = "Unauthorized"),
+        @ResponseCode(code = 409, condition = "Conflict"),
+        @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response createFloatingIPs(final NeutronFloatingIPRequest input) {
+        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+        if (floatingIPInterface == null) {
+            throw new ServiceUnavailableException("Floating IP CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD( this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (input.isSingleton()) {
+            NeutronFloatingIP singleton = input.getSingleton();
+            // check existence of id in cache and return badrequest if exists
+            if (floatingIPInterface.floatingIPExists(singleton.getID()))
+                return Response.status(400).build();
+            // check if the external network is specified, exists, and is an external network
+            String externalNetworkUUID = singleton.getFloatingNetworkUUID();
+            if (externalNetworkUUID == null)
+                return Response.status(400).build();
+            if (!networkInterface.networkExists(externalNetworkUUID))
+                return Response.status(400).build();
+            NeutronNetwork externNetwork = networkInterface.getNetwork(externalNetworkUUID);
+            if (!externNetwork.isRouterExternal())
+                return Response.status(400).build();
+            // if floating IP is specified, make sure it can come from the network
+            String floatingIP = singleton.getFloatingIPAddress();
+            if (floatingIP != null) {
+                if (externNetwork.getSubnets().size() > 1)
+                    return Response.status(400).build();
+                NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));
+                if (!externSubnet.isValidIP(floatingIP))
+                    return Response.status(400).build();
+                if (externSubnet.isIPInUse(floatingIP))
+                    return Response.status(409).build();
+            }
+            // if port_id is specified, then check that the port exists and has at least one IP
+            String port_id = singleton.getPortUUID();
+            if (port_id != null) {
+                String fixedIP = null;        // used for the fixedIP calculation
+                if (!portInterface.portExists(port_id))
+                    return Response.status(404).build();
+                NeutronPort port = portInterface.getPort(port_id);
+                if (port.getFixedIPs().size() < 1)
+                    return Response.status(400).build();
+                // if there is more than one fixed IP then check for fixed_ip_address
+                // and that it is in the list of port addresses
+                if (port.getFixedIPs().size() > 1) {
+                    fixedIP = singleton.getFixedIPAddress();
+                    if (fixedIP == null)
+                        return Response.status(400).build();
+                    Iterator<Neutron_IPs> i = port.getFixedIPs().iterator();
+                    boolean validFixedIP = false;
+                    while (i.hasNext() && !validFixedIP) {
+                        Neutron_IPs ip = i.next();
+                        if (ip.getIpAddress().equals(fixedIP))
+                            validFixedIP = true;
+                    }
+                    if (!validFixedIP)
+                        return Response.status(400).build();
+                } else {
+                    fixedIP = port.getFixedIPs().get(0).getIpAddress();
+                    if (singleton.getFixedIPAddress() != null && !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress()))
+                        return Response.status(400).build();
+                }
+                //lastly check that this fixed IP address isn't already used
+                if (port.isBoundToFloatingIP(fixedIP))
+                    return Response.status(409).build();
+                singleton.setFixedIPAddress(fixedIP);
+            }
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+                    int status = service.canCreateFloatingIP(singleton);
+                    if (status < 200 || status > 299)
+                        return Response.status(status).build();
+                }
+            }
+            floatingIPInterface.addFloatingIP(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+                    service.neutronFloatingIPCreated(singleton);
+                }
+            }
+        } else {
+            return Response.status(400).build();
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a FloatingIP */
+
+    @Path("{floatingipUUID}")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response updateFloatingIP(
+            @PathParam("floatingipUUID") String floatingipUUID,
+            NeutronFloatingIPRequest input
+            ) {
+        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+        if (floatingIPInterface == null) {
+            throw new ServiceUnavailableException("Floating IP CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD( this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!floatingIPInterface.floatingIPExists(floatingipUUID))
+            return Response.status(404).build();
+
+        NeutronFloatingIP sourceFloatingIP = floatingIPInterface.getFloatingIP(floatingipUUID);
+        if (!input.isSingleton())
+            return Response.status(400).build();
+        NeutronFloatingIP singleton = input.getSingleton();
+        if (singleton.getID() != null)
+            return Response.status(400).build();
+
+        NeutronNetwork externNetwork = networkInterface.getNetwork(
+                sourceFloatingIP.getFloatingNetworkUUID());
+
+        // if floating IP is specified, make sure it can come from the network
+        String floatingIP = singleton.getFloatingIPAddress();
+        if (floatingIP != null) {
+            if (externNetwork.getSubnets().size() > 1)
+                return Response.status(400).build();
+            NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));
+            if (!externSubnet.isValidIP(floatingIP))
+                return Response.status(400).build();
+            if (externSubnet.isIPInUse(floatingIP))
+                return Response.status(409).build();
+        }
+
+        // if port_id is specified, then check that the port exists and has at least one IP
+        String port_id = singleton.getPortUUID();
+        if (port_id != null) {
+            String fixedIP = null;        // used for the fixedIP calculation
+            if (!portInterface.portExists(port_id))
+                return Response.status(404).build();
+            NeutronPort port = portInterface.getPort(port_id);
+            if (port.getFixedIPs().size() < 1)
+                return Response.status(400).build();
+            // if there is more than one fixed IP then check for fixed_ip_address
+            // and that it is in the list of port addresses
+            if (port.getFixedIPs().size() > 1) {
+                fixedIP = singleton.getFixedIPAddress();
+                if (fixedIP == null)
+                    return Response.status(400).build();
+                Iterator<Neutron_IPs> i = port.getFixedIPs().iterator();
+                boolean validFixedIP = false;
+                while (i.hasNext() && !validFixedIP) {
+                    Neutron_IPs ip = i.next();
+                    if (ip.getIpAddress().equals(fixedIP))
+                        validFixedIP = true;
+                }
+                if (!validFixedIP)
+                    return Response.status(400).build();
+            } else {
+                fixedIP = port.getFixedIPs().get(0).getIpAddress();
+                if (singleton.getFixedIPAddress() != null &&
+                        !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress()))
+                    return Response.status(400).build();
+            }
+            //lastly check that this fixed IP address isn't already used
+            if (port.isBoundToFloatingIP(fixedIP))
+                return Response.status(409).build();
+            singleton.setFixedIPAddress(fixedIP);
+        }
+        NeutronFloatingIP target = floatingIPInterface.getFloatingIP(floatingipUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+                int status = service.canUpdateFloatingIP(singleton, target);
+                if (status < 200 || status > 299)
+                    return Response.status(status).build();
+            }
+        }
+        floatingIPInterface.updateFloatingIP(floatingipUUID, singleton);
+        target = floatingIPInterface.getFloatingIP(floatingipUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+                service.neutronFloatingIPUpdated(target);
+            }
+        }
+        return Response.status(200).entity(
+                new NeutronFloatingIPRequest(target)).build();
+
+    }
+
+    /**
+     * Deletes a FloatingIP */
+
+    @Path("{floatingipUUID}")
+    @DELETE
+    @StatusCodes({
+            @ResponseCode(code = 204, condition = "No Content"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response deleteFloatingIP(
+            @PathParam("floatingipUUID") String floatingipUUID) {
+        INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+        if (floatingIPInterface == null) {
+            throw new ServiceUnavailableException("Floating IP CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!floatingIPInterface.floatingIPExists(floatingipUUID))
+            return Response.status(404).build();
+        // TODO: need to undo port association if it exists
+        NeutronFloatingIP singleton = floatingIPInterface.getFloatingIP(floatingipUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+                int status = service.canDeleteFloatingIP(singleton);
+                if (status < 200 || status > 299)
+                    return Response.status(status).build();
+            }
+        }
+        floatingIPInterface.removeFloatingIP(floatingipUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+                service.neutronFloatingIPDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
index 9d449380a5743548bdfb39a240655ada7fd8a59b..cebd3c267dd1a1ad2d3b345f2f97d498046631b0 100644 (file)
@@ -1,55 +1,55 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronNetworkRequest {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="network")\r
-    NeutronNetwork singletonNetwork;\r
-\r
-    @XmlElement(name="networks")\r
-    List<NeutronNetwork> bulkRequest;\r
-\r
-    NeutronNetworkRequest() {\r
-    }\r
-\r
-    NeutronNetworkRequest(List<NeutronNetwork> bulk) {\r
-        bulkRequest = bulk;\r
-        singletonNetwork = null;\r
-    }\r
-\r
-    NeutronNetworkRequest(NeutronNetwork net) {\r
-        singletonNetwork = net;\r
-    }\r
-\r
-    public NeutronNetwork getSingleton() {\r
-        return singletonNetwork;\r
-    }\r
-\r
-    public boolean isSingleton() {\r
-        return (singletonNetwork != null);\r
-    }\r
-\r
-    public List<NeutronNetwork> getBulk() {\r
-        return bulkRequest;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronNetworkRequest {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="network")
+    NeutronNetwork singletonNetwork;
+
+    @XmlElement(name="networks")
+    List<NeutronNetwork> bulkRequest;
+
+    NeutronNetworkRequest() {
+    }
+
+    NeutronNetworkRequest(List<NeutronNetwork> bulk) {
+        bulkRequest = bulk;
+        singletonNetwork = null;
+    }
+
+    NeutronNetworkRequest(NeutronNetwork net) {
+        singletonNetwork = net;
+    }
+
+    public NeutronNetwork getSingleton() {
+        return singletonNetwork;
+    }
+
+    public boolean isSingleton() {
+        return (singletonNetwork != null);
+    }
+
+    public List<NeutronNetwork> getBulk() {
+        return bulkRequest;
+    }
+}
index 383009b9d519366d9ffd3efe17783ad0be7624ad..e8690aa889aee1d449601a3156757d298de9dd72 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.codehaus.enunciate.jaxrs.TypeHint;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs for Network.<br>\r
- * This class provides REST APIs for managing open DOVE internals related to Networks\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/networks")\r
-public class NeutronNetworksNorthbound {\r
-\r
-    private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {\r
-        return o.extractFields(fields);\r
-    }\r
-\r
-    /**\r
-     * Returns a list of all Networks */\r
-\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackNetworks.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized") })\r
-    public Response listNetworks(\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields,\r
-            // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
-            @QueryParam("id") String queryID,\r
-            @QueryParam("name") String queryName,\r
-            @QueryParam("admin_state_up") String queryAdminStateUp,\r
-            @QueryParam("status") String queryStatus,\r
-            @QueryParam("shared") String queryShared,\r
-            @QueryParam("tenant_id") String queryTenantID,\r
-            @QueryParam("router_external") String queryRouterExternal,\r
-            @QueryParam("provider_network_type") String queryProviderNetworkType,\r
-            @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,\r
-            @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,\r
-            // pagination\r
-            @QueryParam("limit") String limit,\r
-            @QueryParam("marker") String marker,\r
-            @QueryParam("page_reverse") String pageReverse\r
-            // sorting not supported\r
-        ) {\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        List<NeutronNetwork> allNetworks = networkInterface.getAllNetworks();\r
-        List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();\r
-        Iterator<NeutronNetwork> i = allNetworks.iterator();\r
-        while (i.hasNext()) {\r
-            NeutronNetwork oSN = i.next();\r
-            //match filters: TODO provider extension\r
-            Boolean bAdminStateUp = null;\r
-            Boolean bShared = null;\r
-            Boolean bRouterExternal = null;\r
-            if (queryAdminStateUp != null)\r
-                bAdminStateUp = Boolean.valueOf(queryAdminStateUp);\r
-            if (queryShared != null)\r
-                bShared = Boolean.valueOf(queryShared);\r
-            if (queryRouterExternal != null)\r
-                bRouterExternal = Boolean.valueOf(queryRouterExternal);\r
-            if ((queryID == null || queryID.equals(oSN.getID())) &&\r
-                    (queryName == null || queryName.equals(oSN.getNetworkName())) &&\r
-                    (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&\r
-                    (queryStatus == null || queryStatus.equals(oSN.getStatus())) &&\r
-                    (bShared == null || bShared.booleanValue() == oSN.isShared()) &&\r
-                    (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&\r
-                    (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {\r
-                if (fields.size() > 0)\r
-                    ans.add(extractFields(oSN,fields));\r
-                else\r
-                    ans.add(oSN);\r
-            }\r
-        }\r
-        //TODO: apply pagination to results\r
-        return Response.status(200).entity(\r
-                new NeutronNetworkRequest(ans)).build();\r
-    }\r
-\r
-    /**\r
-     * Returns a specific Network */\r
-\r
-    @Path("{netUUID}")\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackNetworks.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found") })\r
-    public Response showNetwork(\r
-            @PathParam("netUUID") String netUUID,\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields\r
-            ) {\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (!networkInterface.networkExists(netUUID))\r
-            return Response.status(404).build();\r
-        if (fields.size() > 0) {\r
-            NeutronNetwork ans = networkInterface.getNetwork(netUUID);\r
-            return Response.status(200).entity(\r
-                    new NeutronNetworkRequest(extractFields(ans, fields))).build();\r
-        } else\r
-            return Response.status(200).entity(\r
-                    new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();\r
-    }\r
-\r
-    /**\r
-     * Creates new Networks */\r
-    @POST\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    @TypeHint(NeutronNetwork.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 201, condition = "Created"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized") })\r
-    public Response createNetworks(final NeutronNetworkRequest input) {\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (input.isSingleton()) {\r
-            NeutronNetwork singleton = input.getSingleton();\r
-\r
-            /*\r
-             * network ID can't already exist\r
-             */\r
-            if (networkInterface.networkExists(singleton.getID()))\r
-                return Response.status(400).build();\r
-\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
-                    int status = service.canCreateNetwork(singleton);\r
-                    if (status < 200 || status > 299)\r
-                        return Response.status(status).build();\r
-                }\r
-            }\r
-\r
-            // add network to cache\r
-            networkInterface.addNetwork(singleton);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
-                    service.neutronNetworkCreated(singleton);\r
-                }\r
-            }\r
-\r
-        } else {\r
-            List<NeutronNetwork> bulk = input.getBulk();\r
-            Iterator<NeutronNetwork> i = bulk.iterator();\r
-            HashMap<String, NeutronNetwork> testMap = new HashMap<String, NeutronNetwork>();\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
-            while (i.hasNext()) {\r
-                NeutronNetwork test = i.next();\r
-\r
-                /*\r
-                 * network ID can't already exist, nor can there be an entry for this UUID\r
-                 * already in this bulk request\r
-                 */\r
-                if (networkInterface.networkExists(test.getID()))\r
-                    return Response.status(400).build();\r
-                if (testMap.containsKey(test.getID()))\r
-                    return Response.status(400).build();\r
-                if (instances != null) {\r
-                    for (Object instance: instances) {\r
-                        INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
-                        int status = service.canCreateNetwork(test);\r
-                        if (status < 200 || status > 299)\r
-                            return Response.status(status).build();\r
-                    }\r
-                }\r
-                testMap.put(test.getID(),test);\r
-            }\r
-\r
-            // now that everything passed, add items to the cache\r
-            i = bulk.iterator();\r
-            while (i.hasNext()) {\r
-                NeutronNetwork test = i.next();\r
-                test.initDefaults();\r
-                networkInterface.addNetwork(test);\r
-                if (instances != null) {\r
-                    for (Object instance: instances) {\r
-                        INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
-                        service.neutronNetworkCreated(test);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        return Response.status(201).entity(input).build();\r
-    }\r
-\r
-    /**\r
-     * Updates a Network */\r
-    @Path("{netUUID}")\r
-    @PUT\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackNetworks.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 403, condition = "Forbidden"),\r
-            @ResponseCode(code = 404, condition = "Not Found"), })\r
-    public Response updateNetwork(\r
-            @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input\r
-            ) {\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        /*\r
-         * network has to exist and only a single delta is supported\r
-         */\r
-        if (!networkInterface.networkExists(netUUID))\r
-            return Response.status(404).build();\r
-        if (!input.isSingleton())\r
-            return Response.status(400).build();\r
-        NeutronNetwork delta = input.getSingleton();\r
-\r
-        /*\r
-         * transitions forbidden by Neutron\r
-         */\r
-        if (delta.getID() != null || delta.getTenantID() != null ||\r
-                delta.getStatus() != null)\r
-            return Response.status(400).build();\r
-\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
-                NeutronNetwork original = networkInterface.getNetwork(netUUID);\r
-                int status = service.canUpdateNetwork(delta, original);\r
-                if (status < 200 || status > 299)\r
-                    return Response.status(status).build();\r
-            }\r
-        }\r
-\r
-        // update network object and return the modified object\r
-        networkInterface.updateNetwork(netUUID, delta);\r
-        NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
-                service.neutronNetworkUpdated(updatedSingleton);\r
-            }\r
-        }\r
-        return Response.status(200).entity(\r
-                new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();\r
-    }\r
-\r
-    /**\r
-     * Deletes a Network */\r
-\r
-    @Path("{netUUID}")\r
-    @DELETE\r
-    @StatusCodes({\r
-            @ResponseCode(code = 204, condition = "No Content"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Network In Use") })\r
-    public Response deleteNetwork(\r
-            @PathParam("netUUID") String netUUID) {\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        /*\r
-         * network has to exist and not be in use before it can be removed\r
-         */\r
-        if (!networkInterface.networkExists(netUUID))\r
-            return Response.status(404).build();\r
-        if (networkInterface.networkInUse(netUUID))\r
-            return Response.status(409).build();\r
-\r
-        NeutronNetwork singleton = networkInterface.getNetwork(netUUID);\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
-                int status = service.canDeleteNetwork(singleton);\r
-                if (status < 200 || status > 299)\r
-                    return Response.status(status).build();\r
-            }\r
-        }\r
-        networkInterface.removeNetwork(netUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
-                service.neutronNetworkDeleted(singleton);\r
-            }\r
-        }\r
-        return Response.status(204).build();\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.codehaus.enunciate.jaxrs.TypeHint;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+/**
+ * Open DOVE Northbound REST APIs for Network.<br>
+ * This class provides REST APIs for managing open DOVE internals related to Networks
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/networks")
+public class NeutronNetworksNorthbound {
+
+    private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all Networks */
+
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackNetworks.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized") })
+    public Response listNetworks(
+            // return fields
+            @QueryParam("fields") List<String> fields,
+            // note: openstack isn't clear about filtering on lists, so we aren't handling them
+            @QueryParam("id") String queryID,
+            @QueryParam("name") String queryName,
+            @QueryParam("admin_state_up") String queryAdminStateUp,
+            @QueryParam("status") String queryStatus,
+            @QueryParam("shared") String queryShared,
+            @QueryParam("tenant_id") String queryTenantID,
+            @QueryParam("router_external") String queryRouterExternal,
+            @QueryParam("provider_network_type") String queryProviderNetworkType,
+            @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,
+            @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,
+            // pagination
+            @QueryParam("limit") String limit,
+            @QueryParam("marker") String marker,
+            @QueryParam("page_reverse") String pageReverse
+            // sorting not supported
+        ) {
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronNetwork> allNetworks = networkInterface.getAllNetworks();
+        List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();
+        Iterator<NeutronNetwork> i = allNetworks.iterator();
+        while (i.hasNext()) {
+            NeutronNetwork oSN = i.next();
+            //match filters: TODO provider extension
+            Boolean bAdminStateUp = null;
+            Boolean bShared = null;
+            Boolean bRouterExternal = null;
+            if (queryAdminStateUp != null)
+                bAdminStateUp = Boolean.valueOf(queryAdminStateUp);
+            if (queryShared != null)
+                bShared = Boolean.valueOf(queryShared);
+            if (queryRouterExternal != null)
+                bRouterExternal = Boolean.valueOf(queryRouterExternal);
+            if ((queryID == null || queryID.equals(oSN.getID())) &&
+                    (queryName == null || queryName.equals(oSN.getNetworkName())) &&
+                    (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&
+                    (queryStatus == null || queryStatus.equals(oSN.getStatus())) &&
+                    (bShared == null || bShared.booleanValue() == oSN.isShared()) &&
+                    (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&
+                    (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {
+                if (fields.size() > 0)
+                    ans.add(extractFields(oSN,fields));
+                else
+                    ans.add(oSN);
+            }
+        }
+        //TODO: apply pagination to results
+        return Response.status(200).entity(
+                new NeutronNetworkRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Network */
+
+    @Path("{netUUID}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackNetworks.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found") })
+    public Response showNetwork(
+            @PathParam("netUUID") String netUUID,
+            // return fields
+            @QueryParam("fields") List<String> fields
+            ) {
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!networkInterface.networkExists(netUUID))
+            return Response.status(404).build();
+        if (fields.size() > 0) {
+            NeutronNetwork ans = networkInterface.getNetwork(netUUID);
+            return Response.status(200).entity(
+                    new NeutronNetworkRequest(extractFields(ans, fields))).build();
+        } else
+            return Response.status(200).entity(
+                    new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
+    }
+
+    /**
+     * Creates new Networks */
+    @POST
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @TypeHint(NeutronNetwork.class)
+    @StatusCodes({
+            @ResponseCode(code = 201, condition = "Created"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized") })
+    public Response createNetworks(final NeutronNetworkRequest input) {
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (input.isSingleton()) {
+            NeutronNetwork singleton = input.getSingleton();
+
+            /*
+             * network ID can't already exist
+             */
+            if (networkInterface.networkExists(singleton.getID()))
+                return Response.status(400).build();
+
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                    int status = service.canCreateNetwork(singleton);
+                    if (status < 200 || status > 299)
+                        return Response.status(status).build();
+                }
+            }
+
+            // add network to cache
+            networkInterface.addNetwork(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                    service.neutronNetworkCreated(singleton);
+                }
+            }
+
+        } else {
+            List<NeutronNetwork> bulk = input.getBulk();
+            Iterator<NeutronNetwork> i = bulk.iterator();
+            HashMap<String, NeutronNetwork> testMap = new HashMap<String, NeutronNetwork>();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
+            while (i.hasNext()) {
+                NeutronNetwork test = i.next();
+
+                /*
+                 * network ID can't already exist, nor can there be an entry for this UUID
+                 * already in this bulk request
+                 */
+                if (networkInterface.networkExists(test.getID()))
+                    return Response.status(400).build();
+                if (testMap.containsKey(test.getID()))
+                    return Response.status(400).build();
+                if (instances != null) {
+                    for (Object instance: instances) {
+                        INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                        int status = service.canCreateNetwork(test);
+                        if (status < 200 || status > 299)
+                            return Response.status(status).build();
+                    }
+                }
+                testMap.put(test.getID(),test);
+            }
+
+            // now that everything passed, add items to the cache
+            i = bulk.iterator();
+            while (i.hasNext()) {
+                NeutronNetwork test = i.next();
+                test.initDefaults();
+                networkInterface.addNetwork(test);
+                if (instances != null) {
+                    for (Object instance: instances) {
+                        INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                        service.neutronNetworkCreated(test);
+                    }
+                }
+            }
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Network */
+    @Path("{netUUID}")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackNetworks.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"), })
+    public Response updateNetwork(
+            @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input
+            ) {
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * network has to exist and only a single delta is supported
+         */
+        if (!networkInterface.networkExists(netUUID))
+            return Response.status(404).build();
+        if (!input.isSingleton())
+            return Response.status(400).build();
+        NeutronNetwork delta = input.getSingleton();
+
+        /*
+         * transitions forbidden by Neutron
+         */
+        if (delta.getID() != null || delta.getTenantID() != null ||
+                delta.getStatus() != null)
+            return Response.status(400).build();
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                NeutronNetwork original = networkInterface.getNetwork(netUUID);
+                int status = service.canUpdateNetwork(delta, original);
+                if (status < 200 || status > 299)
+                    return Response.status(status).build();
+            }
+        }
+
+        // update network object and return the modified object
+        networkInterface.updateNetwork(netUUID, delta);
+        NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                service.neutronNetworkUpdated(updatedSingleton);
+            }
+        }
+        return Response.status(200).entity(
+                new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
+    }
+
+    /**
+     * Deletes a Network */
+
+    @Path("{netUUID}")
+    @DELETE
+    @StatusCodes({
+            @ResponseCode(code = 204, condition = "No Content"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Network In Use") })
+    public Response deleteNetwork(
+            @PathParam("netUUID") String netUUID) {
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * network has to exist and not be in use before it can be removed
+         */
+        if (!networkInterface.networkExists(netUUID))
+            return Response.status(404).build();
+        if (networkInterface.networkInUse(netUUID))
+            return Response.status(409).build();
+
+        NeutronNetwork singleton = networkInterface.getNetwork(netUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                int status = service.canDeleteNetwork(singleton);
+                if (status < 200 || status > 299)
+                    return Response.status(status).build();
+            }
+        }
+        networkInterface.removeNetwork(netUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                service.neutronNetworkDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
index 7e2a06be59f668b1109e7ce6e37d7d8dbe9b8e0b..76c39e4294dd05a0ada503edd05d1243c9b436f5 100644 (file)
@@ -1,58 +1,58 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import javax.ws.rs.core.Application;\r
-import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;\r
-\r
-\r
-/**\r
- * This class is an instance of javax.ws.rs.core.Application and is used to return the classes\r
- * that will be instantiated for JAXRS processing. This is necessary\r
- * because package scanning in jersey doesn't yet work in OSGi environment.\r
- *\r
- */\r
-public class NeutronNorthboundRSApplication extends Application {\r
-    @Override\r
-    public Set<Class<?>> getClasses() {\r
-        Set<Class<?>> classes = new HashSet<Class<?>>();\r
-// northbound URIs\r
-        classes.add(NeutronNetworksNorthbound.class);\r
-        classes.add(NeutronSubnetsNorthbound.class);\r
-        classes.add(NeutronPortsNorthbound.class);\r
-        classes.add(NeutronRoutersNorthbound.class);\r
-        classes.add(NeutronFloatingIPsNorthbound.class);\r
-        return classes;\r
-    }\r
-\r
-    @Override\r
-    public Set<Object> getSingletons() {\r
-        MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider();\r
-\r
-        moxyJsonProvider.setAttributePrefix("@");\r
-        moxyJsonProvider.setFormattedOutput(true);\r
-        moxyJsonProvider.setIncludeRoot(false);\r
-        moxyJsonProvider.setMarshalEmptyCollections(true);\r
-        moxyJsonProvider.setValueWrapper("$");\r
-\r
-        Map<String, String> namespacePrefixMapper = new HashMap<String, String>(1);\r
-        namespacePrefixMapper.put("router", "router");        // FIXME: fill in with XSD\r
-        namespacePrefixMapper.put("provider", "provider");    // FIXME: fill in with XSD\r
-        moxyJsonProvider.setNamespacePrefixMapper(namespacePrefixMapper);\r
-        moxyJsonProvider.setNamespaceSeparator(':');\r
-\r
-        HashSet<Object> set = new HashSet<Object>(1);\r
-        set.add(moxyJsonProvider);\r
-        return set;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.ws.rs.core.Application;
+import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
+
+
+/**
+ * This class is an instance of javax.ws.rs.core.Application and is used to return the classes
+ * that will be instantiated for JAXRS processing. This is necessary
+ * because package scanning in jersey doesn't yet work in OSGi environment.
+ *
+ */
+public class NeutronNorthboundRSApplication extends Application {
+    @Override
+    public Set<Class<?>> getClasses() {
+        Set<Class<?>> classes = new HashSet<Class<?>>();
+// northbound URIs
+        classes.add(NeutronNetworksNorthbound.class);
+        classes.add(NeutronSubnetsNorthbound.class);
+        classes.add(NeutronPortsNorthbound.class);
+        classes.add(NeutronRoutersNorthbound.class);
+        classes.add(NeutronFloatingIPsNorthbound.class);
+        return classes;
+    }
+
+    @Override
+    public Set<Object> getSingletons() {
+        MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider();
+
+        moxyJsonProvider.setAttributePrefix("@");
+        moxyJsonProvider.setFormattedOutput(true);
+        moxyJsonProvider.setIncludeRoot(false);
+        moxyJsonProvider.setMarshalEmptyCollections(true);
+        moxyJsonProvider.setValueWrapper("$");
+
+        Map<String, String> namespacePrefixMapper = new HashMap<String, String>(1);
+        namespacePrefixMapper.put("router", "router");        // FIXME: fill in with XSD
+        namespacePrefixMapper.put("provider", "provider");    // FIXME: fill in with XSD
+        moxyJsonProvider.setNamespacePrefixMapper(namespacePrefixMapper);
+        moxyJsonProvider.setNamespaceSeparator(':');
+
+        HashSet<Object> set = new HashSet<Object>(1);
+        set.add(moxyJsonProvider);
+        return set;
+    }
+}
index f6765fb221fbeb9e6c52ad476675cf96bfaf14c2..9b3399d9a8bfe72266843b0d4d8c34d6b163ef52 100644 (file)
@@ -1,55 +1,55 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronPortRequest {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="port")\r
-    NeutronPort singletonPort;\r
-\r
-    @XmlElement(name="ports")\r
-    List<NeutronPort> bulkRequest;\r
-\r
-    NeutronPortRequest() {\r
-    }\r
-\r
-    NeutronPortRequest(List<NeutronPort> bulk) {\r
-        bulkRequest = bulk;\r
-        singletonPort = null;\r
-    }\r
-\r
-    NeutronPortRequest(NeutronPort port) {\r
-        singletonPort = port;\r
-    }\r
-\r
-    public NeutronPort getSingleton() {\r
-        return singletonPort;\r
-    }\r
-\r
-    public boolean isSingleton() {\r
-        return (singletonPort != null);\r
-    }\r
-\r
-    public List<NeutronPort> getBulk() {\r
-        return bulkRequest;\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronPortRequest {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="port")
+    NeutronPort singletonPort;
+
+    @XmlElement(name="ports")
+    List<NeutronPort> bulkRequest;
+
+    NeutronPortRequest() {
+    }
+
+    NeutronPortRequest(List<NeutronPort> bulk) {
+        bulkRequest = bulk;
+        singletonPort = null;
+    }
+
+    NeutronPortRequest(NeutronPort port) {
+        singletonPort = port;
+    }
+
+    public NeutronPort getSingleton() {
+        return singletonPort;
+    }
+
+    public boolean isSingleton() {
+        return (singletonPort != null);
+    }
+
+    public List<NeutronPort> getBulk() {
+        return bulkRequest;
+    }
+}
index f48a70d9d728a512401bc5cbc4efc793548e1e12..08e5dfbb364d6cf7c82b2c677cff3359f533a13b 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs.<br>\r
- * This class provides REST APIs for managing the open DOVE\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/ports")\r
-public class NeutronPortsNorthbound {\r
-\r
-    private NeutronPort extractFields(NeutronPort o, List<String> fields) {\r
-        return o.extractFields(fields);\r
-    }\r
-\r
-    /**\r
-     * Returns a list of all Ports */\r
-\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackPorts.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response listPorts(\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields,\r
-            // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
-            @QueryParam("id") String queryID,\r
-            @QueryParam("network_id") String queryNetworkID,\r
-            @QueryParam("name") String queryName,\r
-            @QueryParam("admin_state_up") String queryAdminStateUp,\r
-            @QueryParam("status") String queryStatus,\r
-            @QueryParam("mac_address") String queryMACAddress,\r
-            @QueryParam("device_id") String queryDeviceID,\r
-            @QueryParam("device_owner") String queryDeviceOwner,\r
-            @QueryParam("tenant_id") String queryTenantID,\r
-            // pagination\r
-            @QueryParam("limit") String limit,\r
-            @QueryParam("marker") String marker,\r
-            @QueryParam("page_reverse") String pageReverse\r
-            // sorting not supported\r
-            ) {\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        List<NeutronPort> allPorts = portInterface.getAllPorts();\r
-        List<NeutronPort> ans = new ArrayList<NeutronPort>();\r
-        Iterator<NeutronPort> i = allPorts.iterator();\r
-        while (i.hasNext()) {\r
-            NeutronPort oSS = i.next();\r
-            if ((queryID == null || queryID.equals(oSS.getID())) &&\r
-                    (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&\r
-                    (queryName == null || queryName.equals(oSS.getName())) &&\r
-                    (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&\r
-                    (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&\r
-                    (queryMACAddress == null || queryMACAddress.equals(oSS.getMacAddress())) &&\r
-                    (queryDeviceID == null || queryDeviceID.equals(oSS.getDeviceID())) &&\r
-                    (queryDeviceOwner == null || queryDeviceOwner.equals(oSS.getDeviceOwner())) &&\r
-                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
-                if (fields.size() > 0)\r
-                    ans.add(extractFields(oSS,fields));\r
-                else\r
-                    ans.add(oSS);\r
-            }\r
-        }\r
-        //TODO: apply pagination to results\r
-        return Response.status(200).entity(\r
-                new NeutronPortRequest(ans)).build();\r
-    }\r
-\r
-    /**\r
-     * Returns a specific Port */\r
-\r
-    @Path("{portUUID}")\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackPorts.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response showPort(\r
-            @PathParam("portUUID") String portUUID,\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields ) {\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (!portInterface.portExists(portUUID))\r
-            return Response.status(404).build();\r
-        if (fields.size() > 0) {\r
-            NeutronPort ans = portInterface.getPort(portUUID);\r
-            return Response.status(200).entity(\r
-                    new NeutronPortRequest(extractFields(ans, fields))).build();\r
-        } else\r
-            return Response.status(200).entity(\r
-                    new NeutronPortRequest(portInterface.getPort(portUUID))).build();\r
-    }\r
-\r
-    /**\r
-     * Creates new Ports */\r
-\r
-    @POST\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackPorts.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 201, condition = "Created"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 403, condition = "Forbidden"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Conflict"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented"),\r
-            @ResponseCode(code = 503, condition = "MAC generation failure") })\r
-    public Response createPorts(final NeutronPortRequest input) {\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (input.isSingleton()) {\r
-            NeutronPort singleton = input.getSingleton();\r
-\r
-            /*\r
-             * the port must be part of an existing network, must not already exist,\r
-             * have a valid MAC and the MAC not be in use\r
-             */\r
-            if (singleton.getNetworkUUID() == null)\r
-                return Response.status(400).build();\r
-            if (portInterface.portExists(singleton.getID()))\r
-                return Response.status(400).build();\r
-            if (!networkInterface.networkExists(singleton.getNetworkUUID()))\r
-                return Response.status(404).build();\r
-            if (singleton.getMacAddress() == null ||\r
-                    !singleton.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))\r
-                return Response.status(400).build();\r
-            if (portInterface.macInUse(singleton.getMacAddress()))\r
-                return Response.status(409).build();\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronPortAware service = (INeutronPortAware) instance;\r
-                    int status = service.canCreatePort(singleton);\r
-                    if (status < 200 || status > 299)\r
-                        return Response.status(status).build();\r
-                }\r
-            }\r
-            /*\r
-             * if fixed IPs are specified, each one has to have an existing subnet ID\r
-             * that is in the same scoping network as the port.  In addition, if an IP\r
-             * address is specified it has to be a valid address for the subnet and not\r
-             * already in use\r
-             */\r
-            List<Neutron_IPs> fixedIPs = singleton.getFixedIPs();\r
-            if (fixedIPs != null && fixedIPs.size() > 0) {\r
-                Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();\r
-                while (fixedIPIterator.hasNext()) {\r
-                    Neutron_IPs ip = fixedIPIterator.next();\r
-                    if (ip.getSubnetUUID() == null)\r
-                        return Response.status(400).build();\r
-                    if (!subnetInterface.subnetExists(ip.getSubnetUUID()))\r
-                        return Response.status(400).build();\r
-                    NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());\r
-                    if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))\r
-                        return Response.status(400).build();\r
-                    if (ip.getIpAddress() != null) {\r
-                        if (!subnet.isValidIP(ip.getIpAddress()))\r
-                            return Response.status(400).build();\r
-                        if (subnet.isIPInUse(ip.getIpAddress()))\r
-                            return Response.status(409).build();\r
-                    }\r
-                }\r
-            }\r
-\r
-            // add the port to the cache\r
-            portInterface.addPort(singleton);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronPortAware service = (INeutronPortAware) instance;\r
-                    service.neutronPortCreated(singleton);\r
-                }\r
-            }\r
-        } else {\r
-            List<NeutronPort> bulk = input.getBulk();\r
-            Iterator<NeutronPort> i = bulk.iterator();\r
-            HashMap<String, NeutronPort> testMap = new HashMap<String, NeutronPort>();\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
-            while (i.hasNext()) {\r
-                NeutronPort test = i.next();\r
-\r
-                /*\r
-                 * the port must be part of an existing network, must not already exist,\r
-                 * have a valid MAC and the MAC not be in use.  Further the bulk request\r
-                 * can't already contain a new port with the same UUID\r
-                 */\r
-                if (portInterface.portExists(test.getID()))\r
-                    return Response.status(400).build();\r
-                if (testMap.containsKey(test.getID()))\r
-                    return Response.status(400).build();\r
-                for (NeutronPort check : testMap.values()) {\r
-                    if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress()))\r
-                        return Response.status(409).build();\r
-                    for (Neutron_IPs test_fixedIP : test.getFixedIPs()) {\r
-                        for (Neutron_IPs check_fixedIP : check.getFixedIPs()) {\r
-                            if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress()))\r
-                                return Response.status(409).build();\r
-                        }\r
-                    }\r
-                }\r
-                testMap.put(test.getID(), test);\r
-                if (!networkInterface.networkExists(test.getNetworkUUID()))\r
-                    return Response.status(404).build();\r
-                if (!test.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))\r
-                    return Response.status(400).build();\r
-                if (portInterface.macInUse(test.getMacAddress()))\r
-                    return Response.status(409).build();\r
-                if (instances != null) {\r
-                    for (Object instance : instances) {\r
-                        INeutronPortAware service = (INeutronPortAware) instance;\r
-                        int status = service.canCreatePort(test);\r
-                        if (status < 200 || status > 299)\r
-                            return Response.status(status).build();\r
-                    }\r
-                }\r
-                /*\r
-                 * if fixed IPs are specified, each one has to have an existing subnet ID\r
-                 * that is in the same scoping network as the port.  In addition, if an IP\r
-                 * address is specified it has to be a valid address for the subnet and not\r
-                 * already in use (or be the gateway IP address of the subnet)\r
-                 */\r
-                List<Neutron_IPs> fixedIPs = test.getFixedIPs();\r
-                if (fixedIPs != null && fixedIPs.size() > 0) {\r
-                    Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();\r
-                    while (fixedIPIterator.hasNext()) {\r
-                        Neutron_IPs ip = fixedIPIterator.next();\r
-                        if (ip.getSubnetUUID() == null)\r
-                            return Response.status(400).build();\r
-                        if (!subnetInterface.subnetExists(ip.getSubnetUUID()))\r
-                            return Response.status(400).build();\r
-                        NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());\r
-                        if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))\r
-                            return Response.status(400).build();\r
-                        if (ip.getIpAddress() != null) {\r
-                            if (!subnet.isValidIP(ip.getIpAddress()))\r
-                                return Response.status(400).build();\r
-                            //TODO: need to add consideration for a fixed IP being assigned the same address as a allocated IP in the\r
-                            //same bulk create\r
-                            if (subnet.isIPInUse(ip.getIpAddress()))\r
-                                return Response.status(409).build();\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-\r
-            //once everything has passed, then we can add to the cache\r
-            i = bulk.iterator();\r
-            while (i.hasNext()) {\r
-                NeutronPort test = i.next();\r
-                portInterface.addPort(test);\r
-                if (instances != null) {\r
-                    for (Object instance : instances) {\r
-                        INeutronPortAware service = (INeutronPortAware) instance;\r
-                        service.neutronPortCreated(test);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        return Response.status(201).entity(input).build();\r
-    }\r
-\r
-    /**\r
-     * Updates a Port */\r
-\r
-    @Path("{portUUID}")\r
-    @PUT\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackPorts.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 403, condition = "Forbidden"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Conflict"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response updatePort(\r
-            @PathParam("portUUID") String portUUID,\r
-            NeutronPortRequest input\r
-            ) {\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        // port has to exist and only a single delta is supported\r
-        if (!portInterface.portExists(portUUID))\r
-            return Response.status(404).build();\r
-        NeutronPort target = portInterface.getPort(portUUID);\r
-        if (!input.isSingleton())\r
-            return Response.status(400).build();\r
-        NeutronPort singleton = input.getSingleton();\r
-        NeutronPort original = portInterface.getPort(portUUID);\r
-\r
-        // deltas restricted by Neutron\r
-        if (singleton.getID() != null || singleton.getTenantID() != null ||\r
-                singleton.getStatus() != null)\r
-            return Response.status(400).build();\r
-\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronPortAware service = (INeutronPortAware) instance;\r
-                int status = service.canUpdatePort(singleton, original);\r
-                if (status < 200 || status > 299)\r
-                    return Response.status(status).build();\r
-            }\r
-        }\r
-\r
-        // Verify the new fixed ips are valid\r
-        List<Neutron_IPs> fixedIPs = singleton.getFixedIPs();\r
-        if (fixedIPs != null && fixedIPs.size() > 0) {\r
-            Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();\r
-            while (fixedIPIterator.hasNext()) {\r
-                Neutron_IPs ip = fixedIPIterator.next();\r
-                if (ip.getSubnetUUID() == null)\r
-                    return Response.status(400).build();\r
-                if (!subnetInterface.subnetExists(ip.getSubnetUUID()))\r
-                    return Response.status(400).build();\r
-                NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());\r
-                if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))\r
-                    return Response.status(400).build();\r
-                if (ip.getIpAddress() != null) {\r
-                    if (!subnet.isValidIP(ip.getIpAddress()))\r
-                        return Response.status(400).build();\r
-                    if (subnet.isIPInUse(ip.getIpAddress()))\r
-                        return Response.status(409).build();\r
-                }\r
-            }\r
-        }\r
-\r
-//        TODO: Support change of security groups\r
-        // update the port and return the modified object\r
-        portInterface.updatePort(portUUID, singleton);\r
-        NeutronPort updatedPort = portInterface.getPort(portUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronPortAware service = (INeutronPortAware) instance;\r
-                service.neutronPortUpdated(updatedPort);\r
-            }\r
-        }\r
-        return Response.status(200).entity(\r
-                new NeutronPortRequest(updatedPort)).build();\r
-\r
-    }\r
-\r
-    /**\r
-     * Deletes a Port */\r
-\r
-    @Path("{portUUID}")\r
-    @DELETE\r
-    @StatusCodes({\r
-        @ResponseCode(code = 204, condition = "No Content"),\r
-        @ResponseCode(code = 401, condition = "Unauthorized"),\r
-        @ResponseCode(code = 403, condition = "Forbidden"),\r
-        @ResponseCode(code = 404, condition = "Not Found"),\r
-        @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response deletePort(\r
-            @PathParam("portUUID") String portUUID) {\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        // port has to exist and not be owned by anyone.  then it can be removed from the cache\r
-        if (!portInterface.portExists(portUUID))\r
-            return Response.status(404).build();\r
-        NeutronPort port = portInterface.getPort(portUUID);\r
-        if (port.getDeviceID() != null ||\r
-                port.getDeviceOwner() != null)\r
-            Response.status(403).build();\r
-        NeutronPort singleton = portInterface.getPort(portUUID);\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronPortAware service = (INeutronPortAware) instance;\r
-                int status = service.canDeletePort(singleton);\r
-                if (status < 200 || status > 299)\r
-                    return Response.status(status).build();\r
-            }\r
-        }\r
-        portInterface.removePort(portUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronPortAware service = (INeutronPortAware) instance;\r
-                service.neutronPortDeleted(singleton);\r
-            }\r
-        }\r
-        return Response.status(204).build();\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+/**
+ * Open DOVE Northbound REST APIs.<br>
+ * This class provides REST APIs for managing the open DOVE
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/ports")
+public class NeutronPortsNorthbound {
+
+    private NeutronPort extractFields(NeutronPort o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all Ports */
+
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackPorts.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response listPorts(
+            // return fields
+            @QueryParam("fields") List<String> fields,
+            // note: openstack isn't clear about filtering on lists, so we aren't handling them
+            @QueryParam("id") String queryID,
+            @QueryParam("network_id") String queryNetworkID,
+            @QueryParam("name") String queryName,
+            @QueryParam("admin_state_up") String queryAdminStateUp,
+            @QueryParam("status") String queryStatus,
+            @QueryParam("mac_address") String queryMACAddress,
+            @QueryParam("device_id") String queryDeviceID,
+            @QueryParam("device_owner") String queryDeviceOwner,
+            @QueryParam("tenant_id") String queryTenantID,
+            // pagination
+            @QueryParam("limit") String limit,
+            @QueryParam("marker") String marker,
+            @QueryParam("page_reverse") String pageReverse
+            // sorting not supported
+            ) {
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronPort> allPorts = portInterface.getAllPorts();
+        List<NeutronPort> ans = new ArrayList<NeutronPort>();
+        Iterator<NeutronPort> i = allPorts.iterator();
+        while (i.hasNext()) {
+            NeutronPort oSS = i.next();
+            if ((queryID == null || queryID.equals(oSS.getID())) &&
+                    (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&
+                    (queryName == null || queryName.equals(oSS.getName())) &&
+                    (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&
+                    (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&
+                    (queryMACAddress == null || queryMACAddress.equals(oSS.getMacAddress())) &&
+                    (queryDeviceID == null || queryDeviceID.equals(oSS.getDeviceID())) &&
+                    (queryDeviceOwner == null || queryDeviceOwner.equals(oSS.getDeviceOwner())) &&
+                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
+                if (fields.size() > 0)
+                    ans.add(extractFields(oSS,fields));
+                else
+                    ans.add(oSS);
+            }
+        }
+        //TODO: apply pagination to results
+        return Response.status(200).entity(
+                new NeutronPortRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Port */
+
+    @Path("{portUUID}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackPorts.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response showPort(
+            @PathParam("portUUID") String portUUID,
+            // return fields
+            @QueryParam("fields") List<String> fields ) {
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!portInterface.portExists(portUUID))
+            return Response.status(404).build();
+        if (fields.size() > 0) {
+            NeutronPort ans = portInterface.getPort(portUUID);
+            return Response.status(200).entity(
+                    new NeutronPortRequest(extractFields(ans, fields))).build();
+        } else
+            return Response.status(200).entity(
+                    new NeutronPortRequest(portInterface.getPort(portUUID))).build();
+    }
+
+    /**
+     * Creates new Ports */
+
+    @POST
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackPorts.class)
+    @StatusCodes({
+            @ResponseCode(code = 201, condition = "Created"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented"),
+            @ResponseCode(code = 503, condition = "MAC generation failure") })
+    public Response createPorts(final NeutronPortRequest input) {
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (input.isSingleton()) {
+            NeutronPort singleton = input.getSingleton();
+
+            /*
+             * the port must be part of an existing network, must not already exist,
+             * have a valid MAC and the MAC not be in use
+             */
+            if (singleton.getNetworkUUID() == null)
+                return Response.status(400).build();
+            if (portInterface.portExists(singleton.getID()))
+                return Response.status(400).build();
+            if (!networkInterface.networkExists(singleton.getNetworkUUID()))
+                return Response.status(404).build();
+            if (singleton.getMacAddress() == null ||
+                    !singleton.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))
+                return Response.status(400).build();
+            if (portInterface.macInUse(singleton.getMacAddress()))
+                return Response.status(409).build();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronPortAware service = (INeutronPortAware) instance;
+                    int status = service.canCreatePort(singleton);
+                    if (status < 200 || status > 299)
+                        return Response.status(status).build();
+                }
+            }
+            /*
+             * if fixed IPs are specified, each one has to have an existing subnet ID
+             * that is in the same scoping network as the port.  In addition, if an IP
+             * address is specified it has to be a valid address for the subnet and not
+             * already in use
+             */
+            List<Neutron_IPs> fixedIPs = singleton.getFixedIPs();
+            if (fixedIPs != null && fixedIPs.size() > 0) {
+                Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
+                while (fixedIPIterator.hasNext()) {
+                    Neutron_IPs ip = fixedIPIterator.next();
+                    if (ip.getSubnetUUID() == null)
+                        return Response.status(400).build();
+                    if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+                        return Response.status(400).build();
+                    NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
+                    if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+                        return Response.status(400).build();
+                    if (ip.getIpAddress() != null) {
+                        if (!subnet.isValidIP(ip.getIpAddress()))
+                            return Response.status(400).build();
+                        if (subnet.isIPInUse(ip.getIpAddress()))
+                            return Response.status(409).build();
+                    }
+                }
+            }
+
+            // add the port to the cache
+            portInterface.addPort(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronPortAware service = (INeutronPortAware) instance;
+                    service.neutronPortCreated(singleton);
+                }
+            }
+        } else {
+            List<NeutronPort> bulk = input.getBulk();
+            Iterator<NeutronPort> i = bulk.iterator();
+            HashMap<String, NeutronPort> testMap = new HashMap<String, NeutronPort>();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+            while (i.hasNext()) {
+                NeutronPort test = i.next();
+
+                /*
+                 * the port must be part of an existing network, must not already exist,
+                 * have a valid MAC and the MAC not be in use.  Further the bulk request
+                 * can't already contain a new port with the same UUID
+                 */
+                if (portInterface.portExists(test.getID()))
+                    return Response.status(400).build();
+                if (testMap.containsKey(test.getID()))
+                    return Response.status(400).build();
+                for (NeutronPort check : testMap.values()) {
+                    if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress()))
+                        return Response.status(409).build();
+                    for (Neutron_IPs test_fixedIP : test.getFixedIPs()) {
+                        for (Neutron_IPs check_fixedIP : check.getFixedIPs()) {
+                            if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress()))
+                                return Response.status(409).build();
+                        }
+                    }
+                }
+                testMap.put(test.getID(), test);
+                if (!networkInterface.networkExists(test.getNetworkUUID()))
+                    return Response.status(404).build();
+                if (!test.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))
+                    return Response.status(400).build();
+                if (portInterface.macInUse(test.getMacAddress()))
+                    return Response.status(409).build();
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronPortAware service = (INeutronPortAware) instance;
+                        int status = service.canCreatePort(test);
+                        if (status < 200 || status > 299)
+                            return Response.status(status).build();
+                    }
+                }
+                /*
+                 * if fixed IPs are specified, each one has to have an existing subnet ID
+                 * that is in the same scoping network as the port.  In addition, if an IP
+                 * address is specified it has to be a valid address for the subnet and not
+                 * already in use (or be the gateway IP address of the subnet)
+                 */
+                List<Neutron_IPs> fixedIPs = test.getFixedIPs();
+                if (fixedIPs != null && fixedIPs.size() > 0) {
+                    Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
+                    while (fixedIPIterator.hasNext()) {
+                        Neutron_IPs ip = fixedIPIterator.next();
+                        if (ip.getSubnetUUID() == null)
+                            return Response.status(400).build();
+                        if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+                            return Response.status(400).build();
+                        NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
+                        if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+                            return Response.status(400).build();
+                        if (ip.getIpAddress() != null) {
+                            if (!subnet.isValidIP(ip.getIpAddress()))
+                                return Response.status(400).build();
+                            //TODO: need to add consideration for a fixed IP being assigned the same address as a allocated IP in the
+                            //same bulk create
+                            if (subnet.isIPInUse(ip.getIpAddress()))
+                                return Response.status(409).build();
+                        }
+                    }
+                }
+            }
+
+            //once everything has passed, then we can add to the cache
+            i = bulk.iterator();
+            while (i.hasNext()) {
+                NeutronPort test = i.next();
+                portInterface.addPort(test);
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronPortAware service = (INeutronPortAware) instance;
+                        service.neutronPortCreated(test);
+                    }
+                }
+            }
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Port */
+
+    @Path("{portUUID}")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackPorts.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response updatePort(
+            @PathParam("portUUID") String portUUID,
+            NeutronPortRequest input
+            ) {
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        // port has to exist and only a single delta is supported
+        if (!portInterface.portExists(portUUID))
+            return Response.status(404).build();
+        NeutronPort target = portInterface.getPort(portUUID);
+        if (!input.isSingleton())
+            return Response.status(400).build();
+        NeutronPort singleton = input.getSingleton();
+        NeutronPort original = portInterface.getPort(portUUID);
+
+        // deltas restricted by Neutron
+        if (singleton.getID() != null || singleton.getTenantID() != null ||
+                singleton.getStatus() != null)
+            return Response.status(400).build();
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronPortAware service = (INeutronPortAware) instance;
+                int status = service.canUpdatePort(singleton, original);
+                if (status < 200 || status > 299)
+                    return Response.status(status).build();
+            }
+        }
+
+        // Verify the new fixed ips are valid
+        List<Neutron_IPs> fixedIPs = singleton.getFixedIPs();
+        if (fixedIPs != null && fixedIPs.size() > 0) {
+            Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
+            while (fixedIPIterator.hasNext()) {
+                Neutron_IPs ip = fixedIPIterator.next();
+                if (ip.getSubnetUUID() == null)
+                    return Response.status(400).build();
+                if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+                    return Response.status(400).build();
+                NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
+                if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+                    return Response.status(400).build();
+                if (ip.getIpAddress() != null) {
+                    if (!subnet.isValidIP(ip.getIpAddress()))
+                        return Response.status(400).build();
+                    if (subnet.isIPInUse(ip.getIpAddress()))
+                        return Response.status(409).build();
+                }
+            }
+        }
+
+//        TODO: Support change of security groups
+        // update the port and return the modified object
+        portInterface.updatePort(portUUID, singleton);
+        NeutronPort updatedPort = portInterface.getPort(portUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronPortAware service = (INeutronPortAware) instance;
+                service.neutronPortUpdated(updatedPort);
+            }
+        }
+        return Response.status(200).entity(
+                new NeutronPortRequest(updatedPort)).build();
+
+    }
+
+    /**
+     * Deletes a Port */
+
+    @Path("{portUUID}")
+    @DELETE
+    @StatusCodes({
+        @ResponseCode(code = 204, condition = "No Content"),
+        @ResponseCode(code = 401, condition = "Unauthorized"),
+        @ResponseCode(code = 403, condition = "Forbidden"),
+        @ResponseCode(code = 404, condition = "Not Found"),
+        @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response deletePort(
+            @PathParam("portUUID") String portUUID) {
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        // port has to exist and not be owned by anyone.  then it can be removed from the cache
+        if (!portInterface.portExists(portUUID))
+            return Response.status(404).build();
+        NeutronPort port = portInterface.getPort(portUUID);
+        if (port.getDeviceID() != null ||
+                port.getDeviceOwner() != null)
+            Response.status(403).build();
+        NeutronPort singleton = portInterface.getPort(portUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronPortAware service = (INeutronPortAware) instance;
+                int status = service.canDeletePort(singleton);
+                if (status < 200 || status > 299)
+                    return Response.status(status).build();
+            }
+        }
+        portInterface.removePort(portUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronPortAware service = (INeutronPortAware) instance;
+                service.neutronPortDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
index 1fcc9a9e912b25d0912a3ed99b3253d599e615ba..806fd69e8af50ff0b85f48366521b0f0556f25a4 100644 (file)
@@ -1,57 +1,57 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;\r
-\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronRouterRequest {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="router")\r
-    NeutronRouter singletonRouter;\r
-\r
-    @XmlElement(name="routers")\r
-    List<NeutronRouter> bulkRequest;\r
-\r
-    NeutronRouterRequest() {\r
-    }\r
-\r
-    NeutronRouterRequest(List<NeutronRouter> bulk) {\r
-        bulkRequest = bulk;\r
-        singletonRouter = null;\r
-    }\r
-\r
-    NeutronRouterRequest(NeutronRouter router) {\r
-        singletonRouter = router;\r
-    }\r
-\r
-    public List<NeutronRouter> getBulk() {\r
-        return bulkRequest;\r
-    }\r
-\r
-    public NeutronRouter getSingleton() {\r
-        return singletonRouter;\r
-    }\r
-\r
-    public boolean isSingleton() {\r
-        return (singletonRouter != null);\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronRouterRequest {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="router")
+    NeutronRouter singletonRouter;
+
+    @XmlElement(name="routers")
+    List<NeutronRouter> bulkRequest;
+
+    NeutronRouterRequest() {
+    }
+
+    NeutronRouterRequest(List<NeutronRouter> bulk) {
+        bulkRequest = bulk;
+        singletonRouter = null;
+    }
+
+    NeutronRouterRequest(NeutronRouter router) {
+        singletonRouter = router;
+    }
+
+    public List<NeutronRouter> getBulk() {
+        return bulkRequest;
+    }
+
+    public NeutronRouter getSingleton() {
+        return singletonRouter;
+    }
+
+    public boolean isSingleton() {
+        return (singletonRouter != null);
+    }
+}
index df2009ed2b76170bd281be4fd57d100f3f2203dc..fc7e0f7efbf429014859c760caf86add6f326518 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronRouterAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronRouter_Interface;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs.<br>\r
- * This class provides REST APIs for managing the open DOVE\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/routers")\r
-public class NeutronRoutersNorthbound {\r
-\r
-    private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {\r
-        return o.extractFields(fields);\r
-    }\r
-\r
-    /**\r
-     * Returns a list of all Routers */\r
-\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackRouters.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response listRouters(\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields,\r
-            // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
-            @QueryParam("id") String queryID,\r
-            @QueryParam("name") String queryName,\r
-            @QueryParam("admin_state_up") String queryAdminStateUp,\r
-            @QueryParam("status") String queryStatus,\r
-            @QueryParam("tenant_id") String queryTenantID,\r
-            @QueryParam("external_gateway_info") String queryExternalGatewayInfo,\r
-            // pagination\r
-            @QueryParam("limit") String limit,\r
-            @QueryParam("marker") String marker,\r
-            @QueryParam("page_reverse") String pageReverse\r
-            // sorting not supported\r
-            ) {\r
-        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
-        if (routerInterface == null) {\r
-            throw new ServiceUnavailableException("Router CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        List<NeutronRouter> allRouters = routerInterface.getAllRouters();\r
-        List<NeutronRouter> ans = new ArrayList<NeutronRouter>();\r
-        Iterator<NeutronRouter> i = allRouters.iterator();\r
-        while (i.hasNext()) {\r
-            NeutronRouter oSS = i.next();\r
-            if ((queryID == null || queryID.equals(oSS.getID())) &&\r
-                    (queryName == null || queryName.equals(oSS.getName())) &&\r
-                    (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&\r
-                    (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&\r
-                    (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&\r
-                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
-                if (fields.size() > 0)\r
-                    ans.add(extractFields(oSS,fields));\r
-                else\r
-                    ans.add(oSS);\r
-            }\r
-        }\r
-        //TODO: apply pagination to results\r
-        return Response.status(200).entity(\r
-                new NeutronRouterRequest(ans)).build();\r
-    }\r
-\r
-    /**\r
-     * Returns a specific Router */\r
-\r
-    @Path("{routerUUID}")\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackRouters.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 403, condition = "Forbidden"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response showRouter(\r
-            @PathParam("routerUUID") String routerUUID,\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields) {\r
-        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
-        if (routerInterface == null) {\r
-            throw new ServiceUnavailableException("Router CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (!routerInterface.routerExists(routerUUID))\r
-            return Response.status(404).build();\r
-        if (fields.size() > 0) {\r
-            NeutronRouter ans = routerInterface.getRouter(routerUUID);\r
-            return Response.status(200).entity(\r
-                    new NeutronRouterRequest(extractFields(ans, fields))).build();\r
-        } else\r
-            return Response.status(200).entity(\r
-                    new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
-    }\r
-\r
-    /**\r
-     * Creates new Routers */\r
-\r
-    @POST\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackRouters.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 201, condition = "Created"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response createRouters(final NeutronRouterRequest input) {\r
-        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
-        if (routerInterface == null) {\r
-            throw new ServiceUnavailableException("Router CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (input.isSingleton()) {\r
-            NeutronRouter singleton = input.getSingleton();\r
-\r
-            /*\r
-             * verify that the router doesn't already exist (issue: is deeper inspection necessary?)\r
-             * if there is external gateway information provided, verify that the specified network\r
-             * exists and has been designated as "router:external"\r
-             */\r
-            if (routerInterface.routerExists(singleton.getID()))\r
-                return Response.status(400).build();\r
-            if (singleton.getExternalGatewayInfo() != null) {\r
-                String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();\r
-                if (!networkInterface.networkExists(externNetworkPtr))\r
-                    return Response.status(400).build();\r
-                NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);\r
-                if (!externNetwork.isRouterExternal())\r
-                    return Response.status(400).build();\r
-            }\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                    int status = service.canCreateRouter(singleton);\r
-                    if (status < 200 || status > 299)\r
-                        return Response.status(status).build();\r
-                }\r
-            }\r
-\r
-            /*\r
-             * add router to the cache\r
-             */\r
-            routerInterface.addRouter(singleton);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                    service.neutronRouterCreated(singleton);\r
-                }\r
-            }\r
-        } else {\r
-\r
-            /*\r
-             * only singleton router creates supported\r
-             */\r
-            return Response.status(400).build();\r
-        }\r
-        return Response.status(201).entity(input).build();\r
-    }\r
-\r
-    /**\r
-     * Updates a Router */\r
-\r
-    @Path("{routerUUID}")\r
-    @PUT\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackRouters.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response updateRouter(\r
-            @PathParam("routerUUID") String routerUUID,\r
-            NeutronRouterRequest input\r
-            ) {\r
-        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
-        if (routerInterface == null) {\r
-            throw new ServiceUnavailableException("Router CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        /*\r
-         * router has to exist and only a single delta can be supplied\r
-         */\r
-        if (!routerInterface.routerExists(routerUUID))\r
-            return Response.status(404).build();\r
-        if (!input.isSingleton())\r
-            return Response.status(400).build();\r
-        NeutronRouter singleton = input.getSingleton();\r
-        NeutronRouter original = routerInterface.getRouter(routerUUID);\r
-\r
-        /*\r
-         * attribute changes blocked by Neutron\r
-         */\r
-        if (singleton.getID() != null || singleton.getTenantID() != null ||\r
-                singleton.getStatus() != null)\r
-            return Response.status(400).build();\r
-\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                int status = service.canUpdateRouter(singleton, original);\r
-                if (status < 200 || status > 299)\r
-                    return Response.status(status).build();\r
-            }\r
-        }\r
-        /*\r
-         * if the external gateway info is being changed, verify that the new network\r
-         * exists and has been designated as an external network\r
-         */\r
-        if (singleton.getExternalGatewayInfo() != null) {\r
-            String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();\r
-            if (!networkInterface.networkExists(externNetworkPtr))\r
-                return Response.status(400).build();\r
-            NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);\r
-            if (!externNetwork.isRouterExternal())\r
-                return Response.status(400).build();\r
-        }\r
-\r
-        /*\r
-         * update the router entry and return the modified object\r
-         */\r
-        routerInterface.updateRouter(routerUUID, singleton);\r
-        NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                service.neutronRouterUpdated(updatedRouter);\r
-            }\r
-        }\r
-        return Response.status(200).entity(\r
-                new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
-\r
-    }\r
-\r
-    /**\r
-     * Deletes a Router */\r
-\r
-    @Path("{routerUUID}")\r
-    @DELETE\r
-    @StatusCodes({\r
-            @ResponseCode(code = 204, condition = "No Content"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Conflict"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response deleteRouter(\r
-            @PathParam("routerUUID") String routerUUID) {\r
-        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
-        if (routerInterface == null) {\r
-            throw new ServiceUnavailableException("Router CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        /*\r
-         * verify that the router exists and is not in use before removing it\r
-         */\r
-        if (!routerInterface.routerExists(routerUUID))\r
-            return Response.status(404).build();\r
-        if (routerInterface.routerInUse(routerUUID))\r
-            return Response.status(409).build();\r
-        NeutronRouter singleton = routerInterface.getRouter(routerUUID);\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                int status = service.canDeleteRouter(singleton);\r
-                if (status < 200 || status > 299)\r
-                    return Response.status(status).build();\r
-            }\r
-        }\r
-        routerInterface.removeRouter(routerUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                service.neutronRouterDeleted(singleton);\r
-            }\r
-        }\r
-        return Response.status(204).build();\r
-    }\r
-\r
-    /**\r
-     * Adds an interface to a router */\r
-\r
-    @Path("{routerUUID}/add_router_interface")\r
-    @PUT\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackRouterInterfaces.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Conflict"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response addRouterInterface(\r
-            @PathParam("routerUUID") String routerUUID,\r
-            NeutronRouter_Interface input\r
-            ) {\r
-        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
-        if (routerInterface == null) {\r
-            throw new ServiceUnavailableException("Router CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        /*\r
-         *  While the Neutron specification says that the router has to exist and the input can only specify either a subnet id\r
-         *  or a port id, but not both, this code assumes that the plugin has filled everything in for us and so both must be present\r
-         */\r
-        if (!routerInterface.routerExists(routerUUID))\r
-            return Response.status(400).build();\r
-        NeutronRouter target = routerInterface.getRouter(routerUUID);\r
-        if (input.getSubnetUUID() == null ||\r
-                    input.getPortUUID() == null)\r
-                return Response.status(400).build();\r
-\r
-        // check that the port is part of the subnet\r
-        NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());\r
-        if (targetSubnet == null)\r
-            return Response.status(400).build();\r
-        NeutronPort targetPort = portInterface.getPort(input.getPortUUID());\r
-        if (targetPort == null)\r
-            return Response.status(400).build();\r
-        if (!targetSubnet.getPortsInSubnet().contains(targetPort))\r
-            return Response.status(400).build();\r
-\r
-        if (targetPort.getFixedIPs().size() != 1)\r
-            return Response.status(400).build();\r
-        if (targetPort.getDeviceID() != null ||\r
-                targetPort.getDeviceOwner() != null)\r
-            return Response.status(409).build();\r
-\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                service.canAttachInterface(target, input);\r
-            }\r
-        }\r
-\r
-        //mark the port device id and device owner fields\r
-        targetPort.setDeviceOwner("network:router_interface");\r
-        targetPort.setDeviceID(routerUUID);\r
-\r
-        target.addInterface(input.getPortUUID(), input);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                service.neutronRouterInterfaceAttached(target, input);\r
-            }\r
-        }\r
-\r
-        return Response.status(200).entity(input).build();\r
-    }\r
-\r
-    /**\r
-     * Removes an interface to a router */\r
-\r
-    @Path("{routerUUID}/remove_router_interface")\r
-    @PUT\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackRouterInterfaces.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Conflict"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response removeRouterInterface(\r
-            @PathParam("routerUUID") String routerUUID,\r
-            NeutronRouter_Interface input\r
-            ) {\r
-        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
-        if (routerInterface == null) {\r
-            throw new ServiceUnavailableException("Router CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-        if (portInterface == null) {\r
-            throw new ServiceUnavailableException("Port CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        // verify the router exists\r
-        if (!routerInterface.routerExists(routerUUID))\r
-            return Response.status(400).build();\r
-        NeutronRouter target = routerInterface.getRouter(routerUUID);\r
-\r
-        /*\r
-         * remove by subnet id.  Collect information about the impacted router for the response and\r
-         * remove the port corresponding to the gateway IP address of the subnet\r
-         */\r
-        if (input.getPortUUID() == null &&\r
-                input.getSubnetUUID() != null) {\r
-            NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());\r
-            if (port == null)\r
-                return Response.status(404).build();\r
-            input.setPortUUID(port.getID());\r
-            input.setID(target.getID());\r
-            input.setTenantID(target.getTenantID());\r
-\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                    service.canDetachInterface(target, input);\r
-                }\r
-            }\r
-\r
-            // reset the port ownership\r
-            port.setDeviceID(null);\r
-            port.setDeviceOwner(null);\r
-\r
-            target.removeInterface(input.getPortUUID());\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                    service.neutronRouterInterfaceDetached(target, input);\r
-                }\r
-            }\r
-            return Response.status(200).entity(input).build();\r
-        }\r
-\r
-        /*\r
-         * remove by port id. collect information about the impacted router for the response\r
-         * remove the interface and reset the port ownership\r
-         */\r
-        if (input.getPortUUID() != null &&\r
-                input.getSubnetUUID() == null) {\r
-            NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());\r
-            input.setSubnetUUID(targetInterface.getSubnetUUID());\r
-            input.setID(target.getID());\r
-            input.setTenantID(target.getTenantID());\r
-            NeutronPort port = portInterface.getPort(input.getPortUUID());\r
-            port.setDeviceID(null);\r
-            port.setDeviceOwner(null);\r
-            target.removeInterface(input.getPortUUID());\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
-            for (Object instance : instances) {\r
-                INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                service.neutronRouterInterfaceDetached(target, input);\r
-            }\r
-            return Response.status(200).entity(input).build();\r
-        }\r
-\r
-        /*\r
-         * remove by both port and subnet ID.  Verify that the first fixed IP of the port is a valid\r
-         * IP address for the subnet, and then remove the interface, collecting information about the\r
-         * impacted router for the response and reset port ownership\r
-         */\r
-        if (input.getPortUUID() != null &&\r
-                input.getSubnetUUID() != null) {\r
-            NeutronPort port = portInterface.getPort(input.getPortUUID());\r
-            NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());\r
-            if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress()))\r
-                return Response.status(409).build();\r
-            input.setID(target.getID());\r
-            input.setTenantID(target.getTenantID());\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                    service.canDetachInterface(target, input);\r
-                }\r
-            }\r
-            port.setDeviceID(null);\r
-            port.setDeviceOwner(null);\r
-            target.removeInterface(input.getPortUUID());\r
-            for (Object instance : instances) {\r
-                INeutronRouterAware service = (INeutronRouterAware) instance;\r
-                service.neutronRouterInterfaceDetached(target, input);\r
-            }\r
-            return Response.status(200).entity(input).build();\r
-        }\r
-\r
-        // have to specify either a port ID or a subnet ID\r
-        return Response.status(400).build();\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter_Interface;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+
+/**
+ * Open DOVE Northbound REST APIs.<br>
+ * This class provides REST APIs for managing the open DOVE
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/routers")
+public class NeutronRoutersNorthbound {
+
+    private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all Routers */
+
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackRouters.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response listRouters(
+            // return fields
+            @QueryParam("fields") List<String> fields,
+            // note: openstack isn't clear about filtering on lists, so we aren't handling them
+            @QueryParam("id") String queryID,
+            @QueryParam("name") String queryName,
+            @QueryParam("admin_state_up") String queryAdminStateUp,
+            @QueryParam("status") String queryStatus,
+            @QueryParam("tenant_id") String queryTenantID,
+            @QueryParam("external_gateway_info") String queryExternalGatewayInfo,
+            // pagination
+            @QueryParam("limit") String limit,
+            @QueryParam("marker") String marker,
+            @QueryParam("page_reverse") String pageReverse
+            // sorting not supported
+            ) {
+        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+        if (routerInterface == null) {
+            throw new ServiceUnavailableException("Router CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronRouter> allRouters = routerInterface.getAllRouters();
+        List<NeutronRouter> ans = new ArrayList<NeutronRouter>();
+        Iterator<NeutronRouter> i = allRouters.iterator();
+        while (i.hasNext()) {
+            NeutronRouter oSS = i.next();
+            if ((queryID == null || queryID.equals(oSS.getID())) &&
+                    (queryName == null || queryName.equals(oSS.getName())) &&
+                    (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&
+                    (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&
+                    (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&
+                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
+                if (fields.size() > 0)
+                    ans.add(extractFields(oSS,fields));
+                else
+                    ans.add(oSS);
+            }
+        }
+        //TODO: apply pagination to results
+        return Response.status(200).entity(
+                new NeutronRouterRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Router */
+
+    @Path("{routerUUID}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackRouters.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response showRouter(
+            @PathParam("routerUUID") String routerUUID,
+            // return fields
+            @QueryParam("fields") List<String> fields) {
+        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+        if (routerInterface == null) {
+            throw new ServiceUnavailableException("Router CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!routerInterface.routerExists(routerUUID))
+            return Response.status(404).build();
+        if (fields.size() > 0) {
+            NeutronRouter ans = routerInterface.getRouter(routerUUID);
+            return Response.status(200).entity(
+                    new NeutronRouterRequest(extractFields(ans, fields))).build();
+        } else
+            return Response.status(200).entity(
+                    new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
+    }
+
+    /**
+     * Creates new Routers */
+
+    @POST
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackRouters.class)
+    @StatusCodes({
+            @ResponseCode(code = 201, condition = "Created"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response createRouters(final NeutronRouterRequest input) {
+        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+        if (routerInterface == null) {
+            throw new ServiceUnavailableException("Router CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (input.isSingleton()) {
+            NeutronRouter singleton = input.getSingleton();
+
+            /*
+             * verify that the router doesn't already exist (issue: is deeper inspection necessary?)
+             * if there is external gateway information provided, verify that the specified network
+             * exists and has been designated as "router:external"
+             */
+            if (routerInterface.routerExists(singleton.getID()))
+                return Response.status(400).build();
+            if (singleton.getExternalGatewayInfo() != null) {
+                String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
+                if (!networkInterface.networkExists(externNetworkPtr))
+                    return Response.status(400).build();
+                NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
+                if (!externNetwork.isRouterExternal())
+                    return Response.status(400).build();
+            }
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronRouterAware service = (INeutronRouterAware) instance;
+                    int status = service.canCreateRouter(singleton);
+                    if (status < 200 || status > 299)
+                        return Response.status(status).build();
+                }
+            }
+
+            /*
+             * add router to the cache
+             */
+            routerInterface.addRouter(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronRouterAware service = (INeutronRouterAware) instance;
+                    service.neutronRouterCreated(singleton);
+                }
+            }
+        } else {
+
+            /*
+             * only singleton router creates supported
+             */
+            return Response.status(400).build();
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Router */
+
+    @Path("{routerUUID}")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackRouters.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response updateRouter(
+            @PathParam("routerUUID") String routerUUID,
+            NeutronRouterRequest input
+            ) {
+        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+        if (routerInterface == null) {
+            throw new ServiceUnavailableException("Router CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * router has to exist and only a single delta can be supplied
+         */
+        if (!routerInterface.routerExists(routerUUID))
+            return Response.status(404).build();
+        if (!input.isSingleton())
+            return Response.status(400).build();
+        NeutronRouter singleton = input.getSingleton();
+        NeutronRouter original = routerInterface.getRouter(routerUUID);
+
+        /*
+         * attribute changes blocked by Neutron
+         */
+        if (singleton.getID() != null || singleton.getTenantID() != null ||
+                singleton.getStatus() != null)
+            return Response.status(400).build();
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronRouterAware service = (INeutronRouterAware) instance;
+                int status = service.canUpdateRouter(singleton, original);
+                if (status < 200 || status > 299)
+                    return Response.status(status).build();
+            }
+        }
+        /*
+         * if the external gateway info is being changed, verify that the new network
+         * exists and has been designated as an external network
+         */
+        if (singleton.getExternalGatewayInfo() != null) {
+            String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
+            if (!networkInterface.networkExists(externNetworkPtr))
+                return Response.status(400).build();
+            NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
+            if (!externNetwork.isRouterExternal())
+                return Response.status(400).build();
+        }
+
+        /*
+         * update the router entry and return the modified object
+         */
+        routerInterface.updateRouter(routerUUID, singleton);
+        NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronRouterAware service = (INeutronRouterAware) instance;
+                service.neutronRouterUpdated(updatedRouter);
+            }
+        }
+        return Response.status(200).entity(
+                new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
+
+    }
+
+    /**
+     * Deletes a Router */
+
+    @Path("{routerUUID}")
+    @DELETE
+    @StatusCodes({
+            @ResponseCode(code = 204, condition = "No Content"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response deleteRouter(
+            @PathParam("routerUUID") String routerUUID) {
+        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+        if (routerInterface == null) {
+            throw new ServiceUnavailableException("Router CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify that the router exists and is not in use before removing it
+         */
+        if (!routerInterface.routerExists(routerUUID))
+            return Response.status(404).build();
+        if (routerInterface.routerInUse(routerUUID))
+            return Response.status(409).build();
+        NeutronRouter singleton = routerInterface.getRouter(routerUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronRouterAware service = (INeutronRouterAware) instance;
+                int status = service.canDeleteRouter(singleton);
+                if (status < 200 || status > 299)
+                    return Response.status(status).build();
+            }
+        }
+        routerInterface.removeRouter(routerUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronRouterAware service = (INeutronRouterAware) instance;
+                service.neutronRouterDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+
+    /**
+     * Adds an interface to a router */
+
+    @Path("{routerUUID}/add_router_interface")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackRouterInterfaces.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response addRouterInterface(
+            @PathParam("routerUUID") String routerUUID,
+            NeutronRouter_Interface input
+            ) {
+        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+        if (routerInterface == null) {
+            throw new ServiceUnavailableException("Router CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         *  While the Neutron specification says that the router has to exist and the input can only specify either a subnet id
+         *  or a port id, but not both, this code assumes that the plugin has filled everything in for us and so both must be present
+         */
+        if (!routerInterface.routerExists(routerUUID))
+            return Response.status(400).build();
+        NeutronRouter target = routerInterface.getRouter(routerUUID);
+        if (input.getSubnetUUID() == null ||
+                    input.getPortUUID() == null)
+                return Response.status(400).build();
+
+        // check that the port is part of the subnet
+        NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());
+        if (targetSubnet == null)
+            return Response.status(400).build();
+        NeutronPort targetPort = portInterface.getPort(input.getPortUUID());
+        if (targetPort == null)
+            return Response.status(400).build();
+        if (!targetSubnet.getPortsInSubnet().contains(targetPort))
+            return Response.status(400).build();
+
+        if (targetPort.getFixedIPs().size() != 1)
+            return Response.status(400).build();
+        if (targetPort.getDeviceID() != null ||
+                targetPort.getDeviceOwner() != null)
+            return Response.status(409).build();
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronRouterAware service = (INeutronRouterAware) instance;
+                service.canAttachInterface(target, input);
+            }
+        }
+
+        //mark the port device id and device owner fields
+        targetPort.setDeviceOwner("network:router_interface");
+        targetPort.setDeviceID(routerUUID);
+
+        target.addInterface(input.getPortUUID(), input);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronRouterAware service = (INeutronRouterAware) instance;
+                service.neutronRouterInterfaceAttached(target, input);
+            }
+        }
+
+        return Response.status(200).entity(input).build();
+    }
+
+    /**
+     * Removes an interface to a router */
+
+    @Path("{routerUUID}/remove_router_interface")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackRouterInterfaces.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response removeRouterInterface(
+            @PathParam("routerUUID") String routerUUID,
+            NeutronRouter_Interface input
+            ) {
+        INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+        if (routerInterface == null) {
+            throw new ServiceUnavailableException("Router CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+        if (portInterface == null) {
+            throw new ServiceUnavailableException("Port CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        // verify the router exists
+        if (!routerInterface.routerExists(routerUUID))
+            return Response.status(400).build();
+        NeutronRouter target = routerInterface.getRouter(routerUUID);
+
+        /*
+         * remove by subnet id.  Collect information about the impacted router for the response and
+         * remove the port corresponding to the gateway IP address of the subnet
+         */
+        if (input.getPortUUID() == null &&
+                input.getSubnetUUID() != null) {
+            NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());
+            if (port == null)
+                return Response.status(404).build();
+            input.setPortUUID(port.getID());
+            input.setID(target.getID());
+            input.setTenantID(target.getTenantID());
+
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronRouterAware service = (INeutronRouterAware) instance;
+                    service.canDetachInterface(target, input);
+                }
+            }
+
+            // reset the port ownership
+            port.setDeviceID(null);
+            port.setDeviceOwner(null);
+
+            target.removeInterface(input.getPortUUID());
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronRouterAware service = (INeutronRouterAware) instance;
+                    service.neutronRouterInterfaceDetached(target, input);
+                }
+            }
+            return Response.status(200).entity(input).build();
+        }
+
+        /*
+         * remove by port id. collect information about the impacted router for the response
+         * remove the interface and reset the port ownership
+         */
+        if (input.getPortUUID() != null &&
+                input.getSubnetUUID() == null) {
+            NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());
+            input.setSubnetUUID(targetInterface.getSubnetUUID());
+            input.setID(target.getID());
+            input.setTenantID(target.getTenantID());
+            NeutronPort port = portInterface.getPort(input.getPortUUID());
+            port.setDeviceID(null);
+            port.setDeviceOwner(null);
+            target.removeInterface(input.getPortUUID());
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+            for (Object instance : instances) {
+                INeutronRouterAware service = (INeutronRouterAware) instance;
+                service.neutronRouterInterfaceDetached(target, input);
+            }
+            return Response.status(200).entity(input).build();
+        }
+
+        /*
+         * remove by both port and subnet ID.  Verify that the first fixed IP of the port is a valid
+         * IP address for the subnet, and then remove the interface, collecting information about the
+         * impacted router for the response and reset port ownership
+         */
+        if (input.getPortUUID() != null &&
+                input.getSubnetUUID() != null) {
+            NeutronPort port = portInterface.getPort(input.getPortUUID());
+            NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());
+            if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress()))
+                return Response.status(409).build();
+            input.setID(target.getID());
+            input.setTenantID(target.getTenantID());
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronRouterAware service = (INeutronRouterAware) instance;
+                    service.canDetachInterface(target, input);
+                }
+            }
+            port.setDeviceID(null);
+            port.setDeviceOwner(null);
+            target.removeInterface(input.getPortUUID());
+            for (Object instance : instances) {
+                INeutronRouterAware service = (INeutronRouterAware) instance;
+                service.neutronRouterInterfaceDetached(target, input);
+            }
+            return Response.status(200).entity(input).build();
+        }
+
+        // have to specify either a port ID or a subnet ID
+        return Response.status(400).build();
+    }
+}
index ab91399879e97ebc97fc0b44dbf318e0eb2c6784..aed9db58bd34c3255c54830c8b76957da6d4de5c 100644 (file)
@@ -1,56 +1,56 @@
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronSubnetRequest {\r
-    // See OpenStack Network API v2.0 Reference for description of\r
-    // annotated attributes\r
-\r
-    @XmlElement(name="subnet")\r
-    NeutronSubnet singletonSubnet;\r
-\r
-    @XmlElement(name="subnets")\r
-    List<NeutronSubnet> bulkRequest;\r
-\r
-    NeutronSubnetRequest() {\r
-    }\r
-\r
-    NeutronSubnetRequest(List<NeutronSubnet> bulk) {\r
-        bulkRequest = bulk;\r
-        singletonSubnet = null;\r
-    }\r
-\r
-    NeutronSubnetRequest(NeutronSubnet subnet) {\r
-        singletonSubnet = subnet;\r
-    }\r
-\r
-    public NeutronSubnet getSingleton() {\r
-        return singletonSubnet;\r
-    }\r
-\r
-    public List<NeutronSubnet> getBulk() {\r
-        return bulkRequest;\r
-    }\r
-\r
-    public boolean isSingleton() {\r
-        return (singletonSubnet != null);\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSubnetRequest {
+    // See OpenStack Network API v2.0 Reference for description of
+    // annotated attributes
+
+    @XmlElement(name="subnet")
+    NeutronSubnet singletonSubnet;
+
+    @XmlElement(name="subnets")
+    List<NeutronSubnet> bulkRequest;
+
+    NeutronSubnetRequest() {
+    }
+
+    NeutronSubnetRequest(List<NeutronSubnet> bulk) {
+        bulkRequest = bulk;
+        singletonSubnet = null;
+    }
+
+    NeutronSubnetRequest(NeutronSubnet subnet) {
+        singletonSubnet = subnet;
+    }
+
+    public NeutronSubnet getSingleton() {
+        return singletonSubnet;
+    }
+
+    public List<NeutronSubnet> getBulk() {
+        return bulkRequest;
+    }
+
+    public boolean isSingleton() {
+        return (singletonSubnet != null);
+    }
+}
index 699aee9fc3a7d3503e7b1a6d464926da1aefd24f..dffac55c5030ac96da1b52bde366f009cbb4a63d 100644 (file)
-/*\r
- * Copyright IBM Corporation, 2013.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs.<br>\r
- * This class provides REST APIs for managing open DOVE internals related to Subnets\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/subnets")\r
-public class NeutronSubnetsNorthbound {\r
-\r
-    private NeutronSubnet extractFields(NeutronSubnet o, List<String> fields) {\r
-        return o.extractFields(fields);\r
-    }\r
-\r
-\r
-    /**\r
-     * Returns a list of all Subnets */\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackSubnets.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response listSubnets(\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields,\r
-            // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
-            @QueryParam("id") String queryID,\r
-            @QueryParam("network_id") String queryNetworkID,\r
-            @QueryParam("name") String queryName,\r
-            @QueryParam("ip_version") String queryIPVersion,\r
-            @QueryParam("cidr") String queryCIDR,\r
-            @QueryParam("gateway_ip") String queryGatewayIP,\r
-            @QueryParam("enable_dhcp") String queryEnableDHCP,\r
-            @QueryParam("tenant_id") String queryTenantID,\r
-            // pagination\r
-            @QueryParam("limit") String limit,\r
-            @QueryParam("marker") String marker,\r
-            @QueryParam("page_reverse") String pageReverse\r
-            // sorting not supported\r
-            ) {\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        List<NeutronSubnet> allNetworks = subnetInterface.getAllSubnets();\r
-        List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();\r
-        Iterator<NeutronSubnet> i = allNetworks.iterator();\r
-        while (i.hasNext()) {\r
-            NeutronSubnet oSS = i.next();\r
-            if ((queryID == null || queryID.equals(oSS.getID())) &&\r
-                    (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&\r
-                    (queryName == null || queryName.equals(oSS.getName())) &&\r
-                    (queryIPVersion == null || queryIPVersion.equals(oSS.getIpVersion())) &&\r
-                    (queryCIDR == null || queryCIDR.equals(oSS.getCidr())) &&\r
-                    (queryGatewayIP == null || queryGatewayIP.equals(oSS.getGatewayIP())) &&\r
-                    (queryEnableDHCP == null || queryEnableDHCP.equals(oSS.getEnableDHCP())) &&\r
-                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
-                if (fields.size() > 0) {\r
-                    ans.add(extractFields(oSS,fields));\r
-                } else {\r
-                    ans.add(oSS);\r
-                }\r
-            }\r
-        }\r
-        //TODO: apply pagination to results\r
-        return Response.status(200).entity(\r
-                new NeutronSubnetRequest(ans)).build();\r
-    }\r
-\r
-    /**\r
-     * Returns a specific Subnet */\r
-\r
-    @Path("{subnetUUID}")\r
-    @GET\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackSubnets.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response showSubnet(\r
-            @PathParam("subnetUUID") String subnetUUID,\r
-            // return fields\r
-            @QueryParam("fields") List<String> fields) {\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (!subnetInterface.subnetExists(subnetUUID)) {\r
-            return Response.status(404).build();\r
-        }\r
-        if (fields.size() > 0) {\r
-            NeutronSubnet ans = subnetInterface.getSubnet(subnetUUID);\r
-            return Response.status(200).entity(\r
-                    new NeutronSubnetRequest(extractFields(ans, fields))).build();\r
-        } else {\r
-            return Response.status(200).entity(\r
-                    new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Creates new Subnets */\r
-\r
-    @POST\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackSubnets.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 201, condition = "Created"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 403, condition = "Forbidden"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Conflict"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response createSubnets(final NeutronSubnetRequest input) {\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
-        if (networkInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-        if (input.isSingleton()) {\r
-            NeutronSubnet singleton = input.getSingleton();\r
-\r
-            /*\r
-             *  Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)\r
-             *  the specified network exists, the subnet has a valid network address,\r
-             *  and that the gateway IP doesn't overlap with the allocation pools\r
-             *  *then* add the subnet to the cache\r
-             */\r
-            if (subnetInterface.subnetExists(singleton.getID())) {\r
-                return Response.status(400).build();\r
-            }\r
-            if (!networkInterface.networkExists(singleton.getNetworkUUID())) {\r
-                return Response.status(404).build();\r
-            }\r
-            if (!singleton.isValidCIDR()) {\r
-                return Response.status(400).build();\r
-            }\r
-            if (!singleton.initDefaults()) {\r
-                throw new InternalServerErrorException("subnet object could not be initialized properly");\r
-            }\r
-            if (singleton.gatewayIP_Pool_overlap()) {\r
-                return Response.status(409).build();\r
-            }\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
-                    int status = service.canCreateSubnet(singleton);\r
-                    if (status < 200 || status > 299) {\r
-                        return Response.status(status).build();\r
-                    }\r
-                }\r
-            }\r
-            subnetInterface.addSubnet(singleton);\r
-            if (instances != null) {\r
-                for (Object instance : instances) {\r
-                    INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
-                    service.neutronSubnetCreated(singleton);\r
-                }\r
-            }\r
-        } else {\r
-            List<NeutronSubnet> bulk = input.getBulk();\r
-            Iterator<NeutronSubnet> i = bulk.iterator();\r
-            HashMap<String, NeutronSubnet> testMap = new HashMap<String, NeutronSubnet>();\r
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
-            while (i.hasNext()) {\r
-                NeutronSubnet test = i.next();\r
-\r
-                /*\r
-                 *  Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)\r
-                 *  the specified network exists, the subnet has a valid network address,\r
-                 *  and that the gateway IP doesn't overlap with the allocation pools,\r
-                 *  and that the bulk request doesn't already contain a subnet with this id\r
-                 */\r
-\r
-                if (!test.initDefaults()) {\r
-                    throw new InternalServerErrorException("subnet object could not be initialized properly");\r
-                }\r
-                if (subnetInterface.subnetExists(test.getID())) {\r
-                    return Response.status(400).build();\r
-                }\r
-                if (testMap.containsKey(test.getID())) {\r
-                    return Response.status(400).build();\r
-                }\r
-                testMap.put(test.getID(), test);\r
-                if (!networkInterface.networkExists(test.getNetworkUUID())) {\r
-                    return Response.status(404).build();\r
-                }\r
-                if (!test.isValidCIDR()) {\r
-                    return Response.status(400).build();\r
-                }\r
-                if (test.gatewayIP_Pool_overlap()) {\r
-                    return Response.status(409).build();\r
-                }\r
-                if (instances != null) {\r
-                    for (Object instance : instances) {\r
-                        INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
-                        int status = service.canCreateSubnet(test);\r
-                        if (status < 200 || status > 299) {\r
-                            return Response.status(status).build();\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-\r
-            /*\r
-             * now, each element of the bulk request can be added to the cache\r
-             */\r
-            i = bulk.iterator();\r
-            while (i.hasNext()) {\r
-                NeutronSubnet test = i.next();\r
-                subnetInterface.addSubnet(test);\r
-                if (instances != null) {\r
-                    for (Object instance : instances) {\r
-                        INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
-                        service.neutronSubnetCreated(test);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        return Response.status(201).entity(input).build();\r
-    }\r
-\r
-    /**\r
-     * Updates a Subnet */\r
-\r
-    @Path("{subnetUUID}")\r
-    @PUT\r
-    @Produces({ MediaType.APPLICATION_JSON })\r
-    @Consumes({ MediaType.APPLICATION_JSON })\r
-    //@TypeHint(OpenStackSubnets.class)\r
-    @StatusCodes({\r
-            @ResponseCode(code = 200, condition = "Operation successful"),\r
-            @ResponseCode(code = 400, condition = "Bad Request"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 403, condition = "Forbidden"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response updateSubnet(\r
-            @PathParam("subnetUUID") String subnetUUID, final NeutronSubnetRequest input\r
-            ) {\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Subnet CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        /*\r
-         * verify the subnet exists and there is only one delta provided\r
-         */\r
-        if (!subnetInterface.subnetExists(subnetUUID)) {\r
-            return Response.status(404).build();\r
-        }\r
-        if (!input.isSingleton()) {\r
-            return Response.status(400).build();\r
-        }\r
-        NeutronSubnet delta = input.getSingleton();\r
-        NeutronSubnet original = subnetInterface.getSubnet(subnetUUID);\r
-\r
-        /*\r
-         * updates restricted by Neutron\r
-         */\r
-        if (delta.getID() != null || delta.getTenantID() != null ||\r
-                delta.getIpVersion() != null || delta.getCidr() != null ||\r
-                delta.getAllocationPools() != null) {\r
-            return Response.status(400).build();\r
-        }\r
-\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
-                int status = service.canUpdateSubnet(delta, original);\r
-                if (status < 200 || status > 299) {\r
-                    return Response.status(status).build();\r
-                }\r
-            }\r
-        }\r
-\r
-        /*\r
-         * update the object and return it\r
-         */\r
-        subnetInterface.updateSubnet(subnetUUID, delta);\r
-        NeutronSubnet updatedSubnet = subnetInterface.getSubnet(subnetUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
-                service.neutronSubnetUpdated(updatedSubnet);\r
-            }\r
-        }\r
-        return Response.status(200).entity(\r
-                new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();\r
-    }\r
-\r
-    /**\r
-     * Deletes a Subnet */\r
-\r
-    @Path("{subnetUUID}")\r
-    @DELETE\r
-    @StatusCodes({\r
-            @ResponseCode(code = 204, condition = "No Content"),\r
-            @ResponseCode(code = 401, condition = "Unauthorized"),\r
-            @ResponseCode(code = 404, condition = "Not Found"),\r
-            @ResponseCode(code = 409, condition = "Conflict"),\r
-            @ResponseCode(code = 501, condition = "Not Implemented") })\r
-    public Response deleteSubnet(\r
-            @PathParam("subnetUUID") String subnetUUID) {\r
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
-        if (subnetInterface == null) {\r
-            throw new ServiceUnavailableException("Network CRUD Interface "\r
-                    + RestMessages.SERVICEUNAVAILABLE.toString());\r
-        }\r
-\r
-        /*\r
-         * verify the subnet exists and it isn't currently in use\r
-         */\r
-        if (!subnetInterface.subnetExists(subnetUUID)) {\r
-            return Response.status(404).build();\r
-        }\r
-        if (subnetInterface.subnetInUse(subnetUUID)) {\r
-            return Response.status(409).build();\r
-        }\r
-        NeutronSubnet singleton = subnetInterface.getSubnet(subnetUUID);\r
-        Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
-                int status = service.canDeleteSubnet(singleton);\r
-                if (status < 200 || status > 299) {\r
-                    return Response.status(status).build();\r
-                }\r
-            }\r
-        }\r
-\r
-        /*\r
-         * remove it and return 204 status\r
-         */\r
-        subnetInterface.removeSubnet(subnetUUID);\r
-        if (instances != null) {\r
-            for (Object instance : instances) {\r
-                INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
-                service.neutronSubnetDeleted(singleton);\r
-            }\r
-        }\r
-        return Response.status(204).build();\r
-    }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013.  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.networkconfig.neutron.northbound;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+/**
+ * Open DOVE Northbound REST APIs.<br>
+ * This class provides REST APIs for managing open DOVE internals related to Subnets
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/subnets")
+public class NeutronSubnetsNorthbound {
+
+    private NeutronSubnet extractFields(NeutronSubnet o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+
+    /**
+     * Returns a list of all Subnets */
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackSubnets.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response listSubnets(
+            // return fields
+            @QueryParam("fields") List<String> fields,
+            // note: openstack isn't clear about filtering on lists, so we aren't handling them
+            @QueryParam("id") String queryID,
+            @QueryParam("network_id") String queryNetworkID,
+            @QueryParam("name") String queryName,
+            @QueryParam("ip_version") String queryIPVersion,
+            @QueryParam("cidr") String queryCIDR,
+            @QueryParam("gateway_ip") String queryGatewayIP,
+            @QueryParam("enable_dhcp") String queryEnableDHCP,
+            @QueryParam("tenant_id") String queryTenantID,
+            // pagination
+            @QueryParam("limit") String limit,
+            @QueryParam("marker") String marker,
+            @QueryParam("page_reverse") String pageReverse
+            // sorting not supported
+            ) {
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronSubnet> allNetworks = subnetInterface.getAllSubnets();
+        List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();
+        Iterator<NeutronSubnet> i = allNetworks.iterator();
+        while (i.hasNext()) {
+            NeutronSubnet oSS = i.next();
+            if ((queryID == null || queryID.equals(oSS.getID())) &&
+                    (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&
+                    (queryName == null || queryName.equals(oSS.getName())) &&
+                    (queryIPVersion == null || queryIPVersion.equals(oSS.getIpVersion())) &&
+                    (queryCIDR == null || queryCIDR.equals(oSS.getCidr())) &&
+                    (queryGatewayIP == null || queryGatewayIP.equals(oSS.getGatewayIP())) &&
+                    (queryEnableDHCP == null || queryEnableDHCP.equals(oSS.getEnableDHCP())) &&
+                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
+                if (fields.size() > 0) {
+                    ans.add(extractFields(oSS,fields));
+                } else {
+                    ans.add(oSS);
+                }
+            }
+        }
+        //TODO: apply pagination to results
+        return Response.status(200).entity(
+                new NeutronSubnetRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Subnet */
+
+    @Path("{subnetUUID}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackSubnets.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response showSubnet(
+            @PathParam("subnetUUID") String subnetUUID,
+            // return fields
+            @QueryParam("fields") List<String> fields) {
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!subnetInterface.subnetExists(subnetUUID)) {
+            return Response.status(404).build();
+        }
+        if (fields.size() > 0) {
+            NeutronSubnet ans = subnetInterface.getSubnet(subnetUUID);
+            return Response.status(200).entity(
+                    new NeutronSubnetRequest(extractFields(ans, fields))).build();
+        } else {
+            return Response.status(200).entity(
+                    new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();
+        }
+    }
+
+    /**
+     * Creates new Subnets */
+
+    @POST
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackSubnets.class)
+    @StatusCodes({
+            @ResponseCode(code = 201, condition = "Created"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response createSubnets(final NeutronSubnetRequest input) {
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        if (networkInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (input.isSingleton()) {
+            NeutronSubnet singleton = input.getSingleton();
+
+            /*
+             *  Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)
+             *  the specified network exists, the subnet has a valid network address,
+             *  and that the gateway IP doesn't overlap with the allocation pools
+             *  *then* add the subnet to the cache
+             */
+            if (subnetInterface.subnetExists(singleton.getID())) {
+                return Response.status(400).build();
+            }
+            if (!networkInterface.networkExists(singleton.getNetworkUUID())) {
+                return Response.status(404).build();
+            }
+            if (!singleton.isValidCIDR()) {
+                return Response.status(400).build();
+            }
+            if (!singleton.initDefaults()) {
+                throw new InternalServerErrorException("subnet object could not be initialized properly");
+            }
+            if (singleton.gatewayIP_Pool_overlap()) {
+                return Response.status(409).build();
+            }
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronSubnetAware service = (INeutronSubnetAware) instance;
+                    int status = service.canCreateSubnet(singleton);
+                    if (status < 200 || status > 299) {
+                        return Response.status(status).build();
+                    }
+                }
+            }
+            subnetInterface.addSubnet(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronSubnetAware service = (INeutronSubnetAware) instance;
+                    service.neutronSubnetCreated(singleton);
+                }
+            }
+        } else {
+            List<NeutronSubnet> bulk = input.getBulk();
+            Iterator<NeutronSubnet> i = bulk.iterator();
+            HashMap<String, NeutronSubnet> testMap = new HashMap<String, NeutronSubnet>();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+            while (i.hasNext()) {
+                NeutronSubnet test = i.next();
+
+                /*
+                 *  Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)
+                 *  the specified network exists, the subnet has a valid network address,
+                 *  and that the gateway IP doesn't overlap with the allocation pools,
+                 *  and that the bulk request doesn't already contain a subnet with this id
+                 */
+
+                if (!test.initDefaults()) {
+                    throw new InternalServerErrorException("subnet object could not be initialized properly");
+                }
+                if (subnetInterface.subnetExists(test.getID())) {
+                    return Response.status(400).build();
+                }
+                if (testMap.containsKey(test.getID())) {
+                    return Response.status(400).build();
+                }
+                testMap.put(test.getID(), test);
+                if (!networkInterface.networkExists(test.getNetworkUUID())) {
+                    return Response.status(404).build();
+                }
+                if (!test.isValidCIDR()) {
+                    return Response.status(400).build();
+                }
+                if (test.gatewayIP_Pool_overlap()) {
+                    return Response.status(409).build();
+                }
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronSubnetAware service = (INeutronSubnetAware) instance;
+                        int status = service.canCreateSubnet(test);
+                        if (status < 200 || status > 299) {
+                            return Response.status(status).build();
+                        }
+                    }
+                }
+            }
+
+            /*
+             * now, each element of the bulk request can be added to the cache
+             */
+            i = bulk.iterator();
+            while (i.hasNext()) {
+                NeutronSubnet test = i.next();
+                subnetInterface.addSubnet(test);
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronSubnetAware service = (INeutronSubnetAware) instance;
+                        service.neutronSubnetCreated(test);
+                    }
+                }
+            }
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Subnet */
+
+    @Path("{subnetUUID}")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackSubnets.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response updateSubnet(
+            @PathParam("subnetUUID") String subnetUUID, final NeutronSubnetRequest input
+            ) {
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Subnet CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the subnet exists and there is only one delta provided
+         */
+        if (!subnetInterface.subnetExists(subnetUUID)) {
+            return Response.status(404).build();
+        }
+        if (!input.isSingleton()) {
+            return Response.status(400).build();
+        }
+        NeutronSubnet delta = input.getSingleton();
+        NeutronSubnet original = subnetInterface.getSubnet(subnetUUID);
+
+        /*
+         * updates restricted by Neutron
+         */
+        if (delta.getID() != null || delta.getTenantID() != null ||
+                delta.getIpVersion() != null || delta.getCidr() != null ||
+                delta.getAllocationPools() != null) {
+            return Response.status(400).build();
+        }
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSubnetAware service = (INeutronSubnetAware) instance;
+                int status = service.canUpdateSubnet(delta, original);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * update the object and return it
+         */
+        subnetInterface.updateSubnet(subnetUUID, delta);
+        NeutronSubnet updatedSubnet = subnetInterface.getSubnet(subnetUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSubnetAware service = (INeutronSubnetAware) instance;
+                service.neutronSubnetUpdated(updatedSubnet);
+            }
+        }
+        return Response.status(200).entity(
+                new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();
+    }
+
+    /**
+     * Deletes a Subnet */
+
+    @Path("{subnetUUID}")
+    @DELETE
+    @StatusCodes({
+            @ResponseCode(code = 204, condition = "No Content"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response deleteSubnet(
+            @PathParam("subnetUUID") String subnetUUID) {
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+        if (subnetInterface == null) {
+            throw new ServiceUnavailableException("Network CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the subnet exists and it isn't currently in use
+         */
+        if (!subnetInterface.subnetExists(subnetUUID)) {
+            return Response.status(404).build();
+        }
+        if (subnetInterface.subnetInUse(subnetUUID)) {
+            return Response.status(409).build();
+        }
+        NeutronSubnet singleton = subnetInterface.getSubnet(subnetUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSubnetAware service = (INeutronSubnetAware) instance;
+                int status = service.canDeleteSubnet(singleton);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * remove it and return 204 status
+         */
+        subnetInterface.removeSubnet(subnetUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSubnetAware service = (INeutronSubnetAware) instance;
+                service.neutronSubnetDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
index c7522c977f81527adf1acc63696d5a0dda49f38f..ca0ff45d61e4977ed677f761d93c73c86262482e 100644 (file)
@@ -70,7 +70,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.6.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index da7735d4c59a9c086f5ec688612999c28a71b8fa..9041004605dded75ce2fe44f129c617656ab6e60 100644 (file)
@@ -132,12 +132,17 @@ public class MessageReadWriteService implements IMessageReadWrite {
             throw new AsynchronousCloseException();
         }
 
-        inBuffer.flip();
-        msgs = factory.parseMessages(inBuffer);
-        if (inBuffer.hasRemaining()) {
-            inBuffer.compact();
-        } else {
+        try {
+            inBuffer.flip();
+            msgs = factory.parseMessages(inBuffer);
+            if (inBuffer.hasRemaining()) {
+                inBuffer.compact();
+            } else {
+                inBuffer.clear();
+            }
+        } catch (Exception e) {
             inBuffer.clear();
+            logger.debug("Caught exception: ", e);
         }
         return msgs;
     }
index f0922d3658f946c474e48002874bf4a34295221a..90b47cf26421e6ff6a05c0e6ef21451c52173ac9 100644 (file)
@@ -282,12 +282,17 @@ public class SecureMessageReadWriteService implements IMessageReadWrite {
                     peerNetData.position(), peerNetData.limit());
         }
 
-        peerAppData.flip();
-        msgs = factory.parseMessages(peerAppData);
-        if (peerAppData.hasRemaining()) {
-            peerAppData.compact();
-        } else {
+        try {
+            peerAppData.flip();
+            msgs = factory.parseMessages(peerAppData);
+            if (peerAppData.hasRemaining()) {
+                peerAppData.compact();
+            } else {
+                peerAppData.clear();
+            }
+        } catch (Exception e) {
             peerAppData.clear();
+            logger.debug("Caught exception: ", e);
         }
 
         this.socket.register(this.selector, SelectionKey.OP_READ, this);
index 6e000022df12909e1f4facdcbcf4236d20d3fd69..6fddef06a8388a80a5278ce2f9a3234ae4461982 100644 (file)
@@ -359,8 +359,6 @@ public class SwitchHandler implements ISwitch {
         }
 
         if (msgs == null) {
-            logger.info("{} is down", this);
-            reportSwitchStateChange(false);
             return;
         }
         for (OFMessage msg : msgs) {
@@ -369,16 +367,15 @@ public class SwitchHandler implements ISwitch {
             OFType type = msg.getType();
             switch (type) {
             case HELLO:
-                // send feature request
-                OFMessage featureRequest = factory.getMessage(OFType.FEATURES_REQUEST);
-                asyncFastSend(featureRequest);
-                this.state = SwitchState.WAIT_FEATURES_REPLY;
-                startSwitchTimer();
+                sendFeaturesRequest();
                 break;
             case ECHO_REQUEST:
                 OFEchoReply echoReply = (OFEchoReply) factory.getMessage(OFType.ECHO_REPLY);
                 // respond immediately
                 asyncSendNow(echoReply, msg.getXid());
+
+                // send features request if not sent yet
+                sendFeaturesRequest();
                 break;
             case ECHO_REPLY:
                 this.probeSent = false;
@@ -507,6 +504,16 @@ public class SwitchHandler implements ISwitch {
         return this.sid;
     }
 
+    private void sendFeaturesRequest() {
+        if (!isOperational() && (this.state != SwitchState.WAIT_FEATURES_REPLY)) {
+            // send feature request
+            OFMessage featureRequest = factory.getMessage(OFType.FEATURES_REQUEST);
+            asyncFastSend(featureRequest);
+            this.state = SwitchState.WAIT_FEATURES_REPLY;
+            startSwitchTimer();
+        }
+    }
+
     private void processFeaturesReply(OFFeaturesReply reply) {
         if (this.state == SwitchState.WAIT_FEATURES_REPLY) {
             this.sid = reply.getDatapathId();
index 2bbe9c12c6719e736f960bd2fba4a1457825060c..8fa4941b88771c94dbf3b578a3f89717339f899e 100644 (file)
@@ -12,7 +12,9 @@ import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod;
 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
@@ -20,6 +22,7 @@ import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.ActionType;
 import org.opendaylight.controller.sal.action.Controller;
 import org.opendaylight.controller.sal.action.Drop;
+import org.opendaylight.controller.sal.action.Enqueue;
 import org.opendaylight.controller.sal.action.Flood;
 import org.opendaylight.controller.sal.action.FloodAll;
 import org.opendaylight.controller.sal.action.HwPath;
@@ -747,4 +750,50 @@ public class FlowConverter {
         return flow;
     }
 
+    private static final Map<Integer, Class<? extends Action>> actionMap = new HashMap<Integer, Class<? extends Action>>() {
+        private static final long serialVersionUID = 1L;
+        {
+            put(1 << 0, Output.class);
+            put(1 << 1, SetVlanId.class);
+            put(1 << 2, SetVlanPcp.class);
+            put(1 << 3, PopVlan.class);
+            put(1 << 4, SetDlSrc.class);
+            put(1 << 5, SetDlDst.class);
+            put(1 << 6, SetNwSrc.class);
+            put(1 << 7, SetNwDst.class);
+            put(1 << 8, SetNwTos.class);
+            put(1 << 9, SetTpSrc.class);
+            put(1 << 10, SetTpDst.class);
+            put(1 << 11, Enqueue.class);
+        }
+    };
+
+    /**
+     * Returns the supported flow actions for the netwrok node given the bitmask
+     * representing the actions the Openflow 1.0 switch supports
+     *
+     * @param ofActionBitmask
+     *            OF 1.0 action bitmask
+     * @return The correspondent list of SAL Action classes
+     */
+    public static List<Class<? extends Action>> getFlowActions(int ofActionBitmask) {
+        List<Class<? extends Action>> list = new ArrayList<Class<? extends Action>>();
+
+        for (int i = 0; i < Integer.SIZE; i++) {
+            int index = 1 << i;
+            if ((index & ofActionBitmask) > 0) {
+                if (actionMap.containsKey(index)) {
+                    list.add(actionMap.get(index));
+                }
+            }
+        }
+        // Add implicit SAL actions
+        list.add(Controller.class);
+        list.add(SwPath.class);
+        list.add(HwPath.class);
+        list.add(Drop.class);
+
+        return list;
+    }
+
 }
index a920adf71d35163094514674fbb5b8a158bf66d7..f4843cf8283f36f2dc4ae957c2e46c42d363e4d6 100644 (file)
@@ -26,9 +26,9 @@ import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
 import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitchStateListener;
+import org.opendaylight.controller.sal.action.SupportedFlowActions;
 import org.opendaylight.controller.sal.connection.ConnectionLocality;
 import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
-import org.opendaylight.controller.sal.core.Actions;
 import org.opendaylight.controller.sal.core.Buffers;
 import org.opendaylight.controller.sal.core.Capabilities;
 import org.opendaylight.controller.sal.core.ContainerFlow;
@@ -503,7 +503,7 @@ public class InventoryServiceShim implements IContainerListener,
             props.add(c);
         }
         int act = sw.getActions();
-        Actions a = new Actions(act);
+        SupportedFlowActions a = new SupportedFlowActions(FlowConverter.getFlowActions(act));
         if (a != null) {
             props.add(a);
         }
diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java
new file mode 100644 (file)
index 0000000..b3891c8
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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
+ */
+
+package org.opendaylight.controller.sal.action;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.sal.core.NodeConnector;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class Enqueue extends Action {
+    private static final long serialVersionUID = 1L;
+    @XmlElement
+    private NodeConnector port;
+
+    /* Dummy constructor for JAXB */
+    @SuppressWarnings("unused")
+    private Enqueue() {
+    }
+
+    public Enqueue(NodeConnector port) {
+        type = ActionType.ENQUEUE;
+        this.port = port;
+    }
+
+    public NodeConnector getPort() {
+        return port;
+    }
+}
diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SupportedFlowActions.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SupportedFlowActions.java
new file mode 100644 (file)
index 0000000..0a5d9c8
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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
+ */
+
+package org.opendaylight.controller.sal.action;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.opendaylight.controller.sal.core.Property;
+
+/**
+ * @file SupportedFlowActions.java
+ *
+ * @brief Class representing the supported flow actions
+ *
+ *        Describes the supported flow actions
+ */
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class SupportedFlowActions extends Property {
+    private static final long serialVersionUID = 1L;
+    public static final String SupportedFlowActionsPropName = "supportedFlowActions";
+    private List<Class<? extends Action>> actions;
+
+    private SupportedFlowActions() {
+        super(SupportedFlowActionsPropName);
+        this.actions = new ArrayList<Class<? extends Action>>();
+    }
+
+    public SupportedFlowActions(List<Class<? extends Action>> actions) {
+        super(SupportedFlowActionsPropName);
+        this.actions = new ArrayList<Class<? extends Action>>(actions);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + ((actions == null) ? 0 : actions.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        SupportedFlowActions other = (SupportedFlowActions) obj;
+        if (actions == null) {
+            if (other.actions != null) {
+                return false;
+            }
+        } else if (!actions.equals(other.actions)) {
+            return false;
+        }
+        return true;
+    }
+
+    public List<Class<? extends Action>> getActions() {
+        return new ArrayList<Class<? extends Action>>(this.actions);
+    }
+
+    @XmlElement(name = "value")
+    @Override
+    public String getStringValue() {
+        List<String> nameList = new ArrayList<String>();
+        for (Class<? extends Action> clazz : actions) {
+            nameList.add(clazz.getSimpleName());
+        }
+        Collections.sort(nameList);
+        return nameList.toString();
+    }
+
+    @Override
+    public Property clone() {
+        return new SupportedFlowActions(this.actions);
+    }
+
+    @Override
+    public String toString() {
+        return this.getStringValue();
+    }
+}
index 6cada2c0417788291aa62491513e851645599f08..b3fa45bbc957322d3b0839ac86506d30359def7e 100644 (file)
@@ -20,8 +20,9 @@ import javax.xml.bind.annotation.XmlRootElement;
  * @brief  Class representing actions
  *
  * Describes supported actions
+ * @Deprecated This class is OF 1.0 specific. Use SupportedFlowActions instead.
  */
-
+@Deprecated
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
 public class Actions extends Property {
@@ -92,15 +93,19 @@ public class Actions extends Property {
 
     @Override
     public boolean equals(Object obj) {
-        if (this == obj)
+        if (this == obj) {
             return true;
-        if (!super.equals(obj))
+        }
+        if (!super.equals(obj)) {
             return false;
-        if (getClass() != obj.getClass())
+        }
+        if (getClass() != obj.getClass()) {
             return false;
+        }
         Actions other = (Actions) obj;
-        if (actionsValue != other.actionsValue)
+        if (actionsValue != other.actionsValue) {
             return false;
+        }
         return true;
     }
 
index 7281b9a71ffd7b08e60154e796b61ed5342b907e..54ba4865b2231d9e2b15b299e1b76094285a8c85 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
   </dependencies>
 </project>
index 1a787c7dc12ed38f25df230b39cb25fc92b61509..1e78ec7a3df60a545b6ff6c89d0e15567d44f359 100644 (file)
       <artifactId>junit</artifactId>
     </dependency>
     <dependency>
-        <groupId>equinoxSDK381</groupId>
-        <artifactId>org.apache.felix.gogo.runtime</artifactId>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.apache.felix.gogo.runtime</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
     </dependency>
   </dependencies>
 </project>
index 99482debd6d7e51c84415d3064ed38d05b5ca77e..4d2aea203601dafe6e19fcacc208ae4760819b0f 100644 (file)
@@ -111,6 +111,19 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
     private boolean isDefaultContainer = true;
     private static final int REPLACE_RETRY = 1;
 
+    /* Information about the default subnet. If there have been no configured subnets, i.e.,
+     * subnets.size() == 0 or subnetsConfigList.size() == 0, then this subnet will be the
+     * only subnet returned. As soon as a user-configured subnet is created this one will
+     * vanish.
+     */
+    protected static SubnetConfig DEFAULT_SUBNETCONFIG;
+    protected static Subnet DEFAULT_SUBNET;
+    protected static String DEFAULT_SUBNET_NAME = "default (cannot be modifed)";
+    static{
+        DEFAULT_SUBNETCONFIG = new SubnetConfig(DEFAULT_SUBNET_NAME, "0.0.0.0/0", new ArrayList<String>());
+        DEFAULT_SUBNET = new Subnet(DEFAULT_SUBNETCONFIG);
+    }
+
     public void notifySubnetChange(Subnet sub, boolean add) {
         synchronized (switchManagerAware) {
             for (Object subAware : switchManagerAware) {
@@ -295,12 +308,22 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
 
     @Override
     public List<SubnetConfig> getSubnetsConfigList() {
-        return new ArrayList<SubnetConfig>(subnetsConfigList.values());
+        // if there are no subnets, return the default subnet
+        if(subnetsConfigList.size() == 0){
+            return Collections.singletonList(DEFAULT_SUBNETCONFIG);
+        }else{
+            return new ArrayList<SubnetConfig>(subnetsConfigList.values());
+        }
     }
 
     @Override
     public SubnetConfig getSubnetConfig(String subnet) {
-        return subnetsConfigList.get(subnet);
+        // if there are no subnets, return the default subnet
+        if(subnetsConfigList.size() == 0 && subnet == DEFAULT_SUBNET_NAME){
+            return DEFAULT_SUBNETCONFIG;
+        }else{
+            return subnetsConfigList.get(subnet);
+        }
     }
 
     private List<SpanConfig> getSpanConfigList(Node node) {
@@ -646,6 +669,11 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
 
     @Override
     public Subnet getSubnetByNetworkAddress(InetAddress networkAddress) {
+        // if there are no subnets, return the default subnet
+        if (subnets.size() == 0) {
+            return DEFAULT_SUBNET;
+        }
+
         Subnet sub;
         Set<InetAddress> indices = subnets.keySet();
         for (InetAddress i : indices) {
index 91261f6499fe6092595117d9f90e1eb967f4003a..3d33edcbf2272c308cdb2236c574aaa42cd95ed9 100644 (file)
@@ -751,9 +751,15 @@ public class Devices implements IDaylightWeb {
 
         Set<Node> nodes = connectionManager.getLocalNodes();
         List<NodeJsonBean> result = new LinkedList<NodeJsonBean>();
+        if (nodes == null) {
+            return result;
+        }
         for (Node node : nodes) {
             Description descriptionProperty = (Description) switchManager.getNodeProp(node, "description");
-            String description = descriptionProperty.getValue();
+            String description = node.toString();
+            if (descriptionProperty != null) {
+                description = descriptionProperty.getValue();
+            }
             NodeJsonBean nodeBean = new NodeJsonBean();
             nodeBean.setNodeId(node.getNodeIDString());
             nodeBean.setNodeType(node.getType());
@@ -860,4 +866,4 @@ public class Devices implements IDaylightWeb {
         return "forward:" + "/";
     }
 
-}
\ No newline at end of file
+}
diff --git a/pom.xml b/pom.xml
index b95cdfd62aaf03027969a0b14e0c30a515e3d8cf..c603a9446e2e871ef4bd3667277db5df99b9f505 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <module>opendaylight/commons/checkstyle</module>
     <module>opendaylight/commons/opendaylight</module>
     <module>opendaylight/commons/parent</module>
+    <module>opendaylight/commons/logback_settings</module>
   </modules>
 
     <profiles>
diff --git a/third-party/com.siemens.ct.exi/pom.xml b/third-party/com.siemens.ct.exi/pom.xml
new file mode 100644 (file)
index 0000000..7a4f32f
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <!-- Get some common settings for the project we are using it in -->
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.thirdparty</artifactId>
+    <version>1.1.1-SNAPSHOT</version>
+    <relativePath>../commons/thirdparty</relativePath>
+  </parent>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+    <tag>HEAD</tag>
+  </scm>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.controller.thirdparty</groupId>
+  <artifactId>exificient</artifactId>
+  <version>0.9.2-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Embed-Dependency>*;scope=!provided;type=!pom;inline=false</Embed-Dependency>
+            <Embed-Transitive>false</Embed-Transitive>
+            <Export-Package>
+              com.siemens.ct.exi.*,
+            </Export-Package>
+            <Import-Package>
+                javax.xml.namespace,
+                javax.xml.parsers,
+                javax.xml.stream,
+                javax.xml.stream.events,
+                javax.xml.transform.sax,
+                org.apache.xerces.impl.xs,
+                org.apache.xerces.impl.xs.models,
+                org.apache.xerces.xni,
+                org.apache.xerces.xni.grammars,
+                org.apache.xerces.xni.parser,
+                org.apache.xerces.xs,
+                org.w3c.dom,
+                org.xml.sax,
+                org.xml.sax.ext,
+                org.xml.sax.helpers
+            </Import-Package>
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+
+  <dependencies>
+    <dependency>
+        <groupId>com.siemens.ct.exi</groupId>
+        <artifactId>exificient</artifactId>
+        <version>0.9.2</version>
+    </dependency>
+  </dependencies>
+
+</project>