From 06613e9e35fa37b83c87ef7f03ca8923752b83dc Mon Sep 17 00:00:00 2001 From: Sean Condon Date: Fri, 9 Jun 2017 15:14:01 +0100 Subject: [PATCH] Updating Microsemi Driver to onos-yang-tools 2.x Change-Id: I80e3348087518a8f9a742c813b6238371a3f8f97 --- .../{ea1000driver/BUCK.ignore => BUCK} | 23 +- .../microsemi/{ea1000driver => }/README.md | 151 ++-- drivers/microsemi/ea1000driver/pom.xml | 100 --- drivers/microsemi/ea1000yang/BUCK.ignore | 36 - drivers/microsemi/ea1000yang/pom.xml | 144 ---- .../yang/impl/AbstractYangServiceImpl.java | 185 ----- .../yang/impl/MseaSaFilteringManager.java | 76 -- .../mefservices/uni/CustomEvc.java | 107 --- .../mefservices/uni/evc/CustomEvcPerUni.java | 110 --- .../uni/evc/evcperuni/CustomEvcPerUnic.java | 82 -- .../uni/evc/evcperuni/CustomEvcPerUnin.java | 81 -- .../uni/evc/evcperuni/package-info.java | 21 - .../mefservices/uni/evc/package-info.java | 21 - .../mefservices/uni/package-info.java | 21 - .../src/main/resources/YangMetaData.ser | Bin 997680 -> 0 bytes .../microsemi/yang/MockIetfSystemManager.java | 43 - .../microsemi/yang/MockMseaCfmManager.java | 45 - .../yang/MseaUniEvcServiceManagerTest.java | 456 ----------- .../yms/app/yab/MockYmsManager.java | 152 ---- .../yms/app/ysr/MockYangSchemaRegistry.java | 767 ------------------ .../onosproject/yms/app/ysr/package-info.java | 20 - drivers/microsemi/pom.xml | 49 -- .../microsemi/EA1000FlowRuleProgrammable.java | 474 ++++++----- .../microsemi/EA1000MeterProvider.java | 140 ++-- .../drivers/microsemi/EA1000Pipeliner.java | 0 .../microsemi/Ea1000DeviceDescription.java | 24 +- .../microsemi/FullMetersAvailable.java | 0 .../microsemi/MicrosemiDriversLoader.java | 0 .../microsemi/NetconfConfigGetter.java | 0 .../drivers/microsemi/RpcResultParser.java | 0 .../drivers/microsemi/package-info.java | 0 .../yang/IetfSystemNetconfService.java | 23 +- .../yang/MicrosemiModelRegistrator.java | 135 +++ .../microsemi/yang/MseaCfmNetconfService.java | 33 +- .../yang/MseaSaFilteringNetconfService.java | 36 +- .../yang/MseaUniEvcServiceNetconfService.java | 33 +- .../drivers/microsemi/yang/UniSide.java | 0 .../yang/custom/CustomEvcPerUnic.java | 56 ++ .../yang/custom/CustomEvcPerUnin.java | 57 ++ .../microsemi/yang/custom}/package-info.java | 4 +- .../yang/impl/AbstractYangServiceImpl.java | 245 ++++++ .../yang/impl/IetfSystemManager.java | 102 +-- .../microsemi/yang/impl/MseaCfmManager.java | 103 +-- .../yang/impl/MseaSaFilteringManager.java | 202 +++++ .../yang/impl/MseaUniEvcServiceManager.java | 126 ++- .../microsemi/yang/impl/package-info.java | 0 .../drivers/microsemi/yang/package-info.java | 0 .../microsemi/yang/utils/CeVlanMapUtils.java | 0 .../yang/utils/IetfYangTypesUtils.java | 2 +- .../microsemi/yang/utils/package-info.java | 0 .../src/main/resources/microsemi-drivers.xml | 0 .../EA1000FlowRuleProgrammableTest.java | 0 .../microsemi/EA1000MeterProviderTest.java | 0 .../microsemi/MicrosemiDriversLoaderTest.java | 0 .../microsemi/MockEa1000DriverHandler.java | 0 .../microsemi/RpcResultParserTest.java | 0 .../microsemi/TestEA1000MeterProvider.java | 0 .../microsemi/yang/CeVlanMapUtilsTest.java | 0 .../microsemi/yang/IetfSystemManagerTest.java | 36 +- .../microsemi/yang/MockIetfSystemManager.java | 36 + .../microsemi/yang/MockMseaCfmManager.java | 35 + .../yang/MockMseaSaFilteringManager.java | 26 +- .../yang/MockMseaUniEvcServiceManager.java | 26 +- .../yang/MockNetconfSessionEa1000.java | 102 +-- .../microsemi/yang/MseaCfmManagerTest.java | 31 +- .../yang/MseaSaFilteringManagerTest.java | 94 ++- .../yang/MseaUniEvcServiceManagerTest.java | 496 +++++++++++ .../drivers/microsemi/yang/package-info.java | 0 .../yang/utils/IetfYangTypesUtilsTest.java | 2 +- .../yang/MockYangRuntimeManager.java | 152 ++++ .../xml/MockYangSchemaNodeProvider.java | 138 ++++ .../xml/MockYangSerializerContext.java | 50 ++ ...arrierEthernetFeature-sampleEvcConfig1.txt | 0 .../test/resources/getConfigSaFiltering.xml | 0 .../resources/getConfigSaFilteringReply.xml | 0 .../test/resources/systemReply-Sample1.xml | 0 .../test/resources/systemReply-Sample2.xml | 0 drivers/pom.xml | 1 - models/microsemi/BUCK | 4 + .../src/main/yang/ENTITY-STATE-TC-MIB.yang | 0 .../src/main/yang/fpga-internal.yang | 0 .../src/main/yang/iana-crypt-hash.yang | 0 .../src/main/yang/iana-if-type.yang | 0 .../microsemi}/src/main/yang/ieee-types.yang | 0 .../src/main/yang/ietf-inet-types.yang | 0 .../src/main/yang/ietf-interfaces.yang | 0 .../src/main/yang/ietf-netconf-acm.yang | 0 .../main/yang/ietf-netconf-monitoring.yang | 0 .../main/yang/ietf-netconf-notifications.yang | 0 .../main/yang/ietf-netconf-with-defaults.yang | 0 .../src/main/yang/ietf-netconf.yang | 0 .../src/main/yang/ietf-system-microsemi.yang | 0 .../src/main/yang/ietf-system-tls-auth.yang | 0 .../microsemi}/src/main/yang/ietf-system.yang | 0 .../src/main/yang/ietf-x509-cert-to-name.yang | 0 .../src/main/yang/ietf-yang-types.yang | 0 .../microsemi}/src/main/yang/msea-cfm.yang | 0 .../src/main/yang/msea-sa-filtering.yang | 0 .../src/main/yang/msea-soam-fm.yang | 0 .../src/main/yang/msea-soam-pm.yang | 0 .../microsemi}/src/main/yang/msea-types.yang | 0 .../src/main/yang/msea-uni-evc-interface.yang | 0 .../src/main/yang/msea-uni-evc-service.yang | 0 .../src/main/yang/nc-notifications.yang | 0 .../src/main/yang/netopeer-cfgnetopeer.yang | 0 .../src/main/yang/notifications.yang | 0 .../microsemi}/src/main/yang/rfc-2544.yang | 0 .../src/main/yang/svc-activation-types.yang | 0 .../microsemi}/src/main/yang/y-1564.yang | 0 modules.defs | 4 +- 110 files changed, 2442 insertions(+), 3276 deletions(-) rename drivers/microsemi/{ea1000driver/BUCK.ignore => BUCK} (60%) rename drivers/microsemi/{ea1000driver => }/README.md (78%) delete mode 100644 drivers/microsemi/ea1000driver/pom.xml delete mode 100644 drivers/microsemi/ea1000yang/BUCK.ignore delete mode 100644 drivers/microsemi/ea1000yang/pom.xml delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/CustomEvc.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/CustomEvcPerUni.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/CustomEvcPerUnic.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/CustomEvcPerUnin.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/package-info.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/package-info.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/package-info.java delete mode 100644 drivers/microsemi/ea1000yang/src/main/resources/YangMetaData.ser delete mode 100644 drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java delete mode 100644 drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java delete mode 100644 drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java delete mode 100644 drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/yab/MockYmsManager.java delete mode 100644 drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/ysr/MockYangSchemaRegistry.java delete mode 100644 drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/ysr/package-info.java delete mode 100644 drivers/microsemi/pom.xml rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java (63%) rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java (52%) rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java (100%) rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java (81%) rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java (100%) rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java (100%) rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java (100%) rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java (100%) rename drivers/microsemi/{ea1000driver => }/src/main/java/org/onosproject/drivers/microsemi/package-info.java (100%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java (75%) create mode 100644 drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java (64%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java (55%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java (74%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java (100%) create mode 100644 drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java create mode 100644 drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java rename drivers/microsemi/{ea1000yang/src/test/java/org/onosproject/yms/app/yab => src/main/java/org/onosproject/drivers/microsemi/yang/custom}/package-info.java (85%) create mode 100644 drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java (62%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java (62%) create mode 100644 drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java (62%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java (100%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java (100%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java (100%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java (95%) rename drivers/microsemi/{ea1000yang => }/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java (100%) rename drivers/microsemi/{ea1000driver => }/src/main/resources/microsemi-drivers.xml (100%) rename drivers/microsemi/{ea1000driver => }/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java (100%) rename drivers/microsemi/{ea1000driver => }/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java (100%) rename drivers/microsemi/{ea1000driver => }/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java (100%) rename drivers/microsemi/{ea1000driver => }/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java (100%) rename drivers/microsemi/{ea1000driver => }/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java (100%) rename drivers/microsemi/{ea1000driver => }/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java (100%) rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java (100%) rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java (65%) create mode 100644 drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java create mode 100644 drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java (53%) rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java (53%) rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java (93%) rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java (69%) rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java (50%) create mode 100644 drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/package-info.java (100%) rename drivers/microsemi/{ea1000yang => }/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java (95%) create mode 100644 drivers/microsemi/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java create mode 100644 drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java create mode 100644 drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java rename drivers/microsemi/{ea1000driver => }/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt (100%) rename drivers/microsemi/{ea1000driver => }/src/test/resources/getConfigSaFiltering.xml (100%) rename drivers/microsemi/{ea1000driver => }/src/test/resources/getConfigSaFilteringReply.xml (100%) rename drivers/microsemi/{ea1000driver => }/src/test/resources/systemReply-Sample1.xml (100%) rename drivers/microsemi/{ea1000driver => }/src/test/resources/systemReply-Sample2.xml (100%) create mode 100644 models/microsemi/BUCK rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ENTITY-STATE-TC-MIB.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/fpga-internal.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/iana-crypt-hash.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/iana-if-type.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ieee-types.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-inet-types.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-interfaces.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-netconf-acm.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-netconf-monitoring.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-netconf-notifications.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-netconf-with-defaults.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-netconf.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-system-microsemi.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-system-tls-auth.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-system.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-x509-cert-to-name.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/ietf-yang-types.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/msea-cfm.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/msea-sa-filtering.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/msea-soam-fm.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/msea-soam-pm.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/msea-types.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/msea-uni-evc-interface.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/msea-uni-evc-service.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/nc-notifications.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/netopeer-cfgnetopeer.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/notifications.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/rfc-2544.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/svc-activation-types.yang (100%) rename {drivers/microsemi/ea1000yang => models/microsemi}/src/main/yang/y-1564.yang (100%) diff --git a/drivers/microsemi/ea1000driver/BUCK.ignore b/drivers/microsemi/BUCK similarity index 60% rename from drivers/microsemi/ea1000driver/BUCK.ignore rename to drivers/microsemi/BUCK index bee66fbe4c..2787032fde 100644 --- a/drivers/microsemi/ea1000driver/BUCK.ignore +++ b/drivers/microsemi/BUCK @@ -3,29 +3,31 @@ COMPILE_DEPS = [ '//drivers/utilities:onos-drivers-utilities', '//protocols/netconf/api:onos-protocols-netconf-api', '//protocols/netconf/ctl:onos-protocols-netconf-ctl', - '//drivers/microsemi/ea1000yang:onos-drivers-microsemi-ea1000yang', - '//drivers/microsemi/ea1000yang:onos-drivers-microsemi-ea1000yang-gen', + '//models/microsemi:onos-models-microsemi', '//lib:org.apache.karaf.shell.console', - '//cli:onos-cli', '//incubator/api:onos-incubator-api', -] +] + YANG_TOOLS TEST_DEPS = [ '//lib:TEST_ADAPTERS', '//core/api:onos-api-tests', '//drivers/netconf:onos-drivers-netconf-tests', - '//drivers/microsemi/ea1000yang:onos-drivers-microsemi-ea1000yang-tests', + '//utils/osgi:onlab-osgi-tests' ] -BUNDLES = [ - '//drivers/utilities:onos-drivers-utilities', - '//drivers/microsemi/ea1000yang:onos-drivers-microsemi-ea1000yang', +APPS = [ + 'org.onosproject.yang', +# 'org.onosproject.yang-gui', + 'org.onosproject.config', + 'org.onosproject.netconf', + 'org.onosproject.netconfsb', + 'org.onosproject.drivers.netconf', + 'org.onosproject.models.microsemi' ] osgi_jar_with_tests ( deps = COMPILE_DEPS, test_deps = TEST_DEPS, - srcs = glob(['src/main/java/**/*.java']), resources_root = 'src/main/resources', resources = glob(['src/main/resources/**']), ) @@ -36,6 +38,5 @@ onos_app ( category = 'Drivers', url = 'http://onosproject.org', description = 'ONOS Microsemi device drivers application.', - included_bundles = BUNDLES, - required_apps = [ 'org.onosproject.netconf', 'org.onosproject.yms' ], + required_apps = APPS, ) diff --git a/drivers/microsemi/ea1000driver/README.md b/drivers/microsemi/README.md similarity index 78% rename from drivers/microsemi/ea1000driver/README.md rename to drivers/microsemi/README.md index 41870390b4..1737b086b8 100755 --- a/drivers/microsemi/ea1000driver/README.md +++ b/drivers/microsemi/README.md @@ -7,60 +7,45 @@ The User Guide for this product is available on request from Microsemi, and give Currently only a subset of it's functionality is supported through ONOS, but this will expand to full functionality in future releases. #Compile and Installation -Currently this driver is **not** built using BUCK (because it depends on an older version of onos-yang-tools, while BUCK points to the newer version of the onos-yang-tools)
+Currently this driver is built using BUCK and uses version 2.1 of onos-yang-tools
-Before this driver can work successfully one problem with the Yang Management System (YMS) App has to be taken in to account. This is that the Yang Codec Handler (YCH) part needs to be built in Maven (when compiled in Buck something is not configured properly).
- -To build YMS with Maven: -1. Change directory to onos/apps/yms/app -2. Run the command "mvn clean install" (or use the shortcut 'mci') -3. With onos running, **reinstall** the generated OAR file for YMS on the target machine (could be localhost - replace {bracketed} values with real values) - * onos-app {onos-server} reinstall! target/onos-app-yms-{version}.oar - - -Then this Microsemi driver has to be built using Maven and installed. To build it: -1. Change directory to onos/drivers/microsemi -2. Run the command "mvn clean install" (or use the shortcut 'mci') -3. With onos running, install the 2 generated OAR files on the target machine (could be localhost - replace {bracketed} values with real values) - * onos-app {onos-server} install ea1000yang/target/onos-drivers-microsemi-ea1000yang-{version}.oar - * onos-app {onos-server} install ea1000driver/target/onos-drivers-microsemi-ea1000-{version}.oar -4. Verify that they are installed by calling **apps -s | grep microsemi** at the onos> prompt -5. Activate the modules at the onos prompt - * onos:app activate org.onosproject.drivers.netconf org.onosproject.drivers.microsemi.yang org.onosproject.drivers.microsemi +All that is required to activate the driver is to run the following at the ONOS CLI
+**`onos:app activate org.onosproject.drivers.microsemi`**
+This will load any dependent apps also. To verify the driver has been loaded run the command
+**onos:apps -a -s** #Change NETCONF default connection timeout Connection timeouts need to be increased from default values when using EA1000. At ONOS command line run -`onos:cfg set org.onosproject.netconf.ctl.NetconfControllerImpl netconfConnectTimeout 150`
-`onos:cfg set org.onosproject.netconf.ctl.NetconfControllerImpl netconfReplyTimeout 150`
+`onos:cfg set org.onosproject.netconf.ctl.impl.NetconfControllerImpl netconfConnectTimeout 50`
+`onos:cfg set org.onosproject.netconf.ctl.impl.NetconfControllerImpl netconfReplyTimeout 50`
#Creating Devices EA1000 Devices will not be automatically discovered at present in ONOS. They have to be created through the network/configuration REST interface in ONOS. -* The name must follow the format **netconf::** +* The name must follow the format **netconf:ipaddr:port** * The **ip** and **port** must correspond to the ip and port in the name (above). `{`
-` "devices": {`
-`  "netconf:192.168.56.10:830": {`
-`   "netconf": {`
-`     "username": "admin",`
-`     "password": "admin",`
-`     "ip": "192.168.56.10",`
-`     "port": "830"`
-`   },`
-`   "basic": {`
-`    "driver": "microsemi-netconf",`
-`    "type": "SWITCH",`
-`    "manufacturer": "Microsemi",`
-`    "hwVersion": "EA1000"`
-`   }`
-`  }`
-` }`
+ `"devices": {`
+  `"netconf:192.168.56.10:830": {`
+   `"netconf": {`
+     `"username": "admin",`
+     `"password": "admin",`
+     `"ip": "192.168.56.10",`
+     `"port": "830"`
+   `},`
+   `"basic": {`
+    `"driver": "microsemi-netconf",`
+    `"type": "SWITCH",`
+    `"manufacturer": "Microsemi",`
+    `"hwVersion": "EA1000"`
+   `}`
+  `}`
+ `}`
`}`
- #Connected Device When the EA1000 is configured and connected is should be visible in ONOS through the **devices** command. @@ -94,22 +79,22 @@ A feature of the EA1000 that may be configured through Flow Rules is IP Source A `POST /onos/v1/flows/ HTTP/1.1`
`{`
-` "flows": [`
-`  {`
-`   "priority": 40000,`
-`   "timeout": 0,`
-`   "isPermanent": true,`
-`   "deviceId": "netconf:192.168.56.10:830",`
-`   "tableId": 8,`
-`   "treatment": {`
-`    "instructions": [ {"type": "NOACTION"} ],`
-`    "deferred": []`
-`   },`
-`   "selector": {`
-`    "criteria": [ {`
-`     "type": "IPV4_SRC", "ip": "192.168.8.0/24"`
-`    },{`
-`     "type": "IN_PORT", "port": "0"`
+ `"flows": [`
+  `{`
+   `"priority": 50000,`
+   `"timeout": 0,`
+   `"isPermanent": true,`
+   `"deviceId": "netconf:192.168.56.10:830",`
+   `"tableId": 8,`
+   `"treatment": {`
+    `"instructions": [ {"type": "NOACTION"} ],`
+    `"deferred": []`
+   `},`
+   `"selector": {`
+    `"criteria": [ {`
+     `"type": "IPV4_SRC", "ip": "192.168.8.0/24"`
+    `},{`
+     `"type": "IN_PORT", "port": "0"`
`} ] } } ] }`
## Vlan Tag Manipulation @@ -306,34 +291,34 @@ On the actual EA1000 itself using a NETCONF CLI Client like yangcli-pro, the res `admin@192.168.56.10> sget-config /mef-services/uni source=running`
`rpc-reply {`
-` data {`
-`  mef-services {`
-`   uni {` -- There is only one UNI on the EA1000
-`    name Uni-on-192.168.56.10:830` -- Automatically assigned
-`    evc 1 {` -- From the VLAN 1 from CE app
-`     evc-index 1`
-`     name EVC-1` -- Automatically assigned
-`     evc-per-uni {`
-`      evc-per-uni-c {` -- The UNI-C side
-`       ce-vlan-map 101` -- Could be a range of values
-`       flow-mapping {`
-`        ce-vlan-id 101`
-`        flow-id 31243725464268887` -- For tracking with ONOS
-`       }`
-`       ingress-bwp-group-index 0` -- No meters
-`       tag-push {` -- Push on an a VLAN
-`        push-tag-type pushStag` -- Push type is S-TAG
-`        outer-tag-vlan 1` -- Push value is 1
-`       }`
-`      }`
-`      evc-per-uni-n {` -- For the UNI-N side
-`       ce-vlan-map 1` -- The VLAN to match for egress on this side
-`       flow-mapping {`
-`        ce-vlan-id 1`
-`        flow-id 31243723770830293`
-`       }`
-`       ingress-bwp-group-index 0`
-`       tag-pop {` -- Pop off the S-TAG
+ data `{`
+  `mef-services {`
+   `uni {` -- There is only one UNI on the EA1000
+    `name Uni-on-192.168.56.10:830` -- Automatically assigned
+    `evc 1 {` -- From the VLAN 1 from CE app
+     `evc-index 1`
+     `name EVC-1` -- Automatically assigned
+     `evc-per-uni {`
+      `evc-per-uni-c {` -- The UNI-C side
+       `ce-vlan-map 101` -- Could be a range of values
+       `flow-mapping {`
+        `ce-vlan-id 101`
+        `flow-id 31243725464268887` -- For tracking with ONOS
+       `}`
+       `ingress-bwp-group-index 0` -- No meters
+       `tag-push {` -- Push on an a VLAN
+        `push-tag-type pushStag` -- Push type is S-TAG
+        `outer-tag-vlan 1` -- Push value is 1
+       `}`
+      `}`
+      `evc-per-uni-n {` -- For the UNI-N side
+       `ce-vlan-map 1` -- The VLAN to match for egress on this side
+       `flow-mapping {`
+        `ce-vlan-id 1`
+        `flow-id 31243723770830293`
+       `}`
+       `ingress-bwp-group-index 0`
+       `tag-pop {` -- Pop off the S-TAG
`} } } } } } } }`
`admin@192.168.56.10>`
diff --git a/drivers/microsemi/ea1000driver/pom.xml b/drivers/microsemi/ea1000driver/pom.xml deleted file mode 100644 index 3ba11e8a29..0000000000 --- a/drivers/microsemi/ea1000driver/pom.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - 4.0.0 - - - onos-drivers-microsemi - org.onosproject - 1.11.0-SNAPSHOT - - - onos-drivers-microsemi-ea1000 - bundle - - Microsemi EA1000 device drivers for ONOS - http://www.microsemi.com - - - UTF-8 - ${project.version} - org.onosproject.drivers.microsemi - Microsemi Device Drivers - Microsemi, Inc. - Drivers - http://onosproject.org - For various Microsemi Devices including EdgeAssure - 1000 SFP-NID - org.onosproject.netconf - org.onosproject.drivers.netconf - org.onosproject.yms - org.onosproject.drivers.microsemi.yang - - - - - com.google.guava - guava - - - - org.onosproject - onos-netconf-api - ${project.version} - - - - org.onosproject - onos-incubator-api - - - - org.onosproject - onos-drivers-microsemi-ea1000yang - ${project.version} - - - - org.onosproject - onos-drivers-microsemi-ea1000yang - ${project.version} - test-jar - test - - - - org.onosproject - onos-app-yms-api - ${project.version} - test - - - - org.onosproject - onos-app-yms - ${project.version} - test - - - - org.onosproject - onos-drivers-netconf - ${project.version} - test-jar - test - - - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - - - diff --git a/drivers/microsemi/ea1000yang/BUCK.ignore b/drivers/microsemi/ea1000yang/BUCK.ignore deleted file mode 100644 index 73d20c0a06..0000000000 --- a/drivers/microsemi/ea1000yang/BUCK.ignore +++ /dev/null @@ -1,36 +0,0 @@ -YANG_DEPS = [ - '//lib:CORE_DEPS', - '//lib:onos-yang-datamodel', - '//lib:onos-yang-utils-generator', -] - -COMPILE_DEPS = [ - '//lib:CORE_DEPS', - '//apps/yms/api:onos-apps-yms-api', - '//protocols/netconf/api:onos-protocols-netconf-api', - '//lib:onos-yang-datamodel', - '//lib:onos-yang-utils-generator', - '//lib:org.apache.servicemix.bundles.dom4j', - '//drivers/microsemi/ea1000yang:onos-drivers-microsemi-ea1000yang-gen', -] - -TEST_DEPS = [ - '//lib:TEST_ADAPTERS', - '//apps/yms/app:onos-apps-yms-app', - '//drivers/netconf:onos-drivers-netconf-tests', - '//protocols/netconf/ctl:onos-protocols-netconf-ctl', -] - -yang_osgi_jar( - deps = YANG_DEPS, - name = 'onos-drivers-microsemi-ea1000yang-gen', - srcs = glob(['src/main/yang/**/*.yang']), - visibility = [ 'PUBLIC' ], -) - -osgi_jar_with_tests( - deps = COMPILE_DEPS, - test_deps = TEST_DEPS, - visibility = [ 'PUBLIC' ], - srcs = glob(['src/main/**/*.java']) -) diff --git a/drivers/microsemi/ea1000yang/pom.xml b/drivers/microsemi/ea1000yang/pom.xml deleted file mode 100644 index edf21d6543..0000000000 --- a/drivers/microsemi/ea1000yang/pom.xml +++ /dev/null @@ -1,144 +0,0 @@ - - - - 4.0.0 - - - onos-drivers-microsemi - org.onosproject - 1.11.0-SNAPSHOT - - - onos-drivers-microsemi-ea1000yang - bundle - - Microsemi YANG model for EA1000 - http://www.microsemi.com - - - UTF-8 - ${project.version} - org.onosproject.drivers.microsemi.yang - Microsemi Device Drivers YANG - Microsemi, Inc. - Drivers - http://onosproject.org - For various Microsemi Devices including EdgeAssure - 1000 SFP-NID - 1.11 - - - - - - org.onosproject - onos-netconf-api - ${project.version} - - - - org.onosproject - onos-yang-utils-generator - ${onos.yang.version} - - - - org.onosproject - onos-yang-datamodel - ${onos.yang.version} - - - - org.onosproject - onos-app-yms-api - ${project.version} - - - - org.onosproject - onlab-junit - test - - - - org.onosproject - onos-app-yms - ${project.version} - test - - - - org.onosproject - onos-drivers-netconf - ${project.version} - test-jar - test - - - - - - - org.onosproject - onos-yang-maven-plugin - ${onos.yang.version} - - - - target/generated-sources - - - yang2java - - - - - - org.apache.felix - maven-bundle-plugin - true - - - yang/resources/YangMetaData.ser=target/classes/yang/resources/YangMetaData.ser - - - - - - org.apache.maven.plugins - maven-clean-plugin - 3.0.0 - - - onos-yang-plugin-workaround - - initialize - - clean - - - true - - - target/generated-sources - - - - - - - - - org.jacoco - jacoco-maven-plugin - - - **/delaymeasurement/* - **/lossmeasurement/* - - - - - - - diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java deleted file mode 100644 index 7b65a758b9..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.drivers.microsemi.yang.impl; - -import static org.onosproject.yms.ych.YangProtocolEncodingFormat.XML; -import static org.onosproject.yms.ydt.YmsOperationType.EDIT_CONFIG_REQUEST; -import static org.onosproject.yms.ydt.YmsOperationType.QUERY_REPLY; -import static org.onosproject.yms.ydt.YmsOperationType.QUERY_REQUEST; - -import java.util.List; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.netconf.NetconfException; -import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yms.ych.YangCodecHandler; -import org.onosproject.yms.ych.YangCompositeEncoding; -import org.onosproject.yms.ymsm.YmsService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Abstract class that implements some of the core functions of a YANG model service. - * - */ -@Component(immediate = true) -@Service -public abstract class AbstractYangServiceImpl { - protected final Logger log = LoggerFactory.getLogger(getClass()); - protected boolean alreadyLoaded = false; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected CoreService coreService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected YmsService ymsService; - - protected ApplicationId appId; - - // YCH is not a service and is a class variable. Can be lost on deactivate. - // Must be recreated on activate - protected YangCodecHandler ych; - - @Activate - public abstract void activate(); - - @Deactivate - public void deactivate() { - alreadyLoaded = false; - } - - /** - * Internal method to generically make a NETCONF get query from YANG objects. - * @param yangObjectOpParamFilter A YANG object model - * @param session A NETCONF session - * @return YangObjectModel - * @throws NetconfException if the session has any error - */ - protected final Object getNetconfObject( - Object yangObjectOpParamFilter, NetconfSession session) - throws NetconfException { - if (session == null) { - throw new NetconfException("Session is null when calling getNetconfObject()"); - } - if (yangObjectOpParamFilter == null) { - throw new NetconfException("Query object cannot be null"); - } - //Convert the param to XML to use as a filter - YangCompositeEncoding xmlQuery = - ych.encodeCompositeOperation(null, null, - yangObjectOpParamFilter, XML, QUERY_REQUEST); - - String xmlQueryStr = xmlQuery.getResourceInformation().replace("<>", "").replace("", "").trim(); - log.debug("Sending query on NETCONF session " + session.getSessionId() + - ":\n" + xmlQueryStr); - - String xmlResult = session.get(xmlQueryStr, null); - - List objectList = ych.decode(xmlResult, XML, QUERY_REPLY); - if (objectList != null && objectList.size() > 0) { - Object systemObject = objectList.get(0); - return systemObject; - } else { - return null; - } - } - - /** - * Internal method to generically make a NETCONF get-config query from YANG objects. - * - * @param yangObjectOpParamFilter A YANG object model - * @param session A NETCONF session - * @param targetDs - running,candidate or startup - * @return YangObjectModel - * @throws NetconfException if the session has any error - */ - protected final Object getConfigNetconfObject( - Object yangObjectOpParamFilter, NetconfSession session, TargetConfig targetDs) - throws NetconfException { - if (session == null) { - throw new NetconfException("Session is null when calling getConfigNetconfObject()"); - } - - if (yangObjectOpParamFilter == null) { - throw new NetconfException("Query object cannot be null"); - } - //Convert the param to XML to use as a filter - YangCompositeEncoding xmlQuery = - ych.encodeCompositeOperation(null, null, - yangObjectOpParamFilter, XML, QUERY_REQUEST); - - String xmlQueryStr = xmlQuery.getResourceInformation().replace("<>", "").replace("", "").trim(); - log.debug("Sending for " + targetDs + - " query on NETCONF session " + session.getSessionId() + - ":\n" + xmlQueryStr); - - String xmlResult = session.getConfig(targetDs, xmlQueryStr); - - List objectList = ych.decode(xmlResult, XML, QUERY_REPLY); - if (objectList != null && objectList.size() > 0) { - Object systemObject = objectList.get(0); - return systemObject; - } else { - return null; - } - } - - /** - * Internal method to generically make a NETCONF edit-config call from a set of YANG objects. - * - * @param yangObjectOpParamFilter A YANG object model - * @param session A NETCONF session - * @param targetDs - running,candidate or startup - * @throws NetconfException if the session has any error - */ - protected final void setNetconfObject( - Object yangObjectOpParamFilter, NetconfSession session, TargetConfig targetDs) - throws NetconfException { - if (yangObjectOpParamFilter == null) { - throw new NetconfException("Query object cannot be null"); - } else if (session == null) { - throw new NetconfException("Session is null when calling getMseaSaFiltering()"); - } - //Convert the param to XML to use as a filter - YangCompositeEncoding xmlContent = - ych.encodeCompositeOperation(null, null, - yangObjectOpParamFilter, XML, EDIT_CONFIG_REQUEST); - - String xmlContentStr = xmlContent.getResourceInformation() - .replace("<>", "").replace("", "") - //FIXME: Necessary for MEP ccmInterval - .replaceAll("yangAutoPrefix", "") - .trim(); - - log.debug("Sending XML on NETCONF session " + session.getSessionId() + - ":\n" + xmlContentStr); - - boolean succeeded = session.editConfig(targetDs, null, xmlContentStr); - if (succeeded) { - log.debug(" succeeded through NETCONF"); - } else { - throw new NetconfException("Failed to run edit-config through NETCONF"); - } - } -} diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java deleted file mode 100644 index eeba11ec75..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.drivers.microsemi.yang.impl; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService; -import org.onosproject.netconf.NetconfException; -import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.MseaSaFiltering; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.MseaSaFilteringOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.MseaSaFilteringService; - -/** - * Implementation of the MseaSaFiltering YANG model service. - */ -@Component(immediate = true, inherit = true) -@Service -public class MseaSaFilteringManager extends AbstractYangServiceImpl - implements MseaSaFilteringNetconfService { - public static final String MSEA_SA_FILTERING = "org.onosproject.drivers.microsemi.yang.mseasafiltering"; - - @Activate - public void activate() { - appId = coreService.registerApplication(MSEA_SA_FILTERING); - ych = ymsService.getYangCodecHandler(); - ych.addDeviceSchema(MseaSaFilteringService.class); - log.info("MseaSaFilteringManager Started"); - } - - @Deactivate - public void deactivate() { - super.deactivate(); - ymsService.unRegisterService(this, MseaSaFilteringService.class); - ych = null; - log.info("MseaSaFilteringManager Stopped"); - } - - /** - * Get a filtered subset of the model. - * This is meant to filter the current live model - * against the attribute(s) given in the argument - * and return the filtered model. - */ - @Override - public MseaSaFiltering getMseaSaFiltering(MseaSaFilteringOpParam mseaSaFilteringFilter, NetconfSession session) - throws NetconfException { - return (MseaSaFiltering) getNetconfObject(mseaSaFilteringFilter, session); - } - - /** - * Call NETCONF edit-config with a configuration. - */ - @Override - public void setMseaSaFiltering( - MseaSaFilteringOpParam mseaSaFiltering, NetconfSession session, TargetConfig ncDs) - throws NetconfException { - setNetconfObject(mseaSaFiltering, session, ncDs); - } -} diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/CustomEvc.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/CustomEvc.java deleted file mode 100644 index 722fe788c0..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/CustomEvc.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni; - -import org.onosproject.drivers.microsemi.yang.UniSide; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types - .rev20160229.mseatypes.ServiceListType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni.evc.CustomEvcPerUni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin; - -/** - * A custom implementation of the DefaultEvc - especially its Builder. - * - * This allows the Evc to be modified after creation. These additions to the - * builder are necessary because in the EA1000 YANG model many different Open Flow - * flows can be associated with one EVC - each one has its own Ce-Vlan-Id and - * Flow Reference - */ -public class CustomEvc extends DefaultEvc { - - public static EvcBuilder builder(Evc evc) { - return new EvcBuilder(evc); - } - - public static class EvcBuilder extends DefaultEvc.EvcBuilder { - - /** - * Allow a builder to be constructed from an existing EVC - * @param evc An existing EVC - */ - public EvcBuilder(Evc evc) { - this.evcPerUni = evc.evcPerUni(); - this.evcStatus = evc.evcStatus(); - this.evcIndex = evc.evcIndex(); - this.mtuSize = evc.mtuSize(); - this.cevlanCosPreservation = evc.cevlanCosPreservation(); - this.cevlanIdPreservation = evc.cevlanIdPreservation(); - this.name = evc.name(); - this.yangEvcOpType = evc.yangEvcOpType(); - this.yangAugmentedInfoMap = evc.yangAugmentedInfoMap(); - this.name = evc.name(); - this.serviceType = evc.serviceType(); - this.selectLeafFlags = evc.selectLeafFlags(); - this.uniEvcId = evc.uniEvcId(); - this.valueLeafFlags = evc.valueLeafFlags(); - } - - /** - * Method to allow ceVlanMap to be modified. - * @param additionalCeVlanMap An addition to the existing ceVlanMap - * @param side The Uni Side - Customer or Network - * @return The updated builder - */ - public EvcBuilder addToCeVlanMap(ServiceListType additionalCeVlanMap, UniSide side) { - evcPerUni = CustomEvcPerUni.builder(evcPerUni).addToCeVlanMap(additionalCeVlanMap, side).build(); - return this; - } - - /** - * Method to allow the Flow Mapping list to be modified. - * @param fm the flow mapping - * @param side The Uni Side - Customer or Network - * @return The updated builder - */ - public EvcBuilder addToFlowMapping(FlowMapping fm, UniSide side) { - evcPerUni = CustomEvcPerUni.builder(evcPerUni).addToFlowMapping(fm, side).build(); - return this; - } - - /** - * Method to allow an EVC side to be added. - * @param evcUniN An EVCPerUni object - * @return The updated builder - */ - public EvcBuilder addUniN(EvcPerUnin evcUniN) { - evcPerUni = CustomEvcPerUni.builder(evcPerUni).addUniN(evcUniN).build(); - return this; - } - - /** - * Method to allow an EVC side to be added. - * @param evcUniC An EVCPerUni object - * @return The updated builder - */ - public EvcBuilder addUniC(EvcPerUnic evcUniC) { - evcPerUni = CustomEvcPerUni.builder(evcPerUni).addUniC(evcUniC).build(); - return this; - } - } -} diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/CustomEvcPerUni.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/CustomEvcPerUni.java deleted file mode 100644 index ed53593ee9..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/CustomEvcPerUni.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni.evc; - -import org.onosproject.drivers.microsemi.yang.UniSide; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types - .rev20160229.mseatypes.ServiceListType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.CustomEvcPerUnic; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.CustomEvcPerUnin; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin; - -/** - * A custom implementation of the DefaultEvcPerUni - especially its Builder. - * - * This allows the EvcPerUni to be modified after creation. These additions to the - * builder are necessary because in the EA1000 YANG model the EvcPerUni side can - * be added at separate stages - */ -public class CustomEvcPerUni extends DefaultEvcPerUni { - - public static EvcPerUniBuilder builder(EvcPerUni evcPerUni) { - return new EvcPerUniBuilder(evcPerUni); - } - - public static class EvcPerUniBuilder extends DefaultEvcPerUni.EvcPerUniBuilder { - - /** - * Allow a builder to be constructed from an existing EvcPerUni - * @param evcPerUni An existing EvcPerUni - */ - public EvcPerUniBuilder(EvcPerUni evcPerUni) { - this.evcPerUnic = evcPerUni.evcPerUnic(); - this.evcPerUnin = evcPerUni.evcPerUnin(); - this.evcUniType = evcPerUni.evcUniType(); - this.yangEvcPerUniOpType = evcPerUni.yangEvcPerUniOpType(); - this.valueLeafFlags = evcPerUni.valueLeafFlags(); - this.selectLeafFlags = evcPerUni.selectLeafFlags(); - this.yangAugmentedInfoMap = evcPerUni.yangAugmentedInfoMap(); - } - - /** - * Method to allow ceVlanMap to be modified. - * @param additionalCeVlanMap An addition to the existing ceVlanMap - * @param side The Uni Side - Customer or Network - * @return The updated builder - */ - public EvcPerUniBuilder addToCeVlanMap(ServiceListType additionalCeVlanMap, UniSide side) { - if (side == UniSide.NETWORK) { - evcPerUnin = CustomEvcPerUnin.builder(evcPerUnin).addToCeVlanMap(additionalCeVlanMap).build(); - } else { - evcPerUnic = CustomEvcPerUnic.builder(evcPerUnic).addToCeVlanMap(additionalCeVlanMap).build(); - } - - return this; - } - - /** - * Method to allow the Flow Mapping list to be modified. - * @param fm the flow mapping - * @param side The Uni Side - Customer or Network - * @return The updated builder - */ - public EvcPerUniBuilder addToFlowMapping(FlowMapping fm, UniSide side) { - if (side == UniSide.NETWORK) { - evcPerUnin = CustomEvcPerUnin.builder(evcPerUnin).addToFlowMapping(fm).build(); - } else { - evcPerUnic = CustomEvcPerUnic.builder(evcPerUnic).addToFlowMapping(fm).build(); - } - return this; - } - - /** - * Method to allow an EVC side to be added. - * @param evcUniN An EVCPerUni object - * @return The updated builder - */ - public EvcPerUniBuilder addUniN(EvcPerUnin evcUniN) { - this.evcPerUnin = evcUniN; - return this; - } - - /** - * Method to allow an EVC side to be added. - * @param evcUniC An EVCPerUni object - * @return The updated builder - */ - public EvcPerUniBuilder addUniC(EvcPerUnic evcUniC) { - this.evcPerUnic = evcUniC; - return this; - } - } -} diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/CustomEvcPerUnic.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/CustomEvcPerUnic.java deleted file mode 100644 index 2e8dfc6657..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/CustomEvcPerUnic.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni; - -import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types - .rev20160229.mseatypes.ServiceListType; - -/** - * A custom implementation of the DefaultEvcPerUnic - especially its Builder. - * - * This allows the EvcPerUniC to be modified after creation. These additions to the - * builder are necessary because in the EA1000 YANG model the EvcPerUniC can - * be added at separate stages - */ -public class CustomEvcPerUnic extends DefaultEvcPerUnic { - public static EvcPerUnicBuilder builder(EvcPerUnic evcPerUnic) { - return new EvcPerUnicBuilder(evcPerUnic); - } - - public static EvcPerUnicBuilder builder() { - return new EvcPerUnicBuilder(); - } - - public static class EvcPerUnicBuilder extends DefaultEvcPerUnic.EvcPerUnicBuilder { - - /** - * Allow a new builder to be constructed - */ - public EvcPerUnicBuilder() { - valueLeafFlags.set(LeafIdentifier.CEVLANMAP.getLeafIndex()); - this.ceVlanMap = new ServiceListType("0"); - valueLeafFlags.set(LeafIdentifier.INGRESSBWPGROUPINDEX.getLeafIndex()); - this.ingressBwpGroupIndex = 0; - } - - /** - * Allow a builder to be constructed from an existing EvcPerUnic - * @param evcPerUnic An existing EvcPerUnic - */ - public EvcPerUnicBuilder(EvcPerUnic evcPerUnic) { - this.ceVlanMap = evcPerUnic.ceVlanMap(); - this.evcPerUniServiceType = evcPerUnic.evcPerUniServiceType(); - this.ingressBwpGroupIndex = evcPerUnic.ingressBwpGroupIndex(); - this.tagManipulation = evcPerUnic.tagManipulation(); - this.flowMapping = evcPerUnic.flowMapping(); - this.yangEvcPerUnicOpType = evcPerUnic.yangEvcPerUnicOpType(); - this.yangAugmentedInfoMap = evcPerUnic.yangAugmentedInfoMap(); - this.selectLeafFlags = evcPerUnic.selectLeafFlags(); - this.valueLeafFlags = evcPerUnic.valueLeafFlags(); - } - - /** - * Method to allow ceVlanMap to be modified. - * @param additionalCeVlanMap An addition to the existing ceVlanMap - * @return The updated builder - */ - public EvcPerUnicBuilder addToCeVlanMap(ServiceListType additionalCeVlanMap) { - String combinedCeVlanMap = - CeVlanMapUtils.combineVlanSets(ceVlanMap.string(), additionalCeVlanMap.string()); - //If it contains 0 we should remove it - ceVlanMap = new ServiceListType( - CeVlanMapUtils.removeZeroIfPossible(combinedCeVlanMap)); - - return this; - } - } -} diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/CustomEvcPerUnin.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/CustomEvcPerUnin.java deleted file mode 100644 index 47b438ea78..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/CustomEvcPerUnin.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni; - -import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types - .rev20160229.mseatypes.ServiceListType; - -/** - * A custom implementation of the DefaultEvcPerUnin - especially its Builder. - * - * This allows the EvcPerUniN to be modified after creation. These additions to the - * builder are necessary because in the EA1000 YANG model the EvcPerUniN can - * be added at separate stages - */ -public class CustomEvcPerUnin extends DefaultEvcPerUnin { - public static EvcPerUninBuilder builder(EvcPerUnin evcPerUnin) { - return new EvcPerUninBuilder(evcPerUnin); - } - - public static EvcPerUninBuilder builder() { - return new EvcPerUninBuilder(); - } - - public static class EvcPerUninBuilder extends DefaultEvcPerUnin.EvcPerUninBuilder { - - /** - * Allow a new builder to be constructed - */ - public EvcPerUninBuilder() { - valueLeafFlags.set(LeafIdentifier.CEVLANMAP.getLeafIndex()); - this.ceVlanMap = new ServiceListType("0"); - valueLeafFlags.set(LeafIdentifier.INGRESSBWPGROUPINDEX.getLeafIndex()); - this.ingressBwpGroupIndex = 0; - } - - /** - * Allow a builder to be constructed from an existing EvcPerUnin - * @param evcPerUnin An existing EvcPerUnin - */ - public EvcPerUninBuilder(EvcPerUnin evcPerUnin) { - this.ceVlanMap = evcPerUnin.ceVlanMap(); - this.evcPerUniServiceType = evcPerUnin.evcPerUniServiceType(); - this.ingressBwpGroupIndex = evcPerUnin.ingressBwpGroupIndex(); - this.tagManipulation = evcPerUnin.tagManipulation(); - this.flowMapping = evcPerUnin.flowMapping(); - this.yangEvcPerUninOpType = evcPerUnin.yangEvcPerUninOpType(); - this.yangAugmentedInfoMap = evcPerUnin.yangAugmentedInfoMap(); - this.selectLeafFlags = evcPerUnin.selectLeafFlags(); - this.valueLeafFlags = evcPerUnin.valueLeafFlags(); - } - - /** - * Method to allow ceVlanMap to be modified. - * @param additionalCeVlanMap An addition to the existing ceVlanMap - * @return The updated builder - */ - public EvcPerUninBuilder addToCeVlanMap(ServiceListType additionalCeVlanMap) { - String combinedCeVlanMap = - CeVlanMapUtils.combineVlanSets(ceVlanMap.string(), additionalCeVlanMap.string()); - //If it contains 0 we should remove it - ceVlanMap = new ServiceListType( - CeVlanMapUtils.removeZeroIfPossible(combinedCeVlanMap)); - return this; - } - } -} \ No newline at end of file diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/package-info.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/package-info.java deleted file mode 100644 index 3617d86e40..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/evcperuni/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Package for Microsemi device drivers support for NETCONF for EA1000. - */ -package org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni; \ No newline at end of file diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/package-info.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/package-info.java deleted file mode 100644 index 7813b61224..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/evc/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Package for Microsemi device drivers support for NETCONF for EA1000. - */ -package org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni.evc; \ No newline at end of file diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/package-info.java b/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/package-info.java deleted file mode 100644 index 3bdeda0675..0000000000 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/yang/gen/v1/http/www/microsemi/com/microsemi/edge/assure/msea/uni/evc/service/rev20160317/mseaunievcservice/mefservices/uni/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Package for Microsemi device drivers support for NETCONF for EA1000. - */ -package org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service - .rev20160317.mseaunievcservice.mefservices.uni; \ No newline at end of file diff --git a/drivers/microsemi/ea1000yang/src/main/resources/YangMetaData.ser b/drivers/microsemi/ea1000yang/src/main/resources/YangMetaData.ser deleted file mode 100644 index 581bd7708ebb3f53a454f290fe12d59f0fc09d77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 997680 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 z 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 z iSt`lfGJu*5lk0*4)XF2iY4@Zvcl_BVnzA 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

%m;Bu;K4nm{)ru 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 bYgftF`RD`K=-GF9xq{2c+qfM4*RB5mHP}Gb diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java b/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java deleted file mode 100644 index 49723f0e60..0000000000 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.drivers.microsemi.yang; - -import java.io.IOException; -import java.io.UncheckedIOException; - -import org.onosproject.drivers.microsemi.yang.impl.IetfSystemManager; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.IetfSystemMicrosemiService; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystemService; -import org.onosproject.yms.app.yab.MockYmsManager; - -public class MockIetfSystemManager extends IetfSystemManager { - - @Override - public void activate() { - try { - ymsService = new MockYmsManager(); - ych = ymsService.getYangCodecHandler(); - ych.addDeviceSchema(IetfSystemService.class); - ych.addDeviceSchema(IetfSystemMicrosemiService.class); - } catch (InstantiationException | IllegalAccessException e) { - log.error("Failed to load YMS Manager: " + e.getMessage()); - e.printStackTrace(); - } catch (IOException e) { - log.error("Failed to load YMS Manager: " + e.getMessage()); - throw new UncheckedIOException(e); - } - } -} diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java b/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java deleted file mode 100644 index af34a0211f..0000000000 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.drivers.microsemi.yang; - -import java.io.IOException; -import java.io.UncheckedIOException; - -import org.onosproject.drivers.microsemi.yang.impl.MseaCfmManager; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.MseaCfmService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.soam.fm.rev20160229.MseaSoamFmService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.soam.pm.rev20160229.MseaSoamPmService; -import org.onosproject.yms.app.yab.MockYmsManager; - -public class MockMseaCfmManager extends MseaCfmManager { - - @Override - public void activate() { - try { - ymsService = new MockYmsManager(); - ych = ymsService.getYangCodecHandler(); - ych.addDeviceSchema(MseaCfmService.class); - ych.addDeviceSchema(MseaSoamFmService.class); - ych.addDeviceSchema(MseaSoamPmService.class); - } catch (InstantiationException | IllegalAccessException e) { - log.error("Failed to load YMS Manager: " + e.getMessage()); - e.printStackTrace(); - } catch (IOException e) { - log.error("Failed to load YMS Manager: " + e.getMessage()); - throw new UncheckedIOException(e); - } - } -} diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java b/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java deleted file mode 100644 index 79e34359cf..0000000000 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright 2017-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.drivers.microsemi.yang; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onlab.packet.Ip4Address; -import org.onosproject.drivers.microsemi.yang.impl.MseaUniEvcServiceManager; -import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils; -import org.onosproject.netconf.NetconfDeviceInfo; -import org.onosproject.netconf.NetconfException; -import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.Identifier45; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.ServiceListType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.VlanIdType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.DefaultMefServices; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.MefServices; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.EvcPerUniServiceTypeEnum; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPush; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.tagpush.tagpush.PushTagTypeEnum; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPush; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.Profiles; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultProfiles; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultUni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.Uni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.Cos; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.DefaultCos; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.Bwp; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.DefaultBwp; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.bwp.ColorModeEnum; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.CustomEvc; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.DefaultEvc; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.Evc; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.DefaultEvcPerUni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.EvcPerUni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.CustomEvcPerUnic; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.CustomEvcPerUnin; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnic; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnin; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin; -import org.onosproject.yms.ymsm.YmsService; - -public class MseaUniEvcServiceManagerTest { - - MseaUniEvcServiceManager mseaUniEvcServiceSvc; - YmsService ymsService; - NetconfSession session; - - @Before - public void setUp() throws Exception { - try { - mseaUniEvcServiceSvc = new MockMseaUniEvcServiceManager(); - mseaUniEvcServiceSvc.activate(); - } catch (UncheckedIOException e) { - fail(e.getMessage()); - } - NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf", Ip4Address.valueOf("1.2.3.4"), 830); - session = new MockNetconfSessionEa1000(deviceInfo); - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testGetMseaUniEvcServiceMseaUniEvcServiceOpParamNetconfSession() { - Uni.UniBuilder uniBuilder = new DefaultUni.UniBuilder(); - - MefServices.MefServicesBuilder mefBuilder = new DefaultMefServices.MefServicesBuilder(); - MefServices mefServices = mefBuilder.uni(uniBuilder.build()).build(); - - MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder = - new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder(); - - MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = - (MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build(); - MseaUniEvcService result = null; - try { - result = - mseaUniEvcServiceSvc.getConfigMseaUniEvcService( - mseaUniEvcServiceFilter, session, TargetConfig.RUNNING); - } catch (NetconfException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - fail("Error: " + e.getMessage()); - } - - assertNotNull(result); - } - - @Test - public void testSetMseaUniEvcServiceMseaUniEvcServiceOpParamEvcs() { - TagPush.TagPushBuilder tpBuilder1 = new DefaultTagPush.TagPushBuilder(); - org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc - .service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation - .tagpush.TagPush.TagPushBuilder tpInnerBuilder1 = - new org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea - .uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes - .tagmanipulation.tagpush.DefaultTagPush.TagPushBuilder(); - TagPush tp1 = tpBuilder1 - .tagPush(tpInnerBuilder1 - .outerTagVlan(new VlanIdType(3)) - .pushTagType(PushTagTypeEnum.PUSHSTAG) - .build()) - .build(); - - EvcPerUnin.EvcPerUninBuilder epunBuilder1 = new DefaultEvcPerUnin.EvcPerUninBuilder(); - EvcPerUnin epun1 = epunBuilder1 - .evcPerUniServiceType(EvcPerUniServiceTypeEnum.EVPL) - .ceVlanMap(ServiceListType.fromString("10")) - .ingressBwpGroupIndex("0") - .tagManipulation(tp1) - .build(); - - EvcPerUnic.EvcPerUnicBuilder epucBuilder1 = new DefaultEvcPerUnic.EvcPerUnicBuilder(); - EvcPerUnic epuc1 = epucBuilder1 - .ceVlanMap(new ServiceListType("11")) - .ingressBwpGroupIndex("0") - .build(); - - EvcPerUni.EvcPerUniBuilder epuBuilder = new DefaultEvcPerUni.EvcPerUniBuilder(); - - List evcList = new ArrayList(); - Evc.EvcBuilder evcBuilder1 = new DefaultEvc.EvcBuilder(); - evcList.add(evcBuilder1 - .evcIndex(1) - .name(new Identifier45("evc-1")) - .evcPerUni(epuBuilder.evcPerUnin(epun1).evcPerUnic(epuc1).build()) - .build()); - - - EvcPerUnin.EvcPerUninBuilder epunBuilder2 = new DefaultEvcPerUnin.EvcPerUninBuilder(); - EvcPerUnin epun2 = epunBuilder2 - .ceVlanMap(ServiceListType.fromString("13")) - .ingressBwpGroupIndex("0") - .build(); - - EvcPerUnic.EvcPerUnicBuilder epucBuilder2 = new DefaultEvcPerUnic.EvcPerUnicBuilder(); - EvcPerUnic epuc2 = epucBuilder2 - .ceVlanMap(new ServiceListType("12")) - .ingressBwpGroupIndex("0") - .build(); - - Evc.EvcBuilder evcBuilder2 = new DefaultEvc.EvcBuilder(); - evcList.add(evcBuilder2 - .evcIndex(2) - .name(new Identifier45("evc-2")) - .evcPerUni(epuBuilder.evcPerUnin(epun2).evcPerUnic(epuc2).build()) - .build()); - - Uni.UniBuilder uniBuilder = new DefaultUni.UniBuilder(); - Uni uni = uniBuilder.name(new Identifier45("testUni")).evc(evcList).build(); - - MefServices.MefServicesBuilder mefBuilder = new DefaultMefServices.MefServicesBuilder(); - MefServices mefServices = mefBuilder.uni(uni).build(); - - MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder = - new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder(); - - MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = - (MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build(); - try { - mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, TargetConfig.RUNNING); - } catch (NetconfException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - fail("Error: " + e.getMessage()); - } - } - - @Test - public void testSetMseaUniEvcServiceMseaUniEvcServiceOpParamProfiles() { - List cosList = new ArrayList(); - Cos.CosBuilder cosBuilder0 = new DefaultCos.CosBuilder(); - cosList.add(cosBuilder0.cosIndex(0).name("cos0").build()); - Cos.CosBuilder cosBuilder1 = new DefaultCos.CosBuilder(); - cosList.add(cosBuilder1.cosIndex(1).name("cos1").build()); - - List bwpGroupList = new ArrayList(); - BwpGroup.BwpGroupBuilder bwpGrpBuilder = new DefaultBwpGroup.BwpGroupBuilder(); - bwpGroupList.add(bwpGrpBuilder.groupIndex((short) 0).build()); - - List bwpList = new ArrayList(); - Bwp.BwpBuilder bwpBuilder1 = new DefaultBwp.BwpBuilder(); - bwpList.add(bwpBuilder1.cosIndex(0).colorMode(ColorModeEnum.COLORAWARE).build()); - Bwp.BwpBuilder bwpBuilder2 = new DefaultBwp.BwpBuilder(); - bwpList.add(bwpBuilder2.cosIndex(1).colorMode(ColorModeEnum.COLORBLIND).build()); - - BwpGroup.BwpGroupBuilder bwpGrpBuilder1 = new DefaultBwpGroup.BwpGroupBuilder(); - bwpGroupList.add(bwpGrpBuilder1.groupIndex((short) 1).bwp(bwpList).build()); - - Profiles.ProfilesBuilder profilesBuilder = new DefaultProfiles.ProfilesBuilder(); - Profiles profiles = profilesBuilder.bwpGroup(bwpGroupList).build(); - - MefServices.MefServicesBuilder mefBuilder = new DefaultMefServices.MefServicesBuilder(); - MefServices mefServices = mefBuilder.profiles(profiles).build(); - - MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder = - new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder(); - - MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = - (MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build(); - try { - mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, TargetConfig.RUNNING); - } catch (NetconfException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - fail("Error: " + e.getMessage()); - } - } - - @Test - public void testGetMseaUniEvcCeVlanMaps() { - - try { - MseaUniEvcService ceVlanMapsResult7 = - mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, TargetConfig.RUNNING); - - assertNotNull(ceVlanMapsResult7.mefServices().uni().evc()); - - List evcList = ceVlanMapsResult7.mefServices().uni().evc(); - assertEquals(3, evcList.size()); - for (Evc evc : evcList) { - assertNotNull(evc.evcPerUni().evcPerUnic().ceVlanMap()); - assertNotNull(evc.evcPerUni().evcPerUnin().ceVlanMap()); - - if (evc.evcIndex() == 7) { - assertEquals("700,710,720", evc.evcPerUni().evcPerUnic().ceVlanMap().string()); - assertEquals("701:703", evc.evcPerUni().evcPerUnin().ceVlanMap().string()); - } - } - - } catch (NetconfException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - fail("Error: " + e.getMessage()); - } - } - - @Test - public void testChangeEvcCeVlanMap() { - EvcPerUnin.EvcPerUninBuilder epunBuilder1 = new DefaultEvcPerUnin.EvcPerUninBuilder(); - EvcPerUnin epun1 = epunBuilder1 - .evcPerUniServiceType(EvcPerUniServiceTypeEnum.EVPL) - .ceVlanMap(ServiceListType.fromString("10")) - .ingressBwpGroupIndex("0") - .build(); - - EvcPerUnic.EvcPerUnicBuilder epucBuilder1 = new DefaultEvcPerUnic.EvcPerUnicBuilder(); - EvcPerUnic epuc1 = epucBuilder1 - .ceVlanMap(new ServiceListType("11")) - .ingressBwpGroupIndex("0") - .build(); - - EvcPerUni.EvcPerUniBuilder epuBuilder = DefaultEvcPerUni.builder().evcPerUnic(epuc1).evcPerUnin(epun1); - - Evc evc = CustomEvc.builder().evcPerUni(epuBuilder.build()).build(); - - assertEquals("10", evc.evcPerUni().evcPerUnin().ceVlanMap().string()); - assertEquals("11", evc.evcPerUni().evcPerUnic().ceVlanMap().string()); - - evc = CustomEvc.builder(evc).addToCeVlanMap(new ServiceListType("12,13"), UniSide.NETWORK).build(); - - assertEquals("10,12:13", evc.evcPerUni().evcPerUnin().ceVlanMap().string()); - assertEquals("11", evc.evcPerUni().evcPerUnic().ceVlanMap().string()); - - } - - @Test - public void testChangeEvcCeVlanMapNoValues() { - EvcPerUnin.EvcPerUninBuilder epunBuilder1 = CustomEvcPerUnin.builder(); - EvcPerUnin epun1 = epunBuilder1 - .evcPerUniServiceType(EvcPerUniServiceTypeEnum.EVPL) - .ingressBwpGroupIndex("0") - .build(); - - EvcPerUnic.EvcPerUnicBuilder epucBuilder1 = CustomEvcPerUnic.builder(); - EvcPerUnic epuc1 = epucBuilder1 - .ingressBwpGroupIndex("0") - .build(); - - EvcPerUni.EvcPerUniBuilder epuBuilder = DefaultEvcPerUni.builder().evcPerUnic(epuc1).evcPerUnin(epun1); - - Evc evc = CustomEvc.builder().evcPerUni(epuBuilder.build()).build(); - - assertEquals("0", evc.evcPerUni().evcPerUnin().ceVlanMap().string()); - assertEquals("0", evc.evcPerUni().evcPerUnic().ceVlanMap().string()); - } - - @Test - public void testRemoveEvcUniFlowEntries() { - - Map ceVlanUpdates = new TreeMap<>(); - ceVlanUpdates.put((1 << 2), ""); - ceVlanUpdates.put((1 << 2) + 1, ""); - ceVlanUpdates.put((2 << 2), ""); - ceVlanUpdates.put((2 << 2) + 1, ""); - - ceVlanUpdates.put((7 << 2), "700,710,720"); - ceVlanUpdates.put((7 << 2) + 1, "701:703"); - ceVlanUpdates.put((8 << 2), "800,810,820"); - ceVlanUpdates.put((8 << 2) + 1, "801,802,803"); - - Map> flowVlanIdMap = new HashMap<>(); - //These should get ignored because whole EVC is being deleted - flowVlanIdMap.put(1 << 2, new ArrayList()); - flowVlanIdMap.get(1 << 2).add((short) 11); - - flowVlanIdMap.put((1 << 2) + 1, new ArrayList()); - flowVlanIdMap.get((1 << 2) + 1).add((short) 12L); - - //These are the EVCs being removed - flowVlanIdMap.put(7 << 2, new ArrayList()); - flowVlanIdMap.get(7 << 2).add((short) 730L); - flowVlanIdMap.get(7 << 2).add((short) 740L); - - flowVlanIdMap.put((7 << 2) + 1, new ArrayList()); - flowVlanIdMap.get((7 << 2) + 1).add((short) 705L); - flowVlanIdMap.get((7 << 2) + 1).add((short) 706L); - - flowVlanIdMap.put(8 << 2, new ArrayList()); - flowVlanIdMap.get(8 << 2).add((short) 830L); - flowVlanIdMap.get(8 << 2).add((short) 840L); - - flowVlanIdMap.put((8 << 2) + 1, new ArrayList()); - flowVlanIdMap.get((8 << 2) + 1).add((short) 805L); - flowVlanIdMap.get((8 << 2) + 1).add((short) 806L); - - try { - mseaUniEvcServiceSvc.removeEvcUniFlowEntries( - ceVlanUpdates, flowVlanIdMap, session, TargetConfig.RUNNING, - UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS); - } catch (NetconfException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - fail("Error: " + e.getMessage()); - } - } - - @Test - public void testGetVlanSet1() { - Short[] vlanIds = CeVlanMapUtils.getVlanSet("10"); - assertEquals(1, vlanIds.length); - } - - @Test - public void testGetVlanSet2() { - Short[] vlanIds = CeVlanMapUtils.getVlanSet("10:20"); - assertEquals(11, vlanIds.length); - assertEquals(10, vlanIds[0].shortValue()); - assertEquals(20, vlanIds[10].shortValue()); - } - - @Test - public void testGetVlanSet3() { - Short[] vlanIds = CeVlanMapUtils.getVlanSet("10:20,30:40"); - assertEquals(22, vlanIds.length); - assertEquals(10, vlanIds[0].shortValue()); - assertEquals(40, vlanIds[21].shortValue()); - } - - @Test - public void testGetVlanSet4() { - Short[] vlanIds = CeVlanMapUtils.getVlanSet("10,20,30"); - assertEquals(3, vlanIds.length); - assertEquals(10, vlanIds[0].shortValue()); - assertEquals(30, vlanIds[2].shortValue()); - } - - @Test - public void testVlanListAsString() { - assertEquals("20:22", CeVlanMapUtils.vlanListAsString(new Short[]{20, 21, 22})); - - assertEquals("20:22,24:25", - CeVlanMapUtils.vlanListAsString(new Short[]{20, 21, 22, 24, 25})); - - assertEquals("30,33,36:40", - CeVlanMapUtils.vlanListAsString(new Short[]{30, 33, 36, 37, 38, 39, 40})); - - assertEquals("20", CeVlanMapUtils.vlanListAsString(new Short[]{20})); - - assertEquals("20,22,24,26,28", - CeVlanMapUtils.vlanListAsString(new Short[]{20, 22, 24, 26, 28})); - } - - @Test - public void testAddtoCeVlanMap() { - assertEquals("20,22:24,26,28", - CeVlanMapUtils.addtoCeVlanMap("20,22,24,26,28", (short) 23)); - - assertEquals("20:26,28", - CeVlanMapUtils.addtoCeVlanMap("20,21,22,24,25,26,28", (short) 23)); - - assertEquals("20,23", - CeVlanMapUtils.addtoCeVlanMap("20", (short) 23)); - - assertEquals("20,22:23", - CeVlanMapUtils.addtoCeVlanMap("20,22", (short) 23)); - } - - @Test - public void testCombineVlanSets() { - assertEquals("10:11,13:14", CeVlanMapUtils.combineVlanSets("10:11", "13:14")); - - assertEquals("10:14", CeVlanMapUtils.combineVlanSets("10:11", "12:14")); - - assertEquals("10:11,14", CeVlanMapUtils.combineVlanSets("10:11", "14")); - - assertEquals("10:12", CeVlanMapUtils.combineVlanSets("10:11", "11:12")); - } - - @Test - public void testRemoveZeroIfPossible() { - assertEquals("0", CeVlanMapUtils.removeZeroIfPossible("")); - - assertEquals("0", CeVlanMapUtils.removeZeroIfPossible("0")); - - assertEquals("1,3", CeVlanMapUtils.removeZeroIfPossible("0:1,3")); - - assertEquals("1:2", CeVlanMapUtils.removeZeroIfPossible("0:2")); - - assertEquals("10:12", CeVlanMapUtils.removeZeroIfPossible("0,10:12")); - } -} diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/yab/MockYmsManager.java b/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/yab/MockYmsManager.java deleted file mode 100644 index 7645a325b1..0000000000 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/yab/MockYmsManager.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2016-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.yms.app.yab; - -import static java.lang.String.valueOf; - -import java.io.IOException; -import java.util.List; - -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.onosproject.core.CoreService; -import org.onosproject.core.IdGenerator; -import org.onosproject.drivers.netconf.MockCoreService; -import org.onosproject.yms.app.ych.DefaultYangCodecHandler; -import org.onosproject.yms.app.ych.defaultcodecs.YangCodecRegistry; -import org.onosproject.yms.app.ydt.YangRequestWorkBench; -import org.onosproject.yms.app.ysr.DefaultYangModuleLibrary; -import org.onosproject.yms.app.ysr.MockYangSchemaRegistry; -import org.onosproject.yms.app.ysr.YangSchemaRegistry; -import org.onosproject.yms.ych.YangCodecHandler; -import org.onosproject.yms.ych.YangDataTreeCodec; -import org.onosproject.yms.ych.YangProtocolEncodingFormat; -import org.onosproject.yms.ydt.YdtBuilder; -import org.onosproject.yms.ydt.YdtResponse; -import org.onosproject.yms.ydt.YdtWalker; -import org.onosproject.yms.ydt.YmsOperationType; -import org.onosproject.yms.ymsm.YmsService; -import org.onosproject.yms.ynh.YangNotificationService; -import org.onosproject.yms.ysr.YangModuleIdentifier; -import org.onosproject.yms.ysr.YangModuleLibrary; - -/** - * Represents implementation of YANG application management system manager. - */ -public class MockYmsManager - implements YmsService { - private static final String MODULE_ID = "module-id"; - - YangSchemaRegistry schemaRegistry; - private YangModuleLibrary library; - private IdGenerator moduleIdGenerator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected CoreService coreService; - - public MockYmsManager() - throws InstantiationException, IllegalAccessException, IOException { - coreService = new MockCoreService(); - moduleIdGenerator = coreService.getIdGenerator(MODULE_ID); - library = new DefaultYangModuleLibrary(getNewModuleId()); - YangCodecRegistry.initializeDefaultCodec(); - } - - @Override - public YdtBuilder getYdtBuilder(String logicalRootName, - String rootNamespace, - YmsOperationType operationType) { - return new YangRequestWorkBench(logicalRootName, rootNamespace, - operationType, schemaRegistry, false); - } - - @Override - public YdtBuilder getYdtBuilder(String logicalRootName, - String rootNamespace, - YmsOperationType operationType, - Object schemaRegistryForYdt) { - return null; - } - - @Override - public YdtWalker getYdtWalker() { - return null; - } - - @Override - public YdtResponse executeOperation(YdtBuilder operationRequest) { - YangApplicationBroker requestBroker = - new YangApplicationBroker(schemaRegistry); - switch (operationRequest.getYmsOperationType()) { - case EDIT_CONFIG_REQUEST: - try { - return requestBroker.processEdit(operationRequest); - } catch (CloneNotSupportedException e) { - } - break; - case QUERY_CONFIG_REQUEST: - case QUERY_REQUEST: - return requestBroker.processQuery(operationRequest); - case RPC_REQUEST: - return requestBroker.processOperation(operationRequest); - default: - } - return null; - } - - @Override - public YangNotificationService getYangNotificationService() { - return null; - } - - @Override - public void registerService(Object appManager, Class yangService, - List supportedFeatureList) { - } - - @Override - public void unRegisterService(Object appManager, Class yangService) { - - } - - @Override - public YangModuleLibrary getYangModuleLibrary() { - return library; - } - - @Override - public String getYangFile(YangModuleIdentifier moduleIdentifier) { - return null; - } - - @Override - public void registerDefaultCodec(YangDataTreeCodec defaultCodec, - YangProtocolEncodingFormat dataFormat) { - } - - @Override - public YangCodecHandler getYangCodecHandler() { - YangSchemaRegistry registry = new MockYangSchemaRegistry(); - DefaultYangCodecHandler handler = new DefaultYangCodecHandler(registry); - handler.setLibrary(new DefaultYangModuleLibrary(getNewModuleId())); - return handler; - } - - private String getNewModuleId() { - return valueOf(moduleIdGenerator.getNewId()); - } -} diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/ysr/MockYangSchemaRegistry.java b/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/ysr/MockYangSchemaRegistry.java deleted file mode 100644 index 5de56fda1f..0000000000 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/ysr/MockYangSchemaRegistry.java +++ /dev/null @@ -1,767 +0,0 @@ -/* - * Copyright 2016-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.yms.app.ysr; - -import org.onosproject.yangutils.datamodel.YangInclude; -import org.onosproject.yangutils.datamodel.YangModule; -import org.onosproject.yangutils.datamodel.YangNode; -import org.onosproject.yangutils.datamodel.YangSchemaNode; -import org.onosproject.yangutils.datamodel.YangSubModule; -import org.onosproject.yangutils.datamodel.exceptions.DataModelException; -import org.onosproject.yms.ysr.YangModuleIdentifier; -import org.onosproject.yms.ysr.YangModuleInformation; -import org.onosproject.yms.ysr.YangModuleLibrary; -import org.slf4j.Logger; - -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.regex.Pattern; - -import static java.util.Collections.sort; -import static org.apache.commons.io.FileUtils.deleteDirectory; -import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.deSerializeDataModel; -import static org.onosproject.yangutils.utils.UtilConstants.EVENT_STRING; -import static org.onosproject.yangutils.utils.UtilConstants.HYPHEN; -import static org.onosproject.yangutils.utils.UtilConstants.OP_PARAM; -import static org.onosproject.yangutils.utils.UtilConstants.PERIOD; -import static org.onosproject.yangutils.utils.UtilConstants.SERVICE; -import static org.onosproject.yangutils.utils.UtilConstants.SLASH; -import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase; -import static org.slf4j.LoggerFactory.getLogger; - - -/** - * Representation of default YANG schema registry. Yang schema registry - * provides interface to an application to register its YANG schema - * with YMS. It provides YANG schema nodes to YDT, YNB and YSB. - */ -public class MockYangSchemaRegistry implements YangSchemaRegistry { - - private static final String SYSTEM = SLASH + "system" + SLASH; - private static final String MAVEN = "mvn:"; - private static final String JAR = ".jar"; - private static final String USER_DIRECTORY = "user.dir"; - private static final String AT = "@"; - private static final String DATE_FORMAT = "yyyy-mm-dd"; - private static final String ONOS = "org.onosproject"; - private static final Logger log = getLogger(MockYangSchemaRegistry.class); - - private static final String FS = File.separator; - private static final String USER_DIR = System.getProperty("user.dir").replaceAll("ea1000driver", "ea1000yang"); -// private static final String BUCK_OUT_DIR = "/buck-out/gen/drivers/microsemi/ea1000yang/"; - private static final String BUCK_OUT_BIN_LOC = - "/buck-out/bin/drivers/microsemi/ea1000yang/" - + "lib__onos-drivers-microsemi-ea1000yang__classes/YangMetaData.ser"; - private static final String PATH = FS + "target" + FS + "classes" + FS; - private static final String SER_FILE_PATH = "yang" + FS + "resources" + - FS + "YangMetaData.ser"; - private static final String RESOURCE = "src/test/resources"; - - - /* - * Map for storing app objects. - */ - private final ConcurrentMap appObjectStore; - - /* - * Map for storing YANG schema nodes. - */ - private final ConcurrentMap> - yangSchemaStore; - - /* - * Map for storing YANG schema nodes with respect to root's generated - * interface file name. - */ - private final ConcurrentMap interfaceNameKeyStore; - - /* - * Map for storing YANG schema nodes root's generated op param file name. - */ - private final ConcurrentMap opParamNameKeyStore; - - /* - * Map for storing YANG schema nodes with respect to notifications. - */ - private final ConcurrentMap eventNameKeyStore; - - /* - * Map for storing YANG schema nodes with respect to app name. - */ - private final ConcurrentMap appNameKeyStore; - - /* - * Map for storing registered classes. - */ - private final ConcurrentMap> registerClassStore; - - /* - * Map for storing YANG file details. - */ - private final ConcurrentMap yangFileStore; - - /** - * Map for storing schema nodes with respect to namespace. - */ - private final ConcurrentMap nameSpaceSchemaStore; - - private final ConcurrentMap ynhRegistrationStore; - private final ConcurrentMap jarPathStore; - - /** - * Creates an instance of default YANG schema registry. - */ - public MockYangSchemaRegistry() { - appObjectStore = new ConcurrentHashMap<>(); - yangSchemaStore = new ConcurrentHashMap<>(); - interfaceNameKeyStore = new ConcurrentHashMap<>(); - opParamNameKeyStore = new ConcurrentHashMap<>(); - eventNameKeyStore = new ConcurrentHashMap<>(); - registerClassStore = new ConcurrentHashMap<>(); - yangFileStore = new ConcurrentHashMap<>(); - appNameKeyStore = new ConcurrentHashMap<>(); - ynhRegistrationStore = new ConcurrentHashMap<>(); - jarPathStore = new ConcurrentHashMap<>(); - nameSpaceSchemaStore = new ConcurrentHashMap<>(); - } - - - /** - * This is overridden for Maven and Buck. - * - * Because they don't have a Bundle Context, and the JAR file doesn't exist - * when this is called, we have to work with the .ser file - */ - @Override - public void registerApplication(Object appObject, Class serviceClass) { - synchronized (MockYangSchemaRegistry.class) { - doPreProcessing(serviceClass, appObject); - if (!verifyIfApplicationAlreadyRegistered(serviceClass)) { - - List curNodes = new ArrayList<>(); - Path serFile = Paths.get(USER_DIR, PATH, SER_FILE_PATH); - if (USER_DIR.contains("ea1000yang")) { - serFile = Paths.get(USER_DIR, PATH, SER_FILE_PATH); - } else { - serFile = Paths.get(USER_DIR, BUCK_OUT_BIN_LOC); - } - - if (Files.notExists(serFile)) { - throw new UncheckedIOException( - new IOException("File " + serFile.toString() + " does not exist!")); - } - - try { - curNodes.addAll(deSerializeDataModel(serFile.toString())); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - - // process application registration. - if (curNodes != null && !curNodes.isEmpty()) { - jarPathStore.put(serviceClass.getName(), serFile.toString()); - processRegistration(serviceClass, serFile.toString(), - curNodes, appObject, false); - } else { - throw new UncheckedIOException( - new IOException("Unable to find Yang Nodes in serFile: " + serFile.toString())); - } - } - } - } - - @Override - public void unRegisterApplication(Object managerObject, - Class serviceClass) { - synchronized (MockYangSchemaRegistry.class) { - YangSchemaNode curNode; - String serviceName = serviceClass.getName(); - - //Check if service should be unregistered? - if (managerObject != null) { - verifyApplicationRegistration(managerObject, serviceClass); - } - //Remove registered class from store. - registerClassStore.remove(serviceName); - //check if service is in app store. - curNode = appNameKeyStore.get(serviceName); - if (curNode == null) { - curNode = interfaceNameKeyStore.get(serviceName); - } - - if (curNode != null) { - removeSchemaNode(curNode); - eventNameKeyStore.remove(getEventClassName(curNode)); - appObjectStore.remove(serviceName); - interfaceNameKeyStore.remove(getInterfaceClassName(curNode)); - opParamNameKeyStore.remove(getOpParamClassName(curNode)); - yangFileStore.remove(getModuleIdentifier(curNode)); - appNameKeyStore.remove(serviceName); - nameSpaceSchemaStore.remove(curNode.getNameSpace() - .getModuleNamespace()); - removeYsrGeneratedTemporaryResources(jarPathStore.get(serviceName), - serviceName); - log.info(" service {} is unregistered.", - serviceClass.getSimpleName()); - } else { - throw new RuntimeException(serviceClass.getSimpleName() + - " service was not registered."); - } - } - } - - @Override - public Object getRegisteredApplication(YangSchemaNode schemaNode) { - Object obj = null; - if (schemaNode != null) { - String name = getServiceName(schemaNode); - obj = appObjectStore.get(name); - if (obj == null) { - log.error("{} not found.", name); - } - } - return obj; - } - - @Override - public YangSchemaNode getYangSchemaNodeUsingSchemaName(String schemaName) { - return getSchemaNodeUsingSchemaNameWithRev(schemaName); - } - - @Override - public YangSchemaNode getYangSchemaNodeUsingAppName(String appName) { - YangSchemaNode node = appNameKeyStore.get(appName); - if (node == null) { - log.error("{} not found.", appName); - } - return node; - } - - @Override - public YangSchemaNode - getYangSchemaNodeUsingGeneratedRootNodeInterfaceFileName(String name) { - YangSchemaNode node = interfaceNameKeyStore.get(name); - if (node == null) { - log.error("{} not found.", name); - } - return node; - } - - @Override - public YangSchemaNode getYangSchemaNodeUsingGeneratedRootNodeOpPramFileName( - String name) { - YangSchemaNode node = opParamNameKeyStore.get(name); - if (node == null) { - log.error("{} not found.", name); - } - return node; - } - - @Override - public YangSchemaNode getRootYangSchemaNodeForNotification(String name) { - YangSchemaNode node = eventNameKeyStore.get(name); - if (node == null) { - log.error("{} not found.", name); - } - return node; - } - - @Override - public Class getRegisteredClass(YangSchemaNode schemaNode) { - String interfaceName = getInterfaceClassName(schemaNode); - String serviceName = getServiceName(schemaNode); - Class regClass = registerClassStore.get(serviceName); - if (regClass == null) { - regClass = registerClassStore.get(interfaceName); - } - return regClass; - } - - @Override - public YangSchemaNode getSchemaWrtNameSpace(String nameSpace) { - - YangSchemaNode node = nameSpaceSchemaStore.get(nameSpace); - if (node == null) { - log.error("node with {} namespace not found.", nameSpace); - } - return node; - } - - @Override - public String getYangFile(YangModuleIdentifier moduleIdentifier) { - String file = yangFileStore.get(moduleIdentifier); - if (file == null) { - log.error("YANG files for corresponding module identifier {} not " + - "found", moduleIdentifier); - } - return file; - } - - @Override - public boolean verifyNotificationObject(Object appObj, Class service) { - synchronized (MockYangSchemaRegistry.class) { - YangSchemaNode node = appNameKeyStore.get(service.getName()); - if (node == null) { - log.error("application is not registered with YMS {}", - service.getName()); - return false; - } - try { - if (node.isNotificationPresent()) { - if (appObj != null) { - Boolean ifPresent = ynhRegistrationStore.get(appObj); - if (ifPresent == null) { - ynhRegistrationStore.put(appObj, true); - return true; - } - } - } - } catch (DataModelException e) { - log.error("notification registration error: {} {}", e - .getLocalizedMessage(), e); - } - return false; - } - } - - @Override - public void flushYsrData() { - appObjectStore.clear(); - yangSchemaStore.clear(); - eventNameKeyStore.clear(); - opParamNameKeyStore.clear(); - interfaceNameKeyStore.clear(); - registerClassStore.clear(); - yangFileStore.clear(); - nameSpaceSchemaStore.clear(); - } - - @Override - public void processModuleLibrary(String serviceName, - YangModuleLibrary library) { - synchronized (MockYangSchemaRegistry.class) { - YangSchemaNode node = appNameKeyStore.get(serviceName); - if (node != null) { - YangModuleInformation moduleInformation = - new DefaultYangModuleInformation(getModuleIdentifier(node), - node.getNameSpace()); - addSubModuleIdentifier(node, ( - DefaultYangModuleInformation) moduleInformation); - //TODO: add feature list to module information. - ((DefaultYangModuleLibrary) library) - .addModuleInformation(moduleInformation); - } - } - } - - /** - * Process service class. - * - * @param serviceClass service class - * @param appObject application object - */ - - void doPreProcessing(Class serviceClass, Object appObject) { - - //Check if service should be registered? - if (appObject != null) { - verifyApplicationRegistration(appObject, serviceClass); - } - String name = serviceClass.getName(); - //Add app class to registered service store. - if (!registerClassStore.containsKey(name)) { - registerClassStore.put(name, serviceClass); - } - } - - void updateServiceClass(Class service) { - registerClassStore.put(service.getName(), service); - } - - /** - * Process application registration. - * - * @param service service class - * @param jarPath jar path - * @param nodes YANG nodes - * @param appObj application object - * @param isFromUt if registration is being called form unit test - */ - void processRegistration(Class service, String jarPath, - List nodes, - Object appObj, boolean isFromUt) { - - // process storing operations. - YangNode schemaNode = findNodeWhichShouldBeReg(service.getName(), nodes); - if (schemaNode != null) { - if (appObj != null) { - appObjectStore.put(service.getName(), appObj); - } - //Process application context for registrations. - processApplicationContext(schemaNode, service.getName(), isFromUt); - //Update YANG file store. - updateYangFileStore(schemaNode, jarPath); - } - } - - /** - * Returns the node for which corresponding class is generated. - * - * @param name generated class name - * @param nodes list of yang nodes - * @return node for which corresponding class is generated - */ - private YangNode findNodeWhichShouldBeReg(String name, List nodes) { - for (YangNode node : nodes) { - if (name.equals(getServiceName(node)) || - name.equals(getInterfaceClassName(node))) { - return node; - } - } - return null; - } - - /** - * Verifies if service class should be registered or not. - * - * @param appObject application object - * @param appClass application class - */ - private void verifyApplicationRegistration(Object appObject, - Class appClass) { - Class managerClass = appObject.getClass(); - Class[] services = managerClass.getInterfaces(); - List> classes = new ArrayList<>(); - Collections.addAll(classes, services); - if (!classes.contains(appClass)) { - throw new RuntimeException("service class " + appClass.getName() + - "is not being implemented by " + - managerClass.getName()); - } - } - - /** - * Verifies if application is already registered with YMS. - * - * @param appClass application class - * @return true if application already registered - */ - private boolean verifyIfApplicationAlreadyRegistered(Class appClass) { - String appName = appClass.getName(); - return appObjectStore.containsKey(appName) || - interfaceNameKeyStore.containsKey(appName); - } - - /** - * Updates yang file store for YANG node. - * - * @param node YANG node - * @param jarPath jar file path - */ - private void updateYangFileStore(YangNode node, String jarPath) { - yangFileStore.put(getModuleIdentifier(node), - getYangFilePath(jarPath, node.getFileName())); - } - - /** - * Returns yang file path. - * - * @param jarPath jar path - * @param metaDataFileName name of yang file from metadata - * @return yang file path - */ - private String getYangFilePath(String jarPath, String metaDataFileName) { - String[] metaData = metaDataFileName.split(SLASH); - return jarPath + SLASH + metaData[metaData.length - 1]; - } - - - /** - * Process an application an updates the maps for YANG schema registry. - * - * @param appNode application YANG schema nodes - * @param name class name - * @param isFormUt if method is being called from unit tests - */ - private void processApplicationContext(YangSchemaNode appNode, String name, - boolean isFormUt) { - - //Update map for which registrations is being called. - appNameKeyStore.put(name, appNode); - - // Updates schema store. - addToSchemaStore(appNode); - // update interface store. - interfaceNameKeyStore.put(getInterfaceClassName(appNode), appNode); - - //update op param store. - opParamNameKeyStore.put(getOpParamClassName(appNode), appNode); - - //update namespaceSchema store. - nameSpaceSchemaStore.put(appNode.getNameSpace().getModuleNamespace(), appNode); - - //Checks if notification is present then update notification store map. - String eventSubject = null; - try { - if (appNode.isNotificationPresent()) { - eventSubject = getEventClassName(appNode); - } - } catch (DataModelException e) { - log.error("failed to search notification from schema map : {}", - e.getLocalizedMessage()); - } - if (eventSubject != null) { - eventNameKeyStore.put(eventSubject, appNode); - } - if (!isFormUt) { - log.info("successfully registered this application {}", name); - } - } - - /** - * Returns jar path from bundle mvnLocationPath. - * - * @param mvnLocationPath mvnLocationPath of bundle - * @return path of jar - */ - private String getJarPathFromBundleLocation(String mvnLocationPath, - String currentDirectory) { - String path = currentDirectory + SYSTEM; - if (mvnLocationPath.contains(MAVEN)) { - String[] strArray = mvnLocationPath.split(MAVEN); - if (strArray[1].contains(File.separator)) { - String[] split = strArray[1].split(File.separator); - if (split[0].contains(PERIOD)) { - String[] groupId = split[0].split(Pattern.quote(PERIOD)); - return path + groupId[0] + SLASH + groupId[1] + SLASH + split[1] + - SLASH + split[2] + SLASH + split[1] + HYPHEN + split[2]; - } - } - } - return null; - } - - /** - * Returns schema node based on the revision. - * - * @param name name of the schema node - * @return schema node based on the revision - */ - private YangSchemaNode getSchemaNodeUsingSchemaNameWithRev(String name) { - ConcurrentMap revMap; - YangSchemaNode schemaNode; - if (name.contains(AT)) { - String[] revArray = name.split(AT); - revMap = yangSchemaStore.get(revArray[0]); - schemaNode = revMap.get(name); - if (schemaNode == null) { - log.error("{} not found.", name); - } - return schemaNode; - } - if (yangSchemaStore.containsKey(name)) { - revMap = yangSchemaStore.get(name); - if (revMap != null && !revMap.isEmpty()) { - YangSchemaNode node = revMap.get(name); - if (node != null) { - return node; - } - String revName = getLatestVersion(revMap); - return revMap.get(revName); - } - } - log.error("{} not found.", name); - return null; - } - - private String getLatestVersion(ConcurrentMap revMap) { - List keys = new ArrayList<>(); - for (Map.Entry entry : revMap.entrySet()) { - keys.add(entry.getKey()); - } - sort(keys); - return keys.get(keys.size() - 1); - } - - /** - * Adds schema node when different revision of node has received. - * - * @param schemaNode schema node - */ - private void addToSchemaStore(YangSchemaNode schemaNode) { - - String date = getDateInStringFormat(schemaNode); - String name = schemaNode.getName(); - String revName = name; - if (date != null) { - revName = name + AT + date; - } - //check if already present. - if (!yangSchemaStore.containsKey(name)) { - ConcurrentMap revStore = - new ConcurrentHashMap<>(); - revStore.put(revName, schemaNode); - yangSchemaStore.put(name, revStore); - } else { - yangSchemaStore.get(name).put(revName, schemaNode); - } - } - - /** - * Returns date in string format. - * - * @param schemaNode schema node - * @return date in string format - */ - String getDateInStringFormat(YangSchemaNode schemaNode) { - if (schemaNode != null) { - if (((YangNode) schemaNode).getRevision() != null) { - return new SimpleDateFormat(DATE_FORMAT) - .format(((YangNode) schemaNode).getRevision() - .getRevDate()); - } - } - return null; - } - - /** - * Removes schema node from schema map. - * - * @param removableNode schema node which needs to be removed - */ - private void removeSchemaNode(YangSchemaNode removableNode) { - String name = removableNode.getName(); - String revName = name; - String date = getDateInStringFormat(removableNode); - if (date != null) { - revName = name + AT + date; - } - ConcurrentMap revMap = yangSchemaStore.get(name); - if (revMap != null && !revMap.isEmpty() && revMap.size() != 1) { - revMap.remove(revName); - } else { - yangSchemaStore.remove(removableNode.getName()); - } - } - - /** - * Adds sub module identifier. - * - * @param node schema node - * @param information module information - */ - private void addSubModuleIdentifier( - YangSchemaNode node, DefaultYangModuleInformation information) { - List includeList = new ArrayList<>(); - if (node instanceof YangModule) { - includeList = ((YangModule) node).getIncludeList(); - } else if (node instanceof YangSubModule) { - includeList = ((YangSubModule) node).getIncludeList(); - } - for (YangInclude include : includeList) { - information.addSubModuleIdentifiers(getModuleIdentifier( - include.getIncludedNode())); - } - } - - /** - * Returns module identifier for schema node. - * - * @param schemaNode schema node - * @return module identifier for schema node - */ - private YangModuleIdentifier getModuleIdentifier( - YangSchemaNode schemaNode) { - return new DefaultYangModuleIdentifier( - schemaNode.getName(), getDateInStringFormat(schemaNode)); - } - - /** - * Returns schema node's generated interface class name. - * - * @param schemaNode schema node - * @return schema node's generated interface class name - */ - String getInterfaceClassName(YangSchemaNode schemaNode) { - return schemaNode.getJavaPackage() + PERIOD + - getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType()); - } - - /** - * Returns schema node's generated op param class name. - * - * @param schemaNode schema node - * @return schema node's generated op param class name - */ - private String getOpParamClassName(YangSchemaNode schemaNode) { - return getInterfaceClassName(schemaNode) + OP_PARAM; - } - - /** - * Returns schema node's generated event class name. - * - * @param schemaNode schema node - * @return schema node's generated event class name - */ - private String getEventClassName(YangSchemaNode schemaNode) { - return getInterfaceClassName(schemaNode).toLowerCase() + PERIOD + - getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType()) + - EVENT_STRING; - } - - /** - * Returns schema node's generated service class name. - * - * @param schemaNode schema node - * @return schema node's generated service class name - */ - String getServiceName(YangSchemaNode schemaNode) { - return getInterfaceClassName(schemaNode) + SERVICE; - } - - /** - * Removes YSR generated temporary resources. - * - * @param rscPath resource path - * @param appName application name - */ - private void removeYsrGeneratedTemporaryResources(String rscPath, - String appName) { - if (rscPath != null) { - File jarPath = new File(rscPath); - if (jarPath.exists()) { - try { - deleteDirectory(jarPath); - } catch (IOException e) { - log.error("failed to delete ysr resources for {} : {}", - appName, e.getLocalizedMessage()); - } - } - } - } -} \ No newline at end of file diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/ysr/package-info.java b/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/ysr/package-info.java deleted file mode 100644 index 6e7ab5c6df..0000000000 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/ysr/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2016-present Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Package for Microsemi device drivers support for NETCONF for EA1000. - */ -package org.onosproject.yms.app.ysr; \ No newline at end of file diff --git a/drivers/microsemi/pom.xml b/drivers/microsemi/pom.xml deleted file mode 100644 index c40410001a..0000000000 --- a/drivers/microsemi/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - 4.0.0 - - - org.onosproject - onos-drivers-general - 1.11.0-SNAPSHOT - - - onos-drivers-microsemi - pom - - - UTF-8 - - - - ea1000yang - ea1000driver - - - - - - snapshots - https://oss.sonatype.org/content/repositories/snapshots - - true - daily - fail - - - - - - - com.google.guava - guava - - - org.hamcrest - hamcrest-all - 1.3 - test - - - - diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java similarity index 63% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java index 3c593d688e..4df22ecc18 100644 --- a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java @@ -27,6 +27,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; import org.onlab.packet.EthType; @@ -38,6 +39,8 @@ import org.onosproject.core.CoreService; import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService; import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService; import org.onosproject.drivers.microsemi.yang.UniSide; +import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnic; +import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnin; import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils; import org.onosproject.net.PortNumber; import org.onosproject.net.driver.AbstractHandlerBehaviour; @@ -61,54 +64,50 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction; import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanHeaderInstruction; import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; import org.onosproject.net.meter.MeterId; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfController; +import org.onosproject.netconf.NetconfDevice; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.MseaSaFiltering; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.MseaSaFilteringOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.DefaultSourceIpaddressFiltering; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.SourceIpaddressFiltering; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.DefaultInterfaceEth0; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.InterfaceEth0; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.DefaultSourceAddressRange; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.FilterAdminStateEnum; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.Identifier45; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.ServiceListType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.VlanIdType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.DefaultMefServices; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.MefServices; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.DefaultFlowMapping; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagOverwrite; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPop; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPush; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagOverwrite; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPop; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPush; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.tagpush.tagpush.PushTagTypeEnum; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultProfiles; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultUni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.Profiles; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.Uni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.CustomEvc; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.DefaultEvc; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.Evc; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.DefaultEvcPerUni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.EvcPerUni; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.CustomEvcPerUnic; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.CustomEvcPerUnin; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnic.EvcPerUnicBuilder; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnin.EvcPerUninBuilder; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.DefaultSourceIpaddressFiltering; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.DefaultInterfaceEth0; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.InterfaceEth0; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.DefaultSourceAddressRange; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.FilterAdminStateEnum; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.VlanIdType; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.DefaultFlowMapping; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagOverwrite; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPop; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPush; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagOverwrite; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPop; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPush; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.tagpush.tagpush.PushTagTypeEnum; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultUni; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Uni; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.DefaultEvc; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.Evc; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.DefaultEvcPerUni; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.EvcPerUni; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin; import org.slf4j.Logger; /** @@ -146,7 +145,14 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST; NetconfController controller = checkNotNull(handler().get(NetconfController.class)); - NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession(); + NetconfDevice ncDevice = controller.getDevicesMap().get(handler().data().deviceId()); + if (ncDevice == null) { + log.error("Internal ONOS Error. Device has been marked as reachable, " + + "but deviceID {} is not in Devices Map. Continuing with empty description", + handler().data().deviceId()); + return flowEntryCollection; + } + NetconfSession session = ncDevice.getSession(); CoreService coreService = checkNotNull(handler().get(CoreService.class)); ApplicationId appId = coreService.getAppId(MICROSEMI_DRIVERS); MseaSaFilteringNetconfService mseaSaFilteringService = @@ -156,51 +162,58 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme log.debug("getFlowEntries() called on EA1000FlowRuleProgrammable"); //First get the MseaSaFiltering rules - SourceIpaddressFiltering.SourceIpaddressFilteringBuilder sipBuilder = - new DefaultSourceIpaddressFiltering.SourceIpaddressFilteringBuilder(); + SourceIpaddressFiltering sip = + new DefaultSourceIpaddressFiltering(); + + MseaSaFilteringOpParam op = + new MseaSaFilteringOpParam(); + op.sourceIpaddressFiltering(sip); - MseaSaFilteringOpParam.MseaSaFilteringBuilder opBuilder = - new MseaSaFilteringOpParam.MseaSaFilteringBuilder(); - MseaSaFilteringOpParam mseaSaFilteringFilter = - (MseaSaFilteringOpParam) opBuilder - .sourceIpaddressFiltering(sipBuilder.build()) - .build(); try { MseaSaFiltering saFilteringCurrent = - mseaSaFilteringService.getMseaSaFiltering(mseaSaFilteringFilter, session); - if (saFilteringCurrent != null) { + mseaSaFilteringService.getMseaSaFiltering(op, session); + if (saFilteringCurrent != null && + saFilteringCurrent.sourceIpaddressFiltering() != null) { flowEntryCollection.addAll( convertSaFilteringToFlowRules(saFilteringCurrent, appId)); } } catch (NetconfException e) { - log.warn("Unexpected error on getFlowEntries", e); + if (e.getCause() instanceof TimeoutException) { + log.warn("Timeout exception getting SA Filt Flow Entries from {}", + handler().data().deviceId()); + return flowEntryCollection; + } else { + log.error("Unexpected error on SA Filt getFlowEntries on {}", + handler().data().deviceId(), e); + } } //Then get the EVCs - there will be a flow entry per EVC - Uni.UniBuilder uniBuilder = new DefaultUni.UniBuilder(); + MefServices mefServices = new DefaultMefServices(); + mefServices.uni(new DefaultUni()); - MefServices.MefServicesBuilder mefBuilder = new DefaultMefServices.MefServicesBuilder(); - MefServices mefServices = mefBuilder.uni(uniBuilder.build()).build(); - - MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder = - new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder(); - - MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = - (MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build(); + MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam(); + mseaUniEvcServiceFilter.mefServices(mefServices); try { MseaUniEvcService uniEvcCurrent = mseaUniEvcServiceSvc.getConfigMseaUniEvcService(mseaUniEvcServiceFilter, - session, TargetConfig.RUNNING); + session, DatastoreId.RUNNING); flowEntryCollection.addAll( convertEvcUniToFlowRules(uniEvcCurrent, portAssignment)); } catch (NetconfException e) { - log.warn("Unexpected error on getFlowEntries", e); + if (e.getCause() instanceof TimeoutException) { + log.warn("Timeout exception getting EVC Flow Entries from {}", + handler().data().deviceId()); + return flowEntryCollection; + } else { + log.error("Unexpected error on EVC getFlowEntries on {}", + handler().data().deviceId(), e); + } } - return flowEntryCollection; } @@ -238,7 +251,7 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme try { sessionMutex.acquire(); MseaUniEvcService evcResponse = - mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, TargetConfig.RUNNING); + mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING); //There could be zero or more EVCs if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) { activeEvcs.addAll(evcResponse.mefServices().uni().evc()); @@ -271,7 +284,7 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme if (saRangeList.size() > 0) { try { mseaSaFilteringService.setMseaSaFiltering( - buildSaFilteringObject(saRangeList), session, TargetConfig.RUNNING); + buildSaFilteringObject(saRangeList), session, DatastoreId.RUNNING); } catch (NetconfException e) { log.error("Error applying Flow Rules to SA Filtering - will try again: " + e.getMessage()); sessionMutex.release(); @@ -283,26 +296,27 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme List evcList = evcMap.entrySet().stream() .map(x -> x.getValue()) .collect(Collectors.toList()); - Uni.UniBuilder uniBuilder = new DefaultUni.UniBuilder(); + Uni uni = new DefaultUni(); URI deviceName = handler().data().deviceId().uri(); - Uni uni = uniBuilder.name(new Identifier45("Uni-on-" - + deviceName.getSchemeSpecificPart())).evc(evcList).build(); + uni.name(new Identifier45("Uni-on-" + + deviceName.getSchemeSpecificPart())); + uni.evc(evcList); List bwpGroupList = new ArrayList(); - BwpGroup.BwpGroupBuilder bwpGrpBuilder = new DefaultBwpGroup.BwpGroupBuilder(); - bwpGroupList.add(bwpGrpBuilder.groupIndex((short) 0).build()); - Profiles profiles = (new DefaultProfiles.ProfilesBuilder()).bwpGroup(bwpGroupList).build(); + BwpGroup bwpGrp = new DefaultBwpGroup(); + bwpGrp.groupIndex((short) 0); + bwpGroupList.add(bwpGrp); + Profiles profiles = new DefaultProfiles(); + profiles.bwpGroup(bwpGroupList); - MefServices.MefServicesBuilder mefBuilder = new DefaultMefServices.MefServicesBuilder(); - MefServices mefServices = mefBuilder.uni(uni).profiles(profiles).build(); + MefServices mefServices = new DefaultMefServices(); + mefServices.uni(uni); + mefServices.profiles(profiles); - MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder = - new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder(); - - MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = - (MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build(); + MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam(); + mseaUniEvcServiceFilter.mefServices(mefServices); try { - mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, TargetConfig.RUNNING); + mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, DatastoreId.RUNNING); } catch (NetconfException e) { log.error("Error applying Flow Rules to EVC - will try again: " + e.getMessage()); sessionMutex.release(); @@ -338,14 +352,18 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme //Retrieve the list of actual EVCs and the CeVlanMaps from device List activeEvcs = new ArrayList<>(); + List acvtiveFiltRanges = new ArrayList<>(); try { sessionMutex.acquire(); MseaUniEvcService evcResponse = - mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, TargetConfig.RUNNING); + mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING); //There could be zero or more EVCs if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) { activeEvcs.addAll(evcResponse.mefServices().uni().evc()); } + mseaSaFilteringService.getConfigMseaSaFilterIds(session).forEach( + r -> acvtiveFiltRanges.add(r.rangeId())); + } catch (NetconfException | InterruptedException e1) { log.warn("Error on removeFlowRules.", e1); } @@ -360,14 +378,9 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme if (ruleToRemove.selector().getCriterion(Type.IPV4_SRC) != null && ruleToRemove.selector().getCriterion(Type.IN_PORT) != null && ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) { - SourceAddressRange.SourceAddressRangeBuilder saBuilder = - new DefaultSourceAddressRange.SourceAddressRangeBuilder(); - SourceAddressRange sar = saBuilder - .rangeId((short) ruleToRemove.tableId()) - .yangSourceAddressRangeOpType(org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi. - edge.assure.msea.sa.filtering.rev20160412.MseaSaFiltering.OnosYangOpType.DELETE) - .build(); - + SourceAddressRange sar = new DefaultSourceAddressRange(); + sar.rangeId((short) ruleToRemove.tableId()); + acvtiveFiltRanges.remove(Short.valueOf((short) ruleToRemove.tableId())); rulesRemoved.add(ruleToRemove); saRangeList.add(sar); @@ -408,10 +421,23 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme //If there are IPv4 Flow Rules created commit them now through the //MseaSaFiltering service - if (saRangeList.size() > 0) { + if (saRangeList.size() > 0 && acvtiveFiltRanges.size() == 0) { try { - mseaSaFilteringService.setMseaSaFiltering( - buildSaFilteringObject(saRangeList), session, TargetConfig.RUNNING); + SourceIpaddressFiltering saFilter = + new DefaultSourceIpaddressFiltering(); + MseaSaFilteringOpParam mseaSaFiltering = new MseaSaFilteringOpParam(); + mseaSaFiltering.sourceIpaddressFiltering(saFilter); + + mseaSaFilteringService.deleteMseaSaFilteringRange( + mseaSaFiltering, session, DatastoreId.RUNNING); + } catch (NetconfException e) { + log.warn("Remove FlowRule on MseaSaFilteringService could not delete all SARules - " + + "they may already have been deleted: " + e.getMessage()); + } + } else if (saRangeList.size() > 0) { + try { + mseaSaFilteringService.deleteMseaSaFilteringRange( + buildSaFilteringObject(saRangeList), session, DatastoreId.RUNNING); } catch (NetconfException e) { log.warn("Remove FlowRule on MseaSaFilteringService could not delete SARule - " + "it may already have been deleted: " + e.getMessage()); @@ -421,7 +447,7 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme if (ceVlanMapMap.size() > 0) { try { mseaUniEvcServiceSvc.removeEvcUniFlowEntries(ceVlanMapMap, flowIdMap, - session, TargetConfig.RUNNING, portAssignment); + session, DatastoreId.RUNNING, portAssignment); } catch (NetconfException e) { log.warn("Remove FlowRule on MseaUniEvcService could not delete EVC - " + "it may already have been deleted: " + e.getMessage()); @@ -472,14 +498,12 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme log.debug("Applying IP address to " + ipAddrStr + " (on Port 0) to IP SA Filtering on EA1000 through NETCONF"); - SourceAddressRange.SourceAddressRangeBuilder saBuilder = - new DefaultSourceAddressRange.SourceAddressRangeBuilder(); + SourceAddressRange sar = + new DefaultSourceAddressRange(); - SourceAddressRange sar = saBuilder - .rangeId((short) fr.tableId()) - .name("Flow:" + fr.id().toString()) - .ipv4AddressPrefix(ipAddrStr) - .build(); + sar.rangeId((short) fr.tableId()); + sar.name("Flow:" + fr.id().toString()); + sar.ipv4AddressPrefix(ipAddrStr); frList.add(fr); saRangeList.add(sar); @@ -493,40 +517,52 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong()); Integer evcKey = (fr.tableId() << 2) + port.portNum(); VlanId sourceVid = ((VlanIdCriterion) fr.selector().getCriterion(Type.VLAN_VID)).vlanId(); - FlowMapping.FlowMappingBuilder fmBuilder = - DefaultFlowMapping.builder() - .ceVlanId(VlanIdType.of(sourceVid.id())) - .flowId(BigInteger.valueOf(fr.id().value())); + FlowMapping fm = new DefaultFlowMapping(); + fm.ceVlanId(VlanIdType.of(sourceVid.id())); + fm.flowId(BigInteger.valueOf(fr.id().value())); + if (evcMap.containsKey(evcKey)) { //Is there an entry already for this EVC and port? //Replace ceVlanMap - evcMap.put(evcKey, CustomEvc.builder(evcMap.get(evcKey)) - .addToCeVlanMap(new ServiceListType(sourceVid.toString()), port.nOrC(portAssignment)) - .addToFlowMapping(fmBuilder.build(), port.nOrC(portAssignment)) - .build()); - + if (port.nOrC(portAssignment) == UniSide.CUSTOMER) { + evcMap.get(evcKey).evcPerUni().evcPerUnic().addToFlowMapping(fm); + ServiceListType newCeVlanMap = new ServiceListType( + CeVlanMapUtils.addtoCeVlanMap( + evcMap.get(evcKey).evcPerUni().evcPerUnic().ceVlanMap().toString(), + sourceVid.toShort())); + evcMap.get(evcKey).evcPerUni().evcPerUnic().ceVlanMap(newCeVlanMap); + } else { + evcMap.get(evcKey).evcPerUni().evcPerUnin().addToFlowMapping(fm); + ServiceListType newCeVlanMap = new ServiceListType( + CeVlanMapUtils.addtoCeVlanMap( + evcMap.get(evcKey).evcPerUni().evcPerUnin().ceVlanMap().toString(), + sourceVid.toShort())); + evcMap.get(evcKey).evcPerUni().evcPerUnin().ceVlanMap(newCeVlanMap); + } } else if (evcMap.containsKey((evcKey ^ 1))) { //Is there an entry for this EVC but the opposite port? TagManipulation tm = getTagManipulation(fr); if (port.nOrC(portAssignment) == UniSide.NETWORK) { - EvcPerUnin epun = CustomEvcPerUnin.builder(evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin()) - .addToCeVlanMap(new ServiceListType(sourceVid.toString())) - .tagManipulation(tm) - .addToFlowMapping(fmBuilder.build()) - .ingressBwpGroupIndex(getMeterId(fr.treatment())) - .build(); - evcMap.put((evcKey ^ 1), CustomEvc.builder(evcMap.get((evcKey ^ 1))).addUniN(epun).build()); + ServiceListType newCeVlanMap = new ServiceListType( + CeVlanMapUtils.addtoCeVlanMap( + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ceVlanMap().toString(), + sourceVid.toShort())); + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ceVlanMap(newCeVlanMap); + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().tagManipulation(tm); + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().addToFlowMapping(fm); + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ingressBwpGroupIndex(getMeterId(fr.treatment())); } else { - EvcPerUnic epuc = CustomEvcPerUnic.builder(evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic()) - .addToCeVlanMap(new ServiceListType(sourceVid.toString())) - .tagManipulation(tm) - .addToFlowMapping(fmBuilder.build()) - .ingressBwpGroupIndex(getMeterId(fr.treatment())) - .build(); - evcMap.put((evcKey ^ 1), CustomEvc.builder(evcMap.get((evcKey ^ 1))).addUniC(epuc).build()); + ServiceListType newCeVlanMap = new ServiceListType( + CeVlanMapUtils.addtoCeVlanMap( + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ceVlanMap().toString(), + sourceVid.toShort())); + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ceVlanMap(newCeVlanMap); + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().tagManipulation(tm); + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().addToFlowMapping(fm); + evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ingressBwpGroupIndex(getMeterId(fr.treatment())); } } else { - Evc.EvcBuilder evcBuilder = new DefaultEvc.EvcBuilder(); - EvcPerUninBuilder epunBuilder = new CustomEvcPerUnin.EvcPerUninBuilder(); - EvcPerUnicBuilder epucBuilder = new CustomEvcPerUnic.EvcPerUnicBuilder(); + Evc evc = new DefaultEvc(); + EvcPerUnin epun = new CustomEvcPerUnin(); + EvcPerUnic epuc = new CustomEvcPerUnic(); TagManipulation tm = getTagManipulation(fr); UniSide side = port.nOrC(portAssignment); @@ -538,31 +574,32 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme port.opposite().nOrC(portAssignment)); oppositeCeVlanMap = oppositeCeVlanMap.isEmpty() ? "0" : oppositeCeVlanMap; if (side == UniSide.NETWORK) { - epunBuilder - .ceVlanMap(new ServiceListType(newCeVlanMap)) - .tagManipulation(tm) - .addToFlowMapping(fmBuilder.build()) - .ingressBwpGroupIndex(getMeterId(fr.treatment())); + epun.ceVlanMap(new ServiceListType(newCeVlanMap)); + epun.tagManipulation(tm); + epun.addToFlowMapping(fm); + epun.ingressBwpGroupIndex(getMeterId(fr.treatment())); - epucBuilder.ceVlanMap(new ServiceListType(oppositeCeVlanMap)); + epuc.ceVlanMap(new ServiceListType(oppositeCeVlanMap)); + epuc.ingressBwpGroupIndex(new Long(0)); } else { - epucBuilder - .ceVlanMap(new ServiceListType(newCeVlanMap)) - .tagManipulation(tm) - .addToFlowMapping(fmBuilder.build()) - .ingressBwpGroupIndex(getMeterId(fr.treatment())); + epuc.ceVlanMap(new ServiceListType(newCeVlanMap)); + epuc.tagManipulation(tm); + epuc.addToFlowMapping(fm); + epuc.ingressBwpGroupIndex(getMeterId(fr.treatment())); - epunBuilder.ceVlanMap(new ServiceListType(oppositeCeVlanMap)); + epun.ceVlanMap(new ServiceListType(oppositeCeVlanMap)); + epun.ingressBwpGroupIndex(new Long(0)); } - evcBuilder - .evcIndex(fr.tableId()) - .name(new Identifier45("EVC-" + String.valueOf(fr.tableId()))) - .evcPerUni(new DefaultEvcPerUni.EvcPerUniBuilder() - .evcPerUnin(epunBuilder.build()) - .evcPerUnic(epucBuilder.build()) - .build()); - evcMap.put(evcKey, evcBuilder.build()); + evc.evcIndex(fr.tableId()); + evc.name(new Identifier45("EVC-" + String.valueOf(fr.tableId()))); + + DefaultEvcPerUni epu = new DefaultEvcPerUni(); + epu.evcPerUnin(epun); + epu.evcPerUnic(epuc); + evc.evcPerUni(epu); + + evcMap.put(evcKey, evc); } frList.add(fr); @@ -570,20 +607,18 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme private MseaSaFilteringOpParam buildSaFilteringObject(List saRangeList) { - InterfaceEth0.InterfaceEth0Builder ifBuilder = new DefaultInterfaceEth0.InterfaceEth0Builder(); + InterfaceEth0 saIf = new DefaultInterfaceEth0(); for (SourceAddressRange sa:saRangeList) { - ifBuilder = ifBuilder.addToSourceAddressRange(sa); + saIf.addToSourceAddressRange(sa); } - InterfaceEth0 saIf = ifBuilder.filterAdminState(FilterAdminStateEnum.BLACKLIST).build(); + saIf.filterAdminState(FilterAdminStateEnum.BLACKLIST); - SourceIpaddressFiltering.SourceIpaddressFilteringBuilder saFilterBuilder = - new DefaultSourceIpaddressFiltering.SourceIpaddressFilteringBuilder(); - SourceIpaddressFiltering saFilter = saFilterBuilder.interfaceEth0(saIf).build(); + SourceIpaddressFiltering saFilter = + new DefaultSourceIpaddressFiltering(); + saFilter.interfaceEth0(saIf); - MseaSaFilteringOpParam.MseaSaFilteringBuilder opBuilder = - new MseaSaFilteringOpParam.MseaSaFilteringBuilder(); - MseaSaFilteringOpParam mseaSaFiltering = - (MseaSaFilteringOpParam) opBuilder.sourceIpaddressFiltering(saFilter).build(); + MseaSaFilteringOpParam mseaSaFiltering = new MseaSaFilteringOpParam(); + mseaSaFiltering.sourceIpaddressFiltering(saFilter); return mseaSaFiltering; } @@ -597,35 +632,37 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0)); TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder(); - for (SourceAddressRange sa:saRangelist) { - Criterion matchIpSrc = Criteria.matchIPSrc(IpPrefix.valueOf(sa.ipv4AddressPrefix())); + if (saRangelist != null) { + for (SourceAddressRange sa : saRangelist) { + Criterion matchIpSrc = Criteria.matchIPSrc(IpPrefix.valueOf(sa.ipv4AddressPrefix())); - TrafficSelector selector = tsBuilder.add(matchIpSrc).add(matchInPort).build(); + TrafficSelector selector = tsBuilder.add(matchIpSrc).add(matchInPort).build(); - TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder(); - TrafficTreatment treatment = trBuilder.drop().build(); + TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder(); + TrafficTreatment treatment = trBuilder.drop().build(); - FlowRule.Builder feBuilder = new DefaultFlowRule.Builder(); - if (sa.name() != null && sa.name().startsWith("Flow:")) { - String[] nameParts = sa.name().split(":"); - Long cookie = Long.valueOf(nameParts[1], 16); - feBuilder = feBuilder.withCookie(cookie); - } else { - feBuilder = feBuilder.fromApp(appId); + FlowRule.Builder feBuilder = new DefaultFlowRule.Builder(); + if (sa.name() != null && sa.name().startsWith("Flow:")) { + String[] nameParts = sa.name().split(":"); + Long cookie = Long.valueOf(nameParts[1], 16); + feBuilder = feBuilder.withCookie(cookie); + } else { + feBuilder = feBuilder.fromApp(appId); + } + + FlowRule fr = feBuilder + .forDevice(handler().data().deviceId()) + .withSelector(selector) + .withTreatment(treatment) + .forTable(sa.rangeId()) + .makePermanent() + .withPriority(PRIORITY_DEFAULT) + .build(); + + flowEntryCollection.add( + new DefaultFlowEntry(fr, FlowEntryState.ADDED, 0, 0, 0)); } - - FlowRule fr = feBuilder - .forDevice(handler().data().deviceId()) - .withSelector(selector) - .withTreatment(treatment) - .forTable(sa.rangeId()) - .makePermanent() - .withPriority(PRIORITY_DEFAULT) - .build(); - - flowEntryCollection.add(new DefaultFlowEntry(fr, FlowEntryState.ADDED, 0, 0, 0)); } - return flowEntryCollection; } @@ -801,46 +838,41 @@ public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour impleme if (isPop) { //The should be no vlanId in this case - TagPop.TagPopBuilder popBuilder = new DefaultTagPop.TagPopBuilder(); - org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc - .service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation - .tagpop.TagPop.TagPopBuilder popInnerBuilder = - new org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea - .uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes - .tagmanipulation.tagpop.DefaultTagPop.TagPopBuilder(); - return popBuilder - .tagPop(popInnerBuilder.build()) - .build(); + TagPop pop = new DefaultTagPop(); + org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice + .evcperuniextensionattributes.tagmanipulation + .tagpop.TagPop popInner = + new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317 + .mseaunievcservice.evcperuniextensionattributes + .tagmanipulation.tagpop.DefaultTagPop(); + pop.tagPop(popInner); + return pop; } else if (isPush && vlanId != null) { - TagPush.TagPushBuilder pushBuilder = new DefaultTagPush.TagPushBuilder(); - org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc - .service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation - .tagpush.TagPush.TagPushBuilder pushInnerBuilder = - new org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea - .uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes - .tagmanipulation.tagpush.DefaultTagPush.TagPushBuilder(); - return pushBuilder - .tagPush(pushInnerBuilder - .outerTagVlan(new VlanIdType(vlanId.id())) - .pushTagType(ethType.equals(EtherType.VLAN.ethType()) ? - PushTagTypeEnum.PUSHCTAG : PushTagTypeEnum.PUSHSTAG) - .build()) - .build(); + TagPush push = new DefaultTagPush(); + org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice + .evcperuniextensionattributes.tagmanipulation + .tagpush.TagPush pushInner = + new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317 + .mseaunievcservice.evcperuniextensionattributes + .tagmanipulation.tagpush.DefaultTagPush(); + pushInner.outerTagVlan(new VlanIdType(vlanId.id())); + pushInner.pushTagType(ethType.equals(EtherType.VLAN.ethType()) ? + PushTagTypeEnum.PUSHCTAG : PushTagTypeEnum.PUSHSTAG); + push.tagPush(pushInner); + return push; } else if (vlanId != null) { //This is overwrite, as it has vlanId, but not push or pop - TagOverwrite.TagOverwriteBuilder ovrBuilder = new DefaultTagOverwrite.TagOverwriteBuilder(); - org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc - .service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation - .tagoverwrite.TagOverwrite.TagOverwriteBuilder ovrInnerBuilder = - new org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea - .uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes - .tagmanipulation.tagoverwrite.DefaultTagOverwrite.TagOverwriteBuilder(); - return ovrBuilder. - tagOverwrite(ovrInnerBuilder - .outerTagVlan(new VlanIdType(vlanId.id())) - .build()) - .build(); + TagOverwrite ovr = new DefaultTagOverwrite(); + org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice + .evcperuniextensionattributes.tagmanipulation + .tagoverwrite.TagOverwrite ovrInner = + new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317 + .mseaunievcservice.evcperuniextensionattributes + .tagmanipulation.tagoverwrite.DefaultTagOverwrite(); + ovrInner.outerTagVlan(new VlanIdType(vlanId.id())); + ovr.tagOverwrite(ovrInner); + return ovr; } return null; diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java similarity index 52% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java index 2ecc70fe3e..226ad2f506 100644 --- a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java @@ -38,33 +38,35 @@ import org.onosproject.net.meter.MeterProviderRegistry; import org.onosproject.net.meter.MeterProviderService; import org.onosproject.net.provider.AbstractProvider; import org.onosproject.net.provider.ProviderId; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfController; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.CosColorType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.PriorityType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.coscolortype.CosColorTypeEnum; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService.OnosYangOpType; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.DefaultMefServices; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.MefServices; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultProfiles; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultProfiles.ProfilesBuilder; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.Cos; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.DefaultCos; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.Bwp; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.DefaultBwp; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.DefaultEvcCosTypeEvcColorId; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.DefaultEvcCosTypeAll8PrioTo1EvcColor; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.EvcCosTypeAll8PrioTo1EvcColor; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.CosColorType; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.coscolortype.CosColorTypeEnum; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.Cos; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultCos; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.Bwp; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.DefaultBwp; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.DefaultEvcCosTypeEvcColorId; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.EvcCosTypeEvcColorId; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.DefaultEvcCosTypeAll8PrioTo1EvcColor; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.EvcCosTypeAll8PrioTo1EvcColor; import org.slf4j.Logger; /** * Provider which uses an NETCONF controller to handle meters. + * + * TODO: move this to an architecture similar to FlowRuleDriverProvider in order + * to use a behavior to discover meters. */ @Component(immediate = true, enabled = true) public class EA1000MeterProvider extends AbstractProvider implements MeterProvider { @@ -125,11 +127,11 @@ public class EA1000MeterProvider extends AbstractProvider implements MeterProvid String deviceName = deviceId.uri().getSchemeSpecificPart(); Unit unit = meterOp.meter().unit(); - ProfilesBuilder profilesBuilder = DefaultProfiles.builder(); + Profiles profiles = new DefaultProfiles(); if (meterOp.type() == MeterOperation.Type.ADD || meterOp.type() == MeterOperation.Type.MODIFY) { - Bwp.BwpBuilder bwpBuilder = DefaultBwp.builder() - .cosIndex(COS_INDEX_1) - .name("BWP-" + String.valueOf(meterId) + "-" + deviceName); + Bwp bwp = new DefaultBwp(); + bwp.cosIndex(COS_INDEX_1); + bwp.name("BWP-" + String.valueOf(meterId) + "-" + deviceName); long cirRateKbps = 0L; long cbsRateKbps = 0L; @@ -146,51 +148,56 @@ public class EA1000MeterProvider extends AbstractProvider implements MeterProvid ebsRateKbps = band.burst(); //Already in kbps } } - bwpBuilder.committedInformationRate(cirRateKbps).excessInformationRate(eirRateKbps - cirRateKbps); + bwp.committedInformationRate(cirRateKbps); + bwp.excessInformationRate(eirRateKbps - cirRateKbps); if (meterOp.meter().isBurst()) { - bwpBuilder.committedBurstSize(cbsRateKbps).excessBurstSize(ebsRateKbps - cbsRateKbps); + bwp.committedBurstSize(cbsRateKbps); + bwp.excessBurstSize(ebsRateKbps - cbsRateKbps); } - BwpGroup.BwpGroupBuilder bwpgBuilder = - DefaultBwpGroup.builder() - .groupIndex((short) meterId) - .addToBwp(bwpBuilder.build()); + BwpGroup bwpg = new DefaultBwpGroup(); + bwpg.groupIndex((short) meterId); + bwpg.addToBwp(bwp); //Create cos-1 as referenced above - we only support 1 at the moment - Cos.CosBuilder cosBuilder = DefaultCos.builder() - .cosIndex(COS_INDEX_1) - .name("COS-1") - .outgoingCosValue(PriorityType.of(DEFAULT_OUTGOING_PRIO)) - .colorAware(true) - .colorForward(true); - EvcCosTypeAll8PrioTo1EvcColor ect = - DefaultEvcCosTypeAll8PrioTo1EvcColor.builder() - .evcAll8ColorTo(CosColorType.of(CosColorTypeEnum.GREEN)).build(); - profilesBuilder - .addToBwpGroup(bwpgBuilder.build()) - .addToCos(cosBuilder.cosTypeChoice( - DefaultEvcCosTypeEvcColorId.builder() - .evcCosTypeAll8PrioTo1EvcColor(ect).build()).build()) - .build(); - } else if (meterOp.type() == MeterOperation.Type.REMOVE) { - BwpGroup.BwpGroupBuilder bwpgBuilder = - DefaultBwpGroup.builder() - .groupIndex((short) meterId) - .yangBwpGroupOpType(OnosYangOpType.DELETE); + Cos cos = new DefaultCos(); + cos.cosIndex(COS_INDEX_1); + cos.name("COS-1"); + cos.outgoingCosValue(PriorityType.of(DEFAULT_OUTGOING_PRIO)); + cos.colorAware(true); + cos.colorForward(true); - profilesBuilder.addToBwpGroup(bwpgBuilder.build()).build(); + EvcCosTypeAll8PrioTo1EvcColor ect = + new DefaultEvcCosTypeAll8PrioTo1EvcColor(); + ect.evcAll8ColorTo(CosColorType.of(CosColorTypeEnum.GREEN)); + profiles.addToBwpGroup(bwpg); + + EvcCosTypeEvcColorId cid = new DefaultEvcCosTypeEvcColorId(); + cid.evcCosTypeAll8PrioTo1EvcColor(ect); + cos.cosTypeChoice(cid); + profiles.addToCos(cos); + } else if (meterOp.type() == MeterOperation.Type.REMOVE) { + BwpGroup bwpg = new DefaultBwpGroup(); + bwpg.groupIndex((short) meterId); + + profiles.addToBwpGroup(bwpg); } - MefServices mefServices = DefaultMefServices.builder().profiles(profilesBuilder.build()).build(); + MefServices mefServices = new DefaultMefServices(); + mefServices.profiles(profiles); - MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder = - new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder(); + MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam(); + mseaUniEvcServiceFilter.mefServices(mefServices); - MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = - (MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build(); NetconfSession session = controller.getDevicesMap().get(deviceId).getSession(); try { - mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, TargetConfig.RUNNING); + if (meterOp.type() == MeterOperation.Type.REMOVE) { + mseaUniEvcServiceSvc.deleteMseaUniEvcService(mseaUniEvcServiceFilter, + session, DatastoreId.RUNNING); + } else { + mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, + session, DatastoreId.RUNNING); + } } catch (NetconfException e) { //This can fail if the BWP Group is deleted before the EVC that is dependent on it //The delete of the EVC will be called on a separate thread to that should proceed @@ -201,24 +208,25 @@ public class EA1000MeterProvider extends AbstractProvider implements MeterProvid while (retry.getAndDecrement() > 0) { try { Thread.sleep(1000L); - log.debug("Retrying deletion of Bandwith Profile Group {}", String.valueOf(meterId)); + log.debug("Retrying deletion of Bandwith Profile Group {}", + String.valueOf(meterId)); mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, - session, TargetConfig.RUNNING); + session, DatastoreId.RUNNING); return; //If it did not throw an exception } catch (InterruptedException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + log.debug("Error when deleting BWP profile on EA1000" + + " - trying again in 1 sec", e1); } catch (NetconfException e1) { - log.debug("NETCONF failed to delete profile - trying again in 1 sec"); - e1.printStackTrace(); + log.debug("NETCONF failed to delete profile - trying again in 1 sec", e1); } } - log.error("Error deleting BWPGroup {} from {} after 4 tries: {}", meterId, deviceId, e.getMessage()); + log.error("Error deleting BWPGroup {} from {} after 4 tries: {}", + meterId, deviceId, e.getMessage()); } else { - log.error("Error adding BWPGroup {} from {}: {}", meterId, deviceId, e.getMessage()); + log.error("Error adding BWPGroup {} from {}: {}", + meterId, deviceId, e.getMessage()); throw new UnsupportedOperationException(e); } - e.printStackTrace(); } } diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java similarity index 81% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java index ec438333ce..dfb8480a1a 100644 --- a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java @@ -40,12 +40,15 @@ import org.onosproject.net.device.DeviceService; import org.onosproject.net.device.PortDescription; import org.onosproject.net.driver.AbstractHandlerBehaviour; import org.onosproject.netconf.NetconfController; +import org.onosproject.netconf.NetconfDevice; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.system.AugmentedSysSystem; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.systemstate.platform.AugmentedSysPlatform; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystem; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20130715.ietfyangtypes.DateAndTime; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.AugmentedSysSystem; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.DefaultAugmentedSysSystem; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.AugmentedSysPlatform; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.DefaultAugmentedSysPlatform; +import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.DateAndTime; import org.slf4j.Logger; public class Ea1000DeviceDescription extends AbstractHandlerBehaviour implements DeviceDescriptionDiscovery { @@ -65,7 +68,14 @@ public class Ea1000DeviceDescription extends AbstractHandlerBehaviour implements log.info("Adding description for EA1000 device"); NetconfController controller = checkNotNull(handler().get(NetconfController.class)); - NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession(); + NetconfDevice ncDevice = controller.getDevicesMap().get(handler().data().deviceId()); + if (ncDevice == null) { + log.error("Internal ONOS Error. Device has been marked as reachable, " + + "but deviceID {} is not in Devices Map. Continuing with empty description", + handler().data().deviceId()); + return null; + } + NetconfSession session = ncDevice.getSession(); IetfSystemNetconfService ietfSystemService = (IetfSystemNetconfService) checkNotNull(handler().get(IetfSystemNetconfService.class)); @@ -75,7 +85,7 @@ public class Ea1000DeviceDescription extends AbstractHandlerBehaviour implements swVersion = system.systemState().platform().osRelease(); AugmentedSysPlatform augmentedSysPlatform = (AugmentedSysPlatform) system.systemState() - .platform().yangAugmentedInfo(AugmentedSysPlatform.class); + .platform().augmentation(DefaultAugmentedSysPlatform.class); serialNumber = augmentedSysPlatform.deviceIdentification().serialNumber(); DateAndTime deviceDateAndTime = system.systemState().clock().currentDatetime(); OffsetDateTime odt = @@ -89,7 +99,7 @@ public class Ea1000DeviceDescription extends AbstractHandlerBehaviour implements if (system != null && system.system() != null) { AugmentedSysSystem augmentedSystem = - (AugmentedSysSystem) system.system().yangAugmentedInfo(AugmentedSysSystem.class); + (AugmentedSysSystem) system.system().augmentation(DefaultAugmentedSysSystem.class); longitudeStr = augmentedSystem.longitude().toPlainString(); latitudeStr = augmentedSystem.latitude().toPlainString(); } diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java diff --git a/drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/package-info.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/main/java/org/onosproject/drivers/microsemi/package-info.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/package-info.java diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java similarity index 75% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java index 755435060d..44c62f6ab6 100644 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java @@ -17,17 +17,17 @@ package org.onosproject.drivers.microsemi.yang; import java.time.OffsetDateTime; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystem; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystemOpParam; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.ietfsystem.systemrestart.SystemRestartInput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.systemrestart.SystemRestartInput; /** * Extension of ietfSystemService to include NETCONF sessions. @@ -60,10 +60,11 @@ public interface IetfSystemNetconfService { * @param ietfSystem value of ietfSystem * @param session An active NETCONF session * @param ncDs datastore type running, startup or candidate + * @return Boolean to indicate success or failure * @throws NetconfException if the session has any error */ - void setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session, TargetConfig ncDs) - throws NetconfException; + boolean setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session, + DatastoreId ncDs) throws NetconfException; /** * Service interface of setCurrentDatetime. diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java new file mode 100644 index 0000000000..6cf80319f8 --- /dev/null +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java @@ -0,0 +1,135 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi.yang; + +import com.google.common.collect.ImmutableMap; +import org.apache.felix.scr.annotations.Component; +import org.onosproject.yang.AbstractYangModelRegistrator; +import org.onosproject.yang.gen.v1.entitystatetcmib.rev20051122.EntityStateTcMib; +import org.onosproject.yang.gen.v1.fpgainternal.rev20151130.FpgaInternal; +import org.onosproject.yang.gen.v1.ianacrypthash.rev20140806.IanaCryptHash; +import org.onosproject.yang.gen.v1.ianaiftype.rev20140508.IanaIfType; +import org.onosproject.yang.gen.v1.ieeetypes.rev20080522.IeeeTypes; +import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.IetfInetTypes; +import org.onosproject.yang.gen.v1.ietfinterfaces.rev20140508.IetfInterfaces; +import org.onosproject.yang.gen.v1.ietfnetconf.rev20110601.IetfNetconf; +import org.onosproject.yang.gen.v1.ietfnetconfacm.rev20120222.IetfNetconfAcm; +import org.onosproject.yang.gen.v1.ietfnetconfmonitoring.rev20101004.IetfNetconfMonitoring; +import org.onosproject.yang.gen.v1.ietfnetconfnotifications.rev20120206.IetfNetconfNotifications; +import org.onosproject.yang.gen.v1.ietfnetconfwithdefaults.rev20100609.IetfNetconfWithDefaults; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.IetfSystemMicrosemi; +import org.onosproject.yang.gen.v1.ietfsystemtlsauth.rev20140524.IetfSystemTlsAuth; +import org.onosproject.yang.gen.v1.ietfx509certtoname.rev20130326.IetfX509CertToName; +import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.IetfYangTypes; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering; +import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.MseaSoamFm; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.MseaSoamPm; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.MseaTypes; +import org.onosproject.yang.gen.v1.mseaunievcinterface.rev20160317.MseaUniEvcInterface; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService; +import org.onosproject.yang.gen.v1.ncnotifications.rev20080714.NcNotifications; +import org.onosproject.yang.gen.v1.netopeercfgnetopeer.rev20130214.NetopeerCfgnetopeer; +import org.onosproject.yang.gen.v1.notifications.rev20080714.Notifications; +import org.onosproject.yang.gen.v1.rfc2544.rev20151020.Rfc2544; +import org.onosproject.yang.gen.v1.svcactivationtypes.rev20151027.SvcActivationTypes; +import org.onosproject.yang.gen.v1.y1564.rev20151029.Y1564; +import org.onosproject.yang.model.DefaultYangModuleId; +import org.onosproject.yang.model.YangModuleId; +import org.onosproject.yang.runtime.AppModuleInfo; +import org.onosproject.yang.runtime.DefaultAppModuleInfo; + +import java.util.HashMap; +import java.util.Map; + +/** + * Representation of Microsemi model registrator which registers Microsemi device + * models. + */ +@Component(immediate = true) +public class MicrosemiModelRegistrator extends AbstractYangModelRegistrator { + + public MicrosemiModelRegistrator() { + super(IetfSystem.class, getAppInfo()); + } + + private static Map getAppInfo() { + Map appInfo = new HashMap<>(); + + appInfo.put(new DefaultYangModuleId("fpga-internal", "2015-11-30"), + new DefaultAppModuleInfo(FpgaInternal.class, null)); + appInfo.put(new DefaultYangModuleId("iana-if-type", "2014-05-08"), + new DefaultAppModuleInfo(IanaIfType.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-yang-types", "2013-07-15"), + new DefaultAppModuleInfo(IetfYangTypes.class, null)); + appInfo.put(new DefaultYangModuleId("msea-sa-filtering", "2016-04-12"), + new DefaultAppModuleInfo(MseaSaFiltering.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-x509-cert-to-name", "2013-03-26"), + new DefaultAppModuleInfo(IetfX509CertToName.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-system", "2014-08-06"), + new DefaultAppModuleInfo(IetfSystem.class, null)); + appInfo.put(new DefaultYangModuleId("msea-types", "2016-02-29"), + new DefaultAppModuleInfo(MseaTypes.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-inet-types", "2013-07-15"), + new DefaultAppModuleInfo(IetfInetTypes.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-netconf-with-defaults", "2010-06-09"), + new DefaultAppModuleInfo(IetfNetconfWithDefaults.class, null)); + appInfo.put(new DefaultYangModuleId("msea-uni-evc-service", "2016-03-17"), + new DefaultAppModuleInfo(MseaUniEvcService.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-netconf-monitoring", "2010-10-04"), + new DefaultAppModuleInfo(IetfNetconfMonitoring.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-netconf-acm", "2012-02-22"), + new DefaultAppModuleInfo(IetfNetconfAcm.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-system-tls-auth", "2014-05-24"), + new DefaultAppModuleInfo(IetfSystemTlsAuth.class, null)); + appInfo.put(new DefaultYangModuleId("rfc-2544", "2015-10-20"), + new DefaultAppModuleInfo(Rfc2544.class, null)); + appInfo.put(new DefaultYangModuleId("msea-cfm", "2016-02-29"), + new DefaultAppModuleInfo(MseaCfm.class, null)); + appInfo.put(new DefaultYangModuleId("netopeer-cfgnetopeer", "2013-02-14"), + new DefaultAppModuleInfo(NetopeerCfgnetopeer.class, null)); + appInfo.put(new DefaultYangModuleId("ENTITY-STATE-TC-MIB", "2005-11-22"), + new DefaultAppModuleInfo(EntityStateTcMib.class, null)); + appInfo.put(new DefaultYangModuleId("msea-soam-fm", "2016-02-29"), + new DefaultAppModuleInfo(MseaSoamFm.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-netconf-notifications", "2012-02-06"), + new DefaultAppModuleInfo(IetfNetconfNotifications.class, null)); + appInfo.put(new DefaultYangModuleId("nc-notifications", "2008-07-14"), + new DefaultAppModuleInfo(NcNotifications.class, null)); + appInfo.put(new DefaultYangModuleId("iana-crypt-hash", "2014-08-06"), + new DefaultAppModuleInfo(IanaCryptHash.class, null)); + appInfo.put(new DefaultYangModuleId("msea-uni-evc-interface", "2016-03-17"), + new DefaultAppModuleInfo(MseaUniEvcInterface.class, null)); + appInfo.put(new DefaultYangModuleId("msea-soam-pm", "2016-02-29"), + new DefaultAppModuleInfo(MseaSoamPm.class, null)); + appInfo.put(new DefaultYangModuleId("ieee-types", "2008-05-22"), + new DefaultAppModuleInfo(IeeeTypes.class, null)); + appInfo.put(new DefaultYangModuleId("svc-activation-types", "2015-10-27"), + new DefaultAppModuleInfo(SvcActivationTypes.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-netconf", "2011-06-01"), + new DefaultAppModuleInfo(IetfNetconf.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-system-microsemi", "2016-05-05"), + new DefaultAppModuleInfo(IetfSystemMicrosemi.class, null)); + appInfo.put(new DefaultYangModuleId("notifications", "2008-07-14"), + new DefaultAppModuleInfo(Notifications.class, null)); + appInfo.put(new DefaultYangModuleId("y-1564", "2015-10-29"), + new DefaultAppModuleInfo(Y1564.class, null)); + appInfo.put(new DefaultYangModuleId("ietf-interfaces", "2014-05-08"), + new DefaultAppModuleInfo(IetfInterfaces.class, null)); + return ImmutableMap.copyOf(appInfo); + } +} diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java similarity index 64% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java index cf391fa507..cdd3700acd 100644 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java @@ -15,18 +15,15 @@ */ package org.onosproject.drivers.microsemi.yang; -import org.onosproject.event.ListenerService; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.MseaCfm; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.MseaCfmOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.MseaCfmEvent; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.MseaCfmEventListener; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput; /** * Extension of mseaCfmService to include NETCONF sessions. @@ -34,7 +31,7 @@ import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure. * This is manually extended and should be revised if the msea-cfm.yang, * msea-soam-pm.yang or msea-soam-fm.yang files change */ -public interface MseaCfmNetconfService extends ListenerService { +public interface MseaCfmNetconfService { /** * Returns attributes of MEP. @@ -70,9 +67,11 @@ public interface MseaCfmNetconfService extends ListenerService getConfigMseaSaFilterIds(NetconfSession session) + throws NetconfException; + /** * Sets the value to attribute mseaSaFiltering. * * @param mseaSaFiltering value of mseaSaFiltering * @param session An active NETCONF session * @param targetDs The NETCONF datastore to edit + * @return Boolean to indicate success or failure * @throws NetconfException if the session has any error */ - void setMseaSaFiltering(MseaSaFilteringOpParam mseaSaFiltering, NetconfSession session, TargetConfig targetDs) - throws NetconfException; + boolean setMseaSaFiltering(MseaSaFilteringOpParam mseaSaFiltering, + NetconfSession session, DatastoreId targetDs) throws NetconfException; + + /** + * Deletes the value to attribute mseaSaFiltering. + * + * @param mseaSaFiltering value of mseaSaFiltering + * @param session An active NETCONF session + * @param targetDs The NETCONF datastore to edit + * @return Boolean to indicate success or failure + * @throws NetconfException if the session has any error + */ + boolean deleteMseaSaFilteringRange(MseaSaFilteringOpParam mseaSaFiltering, + NetconfSession session, DatastoreId targetDs) throws NetconfException; } diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java similarity index 74% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java index 38ccbf6390..a7f85bf48f 100644 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java @@ -19,12 +19,12 @@ package org.onosproject.drivers.microsemi.yang; import java.util.List; import java.util.Map; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum; /** * Extension of mseaUniEvcServiceService to include NETCONF sessions. @@ -55,8 +55,8 @@ public interface MseaUniEvcServiceNetconfService { * @throws NetconfException if the session has any error */ MseaUniEvcService getConfigMseaUniEvcService( - MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session, TargetConfig targetDs) - throws NetconfException; + MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session, + DatastoreId targetDs) throws NetconfException; /** * Sets the value to attribute mseaUniEvcService. @@ -64,12 +64,25 @@ public interface MseaUniEvcServiceNetconfService { * @param mseaUniEvcService value of mseaUniEvcService * @param session The NETCONF session * @param targetDs one of running, candidate or startup + * @return Boolean to indicate success or failure * @throws NetconfException if the session has any error */ - void setMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService, - NetconfSession session, TargetConfig targetDs) + boolean setMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService, + NetconfSession session, DatastoreId targetDs) throws NetconfException; + /** + * Deletes the objects in mseaUniEvcService. + * + * @param mseaUniEvcService value of mseaUniEvcService + * @param session The NETCONF session + * @param targetDs one of running, candidate or startup + * @return Boolean to indicate success or failure + * @throws NetconfException if the session has any error + */ + boolean deleteMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService, + NetconfSession session, DatastoreId targetDs) throws NetconfException; + /** * Returns a list of the CeVlanMaps on both sides of the EVC. * @@ -79,7 +92,7 @@ public interface MseaUniEvcServiceNetconfService { * @throws NetconfException if the session has any error */ MseaUniEvcService getmseaUniEvcCeVlanMaps( - NetconfSession session, TargetConfig ncDs) + NetconfSession session, DatastoreId ncDs) throws NetconfException; /** @@ -100,7 +113,7 @@ public interface MseaUniEvcServiceNetconfService { Map ceVlanUpdates, Map> flowVlanIds, NetconfSession session, - TargetConfig targetDs, + DatastoreId targetDs, UniSideInterfaceAssignmentEnum portAssign) throws NetconfException; diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java new file mode 100644 index 0000000000..fbf89beac4 --- /dev/null +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi.yang.custom; + +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.EvcPerUniServiceTypeEnum; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnic; + +import java.util.List; + +/** + * Extend the DefaultEvcPerUnic so that the ceVlanMap can always be initialized at 0. + */ +public class CustomEvcPerUnic extends DefaultEvcPerUnic { + @Override + public ServiceListType ceVlanMap() { + if (ceVlanMap == null) { + return new ServiceListType("0"); + } + return ceVlanMap; + } + @Override + public Object ingressBwpGroupIndex() { + return ingressBwpGroupIndex; + } + + @Override + public EvcPerUniServiceTypeEnum evcPerUniServiceType() { + return evcPerUniServiceType; + } + + @Override + public TagManipulation tagManipulation() { + return tagManipulation; + } + + @Override + public List flowMapping() { + return flowMapping; + } +} diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java new file mode 100644 index 0000000000..d8712dc618 --- /dev/null +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi.yang.custom; + +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.EvcPerUniServiceTypeEnum; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnin; + +import java.util.List; + +/** + * Extend the DefaultEvcPerUnin so that the ceVlanMap can always be initialized at 0. + */ +public class CustomEvcPerUnin extends DefaultEvcPerUnin { + @Override + public ServiceListType ceVlanMap() { + if (ceVlanMap == null) { + return new ServiceListType("0"); + } + return ceVlanMap; + } + @Override + public Object ingressBwpGroupIndex() { + return ingressBwpGroupIndex; + } + + @Override + public EvcPerUniServiceTypeEnum evcPerUniServiceType() { + return evcPerUniServiceType; + } + + @Override + public TagManipulation tagManipulation() { + return tagManipulation; + } + + @Override + public List flowMapping() { + return flowMapping; + } + +} diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/yab/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java similarity index 85% rename from drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/yab/package-info.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java index a8a971cfc7..1a7a471f24 100644 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/yms/app/yab/package-info.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-present Open Networking Laboratory + * Copyright 2017-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,4 +17,4 @@ /** * Package for Microsemi device drivers support for NETCONF for EA1000. */ -package org.onosproject.yms.app.yab; \ No newline at end of file +package org.onosproject.drivers.microsemi.yang.custom; \ No newline at end of file diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java new file mode 100644 index 0000000000..3867a2f877 --- /dev/null +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java @@ -0,0 +1,245 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi.yang.impl; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + +import com.google.common.base.Charsets; +import com.google.common.io.ByteSource; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.netconf.DatastoreId; +import org.onosproject.netconf.NetconfException; +import org.onosproject.netconf.NetconfSession; +import org.onosproject.yang.model.ModelConverter; +import org.onosproject.yang.model.ModelObjectData; +import org.onosproject.yang.model.ResourceData; +import org.onosproject.yang.model.ResourceId; +import org.onosproject.yang.model.SchemaContext; +import org.onosproject.yang.model.SchemaContextProvider; +import org.onosproject.yang.runtime.AnnotatedNodeInfo; +import org.onosproject.yang.runtime.CompositeData; +import org.onosproject.yang.runtime.CompositeStream; +import org.onosproject.yang.runtime.DefaultCompositeData; +import org.onosproject.yang.runtime.DefaultCompositeStream; +import org.onosproject.yang.runtime.DefaultYangSerializerContext; +import org.onosproject.yang.runtime.YangModelRegistry; +import org.onosproject.yang.runtime.YangSerializer; +import org.onosproject.yang.runtime.YangSerializerContext; +import org.onosproject.yang.runtime.YangSerializerRegistry; +import org.onosproject.yang.serializers.xml.XmlSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract class that implements some of the core functions of a YANG model service. + * + */ +@Component(immediate = true) +@Service +public abstract class AbstractYangServiceImpl { + public static final String NC_OPERATION = "nc:operation"; + public static final String OP_DELETE = "delete"; + + protected final Logger log = LoggerFactory.getLogger(getClass()); + protected boolean alreadyLoaded = false; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected YangModelRegistry yangModelRegistry; + +// @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) +// protected SchemaContextProvider schemaContextProvider; + + protected ApplicationId appId; + + // xSer is not a service and is a class variable. Can be lost on deactivate. + // Must be recreated on activate + protected XmlSerializer xSer; + protected YangSerializerContext yCtx; + + protected static final Pattern REGEX_XML_HEADER = + Pattern.compile("(<\\?xml).*(\\?>)", Pattern.DOTALL); + protected static final Pattern REGEX_RPC_REPLY = + Pattern.compile("()", Pattern.DOTALL); + protected static final Pattern REGEX_RPC_REPLY_DATA_NS = + Pattern.compile("()"); + protected static final Pattern REGEX_RPC_REPLY_DATA = + Pattern.compile("()"); + protected static final Pattern REGEX_RPC_REPLY_DATA_CLOSE = + Pattern.compile("()"); + protected static final Pattern REGEX_RPC_REPLY_DATA_EMPTY = + Pattern.compile("()"); + protected static final Pattern REGEX_RPC_REPLY_CLOSE = + Pattern.compile("()"); + + @Activate + public void activate() { + Set yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers(); + yangSer.forEach(ser -> { + if (ser instanceof XmlSerializer) { + xSer = (XmlSerializer) ser; + } + }); + SchemaContext context = ((SchemaContextProvider) yangModelRegistry) + .getSchemaContext(ResourceId.builder().addBranchPointSchema("/", null).build()); + + yCtx = new DefaultYangSerializerContext(context, null); + }; + + @Deactivate + public void deactivate() { + alreadyLoaded = false; + } + + /** + * Internal method to generically make a NETCONF get query from YANG objects. + * @param moFilter A YANG object model + * @param session A NETCONF session + * @return YangObjectModel + * @throws NetconfException if the session has any error + */ + protected final ModelObjectData getNetconfObject( + ModelObjectData moFilter, NetconfSession session) + throws NetconfException { + + return getConfigNetconfObject(moFilter, session, null); + } + + /** + * Internal method to generically make a NETCONF get-config query from YANG objects. + * + * @param moFilter A YANG object model + * @param session A NETCONF session + * @param targetDs - running,candidate or startup + * @return YangObjectModel + * @throws NetconfException if the session has any error + */ + protected final ModelObjectData getConfigNetconfObject( + ModelObjectData moFilter, NetconfSession session, DatastoreId targetDs) + throws NetconfException { + if (session == null) { + throw new NetconfException("Session is null when calling getConfigNetconfObject()"); + } + + if (moFilter == null) { + throw new NetconfException("Query object cannot be null"); + } + + String xmlQueryStr = encodeMoToXmlStr(moFilter, null); + + log.debug("Sending query on NETCONF session " + session.getSessionId() + + ":\n" + xmlQueryStr); + String xmlResult; + if (targetDs == null) { + xmlResult = session.get(xmlQueryStr, null); + } else { + xmlResult = session.getConfig(targetDs, xmlQueryStr); + } + xmlResult = removeRpcReplyData(xmlResult); + + DefaultCompositeStream resultDcs = new DefaultCompositeStream( + null, new ByteArrayInputStream(xmlResult.getBytes())); + CompositeData compositeData = xSer.decode(resultDcs, yCtx); + + return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData()); + } + + /** + * Internal method to generically make a NETCONF edit-config call from a set of YANG objects. + * + * @param moConfig A YANG object model + * @param session A NETCONF session + * @param targetDs - running,candidate or startup + * @param annotations A list of AnnotatedNodeInfos to be added to the DataNodes + * @return Boolean value indicating success or failure of command + * @throws NetconfException if the session has any error + */ + protected final boolean setNetconfObject( + ModelObjectData moConfig, NetconfSession session, DatastoreId targetDs, + List annotations) throws NetconfException { + if (moConfig == null) { + throw new NetconfException("Query object cannot be null"); + } else if (session == null) { + throw new NetconfException("Session is null when calling getMseaSaFiltering()"); + } else if (targetDs == null) { + throw new NetconfException("TargetDs is null when calling getMseaSaFiltering()"); + } + + String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations); + log.debug("Sending query on NETCONF session " + session.getSessionId() + + ":\n" + xmlQueryStr); + + return session.editConfig(targetDs, null, xmlQueryStr); + } + + protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter, + List annotations) + throws NetconfException { + //Convert the param to XML to use as a filter + ResourceData rd = ((ModelConverter) yangModelRegistry).createDataNode(yangObjectOpParamFilter); + + DefaultCompositeData.Builder cdBuilder = + DefaultCompositeData.builder().resourceData(rd); + if (annotations != null) { + for (AnnotatedNodeInfo ani : annotations) { + cdBuilder.addAnnotatedNodeInfo(ani); + } + } + CompositeStream cs = xSer.encode(cdBuilder.build(), yCtx); + //Convert the param to XML to use as a filter + + try { + ByteSource byteSource = new ByteSource() { + @Override + public InputStream openStream() throws IOException { + return cs.resourceData(); + } + }; + + return byteSource.asCharSource(Charsets.UTF_8).read(); + } catch (IOException e) { + throw new NetconfException("Error decoding CompositeStream to String", e); + } + } + + protected static final String removeRpcReplyData(String rpcReplyXml) { + rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst(""); + rpcReplyXml = REGEX_RPC_REPLY.matcher(rpcReplyXml).replaceFirst(""); + rpcReplyXml = REGEX_RPC_REPLY_DATA_NS.matcher(rpcReplyXml).replaceFirst(""); + rpcReplyXml = REGEX_RPC_REPLY_DATA.matcher(rpcReplyXml).replaceFirst(""); + rpcReplyXml = REGEX_RPC_REPLY_DATA_CLOSE.matcher(rpcReplyXml).replaceFirst(""); + rpcReplyXml = REGEX_RPC_REPLY_DATA_EMPTY.matcher(rpcReplyXml).replaceFirst(""); + rpcReplyXml = REGEX_RPC_REPLY_CLOSE.matcher(rpcReplyXml).replaceFirst(""); + rpcReplyXml = rpcReplyXml.replace("\t", ""); + return rpcReplyXml; + } +} diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java similarity index 62% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java index 4c611437ee..3673594530 100644 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java @@ -15,32 +15,34 @@ */ package org.onosproject.drivers.microsemi.yang.impl; -import static org.onosproject.yms.ych.YangProtocolEncodingFormat.XML; -import static org.onosproject.yms.ydt.YmsOperationType.QUERY_REPLY; - +import java.io.ByteArrayInputStream; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.regex.Pattern; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Service; import org.onosproject.drivers.microsemi.yang.IetfSystemNetconfService; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.IetfSystemMicrosemiService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystem; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystemOpParam; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystemService; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.ietfsystem.systemrestart.SystemRestartInput; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystem; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystemState; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.systemrestart.SystemRestartInput; +import org.onosproject.yang.model.DefaultModelObjectData; +import org.onosproject.yang.model.ModelConverter; +import org.onosproject.yang.model.ModelObject; +import org.onosproject.yang.model.ModelObjectData; +import org.onosproject.yang.runtime.CompositeData; +import org.onosproject.yang.runtime.DefaultCompositeStream; /** * Implementation of the IetfService YANG model service. @@ -50,28 +52,18 @@ import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20 public class IetfSystemManager extends AbstractYangServiceImpl implements IetfSystemNetconfService { - protected final Pattern regexRemoveSystem = - Pattern.compile("()", Pattern.DOTALL); - protected final Pattern regexRemoveSystemState = - Pattern.compile("()", Pattern.DOTALL); - protected static final String IETF_SYSTEM = "org.onosproject.drivers.microsemi.yang.ietfsystem"; @Activate public void activate() { + super.activate(); appId = coreService.registerApplication(IETF_SYSTEM); - ych = ymsService.getYangCodecHandler(); - ych.addDeviceSchema(IetfSystemService.class); - ych.addDeviceSchema(IetfSystemMicrosemiService.class); log.info("IetfSystemManager Started"); } @Deactivate public void deactivate() { super.deactivate(); - ymsService.unRegisterService(this, IetfSystemService.class); - ymsService.unRegisterService(this, IetfSystemMicrosemiService.class); - ych = null; log.info("IetfSystemManager Stopped"); } @@ -85,7 +77,23 @@ public class IetfSystemManager extends AbstractYangServiceImpl @Override public IetfSystem getIetfSystem(IetfSystemOpParam ietfSystemFilter, NetconfSession session) throws NetconfException { - return (IetfSystem) getNetconfObject(ietfSystemFilter, session); + + ModelObjectData moQuery = DefaultModelObjectData.builder() + .addModelObject((ModelObject) ietfSystemFilter.system()) + .build(); + + ModelObjectData moReply = getNetconfObject(moQuery, session); + + IetfSystemOpParam ietfSystem = new IetfSystemOpParam(); + for (ModelObject mo:moReply.modelObjects()) { + if (mo instanceof DefaultSystem) { + ietfSystem.system((DefaultSystem) mo); + } else if (mo instanceof DefaultSystemState) { + ietfSystem.systemState((DefaultSystemState) mo); + } + } + + return ietfSystem; } @Override @@ -96,34 +104,34 @@ public class IetfSystemManager extends AbstractYangServiceImpl String xmlResult = session.get(getInitRequestBuilder(), null); - //The result will be a followed by - //YCH can decode only one at a time - split it and send half each time - IetfSystem.IetfSystemBuilder iBuilder = new IetfSystemOpParam.IetfSystemBuilder(); + xmlResult = removeRpcReplyData(xmlResult); + DefaultCompositeStream resultDcs = new DefaultCompositeStream( + null, new ByteArrayInputStream(xmlResult.getBytes())); + CompositeData compositeData = xSer.decode(resultDcs, yCtx); - String xmlResultSystem = regexRemoveSystemState.matcher(xmlResult).replaceFirst(""); - List objectListState = ych.decode(xmlResultSystem, XML, QUERY_REPLY); - if (objectListState != null && objectListState.size() > 0) { - IetfSystem system = (IetfSystem) objectListState.get(0); - iBuilder.system(system.system()); + ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData()); + + IetfSystemOpParam ietfSystem = new IetfSystemOpParam(); + for (ModelObject mo:mod.modelObjects()) { + if (mo instanceof DefaultSystem) { + ietfSystem.system((DefaultSystem) mo); + } else if (mo instanceof DefaultSystemState) { + ietfSystem.systemState((DefaultSystemState) mo); + } } - String xmlResultSystemState = regexRemoveSystem.matcher(xmlResult).replaceFirst(""); - List objectListSystemState = ych.decode(xmlResultSystemState, XML, QUERY_REPLY); - if (objectListSystemState != null && objectListSystemState.size() > 0) { - IetfSystem system = (IetfSystem) objectListSystemState.get(0); - iBuilder.systemState(system.systemState()); - } - - return iBuilder.build(); + return ietfSystem; } /** * Call NETCONF edit-config with a configuration. */ @Override - public void setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session, TargetConfig ncDs) - throws NetconfException { - setNetconfObject(ietfSystem, session, ncDs); + public boolean setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session, + DatastoreId ncDs) throws NetconfException { + ModelObjectData mo = DefaultModelObjectData.builder() + .addModelObject(ietfSystem).build(); + return setNetconfObject(mo, session, ncDs, null); } @Override diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java similarity index 62% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java index c2359ab092..36f48c4b8a 100644 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java @@ -15,29 +15,29 @@ */ package org.onosproject.drivers.microsemi.yang.impl; -import static org.onosproject.yms.ych.YangProtocolEncodingFormat.XML; -import static org.onosproject.yms.ydt.YmsOperationType.QUERY_REPLY; - -import java.util.List; - import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Service; import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.MseaCfm; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.MseaCfmOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.MseaCfmService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.MseaCfmEventListener; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.soam.fm.rev20160229.MseaSoamFmService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.soam.pm.rev20160229.MseaSoamPmService; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput; +import org.onosproject.yang.model.DefaultModelObjectData; +import org.onosproject.yang.model.ModelConverter; +import org.onosproject.yang.model.ModelObject; +import org.onosproject.yang.model.ModelObjectData; +import org.onosproject.yang.runtime.CompositeData; +import org.onosproject.yang.runtime.DefaultCompositeStream; + +import java.io.ByteArrayInputStream; /** * Implementation of the MseaCfmServiceNetconf YANG model service. @@ -51,21 +51,14 @@ public class MseaCfmManager extends AbstractYangServiceImpl @Activate public void activate() { + super.activate(); appId = coreService.registerApplication(MSEA_CFM); - ych = ymsService.getYangCodecHandler(); - ych.addDeviceSchema(MseaCfmService.class); - ych.addDeviceSchema(MseaSoamFmService.class); - ych.addDeviceSchema(MseaSoamPmService.class); log.info("MseaCfmService Started"); } @Deactivate public void deactivate() { super.deactivate(); - ymsService.unRegisterService(this, MseaCfmService.class); - ymsService.unRegisterService(this, MseaSoamFmService.class); - ymsService.unRegisterService(this, MseaSoamPmService.class); - ych = null; log.info("MseaCfmService Stopped"); } @@ -82,42 +75,38 @@ public class MseaCfmManager extends AbstractYangServiceImpl ":\n" + xmlQueryStr); String xmlResult = session.get(xmlQueryStr, null); - //FIXME Line is removed because YCH decode does not know how to handle it - xmlResult = xmlResult.replaceAll("()(3.3ms|10ms|100ms|1s)()", ""); - xmlResult = xmlResult.replaceAll("()", ""); - List objectList = ych.decode(xmlResult, XML, QUERY_REPLY); - if (objectList != null && objectList.size() > 0) { - Object systemObject = objectList.get(0); - return (MseaCfm) systemObject; - } else { - throw new NetconfException("Failure of YCH decode - could not parse as MseaCfm: " + xmlResult); + xmlResult = removeRpcReplyData(xmlResult); + DefaultCompositeStream resultDcs = new DefaultCompositeStream( + null, new ByteArrayInputStream(xmlResult.getBytes())); + CompositeData compositeData = xSer.decode(resultDcs, yCtx); + + ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData()); + + MseaCfmOpParam mseaCfm = new MseaCfmOpParam(); + for (ModelObject mo:mod.modelObjects()) { + if (mo instanceof DefaultMefCfm) { + mseaCfm.mefCfm((DefaultMefCfm) mo); + } } + + return mseaCfm; } @Override public MseaCfm getSoamDm(String mdName, String maName, int mepId, int dmId, NetconfSession session) throws NetconfException { String xmlQueryStr = buildDmQueryString(mdName, maName, mepId, dmId); - log.debug("Sending for " + - " query on NETCONF session " + session.getSessionId() + - ":\n" + xmlQueryStr); - - String xmlResult = session.get(xmlQueryStr, null); - - List objectList = ych.decode(xmlResult, XML, QUERY_REPLY); - if (objectList != null && objectList.size() > 0) { - Object systemObject = objectList.get(0); - return (MseaCfm) systemObject; - } else { - throw new NetconfException("Failure of YCH decode - could not parse as MseaCfm: " + xmlResult); - } + throw new UnsupportedOperationException("Not yet implemented"); } @Override - public void setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session, TargetConfig targetDs) - throws NetconfException { - setNetconfObject(mseaCfm, session, targetDs); + public boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session, + DatastoreId targetDs) throws NetconfException { + ModelObjectData moEdit = DefaultModelObjectData.builder() + .addModelObject(mseaCfm).build(); + + return setNetconfObject(moEdit, session, targetDs, null); } /** @@ -139,16 +128,6 @@ public class MseaCfmManager extends AbstractYangServiceImpl throw new UnsupportedOperationException("Not yet implemented"); } - @Override - public void addListener(MseaCfmEventListener listener) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - @Override - public void removeListener(MseaCfmEventListener listener) { - throw new UnsupportedOperationException("Not yet implemented"); - } - private String buildMepQueryString(String mdName, String maName, int mepId) { StringBuilder rpc = new StringBuilder(); @@ -162,7 +141,7 @@ public class MseaCfmManager extends AbstractYangServiceImpl rpc.append("\n"); rpc.append("\n"); rpc.append("" + maName + "\n"); -// rpc.append("10ms\n"); //Have to omit for the moment - YMS problem + rpc.append("10ms\n"); rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); @@ -175,7 +154,7 @@ public class MseaCfmManager extends AbstractYangServiceImpl rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); -// rpc.append("\n");//Have to omit for the moment - YMS problem + rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); @@ -202,7 +181,7 @@ public class MseaCfmManager extends AbstractYangServiceImpl rpc.append("\n"); rpc.append("\n"); rpc.append("" + maName + "\n"); -// rpc.append("10ms\n"); //Have to omit for the moment - YMS problem + rpc.append("10ms\n"); rpc.append("\n"); rpc.append("" + mepId + "\n"); rpc.append(""); diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java new file mode 100644 index 0000000000..01af1384f6 --- /dev/null +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java @@ -0,0 +1,202 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi.yang.impl; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService; +import org.onosproject.netconf.DatastoreId; +import org.onosproject.netconf.NetconfException; +import org.onosproject.netconf.NetconfSession; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering; +import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange; +import org.onosproject.yang.model.DefaultModelObjectData; +import org.onosproject.yang.model.ModelConverter; +import org.onosproject.yang.model.ModelObject; +import org.onosproject.yang.model.ModelObjectData; +import org.onosproject.yang.model.ResourceId; +import org.onosproject.yang.runtime.AnnotatedNodeInfo; +import org.onosproject.yang.runtime.CompositeData; +import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo; +import org.onosproject.yang.runtime.DefaultAnnotation; +import org.onosproject.yang.runtime.DefaultCompositeStream; + +import java.io.ByteArrayInputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of the MseaSaFiltering YANG model service. + */ +@Component(immediate = true, inherit = true) +@Service +public class MseaSaFilteringManager extends AbstractYangServiceImpl + implements MseaSaFilteringNetconfService { + public static final String MSEA_SA_FILTERING = + "org.onosproject.drivers.microsemi.yang.mseasafiltering"; + public static final String MSEA_SA_FILTERING_NS = + "http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering"; + + @Activate + public void activate() { + super.activate(); + appId = coreService.registerApplication(MSEA_SA_FILTERING); + log.info("MseaSaFilteringManager Started"); + } + + @Deactivate + public void deactivate() { + super.deactivate(); + log.info("MseaSaFilteringManager Stopped"); + } + + /** + * Get a filtered subset of the model. + * This is meant to filter the current live model + * against the attribute(s) given in the argument + * and return the filtered model. + */ + @Override + public MseaSaFiltering getMseaSaFiltering( + MseaSaFilteringOpParam mseaSaFilteringFilter, NetconfSession session) + throws NetconfException { + ModelObjectData moQuery = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaSaFilteringFilter + .sourceIpaddressFiltering()) + .build(); + + + ModelObjectData moReply = getNetconfObject(moQuery, session); + + MseaSaFiltering reply = new MseaSaFilteringOpParam(); + for (ModelObject mo:moReply.modelObjects()) { + if (mo instanceof SourceIpaddressFiltering) { + reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo); + } + } + return reply; + } + + /** + * Get a filtered subset of the config model (from running) + * This is meant to filter the current live model + * against the attribute(s) given in the argument + * and return the filtered model. + */ + @Override + public List getConfigMseaSaFilterIds(NetconfSession session) + throws NetconfException { + + String xmlResult = session.getConfig(DatastoreId.RUNNING, saFilterQuery()); + xmlResult = removeRpcReplyData(xmlResult); + + DefaultCompositeStream resultDcs = new DefaultCompositeStream( + null, new ByteArrayInputStream(xmlResult.getBytes())); + CompositeData compositeData = xSer.decode(resultDcs, yCtx); + + ModelObjectData moReply = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData()); + + MseaSaFiltering reply = new MseaSaFilteringOpParam(); + for (ModelObject mo:moReply.modelObjects()) { + if (mo instanceof SourceIpaddressFiltering) { + reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo); + } + } + if (reply != null && reply.sourceIpaddressFiltering() != null && + reply.sourceIpaddressFiltering().interfaceEth0() != null) { + return reply.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange(); + } else { + return new ArrayList(); + } + } + + /** + * Call NETCONF edit-config with a configuration. + */ + @Override + public boolean setMseaSaFiltering(MseaSaFilteringOpParam mseaSaFiltering, + NetconfSession session, DatastoreId ncDs) throws NetconfException { + + ModelObjectData moQuery = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaSaFiltering + .sourceIpaddressFiltering()).build(); + + return setNetconfObject(moQuery, session, ncDs, null); + } + + @Override + public boolean deleteMseaSaFilteringRange(MseaSaFilteringOpParam mseaSaFiltering, + NetconfSession session, DatastoreId ncDs) throws NetconfException { + + ModelObjectData moQuery = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaSaFiltering + .sourceIpaddressFiltering()).build(); + + ArrayList anis = new ArrayList(); + if (mseaSaFiltering.sourceIpaddressFiltering().interfaceEth0() != null && + mseaSaFiltering.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange() != null) { + + for (SourceAddressRange sar:mseaSaFiltering.sourceIpaddressFiltering() + .interfaceEth0().sourceAddressRange()) { + String sarRangeIdStr = String.valueOf(sar.rangeId()); + + ResourceId.Builder ridBuilder = ResourceId.builder() + .addBranchPointSchema("/", null) + .addBranchPointSchema("source-ipaddress-filtering", MSEA_SA_FILTERING_NS) + .addBranchPointSchema("interface-eth0", MSEA_SA_FILTERING_NS) + .addBranchPointSchema("source-address-range", MSEA_SA_FILTERING_NS) + .addKeyLeaf("range-id", MSEA_SA_FILTERING_NS, sarRangeIdStr); + + AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder() + .resourceId(ridBuilder.build()) + .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE)) + .build(); + + anis.add(ani); + } + } else { + //Delete all + ResourceId.Builder ridBuilder = ResourceId.builder() + .addBranchPointSchema("/", null) + .addBranchPointSchema("source-ipaddress-filtering", MSEA_SA_FILTERING_NS); + AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder() + .resourceId(ridBuilder.build()) + .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE)) + .build(); + anis.add(ani); + } + + return setNetconfObject(moQuery, session, ncDs, anis); + } + + + private static String saFilterQuery() { + StringBuilder sb = new StringBuilder(""); + sb.append(""); + sb.append("blacklist"); + sb.append(""); + sb.append(""); + sb.append(""); + sb.append(""); + sb.append(""); + return sb.toString(); + } +} diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java similarity index 62% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java index 82b6116b19..f965541885 100644 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java @@ -15,9 +15,7 @@ */ package org.onosproject.drivers.microsemi.yang.impl; -import static org.onosproject.yms.ych.YangProtocolEncodingFormat.XML; -import static org.onosproject.yms.ydt.YmsOperationType.QUERY_CONFIG_REPLY; - +import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -27,13 +25,24 @@ import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Service; import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.netconf.TargetConfig; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceOpParam; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceService; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup; +import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum; +import org.onosproject.yang.model.DefaultModelObjectData; +import org.onosproject.yang.model.ModelConverter; +import org.onosproject.yang.model.ModelObject; +import org.onosproject.yang.model.ModelObjectData; +import org.onosproject.yang.model.ResourceId; +import org.onosproject.yang.runtime.AnnotatedNodeInfo; +import org.onosproject.yang.runtime.CompositeData; +import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo; +import org.onosproject.yang.runtime.DefaultAnnotation; +import org.onosproject.yang.runtime.DefaultCompositeStream; /** * Implementation of the MseaUniEvcServiceService YANG model service. @@ -42,70 +51,127 @@ import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure. @Service public class MseaUniEvcServiceManager extends AbstractYangServiceImpl implements MseaUniEvcServiceNetconfService { - public static final String MSEA_SA_FILTERING = "org.onosproject.drivers.microsemi.yang.mseaunievcservice"; + public static final String MSEA_UNI_EVC_SVC = + "org.onosproject.drivers.microsemi.yang.mseaunievcservice"; + public static final String MSEA_UNI_EVC_SVC_NS = + "http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service"; @Activate public void activate() { - appId = coreService.registerApplication(MSEA_SA_FILTERING); - ych = ymsService.getYangCodecHandler(); - ych.addDeviceSchema(MseaUniEvcServiceService.class); + super.activate(); + appId = coreService.registerApplication(MSEA_UNI_EVC_SVC); log.info("MseaUniEvcServiceManager Started"); } @Deactivate public void deactivate() { super.deactivate(); - ymsService.unRegisterService(this, MseaUniEvcServiceService.class); - ych = null; log.info("MseaUniEvcServiceManager Stopped"); } @Override public MseaUniEvcService getMseaUniEvcService( - MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session) throws NetconfException { - return (MseaUniEvcService) getNetconfObject(mseaUniEvcService, session); + MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session) + throws NetconfException { + + return getConfigMseaUniEvcService(mseaUniEvcService, session, null); } @Override public MseaUniEvcService getConfigMseaUniEvcService( - MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session, TargetConfig targetDs) - throws NetconfException { - return (MseaUniEvcService) getConfigNetconfObject(mseaUniEvcService, session, targetDs); + MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session, + DatastoreId targetDs) throws NetconfException { + + ModelObjectData moFilter = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build(); + + ModelObjectData moReply = getConfigNetconfObject(moFilter, session, targetDs); + + MseaUniEvcService reply = new MseaUniEvcServiceOpParam(); + for (ModelObject mo:moReply.modelObjects()) { + if (mo instanceof MefServices) { + reply.mefServices((MefServices) mo); + } + } + return reply; } /** * Modify the configuration. */ @Override - public void setMseaUniEvcService( - MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session, TargetConfig ncDs) - throws NetconfException { - setNetconfObject(mseaUniEvcService, session, ncDs); + public boolean setMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService, + NetconfSession session, DatastoreId ncDs) throws NetconfException { + ModelObjectData moEdit = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build(); + + return setNetconfObject(moEdit, session, ncDs, null); } + /** + * Delete the configuration. + */ + @Override + public boolean deleteMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService, + NetconfSession session, DatastoreId ncDs) throws NetconfException { + ModelObjectData moEdit = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build(); + + ArrayList anis = new ArrayList(); + for (BwpGroup bwpGrp:mseaUniEvcService.mefServices().profiles().bwpGroup()) { + String bwpGroupIndex = String.valueOf(bwpGrp.groupIndex()); + + ResourceId.Builder ridBuilder = ResourceId.builder() + .addBranchPointSchema("/", null) + .addBranchPointSchema("mef-services", MSEA_UNI_EVC_SVC_NS) + .addBranchPointSchema("profiles", MSEA_UNI_EVC_SVC_NS) + .addBranchPointSchema("bwp-group", MSEA_UNI_EVC_SVC_NS) + .addKeyLeaf("group-index", MSEA_UNI_EVC_SVC_NS, bwpGroupIndex); + + AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder() + .resourceId(ridBuilder.build()) + .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE)) + .build(); + + anis.add(ani); + } + + + return setNetconfObject(moEdit, session, ncDs, anis); + } + + @Override public MseaUniEvcService getmseaUniEvcCeVlanMaps( - NetconfSession session, TargetConfig ncDs) + NetconfSession session, DatastoreId ncDs) throws NetconfException { if (session == null) { throw new NetconfException("Session is null when calling getMseaSaFiltering()"); } String xmlResult = session.getConfig(ncDs, evcFilterQuery()); + xmlResult = removeRpcReplyData(xmlResult); - List objectList = ych.decode(xmlResult, XML, QUERY_CONFIG_REPLY); - if (objectList != null && objectList.size() > 0) { - return (MseaUniEvcService) objectList.get(0); + DefaultCompositeStream resultDcs = new DefaultCompositeStream( + null, new ByteArrayInputStream(xmlResult.getBytes())); + CompositeData compositeData = xSer.decode(resultDcs, yCtx); + + ModelObjectData moReply = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData()); + + MseaUniEvcService reply = new MseaUniEvcServiceOpParam(); + for (ModelObject mo:moReply.modelObjects()) { + if (mo instanceof MefServices) { + reply.mefServices((MefServices) mo); + } } - - return null; + return reply; } @Override public void removeEvcUniFlowEntries( Map ceVlanUpdates, Map> flowVlanIds, - NetconfSession session, TargetConfig targetDs, + NetconfSession session, DatastoreId targetDs, UniSideInterfaceAssignmentEnum portAssign) throws NetconfException { List evcAlreadyHandled = new ArrayList<>(); diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java similarity index 95% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java index 4b706b6915..275dc25c6f 100644 --- a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java @@ -21,7 +21,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20130715.ietfyangtypes.DateAndTime; +import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.DateAndTime; /** * A utility class to change various YANG types to general purpose classes. diff --git a/drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java rename to drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java diff --git a/drivers/microsemi/ea1000driver/src/main/resources/microsemi-drivers.xml b/drivers/microsemi/src/main/resources/microsemi-drivers.xml similarity index 100% rename from drivers/microsemi/ea1000driver/src/main/resources/microsemi-drivers.xml rename to drivers/microsemi/src/main/resources/microsemi-drivers.xml diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java similarity index 100% rename from drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java similarity index 65% rename from drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java index c792b91590..098ecddbd9 100644 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java @@ -31,21 +31,20 @@ import org.onosproject.drivers.microsemi.yang.impl.IetfSystemManager; import org.onosproject.netconf.NetconfDeviceInfo; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.system.AugmentedSysSystem; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.system.rev20160505.ietfsystemmicrosemi.systemstate.platform.AugmentedSysPlatform; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystem; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.IetfSystemOpParam; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.ietfsystem.DefaultSystem; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.ietfsystem.System; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.ietfsystem.system.Clock; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.ietfsystem.system.DefaultClock; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.system.rev20140806.ietfsystem.system.clock.timezone.DefaultTimezoneName; -import org.onosproject.yms.ymsm.YmsService; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.AugmentedSysSystem; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.DefaultAugmentedSysSystem; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.AugmentedSysPlatform; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystem; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.System; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.system.DefaultClock; +import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.system.clock.timezone.DefaultTimezoneName; +import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.DefaultAugmentedSysPlatform; public class IetfSystemManagerTest { IetfSystemManager sysSvc = null; - YmsService ymsService; NetconfSession session; @Before @@ -67,14 +66,11 @@ public class IetfSystemManagerTest { @Test public void testGetIetfSystemSession() throws NetconfException { - Clock.ClockBuilder cBuilder = new DefaultClock.ClockBuilder(); - Clock clock = cBuilder.build(); + System system = new DefaultSystem(); + system.clock(new DefaultClock()); - System.SystemBuilder sBuilder = new DefaultSystem.SystemBuilder(); - System system = sBuilder.clock(clock).build(); - - IetfSystemOpParam.IetfSystemBuilder builder = new IetfSystemOpParam.IetfSystemBuilder(); - IetfSystemOpParam sampleSystem = (IetfSystemOpParam) builder.system(system).build(); + IetfSystemOpParam sampleSystem = new IetfSystemOpParam(); + sampleSystem.system(system); IetfSystem sys = sysSvc.getIetfSystem(sampleSystem, session); assertNotNull(sys); @@ -91,14 +87,14 @@ public class IetfSystemManagerTest { assertNotNull(sys); assertNotNull(sys.system()); - AugmentedSysSystem sysSystem = (AugmentedSysSystem) sys.system().yangAugmentedInfo(AugmentedSysSystem.class); + AugmentedSysSystem sysSystem = (AugmentedSysSystem) sys.system().augmentation(DefaultAugmentedSysSystem.class); assertEquals("-8.4683990", sysSystem.longitude().toPlainString()); assertEquals("51.9036140", sysSystem.latitude().toPlainString()); assertEquals("4.4.0-53-generic", sys.systemState().platform().osRelease()); AugmentedSysPlatform sysSystemState = - (AugmentedSysPlatform) sys.systemState().platform().yangAugmentedInfo(AugmentedSysPlatform.class); + (AugmentedSysPlatform) sys.systemState().platform().augmentation(DefaultAugmentedSysPlatform.class); assertEquals("Eagle Simulator.", sysSystemState.deviceIdentification().serialNumber()); } diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java new file mode 100644 index 0000000000..f035c70318 --- /dev/null +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi.yang; + + +import org.onosproject.drivers.microsemi.yang.impl.IetfSystemManager; +import org.onosproject.yang.MockYangRuntimeManager; +import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry; +import org.onosproject.yang.serializers.xml.MockYangSerializerContext; +import org.onosproject.yang.serializers.xml.XmlSerializer; + +public class MockIetfSystemManager extends IetfSystemManager { + + @Override + public void activate() { + yCtx = new MockYangSerializerContext(); + xSer = new XmlSerializer(); + yangModelRegistry = new MockYangRuntimeManager(); + ((MockYangRuntimeManager) yangModelRegistry).setModelRegistry( + (DefaultYangModelRegistry) yCtx.getContext()); + ((MockYangRuntimeManager) yangModelRegistry).activate(); + } +} diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java new file mode 100644 index 0000000000..fb20697c16 --- /dev/null +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi.yang; + +import org.onosproject.drivers.microsemi.yang.impl.MseaCfmManager; +import org.onosproject.yang.MockYangRuntimeManager; +import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry; +import org.onosproject.yang.serializers.xml.MockYangSerializerContext; +import org.onosproject.yang.serializers.xml.XmlSerializer; + +public class MockMseaCfmManager extends MseaCfmManager { + + @Override + public void activate() { + yCtx = new MockYangSerializerContext(); + xSer = new XmlSerializer(); + yangModelRegistry = new MockYangRuntimeManager(); + ((MockYangRuntimeManager) yangModelRegistry).setModelRegistry( + (DefaultYangModelRegistry) yCtx.getContext()); + ((MockYangRuntimeManager) yangModelRegistry).activate(); + } +} diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java similarity index 53% rename from drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java index 60aae90dc8..a2de18061d 100644 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java @@ -15,27 +15,21 @@ */ package org.onosproject.drivers.microsemi.yang; -import java.io.IOException; -import java.io.UncheckedIOException; - import org.onosproject.drivers.microsemi.yang.impl.MseaSaFilteringManager; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.MseaSaFilteringService; -import org.onosproject.yms.app.yab.MockYmsManager; +import org.onosproject.yang.MockYangRuntimeManager; +import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry; +import org.onosproject.yang.serializers.xml.MockYangSerializerContext; +import org.onosproject.yang.serializers.xml.XmlSerializer; public class MockMseaSaFilteringManager extends MseaSaFilteringManager { @Override public void activate() { - try { - ymsService = new MockYmsManager(); - ych = ymsService.getYangCodecHandler(); - ych.addDeviceSchema(MseaSaFilteringService.class); - } catch (InstantiationException | IllegalAccessException e) { - log.error("Failed to load YMS Manager: " + e.getMessage()); - e.printStackTrace(); - } catch (IOException e) { - log.error("Failed to load YMS Manager: " + e.getMessage()); - throw new UncheckedIOException(e); - } + yCtx = new MockYangSerializerContext(); + xSer = new XmlSerializer(); + yangModelRegistry = new MockYangRuntimeManager(); + ((MockYangRuntimeManager) yangModelRegistry).setModelRegistry( + (DefaultYangModelRegistry) yCtx.getContext()); + ((MockYangRuntimeManager) yangModelRegistry).activate(); } } diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java similarity index 53% rename from drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java index c715e78b2e..e7921c2b8d 100644 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java @@ -15,26 +15,20 @@ */ package org.onosproject.drivers.microsemi.yang; -import java.io.IOException; -import java.io.UncheckedIOException; - import org.onosproject.drivers.microsemi.yang.impl.MseaUniEvcServiceManager; -import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceService; -import org.onosproject.yms.app.yab.MockYmsManager; +import org.onosproject.yang.MockYangRuntimeManager; +import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry; +import org.onosproject.yang.serializers.xml.MockYangSerializerContext; +import org.onosproject.yang.serializers.xml.XmlSerializer; public class MockMseaUniEvcServiceManager extends MseaUniEvcServiceManager { @Override public void activate() { - try { - ymsService = new MockYmsManager(); - ych = ymsService.getYangCodecHandler(); - ych.addDeviceSchema(MseaUniEvcServiceService.class); - } catch (InstantiationException | IllegalAccessException e) { - log.error("Failed to load YMS Manager: " + e.getMessage()); - e.printStackTrace(); - } catch (IOException e) { - log.error("Failed to load YMS Manager: " + e.getMessage()); - throw new UncheckedIOException(e); - } + yCtx = new MockYangSerializerContext(); + xSer = new XmlSerializer(); + yangModelRegistry = new MockYangRuntimeManager(); + ((MockYangRuntimeManager) yangModelRegistry).setModelRegistry( + (DefaultYangModelRegistry) yCtx.getContext()); + ((MockYangRuntimeManager) yangModelRegistry).activate(); } } diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java similarity index 93% rename from drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java index 19a291ed55..fc6da5839e 100644 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java @@ -20,6 +20,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; +import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfDeviceInfo; import org.onosproject.netconf.NetconfDeviceOutputEventListener; import org.onosproject.netconf.NetconfException; @@ -88,17 +89,21 @@ public class MockNetconfSessionEa1000 implements NetconfSession { + "().*().*().*(]]>){2}", Pattern.DOTALL); private Pattern sampleXmlRegexEditDeleteSaFilt = - Pattern.compile("(<\\?xml).*().*" - + "().*().*" + Pattern.compile("(<\\?xml).*()\\R?" + + "()\\R?" + + "()\\R?" + "().*" - + "().*" - + "().*().*().*" - + "().*" - + "().*().*().*" - + "().*" - + "().*().*" - + "().*().*().*(]]>){2}", Pattern.DOTALL); + + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering\">)\\R?" + + "()\\R?" + + "(()\\R?" + + "()[0-9]*()\\R?" + + "(()[a-zA-Z0-9]*())?\\R?" + + "(()[0-9\\\\./]*())?\\R?" + + "())++\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?().*(]]>){2}", Pattern.DOTALL); private Pattern sampleXmlRegexUniEvc = Pattern.compile("(<\\?xml).*()\\R?" @@ -126,18 +131,18 @@ public class MockNetconfSessionEa1000 implements NetconfSession { + "()\\R?().*()\\R?().*()\\R?" + "()\\R?" + "()\\R?" - + "().*()\\R?" - + "().*()\\R?" - + "()\\R?()pushStag()\\R?().*" - + "()\\R?()\\R?" + + "()[0-9]*()\\R?" + + "()[0-9]*()\\R?" + + "()\\R?()pushStag()\\R?" + + "()[0-9]*()\\R?()\\R?" + "(()\\R?" + "()[0-9]*()\\R?" + "()[0-9]*()\\R?" + "()\\R?)*" + "()\\R?" + "()\\R?" - + "().*()\\R?" - + "().*()\\R?" + + "()[0-9\\:\\,]*()\\R?" + + "()[0-9]*()\\R?" + "()\\R?" + "()[0-9]*()\\R?" @@ -146,7 +151,7 @@ public class MockNetconfSessionEa1000 implements NetconfSession { + "()\\R?" + "()\\R?" + "()\\R?" - + "().*" + + "()\\R?" + "()\\R?" + "()\\R?()\\R?()\\R?(]]>){2}", Pattern.DOTALL); @@ -300,9 +305,10 @@ public class MockNetconfSessionEa1000 implements NetconfSession { + "()\\R?" + "()\\R?" + "()\\R?" - + "()\\R?" + + "(()\\R?" + "()[0-9]*()\\R?" - + "()\\R?" + + "(.*)?" + + "())++\\R?" + "()\\R?" + "()\\R?" + "()\\R?()\\R?()\\R?(]]>){2}", Pattern.DOTALL); @@ -328,7 +334,7 @@ public class MockNetconfSessionEa1000 implements NetconfSession { + "()\\R?" + "()\\R?" + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" - // rpc.append("10ms\n"); //Have to omit for the moment - YMS problem + + "()[0-9]{1,3}(ms)\\R?" + "()\\R?" + "()\\R?" + "()\\R?" @@ -341,7 +347,7 @@ public class MockNetconfSessionEa1000 implements NetconfSession { + "()\\R?" + "()\\R?" + "()\\R?" - // rpc.append("\n");//Have to omit for the moment - YMS problem + + "()\\R?" + "()\\R?" + "()\\R?" + "()\\R?" @@ -816,23 +822,9 @@ public class MockNetconfSessionEa1000 implements NetconfSession { return reply; } - @Override - public String getConfig(String targetConfiguration) throws NetconfException { - return getConfig(TargetConfig.valueOf(targetConfiguration), null); - } @Override - public String getConfig(String targetConfiguration, String configurationSchema) throws NetconfException { - return getConfig(TargetConfig.valueOf(targetConfiguration), null); - } - - @Override - public String getConfig(TargetConfig targetConfiguration) throws NetconfException { - return getConfig(targetConfiguration, null); - } - - @Override - public String getConfig(TargetConfig targetConfiguration, String configurationSchema) throws NetconfException { + public String getConfig(DatastoreId targetConfiguration, String configurationSchema) throws NetconfException { StringBuilder rpc = new StringBuilder(XML_HEADER); rpc.append(" evcList = new ArrayList(); + Evc evc1 = new DefaultEvc(); + evc1.evcIndex(1); + evc1.name(new Identifier45("evc-1")); + evc1.evcPerUni(epu1); + + evcList.add(evc1); + + + EvcPerUnin epun2 = new CustomEvcPerUnin(); + epun2.ceVlanMap(ServiceListType.fromString("13")); + epun2.ingressBwpGroupIndex("0"); + + EvcPerUnic epuc2 = new CustomEvcPerUnic(); + epuc2.ceVlanMap(new ServiceListType("12")); + epuc2.ingressBwpGroupIndex("0"); + + EvcPerUni epu2 = new DefaultEvcPerUni(); + epu2.evcPerUnic(epuc2); + epu2.evcPerUnin(epun2); + + Evc evc2 = new DefaultEvc(); + evc2.evcIndex(2); + evc2.name(new Identifier45("evc-2")); + evc2.evcPerUni(epu2); + + evcList.add(evc2); + + Uni uni = new DefaultUni(); + uni.name(new Identifier45("testUni")); + uni.evc(evcList); + + MefServices mefServices = new DefaultMefServices(); + mefServices.uni(uni); + + MseaUniEvcServiceOpParam evcUni = new MseaUniEvcServiceOpParam(); + evcUni.mefServices(mefServices); + try { + mseaUniEvcServiceSvc.setMseaUniEvcService(evcUni, session, DatastoreId.RUNNING); + } catch (NetconfException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Error: " + e.getMessage()); + } + } + + @Test + public void testSetMseaUniEvcServiceMseaUniEvcServiceOpParamProfiles() { + List cosList = new ArrayList(); + Cos cos0 = new DefaultCos(); + cos0.cosIndex(0); + cos0.name("cos0"); + cosList.add(cos0); + + Cos cos1 = new DefaultCos(); + cos1.cosIndex(1); + cos1.name("cos1"); + cosList.add(cos1); + + List bwpGroupList = new ArrayList(); + BwpGroup bwpGrp = new DefaultBwpGroup(); + bwpGrp.groupIndex((short) 0); + bwpGroupList.add(bwpGrp); + + List bwpList = new ArrayList(); + Bwp bwp1 = new DefaultBwp(); + bwp1.cosIndex(0); + bwp1.colorMode(ColorModeEnum.COLORAWARE); + bwpList.add(bwp1); + + Bwp bwp2 = new DefaultBwp(); + bwp2.cosIndex(1); + bwp2.colorMode(ColorModeEnum.COLORBLIND); + bwpList.add(bwp2); + + BwpGroup bwpGrp1 = new DefaultBwpGroup(); + bwpGrp1.groupIndex((short) 1); + bwpGrp1.bwp(bwpList); + bwpGroupList.add(bwpGrp1); + + Profiles profiles = new DefaultProfiles(); + profiles.bwpGroup(bwpGroupList); + + MefServices mefServices = new DefaultMefServices(); + mefServices.profiles(profiles); + + MseaUniEvcServiceOpParam evcUni = new MseaUniEvcServiceOpParam(); + evcUni.mefServices(mefServices); + try { + mseaUniEvcServiceSvc.setMseaUniEvcService(evcUni, session, DatastoreId.RUNNING); + } catch (NetconfException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Error: " + e.getMessage()); + } + } + + @Test + public void testDeleteMseaUniEvcServiceMseaUniEvcServiceOpParamProfiles() { + List cosList = new ArrayList(); + Cos cos0 = new DefaultCos(); + cos0.cosIndex(0); + cos0.name("cos0"); + cosList.add(cos0); + + Cos cos1 = new DefaultCos(); + cos1.cosIndex(1); + cos1.name("cos1"); + cosList.add(cos1); + + List bwpGroupList = new ArrayList(); + BwpGroup bwpGrp = new DefaultBwpGroup(); + bwpGrp.groupIndex((short) 0); + bwpGroupList.add(bwpGrp); + + List bwpList = new ArrayList(); + Bwp bwp1 = new DefaultBwp(); + bwp1.cosIndex(0); + bwp1.colorMode(ColorModeEnum.COLORAWARE); + bwpList.add(bwp1); + + Bwp bwp2 = new DefaultBwp(); + bwp2.cosIndex(1); + bwp2.colorMode(ColorModeEnum.COLORBLIND); + bwpList.add(bwp2); + + BwpGroup bwpGrp1 = new DefaultBwpGroup(); + bwpGrp1.groupIndex((short) 1); + bwpGrp1.bwp(bwpList); + bwpGroupList.add(bwpGrp1); + + Profiles profiles = new DefaultProfiles(); + profiles.bwpGroup(bwpGroupList); + + MefServices mefServices = new DefaultMefServices(); + mefServices.profiles(profiles); + + MseaUniEvcServiceOpParam evcUni = new MseaUniEvcServiceOpParam(); + evcUni.mefServices(mefServices); + try { + mseaUniEvcServiceSvc.deleteMseaUniEvcService(evcUni, session, DatastoreId.RUNNING); + } catch (NetconfException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Error: " + e.getMessage()); + } + } + + @Test + public void testGetMseaUniEvcCeVlanMaps() { + + try { + MseaUniEvcService ceVlanMapsResult7 = + mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING); + + assertNotNull(ceVlanMapsResult7.mefServices().uni().evc()); + + List evcList = ceVlanMapsResult7.mefServices().uni().evc(); + assertEquals(3, evcList.size()); + for (Evc evc : evcList) { + assertNotNull(evc.evcPerUni().evcPerUnic().ceVlanMap()); + assertNotNull(evc.evcPerUni().evcPerUnin().ceVlanMap()); + + if (evc.evcIndex() == 7) { + assertEquals("700,710,720", evc.evcPerUni().evcPerUnic().ceVlanMap().string()); + assertEquals("701:703", evc.evcPerUni().evcPerUnin().ceVlanMap().string()); + } + } + + } catch (NetconfException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Error: " + e.getMessage()); + } + } + + @Test + public void testChangeEvcCeVlanMap() { + EvcPerUnin epun1 = new CustomEvcPerUnin(); + epun1.evcPerUniServiceType(EvcPerUniServiceTypeEnum.EVPL); + epun1.ceVlanMap(ServiceListType.fromString("10")); + epun1.ingressBwpGroupIndex("0"); + + EvcPerUnic epuc1 = new CustomEvcPerUnic(); + epuc1.ceVlanMap(new ServiceListType("11")); + epuc1.ingressBwpGroupIndex("0"); + + EvcPerUni epu = new DefaultEvcPerUni(); + epu.evcPerUnic(epuc1); + epu.evcPerUnin(epun1); + + Evc evc = new DefaultEvc(); + evc.evcPerUni(epu); + + assertEquals("10", evc.evcPerUni().evcPerUnin().ceVlanMap().string()); + assertEquals("11", evc.evcPerUni().evcPerUnic().ceVlanMap().string()); + + assertEquals("11", evc.evcPerUni().evcPerUnic().ceVlanMap().string()); + } + + @Test + public void testChangeEvcCeVlanMapNoValues() { + EvcPerUnin epun1 = new CustomEvcPerUnin(); + epun1.evcPerUniServiceType(EvcPerUniServiceTypeEnum.EVPL); + epun1.ingressBwpGroupIndex("0"); + + EvcPerUnic epuc1 = new CustomEvcPerUnic(); + epuc1.ingressBwpGroupIndex("0"); + + EvcPerUni epu = new DefaultEvcPerUni(); + epu.evcPerUnic(epuc1); + epu.evcPerUnin(epun1); + + Evc evc = new DefaultEvc(); + evc.evcIndex(1); + evc.evcPerUni(epu); + + assertEquals("0", evc.evcPerUni().evcPerUnin().ceVlanMap().string()); + assertEquals("0", evc.evcPerUni().evcPerUnic().ceVlanMap().string()); + } + + @Test + public void testRemoveEvcUniFlowEntries() { + + Map ceVlanUpdates = new TreeMap<>(); + ceVlanUpdates.put((1 << 2), ""); + ceVlanUpdates.put((1 << 2) + 1, ""); + ceVlanUpdates.put((2 << 2), ""); + ceVlanUpdates.put((2 << 2) + 1, ""); + + ceVlanUpdates.put((7 << 2), "700,710,720"); + ceVlanUpdates.put((7 << 2) + 1, "701:703"); + ceVlanUpdates.put((8 << 2), "800,810,820"); + ceVlanUpdates.put((8 << 2) + 1, "801,802,803"); + + Map> flowVlanIdMap = new HashMap<>(); + //These should get ignored because whole EVC is being deleted + flowVlanIdMap.put(1 << 2, new ArrayList()); + flowVlanIdMap.get(1 << 2).add((short) 11); + + flowVlanIdMap.put((1 << 2) + 1, new ArrayList()); + flowVlanIdMap.get((1 << 2) + 1).add((short) 12L); + + //These are the EVCs being removed + flowVlanIdMap.put(7 << 2, new ArrayList()); + flowVlanIdMap.get(7 << 2).add((short) 730L); + flowVlanIdMap.get(7 << 2).add((short) 740L); + + flowVlanIdMap.put((7 << 2) + 1, new ArrayList()); + flowVlanIdMap.get((7 << 2) + 1).add((short) 705L); + flowVlanIdMap.get((7 << 2) + 1).add((short) 706L); + + flowVlanIdMap.put(8 << 2, new ArrayList()); + flowVlanIdMap.get(8 << 2).add((short) 830L); + flowVlanIdMap.get(8 << 2).add((short) 840L); + + flowVlanIdMap.put((8 << 2) + 1, new ArrayList()); + flowVlanIdMap.get((8 << 2) + 1).add((short) 805L); + flowVlanIdMap.get((8 << 2) + 1).add((short) 806L); + + try { + mseaUniEvcServiceSvc.removeEvcUniFlowEntries( + ceVlanUpdates, flowVlanIdMap, session, DatastoreId.RUNNING, + UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS); + } catch (NetconfException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Error: " + e.getMessage()); + } + } + + @Test + public void testGetVlanSet1() { + Short[] vlanIds = CeVlanMapUtils.getVlanSet("10"); + assertEquals(1, vlanIds.length); + } + + @Test + public void testGetVlanSet2() { + Short[] vlanIds = CeVlanMapUtils.getVlanSet("10:20"); + assertEquals(11, vlanIds.length); + assertEquals(10, vlanIds[0].shortValue()); + assertEquals(20, vlanIds[10].shortValue()); + } + + @Test + public void testGetVlanSet3() { + Short[] vlanIds = CeVlanMapUtils.getVlanSet("10:20,30:40"); + assertEquals(22, vlanIds.length); + assertEquals(10, vlanIds[0].shortValue()); + assertEquals(40, vlanIds[21].shortValue()); + } + + @Test + public void testGetVlanSet4() { + Short[] vlanIds = CeVlanMapUtils.getVlanSet("10,20,30"); + assertEquals(3, vlanIds.length); + assertEquals(10, vlanIds[0].shortValue()); + assertEquals(30, vlanIds[2].shortValue()); + } + + @Test + public void testVlanListAsString() { + assertEquals("20:22", CeVlanMapUtils.vlanListAsString(new Short[]{20, 21, 22})); + + assertEquals("20:22,24:25", + CeVlanMapUtils.vlanListAsString(new Short[]{20, 21, 22, 24, 25})); + + assertEquals("30,33,36:40", + CeVlanMapUtils.vlanListAsString(new Short[]{30, 33, 36, 37, 38, 39, 40})); + + assertEquals("20", CeVlanMapUtils.vlanListAsString(new Short[]{20})); + + assertEquals("20,22,24,26,28", + CeVlanMapUtils.vlanListAsString(new Short[]{20, 22, 24, 26, 28})); + } + + @Test + public void testAddtoCeVlanMap() { + assertEquals("20,22:24,26,28", + CeVlanMapUtils.addtoCeVlanMap("20,22,24,26,28", (short) 23)); + + assertEquals("20:26,28", + CeVlanMapUtils.addtoCeVlanMap("20,21,22,24,25,26,28", (short) 23)); + + assertEquals("20,23", + CeVlanMapUtils.addtoCeVlanMap("20", (short) 23)); + + assertEquals("20,22:23", + CeVlanMapUtils.addtoCeVlanMap("20,22", (short) 23)); + } + + @Test + public void testCombineVlanSets() { + assertEquals("10:11,13:14", CeVlanMapUtils.combineVlanSets("10:11", "13:14")); + + assertEquals("10:14", CeVlanMapUtils.combineVlanSets("10:11", "12:14")); + + assertEquals("10:11,14", CeVlanMapUtils.combineVlanSets("10:11", "14")); + + assertEquals("10:12", CeVlanMapUtils.combineVlanSets("10:11", "11:12")); + } + + @Test + public void testRemoveZeroIfPossible() { + assertEquals("0", CeVlanMapUtils.removeZeroIfPossible("")); + + assertEquals("0", CeVlanMapUtils.removeZeroIfPossible("0")); + + assertEquals("1,3", CeVlanMapUtils.removeZeroIfPossible("0:1,3")); + + assertEquals("1:2", CeVlanMapUtils.removeZeroIfPossible("0:2")); + + assertEquals("10:12", CeVlanMapUtils.removeZeroIfPossible("0,10:12")); + } +} diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/package-info.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/package-info.java similarity index 100% rename from drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/package-info.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/package-info.java diff --git a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java similarity index 95% rename from drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java rename to drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java index 4e62beb829..da0954f983 100644 --- a/drivers/microsemi/ea1000yang/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java @@ -26,7 +26,7 @@ import java.time.ZonedDateTime; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20130715.ietfyangtypes.DateAndTime; +import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.DateAndTime; public class IetfYangTypesUtilsTest { diff --git a/drivers/microsemi/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java b/drivers/microsemi/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java new file mode 100644 index 0000000000..e2f4389dda --- /dev/null +++ b/drivers/microsemi/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java @@ -0,0 +1,152 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.yang; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onosproject.core.CoreService; +import org.onosproject.drivers.netconf.MockCoreService; +import org.onosproject.yang.model.ModelConverter; +import org.onosproject.yang.model.ModelObjectData; +import org.onosproject.yang.model.NodeKey; +import org.onosproject.yang.model.ResourceData; +import org.onosproject.yang.model.ResourceId; +import org.onosproject.yang.model.SchemaContext; +import org.onosproject.yang.model.SchemaContextProvider; +import org.onosproject.yang.model.YangModel; +import org.onosproject.yang.runtime.CompositeData; +import org.onosproject.yang.runtime.CompositeStream; +import org.onosproject.yang.runtime.ModelRegistrationParam; +import org.onosproject.yang.runtime.RuntimeContext; +import org.onosproject.yang.runtime.YangModelRegistry; +import org.onosproject.yang.runtime.YangRuntimeService; +import org.onosproject.yang.runtime.YangSerializer; +import org.onosproject.yang.runtime.YangSerializerRegistry; +import org.onosproject.yang.runtime.impl.DefaultModelConverter; +import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry; +import org.onosproject.yang.runtime.impl.DefaultYangRuntimeHandler; +import org.onosproject.yang.runtime.impl.DefaultYangSerializerRegistry; +import org.onosproject.yang.serializers.json.JsonSerializer; +import org.onosproject.yang.serializers.xml.XmlSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class MockYangRuntimeManager implements YangModelRegistry, + YangSerializerRegistry, YangRuntimeService, ModelConverter, + SchemaContextProvider { + + private static final String APP_ID = "org.onosproject.yang"; + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + private DefaultYangModelRegistry modelRegistry; + private DefaultYangSerializerRegistry serializerRegistry; + private DefaultYangRuntimeHandler runtimeService; + private DefaultModelConverter modelConverter; + + public void setModelRegistry(DefaultYangModelRegistry yReg) { + this.modelRegistry = yReg; + } + + @Activate + public void activate() { + coreService = new MockCoreService(); + coreService.registerApplication(APP_ID); + serializerRegistry = new DefaultYangSerializerRegistry(); + runtimeService = + new DefaultYangRuntimeHandler(serializerRegistry, modelRegistry); + serializerRegistry.registerSerializer(new JsonSerializer()); + serializerRegistry.registerSerializer(new XmlSerializer()); + modelConverter = new DefaultModelConverter(modelRegistry); + log.info("Started"); + } + + @Deactivate + public void deactivate() { + log.info("Stopped"); + } + + + @Override + public void registerModel(ModelRegistrationParam p) { + modelRegistry.registerModel(p); + } + + @Override + public void unregisterModel(ModelRegistrationParam p) { + modelRegistry.unregisterModel(p); + } + + @Override + public Set getModels() { + return modelRegistry.getModels(); + } + + @Override + public void registerSerializer(YangSerializer ys) { + serializerRegistry.registerSerializer(ys); + } + + @Override + public void unregisterSerializer(YangSerializer ys) { + serializerRegistry.unregisterSerializer(ys); + } + + @Override + public Set getSerializers() { + return serializerRegistry.getSerializers(); + } + + @Override + public CompositeData decode(CompositeStream cs, RuntimeContext rc) { + return runtimeService.decode(cs, rc); + } + + @Override + public CompositeStream encode(CompositeData cd, RuntimeContext rc) { + return runtimeService.encode(cd, rc); + } + + @Override + public ModelObjectData createModel(ResourceData resourceData) { + return modelConverter.createModel(resourceData); + } + + @Override + public ResourceData createDataNode(ModelObjectData modelObjectData) { + return modelConverter.createDataNode(modelObjectData); + } + + @Override + public SchemaContext getSchemaContext(ResourceId resourceId) { + checkNotNull(resourceId, " resource id can't be null."); + NodeKey key = resourceId.nodeKeys().get(0); + if (resourceId.nodeKeys().size() == 1 && + "/".equals(key.schemaId().name())) { + return modelRegistry; + } + log.info("To be implemented."); + return null; + } +} diff --git a/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java b/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java new file mode 100644 index 0000000000..dab269d84c --- /dev/null +++ b/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java @@ -0,0 +1,138 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.yang.serializers.xml; + + +import org.onosproject.yang.compiler.datamodel.YangNode; +import org.onosproject.yang.compiler.datamodel.YangSchemaNode; +import org.onosproject.yang.model.YangModel; +import org.onosproject.yang.runtime.AppModuleInfo; +import org.onosproject.yang.runtime.DefaultAppModuleInfo; +import org.onosproject.yang.runtime.DefaultModelRegistrationParam; +import org.onosproject.yang.runtime.ModelRegistrationParam; +import org.onosproject.yang.runtime.YangModelRegistry; +import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.onosproject.yang.compiler.datamodel.utils.DataModelUtils; +import org.onosproject.yang.compiler.utils.UtilConstants; +import org.onosproject.yang.compiler.utils.io.impl.YangIoUtils; +import org.onosproject.yang.runtime.helperutils.YangApacheUtils; +import org.onosproject.yang.runtime.RuntimeHelper; + +public class MockYangSchemaNodeProvider { + + private static final String FS = File.separator; + private static final String PATH = System.getProperty("user.dir") + + FS + "buck-out" + FS + "gen" + + FS + "models" + FS + "microsemi" + FS + "onos-models-microsemi-schema" + FS; + private static final String SER_FILE_PATH = "yang" + FS + "resources" + + FS + "YangMetaData.ser"; + private static final String META_PATH = + PATH.replace("drivers/microsemi", "") + + SER_FILE_PATH; + private static final String TEMP_FOLDER_PATH = PATH + UtilConstants.TEMP; + private YangModelRegistry reg = new DefaultYangModelRegistry(); + private List nodes = new ArrayList<>(); + + /** + * Creates an instance of mock bundle context. + */ + public MockYangSchemaNodeProvider() { + } + + /** + * Process YANG schema node for a application. + */ + public void processSchemaRegistry() { + try { + //Need to deserialize generated meta data file for unit tests. + Set appNode = DataModelUtils.deSerializeDataModel(META_PATH); + RuntimeHelper.addLinkerAndJavaInfo(appNode); + nodes.addAll(appNode); + reg.registerModel(prepareParam(nodes)); + YangIoUtils.deleteDirectory(TEMP_FOLDER_PATH); + } catch (IOException e) { + throw new IllegalArgumentException("YangMetaData.ser could not " + + "be loaded from " + META_PATH, e); + } + } + + /** + * Unregister given nodes from runtime service. + * + * @param nodes list of nodes + */ + public void unRegister(List nodes) { + reg.unregisterModel(prepareParam(nodes)); + } + + /** + * Prepares model registration parameter. + * + * @param nodes list of nodes + * @return model registration parameter + */ + private ModelRegistrationParam prepareParam(List nodes) { + //Process loading class file. + String appName; + ClassLoader classLoader = getClass().getClassLoader(); + + //Create model registration param. + ModelRegistrationParam.Builder b = + DefaultModelRegistrationParam.builder(); + + //create a new YANG model + YangModel model = YangApacheUtils.processYangModel(META_PATH, nodes); + //set YANG model + b.setYangModel(model); + + Iterator it = nodes.iterator(); + while (it.hasNext()) { + YangSchemaNode node = it.next(); + + //If service class is not generated then use + // interface file to load this class. + appName = RuntimeHelper.getInterfaceClassName(node); + Class cls; + try { + cls = classLoader.loadClass(appName); + } catch (ClassNotFoundException e) { + continue; + } + + //generate app info. + AppModuleInfo info = new DefaultAppModuleInfo(cls, null); + b.addAppModuleInfo(YangApacheUtils.processModuleId((YangNode) node), info); + } + return b.build(); + } + + /** + * Returns schema registry. + * + * @return schema registry + */ + public DefaultYangModelRegistry registry() { + return (DefaultYangModelRegistry) reg; + } +} diff --git a/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java b/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java new file mode 100644 index 0000000000..cfe7b9bd58 --- /dev/null +++ b/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.yang.serializers.xml; + +import org.onosproject.yang.model.SchemaContext; +import org.onosproject.yang.runtime.Annotation; +import org.onosproject.yang.runtime.DefaultAnnotation; +import org.onosproject.yang.runtime.YangSerializerContext; +import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry; + +import java.util.LinkedList; +import java.util.List; + +public class MockYangSerializerContext implements YangSerializerContext { + + private static MockYangSchemaNodeProvider schemaProvider = + new MockYangSchemaNodeProvider(); + private static final String NETCONF_NS = + "urn:ietf:params:xml:ns:netconf:base:1.0"; + private static final String XMNLS_NC = "xmlns:xc"; + + + @Override + public SchemaContext getContext() { + schemaProvider.processSchemaRegistry(); + DefaultYangModelRegistry registry = schemaProvider.registry(); + return registry; + } + + @Override + public List getProtocolAnnotations() { + Annotation annotation = new DefaultAnnotation(XMNLS_NC, NETCONF_NS); + List protocolAnnotation = new LinkedList<>(); + protocolAnnotation.add(annotation); + return protocolAnnotation; + } +} diff --git a/drivers/microsemi/ea1000driver/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt b/drivers/microsemi/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt rename to drivers/microsemi/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt diff --git a/drivers/microsemi/ea1000driver/src/test/resources/getConfigSaFiltering.xml b/drivers/microsemi/src/test/resources/getConfigSaFiltering.xml similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/resources/getConfigSaFiltering.xml rename to drivers/microsemi/src/test/resources/getConfigSaFiltering.xml diff --git a/drivers/microsemi/ea1000driver/src/test/resources/getConfigSaFilteringReply.xml b/drivers/microsemi/src/test/resources/getConfigSaFilteringReply.xml similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/resources/getConfigSaFilteringReply.xml rename to drivers/microsemi/src/test/resources/getConfigSaFilteringReply.xml diff --git a/drivers/microsemi/ea1000driver/src/test/resources/systemReply-Sample1.xml b/drivers/microsemi/src/test/resources/systemReply-Sample1.xml similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/resources/systemReply-Sample1.xml rename to drivers/microsemi/src/test/resources/systemReply-Sample1.xml diff --git a/drivers/microsemi/ea1000driver/src/test/resources/systemReply-Sample2.xml b/drivers/microsemi/src/test/resources/systemReply-Sample2.xml similarity index 100% rename from drivers/microsemi/ea1000driver/src/test/resources/systemReply-Sample2.xml rename to drivers/microsemi/src/test/resources/systemReply-Sample2.xml diff --git a/drivers/pom.xml b/drivers/pom.xml index f4e9a80fce..8d0737f475 100644 --- a/drivers/pom.xml +++ b/drivers/pom.xml @@ -47,7 +47,6 @@ juniper lisp flowspec - microsemi oplink hp diff --git a/models/microsemi/BUCK b/models/microsemi/BUCK new file mode 100644 index 0000000000..58b84129dd --- /dev/null +++ b/models/microsemi/BUCK @@ -0,0 +1,4 @@ +yang_model( + app_name = 'org.onosproject.models.microsemi', + title = 'Microsemi YANG Model', +) diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ENTITY-STATE-TC-MIB.yang b/models/microsemi/src/main/yang/ENTITY-STATE-TC-MIB.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ENTITY-STATE-TC-MIB.yang rename to models/microsemi/src/main/yang/ENTITY-STATE-TC-MIB.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/fpga-internal.yang b/models/microsemi/src/main/yang/fpga-internal.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/fpga-internal.yang rename to models/microsemi/src/main/yang/fpga-internal.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/iana-crypt-hash.yang b/models/microsemi/src/main/yang/iana-crypt-hash.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/iana-crypt-hash.yang rename to models/microsemi/src/main/yang/iana-crypt-hash.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/iana-if-type.yang b/models/microsemi/src/main/yang/iana-if-type.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/iana-if-type.yang rename to models/microsemi/src/main/yang/iana-if-type.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ieee-types.yang b/models/microsemi/src/main/yang/ieee-types.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ieee-types.yang rename to models/microsemi/src/main/yang/ieee-types.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-inet-types.yang b/models/microsemi/src/main/yang/ietf-inet-types.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-inet-types.yang rename to models/microsemi/src/main/yang/ietf-inet-types.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-interfaces.yang b/models/microsemi/src/main/yang/ietf-interfaces.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-interfaces.yang rename to models/microsemi/src/main/yang/ietf-interfaces.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf-acm.yang b/models/microsemi/src/main/yang/ietf-netconf-acm.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf-acm.yang rename to models/microsemi/src/main/yang/ietf-netconf-acm.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf-monitoring.yang b/models/microsemi/src/main/yang/ietf-netconf-monitoring.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf-monitoring.yang rename to models/microsemi/src/main/yang/ietf-netconf-monitoring.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf-notifications.yang b/models/microsemi/src/main/yang/ietf-netconf-notifications.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf-notifications.yang rename to models/microsemi/src/main/yang/ietf-netconf-notifications.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf-with-defaults.yang b/models/microsemi/src/main/yang/ietf-netconf-with-defaults.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf-with-defaults.yang rename to models/microsemi/src/main/yang/ietf-netconf-with-defaults.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf.yang b/models/microsemi/src/main/yang/ietf-netconf.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-netconf.yang rename to models/microsemi/src/main/yang/ietf-netconf.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-system-microsemi.yang b/models/microsemi/src/main/yang/ietf-system-microsemi.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-system-microsemi.yang rename to models/microsemi/src/main/yang/ietf-system-microsemi.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-system-tls-auth.yang b/models/microsemi/src/main/yang/ietf-system-tls-auth.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-system-tls-auth.yang rename to models/microsemi/src/main/yang/ietf-system-tls-auth.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-system.yang b/models/microsemi/src/main/yang/ietf-system.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-system.yang rename to models/microsemi/src/main/yang/ietf-system.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-x509-cert-to-name.yang b/models/microsemi/src/main/yang/ietf-x509-cert-to-name.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-x509-cert-to-name.yang rename to models/microsemi/src/main/yang/ietf-x509-cert-to-name.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/ietf-yang-types.yang b/models/microsemi/src/main/yang/ietf-yang-types.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/ietf-yang-types.yang rename to models/microsemi/src/main/yang/ietf-yang-types.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/msea-cfm.yang b/models/microsemi/src/main/yang/msea-cfm.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/msea-cfm.yang rename to models/microsemi/src/main/yang/msea-cfm.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/msea-sa-filtering.yang b/models/microsemi/src/main/yang/msea-sa-filtering.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/msea-sa-filtering.yang rename to models/microsemi/src/main/yang/msea-sa-filtering.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/msea-soam-fm.yang b/models/microsemi/src/main/yang/msea-soam-fm.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/msea-soam-fm.yang rename to models/microsemi/src/main/yang/msea-soam-fm.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/msea-soam-pm.yang b/models/microsemi/src/main/yang/msea-soam-pm.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/msea-soam-pm.yang rename to models/microsemi/src/main/yang/msea-soam-pm.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/msea-types.yang b/models/microsemi/src/main/yang/msea-types.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/msea-types.yang rename to models/microsemi/src/main/yang/msea-types.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/msea-uni-evc-interface.yang b/models/microsemi/src/main/yang/msea-uni-evc-interface.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/msea-uni-evc-interface.yang rename to models/microsemi/src/main/yang/msea-uni-evc-interface.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/msea-uni-evc-service.yang b/models/microsemi/src/main/yang/msea-uni-evc-service.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/msea-uni-evc-service.yang rename to models/microsemi/src/main/yang/msea-uni-evc-service.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/nc-notifications.yang b/models/microsemi/src/main/yang/nc-notifications.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/nc-notifications.yang rename to models/microsemi/src/main/yang/nc-notifications.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/netopeer-cfgnetopeer.yang b/models/microsemi/src/main/yang/netopeer-cfgnetopeer.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/netopeer-cfgnetopeer.yang rename to models/microsemi/src/main/yang/netopeer-cfgnetopeer.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/notifications.yang b/models/microsemi/src/main/yang/notifications.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/notifications.yang rename to models/microsemi/src/main/yang/notifications.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/rfc-2544.yang b/models/microsemi/src/main/yang/rfc-2544.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/rfc-2544.yang rename to models/microsemi/src/main/yang/rfc-2544.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/svc-activation-types.yang b/models/microsemi/src/main/yang/svc-activation-types.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/svc-activation-types.yang rename to models/microsemi/src/main/yang/svc-activation-types.yang diff --git a/drivers/microsemi/ea1000yang/src/main/yang/y-1564.yang b/models/microsemi/src/main/yang/y-1564.yang similarity index 100% rename from drivers/microsemi/ea1000yang/src/main/yang/y-1564.yang rename to models/microsemi/src/main/yang/y-1564.yang diff --git a/modules.defs b/modules.defs index 8205c93ae8..0ad980cbb3 100644 --- a/modules.defs +++ b/modules.defs @@ -107,8 +107,7 @@ ONOS_DRIVERS = [ '//drivers/lisp:onos-drivers-lisp-oar', '//drivers/flowspec:onos-drivers-flowspec-oar', '//drivers/huawei:onos-drivers-huawei-oar', -# Removed until we can handle v1.12 of onos-yang-tools - in the mean time build manually with Maven -# '//drivers/microsemi/ea1000driver:onos-drivers-microsemi-ea1000driver-oar', + '//drivers/microsemi:onos-drivers-microsemi-oar', '//drivers/oplink:onos-drivers-oplink-oar', '//drivers/bmv2:onos-drivers-bmv2-oar', '//drivers/hp:onos-drivers-hp-oar', @@ -218,6 +217,7 @@ MODELS = [ '//models/huawei:onos-models-huawei-oar', '//models/openroadm:onos-models-openroadm-oar', '//models/l3vpn:onos-models-l3vpn-oar', + '//models/microsemi:onos-models-microsemi-oar' ] APP_JARS = [