From 641a6c47b4ee74412e9386b3c95693adda3cafc9 Mon Sep 17 00:00:00 2001 From: cschowdam Date: Tue, 7 Jul 2020 13:43:16 +0000 Subject: [PATCH] VES Heartbeat and Software Management Feature Code changes to support VES Heartbeat and Software Management Feature in tr069 adapter. docker tag change to latest Issue-Id: OAM-127 Change-Id: Ib8aeba0e73f13d73064e7c0dca0274a26007f1a7 Signed-off-by: cschowdam --- acs/application-booter/pom.xml | 4 +- .../tr069adapter/acs/booter/ACSServiceBooter.java | 32 +- .../src/main/resources/log4j2.xml | 56 +- .../src/main/resources/schema-mariadb.sql | 54 +- .../src/test/resources/log4j2.xml | 104 + acs/common/pom.xml | 10 +- .../tr069adapter/acs/common/DeviceDetails.java | 20 + .../tr069adapter/acs/common/DeviceRPCRequest.java | 27 +- .../acs/common/dto/TR069DeviceDetails.java | 20 - .../config/ErrorMessages_tr069.properties | 4 +- acs/cpe/pom.xml | 114 +- acs/nbi/pom.xml | 102 +- acs/pom.xml | 38 +- acs/requestprocessor/pom.xml | 118 +- .../custom/ConfigureMultipleObject.java | 13 +- .../handler/DeviceRPCRequestHandler.java | 5 + .../helper/TR069RequestProcessEngineHelper.java | 2 +- .../impl/TR069EventNotificationService.java | 19 +- .../impl/TR069RequestProcessEngine.java | 68 +- .../util/TR069RequestProcessorUtility.java | 2 + .../common/scheduler/ExecutionContext.java | 2 +- config-data/pom.xml | 7 +- .../controllers/ConfugurationDataController.java | 2 +- .../config/parser/ConfigurationXMLDataParser.java | 11 +- .../config/service/ConfigurationDataService.java | 2 +- config-data/src/main/resources/log4j2.xml | 200 +- config-data/src/main/resources/schema-mariadb.sql | 8 +- .../src/main/resources/xsd/ConfigurationData.xsd | 5482 ++++++++++---------- .../config/ConfigDataApplicationTests.java | 2 +- config-data/src/test/resources/log4j2.xml | 109 + db/pom.xml | 4 +- factory/pom.xml | 4 +- factory/src/main/resources/log4j2.xml | 90 +- factory/src/test/resources/application.properties | 19 + factory/src/test/resources/log4j2.xml | 76 + mapper/Dockerfile | 4 + mapper/mapper-schema/CustomYangModelMOmapping.txt | 4 + mapper/pom.xml | 21 +- mapper/rpc_set_input.xml | 9 + .../mapper/MapperConfigProperties.java | 11 + .../org/commscope/tr069adapter/mapper/Test.java | 42 + .../acs/impl/ACSNotificationHandlerImpl.java | 138 + .../mapper/acs/impl/PnPPreProvisioningHandler.java | 18 +- .../mapper/boot/MapperServiceBooter.java | 4 + .../mapper/dao/DeviceOperationsDAO.java | 11 + .../mapper/entity/DeviceOperationDetails.java | 72 + .../mapper/model/NetConfNotificationDTO.java | 72 + .../tr069adapter/mapper/model/VESNotification.java | 10 + .../mapper/netconf/NetConfNotificationSender.java | 31 +- .../mapper/netconf/NetConfRequestHandler.java | 3 + .../netconf/controller/NetConfRequestReceiver.java | 3 +- .../netconf/impl/NetConfRequestHandlerImpl.java | 318 +- .../tr069adapter/mapper/util/ErrorCodeUtil.java | 15 +- .../mapper/util/FirwareUpgradeErrorCode.java | 25 + .../mapper/util/FirwareUpgradeStatus.java | 16 + .../tr069adapter/mapper/util/MOMetaDataUtil.java | 88 +- .../tr069adapter/mapper/util/MapperConstants.java | 18 + .../tr069adapter/mapper/util/MapperValidator.java | 34 + .../mapper/util/NetconfToTr069MapperUtil.java | 220 +- .../mapper/ves/VESNotificationSender.java | 15 + .../tr069adapter/mapper/ves/VesRequestHandler.java | 9 + .../mapper/ves/VesRequestReceiver.java | 29 + .../mapper/ves/impl/VesRequestHandlerImpl.java | 67 + mapper/src/main/resources/application.properties | 11 + mapper/src/main/resources/log4j2.xml | 60 +- mapper/src/main/resources/schema-mariadb.sql | 1 + .../mapper/NetconfToTr069MapperUtilTest.java | 6 +- mapper/src/test/resources/application.properties | 9 + mapper/src/test/resources/log4j2.xml | 104 + netconf-server/Dockerfile | 3 +- netconf-server/pom.xml | 2 +- netconf-server/schemas/bbf-tr-196-2-0-3-full.yang | 2 +- netconf-server/schemas/iana-hardware.yang | 180 + netconf-server/schemas/ietf-crypto-types.yang | 1783 +++++++ netconf-server/schemas/ietf-hardware.yang | 1141 ++++ netconf-server/schemas/ietf-inet-types.yang | 429 ++ netconf-server/schemas/ietf-netconf-acm.yang | 440 ++ .../schemas/ietf-netconf-monitoring-extension.yang | 31 + .../schemas/ietf-netconf-monitoring.yang | 596 +++ netconf-server/schemas/ietf-yang-types.yang | 435 ++ netconf-server/schemas/o-ran-file-management.yang | 213 + netconf-server/schemas/o-ran-hardware.yang | 271 + .../schemas/o-ran-heartbeat-management.yang | 64 + .../schemas/o-ran-software-management.yang | 595 +++ .../schemas/tr-181-2-12-0-cwmp-full.yang | 2 +- .../netconf/config/NetConfServerProperties.java | 17 +- .../netconf/notification/NetConfSessionUtil.java | 104 +- .../netconf/notification/NotificationHandler.java | 8 +- .../restapi/NetConfServerManagerRestApi.java | 12 +- .../restapi/NotificationReceiverService.java | 31 +- .../netconf/rpc/SoftwareDownloadOperation.java | 57 +- .../tr069adapter/netconf/rpc/XmlUtility.java | 1 + .../netconf/server/NetConfServerManagerImpl.java | 222 +- .../netconf/server/NetconfServerStarter.java | 27 +- .../server/RestartNetconfServerHandler.java | 24 +- .../server/helper/ServerPortAllocationHelper.java | 18 + .../server/utils/NetConfServerConstants.java | 10 + .../netconf/server/ves/VESNotificationSender.java | 30 + .../src/main/resources/application.properties | 1 + netconf-server/src/main/resources/log4j2.xml | 14 +- .../restapi/NotificationServerRestApiTest.java | 20 +- .../server/RestartNetconfServerHandlerTest.java | 40 +- netconf-server/src/test/resources/log4j2.xml | 86 + pom.xml | 4 +- ves-agent/Dockerfile | 7 + ves-agent/pom.xml | 24 +- .../tr069adapter/vesagent/VesConfiguration.java | 20 + .../vesagent/async/AsyncRequestHandler.java | 143 + .../vesagent/async/AsyncThreadPoolConfig.java | 36 + .../vesagent/async/WaitForNotifications.java | 100 + .../vesagent/boot/VESAgentServiceBooter.java | 4 + .../vesagent/controller/AlarmMappingHandler.java | 14 +- .../controller/HeartBeatMessageHandler.java | 182 +- .../vesagent/controller/PnfRegMappingHandler.java | 25 +- .../vesagent/controller/VESAgentService.java | 46 +- .../vesagent/entity/DeviceDataEntity.java | 137 + .../vesagent/exception/VesAgentException.java | 81 + .../vesagent/mapper/MapperRequestSender.java | 46 + .../vesagent/model/HeartbeatFields.java | 30 +- .../vesagent/repository/VesDataRepository.java | 24 + .../vesagent/service/VesAgentServiceHelper.java | 303 ++ .../vesagent/timer/HeartBeatTimeoutTask.java | 80 + .../vesagent/timer/ScheduleConfig.java | 24 + .../tr069adapter/vesagent/timer/ScheduleInfo.java | 32 + .../vesagent/timer/ScheduleTaskService.java | 66 + .../tr069adapter/vesagent/timer/ServiceConfig.java | 28 + .../vesagent/timer/StartupTimerService.java | 68 + .../tr069adapter/vesagent/util/EventUtil.java | 41 + .../vesagent/util/VesAgentConstants.java | 34 + .../tr069adapter/vesagent/util/VesAgentUtils.java | 168 + .../src/main/resources/application.properties | 19 +- ves-agent/src/main/resources/log4j2.xml | 64 +- ves-agent/src/main/resources/schema-mariadb.sql | 15 + .../vesagent/test/VESAgentServiceRestTest.java | 82 +- .../src/test/resources/application.properties | 12 +- ves-agent/src/test/resources/log4j2.xml | 103 + 136 files changed, 13495 insertions(+), 3804 deletions(-) create mode 100644 acs/application-booter/src/test/resources/log4j2.xml create mode 100644 config-data/src/test/resources/log4j2.xml create mode 100644 factory/src/test/resources/application.properties create mode 100644 factory/src/test/resources/log4j2.xml create mode 100644 mapper/mapper-schema/CustomYangModelMOmapping.txt create mode 100644 mapper/rpc_set_input.xml create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/Test.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/dao/DeviceOperationsDAO.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/entity/DeviceOperationDetails.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/model/NetConfNotificationDTO.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/util/FirwareUpgradeErrorCode.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/util/FirwareUpgradeStatus.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MapperConstants.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MapperValidator.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VesRequestHandler.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VesRequestReceiver.java create mode 100644 mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/impl/VesRequestHandlerImpl.java create mode 100644 mapper/src/main/resources/schema-mariadb.sql create mode 100644 mapper/src/test/resources/log4j2.xml create mode 100644 netconf-server/schemas/iana-hardware.yang create mode 100644 netconf-server/schemas/ietf-crypto-types.yang create mode 100644 netconf-server/schemas/ietf-hardware.yang create mode 100644 netconf-server/schemas/ietf-inet-types.yang create mode 100644 netconf-server/schemas/ietf-netconf-acm.yang create mode 100644 netconf-server/schemas/ietf-netconf-monitoring-extension.yang create mode 100644 netconf-server/schemas/ietf-netconf-monitoring.yang create mode 100644 netconf-server/schemas/ietf-yang-types.yang create mode 100644 netconf-server/schemas/o-ran-file-management.yang create mode 100644 netconf-server/schemas/o-ran-hardware.yang create mode 100644 netconf-server/schemas/o-ran-heartbeat-management.yang create mode 100644 netconf-server/schemas/o-ran-software-management.yang create mode 100644 netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/utils/NetConfServerConstants.java create mode 100644 netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/ves/VESNotificationSender.java create mode 100644 netconf-server/src/test/resources/log4j2.xml create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/AsyncRequestHandler.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/AsyncThreadPoolConfig.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/WaitForNotifications.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/entity/DeviceDataEntity.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/exception/VesAgentException.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/mapper/MapperRequestSender.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/repository/VesDataRepository.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/service/VesAgentServiceHelper.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/HeartBeatTimeoutTask.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleConfig.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleInfo.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleTaskService.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ServiceConfig.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/StartupTimerService.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/EventUtil.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/VesAgentConstants.java create mode 100644 ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/VesAgentUtils.java create mode 100644 ves-agent/src/main/resources/schema-mariadb.sql create mode 100644 ves-agent/src/test/resources/log4j2.xml diff --git a/acs/application-booter/pom.xml b/acs/application-booter/pom.xml index 3accec2..291d6e4 100644 --- a/acs/application-booter/pom.xml +++ b/acs/application-booter/pom.xml @@ -87,7 +87,7 @@ com.fasterxml.jackson.core jackson-databind - + org.commscope.tr069adapter.acs.common acs-common 1.0.0 @@ -209,7 +209,7 @@ ${env.CONTAINER_PULL_REGISTRY} - ${docker.image.name} + ${docker.image.name}:${build.version} try ${basedir} diff --git a/acs/application-booter/src/main/java/org/commscope/tr069adapter/acs/booter/ACSServiceBooter.java b/acs/application-booter/src/main/java/org/commscope/tr069adapter/acs/booter/ACSServiceBooter.java index 37dc186..ee7c1f8 100644 --- a/acs/application-booter/src/main/java/org/commscope/tr069adapter/acs/booter/ACSServiceBooter.java +++ b/acs/application-booter/src/main/java/org/commscope/tr069adapter/acs/booter/ACSServiceBooter.java @@ -48,6 +48,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.jms.annotation.EnableJms; import org.springframework.jms.config.DefaultJmsListenerContainerFactory; import org.springframework.jms.config.JmsListenerContainerFactory; +import org.springframework.jms.listener.MessageListenerContainer; import org.springframework.jms.support.converter.MappingJackson2MessageConverter; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.converter.MessageType; @@ -137,33 +138,36 @@ public class ACSServiceBooter { } // End - @Bean - public JmsListenerContainerFactory tr069NBIRequestCF(ConnectionFactory connectionFactory, + public JmsListenerContainerFactory tr069NBIRequestCF( + ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { - DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); - configurer.configure(factory, connectionFactory); - return factory; + return handleJMSCommonConfiguration(connectionFactory, configurer); } @Bean - public JmsListenerContainerFactory tr069DeviceResponseCF(ConnectionFactory connectionFactory, + public JmsListenerContainerFactory tr069DeviceResponseCF( + ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { - DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); - configurer.configure(factory, connectionFactory); - return factory; + return handleJMSCommonConfiguration(connectionFactory, configurer); } @Bean - public JmsListenerContainerFactory nbiNotificationCF(ConnectionFactory connectionFactory, + public JmsListenerContainerFactory nbiNotificationCF( + ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { - DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); - configurer.configure(factory, connectionFactory); - return factory; + return handleJMSCommonConfiguration(connectionFactory, configurer); } @Bean - public JmsListenerContainerFactory nbiOpResultCF(ConnectionFactory connectionFactory, + public JmsListenerContainerFactory nbiOpResultCF( + ConnectionFactory connectionFactory, + DefaultJmsListenerContainerFactoryConfigurer configurer) { + return handleJMSCommonConfiguration(connectionFactory, configurer); + } + + public JmsListenerContainerFactory handleJMSCommonConfiguration( + ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); configurer.configure(factory, connectionFactory); diff --git a/acs/application-booter/src/main/resources/log4j2.xml b/acs/application-booter/src/main/resources/log4j2.xml index c23beac..eb0336c 100644 --- a/acs/application-booter/src/main/resources/log4j2.xml +++ b/acs/application-booter/src/main/resources/log4j2.xml @@ -1,25 +1,25 @@ - - + + %d{yyyy-MM-dd HH:mm:ss} %m%n @@ -86,11 +86,11 @@ - - - - - + + + + + @@ -101,4 +101,4 @@ - + diff --git a/acs/application-booter/src/main/resources/schema-mariadb.sql b/acs/application-booter/src/main/resources/schema-mariadb.sql index 664cb66..f39500d 100644 --- a/acs/application-booter/src/main/resources/schema-mariadb.sql +++ b/acs/application-booter/src/main/resources/schema-mariadb.sql @@ -1,40 +1,40 @@ -- ACS Module related tables - START CREATE TABLE IF NOT EXISTS tr069_device - ( - ID int null, - DEVICE_ID varchar(30) not null, - USER_NAME varchar(256), - PASSWORD varchar(256), - SW_VERSION varchar(20), - HW_VERSION varchar(20), - CONNECTION_REQUEST_URL varchar(1024), - LAST_UPDATED_TIME Timestamp + ( + ID int null, + DEVICE_ID varchar(30) not null, + USER_NAME varchar(256), + PASSWORD varchar(256), + SW_VERSION varchar(20), + HW_VERSION varchar(20), + CONNECTION_REQUEST_URL varchar(1024), + LAST_UPDATED_TIME Timestamp ); CREATE TABLE IF NOT EXISTS tr069_nbi_request - ( - ID int null, - DEVICE_ID varchar(30) not null, - OPERATION_ID bigint unsigned not null, - OPERATION_CODE int null, - ATTRIBUTE_JSON1 varchar(4000), - ATTRIBUTE_JSON2 varchar(4000), - ATTRIBUTE_JSON3 varchar(4000), - REQUEST_TIME_OUT int, - CREATE_TIME DATETIME(6), - IS_PROCESSED int DEFAULT 0 + ( + ID int null, + DEVICE_ID varchar(30) not null, + OPERATION_ID bigint unsigned not null, + OPERATION_CODE int null, + ATTRIBUTE_JSON1 varchar(4000), + ATTRIBUTE_JSON2 varchar(4000), + ATTRIBUTE_JSON3 varchar(4000), + REQUEST_TIME_OUT int, + CREATE_TIME DATETIME(6), + IS_PROCESSED int DEFAULT 0 ); - + CREATE TABLE IF NOT EXISTS tr069_session - ( - DEVICE_ID varchar(30) not null, - SESSION_ID varchar(64) not null, - STATE int, - CURRENT_OPERATION_ID bigint unsigned, - SESSION_START_TIME TIMESTAMP + ( + DEVICE_ID varchar(30) not null, + SESSION_ID varchar(64) not null, + STATE int, + CURRENT_OPERATION_ID bigint unsigned, + SESSION_START_TIME TIMESTAMP ); CREATE SEQUENCE IF NOT EXISTS hibernate_sequence MINVALUE 1 MAXVALUE 4611686018427387903 CYCLE CACHE 10; diff --git a/acs/application-booter/src/test/resources/log4j2.xml b/acs/application-booter/src/test/resources/log4j2.xml new file mode 100644 index 0000000..446cf15 --- /dev/null +++ b/acs/application-booter/src/test/resources/log4j2.xml @@ -0,0 +1,104 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss} %m%n + ./target/test-logs + + + + + + + + + [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] %-25.45c{1} %-5p: %m%n +
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
diff --git a/acs/common/pom.xml b/acs/common/pom.xml index 6e4af40..c8a9b01 100644 --- a/acs/common/pom.xml +++ b/acs/common/pom.xml @@ -24,11 +24,11 @@ org.commscope.tr069adapter.acs.common acs-common ACS common utility - - org.commscope.tr069adapter.acs - acs - 1.0.0 - + + org.commscope.tr069adapter.acs + acs + 1.0.0 + org.springframework.boot diff --git a/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/DeviceDetails.java b/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/DeviceDetails.java index 7db39fd..8063f13 100644 --- a/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/DeviceDetails.java +++ b/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/DeviceDetails.java @@ -35,6 +35,10 @@ public class DeviceDetails implements Serializable { protected String productClass; + // Device version details + protected String softwareVersion; + protected String hardwareVersion; + public String getDeviceId() { return deviceId; } @@ -67,4 +71,20 @@ public class DeviceDetails implements Serializable { this.productClass = productClass; } + public String getSoftwareVersion() { + return softwareVersion; + } + + public void setSoftwareVersion(String softwareVersion) { + this.softwareVersion = softwareVersion; + } + + public String getHardwareVersion() { + return hardwareVersion; + } + + public void setHardwareVersion(String hardwareVersion) { + this.hardwareVersion = hardwareVersion; + } + } diff --git a/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/DeviceRPCRequest.java b/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/DeviceRPCRequest.java index 1657744..1a1ad5d 100644 --- a/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/DeviceRPCRequest.java +++ b/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/DeviceRPCRequest.java @@ -22,7 +22,7 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; -public class DeviceRPCRequest implements Serializable, Cloneable { +public class DeviceRPCRequest implements Serializable { private static final long serialVersionUID = -7300390764969298783L; @@ -33,7 +33,25 @@ public class DeviceRPCRequest implements Serializable, Cloneable { private OperationDetails opDetails; private OperationOptions options; - private Map context = new HashMap<>(); + private transient Map context = new HashMap<>(); + + public DeviceRPCRequest(DeviceDetails deviceDetails, Long operationId, OperationDetails opDetails, + OperationOptions options, Map context) { + super(); + this.deviceDetails = deviceDetails; + this.operationId = operationId; + this.opDetails = opDetails; + this.options = options; + this.context = context; + } + + public DeviceRPCRequest(DeviceRPCRequest deviceRPCRequest) { + deviceDetails = deviceRPCRequest.deviceDetails; + operationId = deviceRPCRequest.operationId; + opDetails = deviceRPCRequest.opDetails; + options = deviceRPCRequest.options; + context = deviceRPCRequest.context; + } public DeviceRPCRequest() { @@ -84,11 +102,6 @@ public class DeviceRPCRequest implements Serializable, Cloneable { this.context.put(name, value); } - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - @Override public String toString() { return "NBIDeviceOperationRequest [deviceId=" + deviceDetails.getDeviceId() + ", deviceType=" diff --git a/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/dto/TR069DeviceDetails.java b/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/dto/TR069DeviceDetails.java index b53338a..4d4ef7e 100644 --- a/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/dto/TR069DeviceDetails.java +++ b/acs/common/src/main/java/org/commscope/tr069adapter/acs/common/dto/TR069DeviceDetails.java @@ -28,10 +28,6 @@ public class TR069DeviceDetails extends DeviceDetails { private String username; private String password; - // Device version details - private String softwareVersion; - private String hardwareVersion; - // Device connection request URL private String connectionRequestURL; @@ -51,22 +47,6 @@ public class TR069DeviceDetails extends DeviceDetails { this.password = password; } - public String getSoftwareVersion() { - return softwareVersion; - } - - public void setSoftwareVersion(String softwareVersion) { - this.softwareVersion = softwareVersion; - } - - public String getHardwareVersion() { - return hardwareVersion; - } - - public void setHardwareVersion(String hardwareVersion) { - this.hardwareVersion = hardwareVersion; - } - public String getConnectionRequestURL() { return connectionRequestURL; } diff --git a/acs/common/src/main/resources/config/ErrorMessages_tr069.properties b/acs/common/src/main/resources/config/ErrorMessages_tr069.properties index 12b34c2..2a5ed3f 100644 --- a/acs/common/src/main/resources/config/ErrorMessages_tr069.properties +++ b/acs/common/src/main/resources/config/ErrorMessages_tr069.properties @@ -29,10 +29,10 @@ TR069.EMPTY_REQUEST_PROCESSING_ERROR=Failed processing the empty request from de TR069.DEVICE_NOT_ACTIVATED=Device is not activated. Device should contact ACS via BOOTSTRAP Inform to be activated TR069.DEVICE_NOT_EXISTS=Device {0} does not exist. Device must be factory imported before contacting ACS. - + TR069.INVALID_NBI_REQUEST=An Empty/NULL device RPC request received from mapper. TR069.MISSING_OPERATION_DETAILS=Device RPC request does not contain valid operation details like operation code. - + TR069.SESSION_CREATION_ERROR=An error occurred during session creation, Reason: {0} TR069.SESSION_ALREADY_LOCKED=Session lock could not be acquired, Session is already busy honoring another request. Lock acquire failure reason: {0} TR069.SESSION_EXPIRED=Session with ID {0}, for the device is expired. diff --git a/acs/cpe/pom.xml b/acs/cpe/pom.xml index 198023e..4c1a000 100644 --- a/acs/cpe/pom.xml +++ b/acs/cpe/pom.xml @@ -21,83 +21,83 @@ --> - 4.0.0 - org.commscope.tr069adapter.acs.cpe - cpe - CPE Management + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + org.commscope.tr069adapter.acs.cpe + cpe + CPE Management - - org.commscope.tr069adapter.acs - acs - 1.0.0 - + + org.commscope.tr069adapter.acs + acs + 1.0.0 + - - - org.springframework - spring-jms - - - org.springframework.boot - spring-boot-starter-web - + + + org.springframework + spring-jms + + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-logging - - + + org.springframework.boot spring-boot-starter-log4j2 - - + + com.lmax disruptor 3.4.2 - + org.springframework.boot spring-boot-starter-activemq - - org.apache.activemq - activemq-broker - - - com.fasterxml.jackson.core - jackson-databind - - - javax.ws.rs - javax.ws.rs-api - 2.0 - - - com.sun.xml.messaging.saaj - saaj-impl - - - javax.xml.bind - jaxb-api - - - commons-httpclient - commons-httpclient - 3.1 - - - org.commscope.tr069adapter.common - common - 1.0.0 - - + + org.apache.activemq + activemq-broker + + + com.fasterxml.jackson.core + jackson-databind + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + com.sun.xml.messaging.saaj + saaj-impl + + + javax.xml.bind + jaxb-api + + + commons-httpclient + commons-httpclient + 3.1 + + + org.commscope.tr069adapter.common + common + 1.0.0 + + org.commscope.tr069adapter.acs.common acs-common 1.0.0 - + diff --git a/acs/nbi/pom.xml b/acs/nbi/pom.xml index d7db474..9decb41 100644 --- a/acs/nbi/pom.xml +++ b/acs/nbi/pom.xml @@ -21,72 +21,72 @@ --> - - 4.0.0 - org.commscope.tr069adapter.acs.nbi - acsnbi - acs nbi service - - - org.commscope.tr069adapter.acs - acs - 1.0.0 - - - - - org.springframework - spring-jms - - - org.springframework.boot - spring-boot-starter-web - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + 4.0.0 + org.commscope.tr069adapter.acs.nbi + acsnbi + acs nbi service + + + org.commscope.tr069adapter.acs + acs + 1.0.0 + + + + + org.springframework + spring-jms + + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-logging - - + + org.springframework.boot spring-boot-starter-log4j2 - - + + com.lmax disruptor 3.4.2 - - org.apache.activemq - activemq-broker - - - com.fasterxml.jackson.core - jackson-databind - - - javax.ws.rs - javax.ws.rs-api - 2.0 - - - org.commscope.tr069adapter.common - common - 1.0.0 - - + + org.apache.activemq + activemq-broker + + + com.fasterxml.jackson.core + jackson-databind + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + org.commscope.tr069adapter.common + common + 1.0.0 + + org.commscope.tr069adapter.acs.common acs-common 1.0.0 - - org.commscope.tr069adapter.acs.requestprocessor - requestprocessor - 1.0.0 - - + + org.commscope.tr069adapter.acs.requestprocessor + requestprocessor + 1.0.0 + + diff --git a/acs/pom.xml b/acs/pom.xml index e954135..2cc9281 100644 --- a/acs/pom.xml +++ b/acs/pom.xml @@ -22,24 +22,24 @@ --> - - - org.commscope.tr069adapter - tr069adapter - 1.0.0 - - - 4.0.0 - org.commscope.tr069adapter.acs - acs - pom + + + org.commscope.tr069adapter + tr069adapter + 1.0.0 + + + 4.0.0 + org.commscope.tr069adapter.acs + acs + pom - acs - - common - application-booter - cpe - requestprocessor - nbi - + acs + + common + application-booter + cpe + requestprocessor + nbi + diff --git a/acs/requestprocessor/pom.xml b/acs/requestprocessor/pom.xml index 0c69d81..70e6312 100644 --- a/acs/requestprocessor/pom.xml +++ b/acs/requestprocessor/pom.xml @@ -21,87 +21,87 @@ --> - 4.0.0 - org.commscope.tr069adapter.acs.requestprocessor - requestprocessor - TR069 Request Processor + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + org.commscope.tr069adapter.acs.requestprocessor + requestprocessor + TR069 Request Processor - - org.commscope.tr069adapter.acs - acs - 1.0.0 - - - - - org.springframework - spring-jms - - - org.springframework.boot - spring-boot-starter-web - + + org.commscope.tr069adapter.acs + acs + 1.0.0 + + + + + org.springframework + spring-jms + + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-logging - - + + org.springframework.boot spring-boot-starter-log4j2 - - + + com.lmax disruptor 3.4.2 - + org.springframework.boot spring-boot-starter-activemq - - org.apache.activemq - activemq-broker - - - com.fasterxml.jackson.core - jackson-databind + + org.apache.activemq + activemq-broker + + + com.fasterxml.jackson.core + jackson-databind + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + org.mariadb.jdbc + mariadb-java-client - javax.ws.rs - javax.ws.rs-api - 2.0 - - - org.mariadb.jdbc - mariadb-java-client - - - com.fasterxml.uuid - java-uuid-generator - 3.1.3 - - - org.springframework.boot - spring-boot-starter-data-jpa - - - com.google.code.gson - gson - - - org.commscope.tr069adapter.common - common - 1.0.0 - + com.fasterxml.uuid + java-uuid-generator + 3.1.3 + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.google.code.gson + gson + + + org.commscope.tr069adapter.common + common + 1.0.0 + + org.commscope.tr069adapter.acs.common acs-common 1.0.0 - + diff --git a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/custom/ConfigureMultipleObject.java b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/custom/ConfigureMultipleObject.java index 5a125ce..768edf3 100644 --- a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/custom/ConfigureMultipleObject.java +++ b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/custom/ConfigureMultipleObject.java @@ -39,7 +39,6 @@ import org.commscope.tr069adapter.acs.common.response.AddObjectResponse; import org.commscope.tr069adapter.acs.common.response.DeleteObjectResponse; import org.commscope.tr069adapter.acs.common.response.GetParameterValueResponse; import org.commscope.tr069adapter.acs.common.response.SetParameterValueResponse; -import org.commscope.tr069adapter.acs.common.utils.ErrorCode; import org.commscope.tr069adapter.acs.requestprocessor.dao.DeviceRPCRequestRepositoryHelper; import org.commscope.tr069adapter.acs.requestprocessor.dto.CustomOperationData; import org.commscope.tr069adapter.acs.requestprocessor.entity.TR069DeviceRPCRequestEntity; @@ -400,16 +399,8 @@ public class ConfigureMultipleObject implements CustomOperation { } - private DeviceRPCRequest cloneNBIRequest(DeviceRPCRequest nbiDeviceOperationRequest) - throws TR069EventProcessingException { - DeviceRPCRequest clonedOpRequest = null; - try { - clonedOpRequest = (DeviceRPCRequest) nbiDeviceOperationRequest.clone(); - } catch (CloneNotSupportedException e) { - throw new TR069EventProcessingException(ErrorCode.UNKNOWN_ERROR, e.getMessage()); - } - - return clonedOpRequest; + private DeviceRPCRequest cloneNBIRequest(DeviceRPCRequest nbiDeviceOperationRequest) { + return new DeviceRPCRequest(nbiDeviceOperationRequest); } private ParameterDTO prepareParamDTO(String name, String value, ParameterDTO paramDTO) { diff --git a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/handler/DeviceRPCRequestHandler.java b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/handler/DeviceRPCRequestHandler.java index e42ec6f..49ec0a7 100644 --- a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/handler/DeviceRPCRequestHandler.java +++ b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/handler/DeviceRPCRequestHandler.java @@ -55,12 +55,17 @@ public class DeviceRPCRequestHandler { logger.debug("Received a TR069 operation request from Mapper with operation ID: {} ", mapperDeviceOperationRequest.getOperationId()); tr069RequestProcessEngine.processDeviceRPCRequest(mapperDeviceOperationRequest); + logger.debug("Processed a TR069 operation request from Mapper with operation ID: {} ", + mapperDeviceOperationRequest.getOperationId()); + } } catch (TR069EventProcessingException ex) { logger.error(ex.getMessage()); } finally { MDC.remove(CLIENT_STR); } + logger.debug("Processed JMS message from Mapper for TR069 Device RPC operation"); + } } diff --git a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/helper/TR069RequestProcessEngineHelper.java b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/helper/TR069RequestProcessEngineHelper.java index b2f78c9..b0315bf 100644 --- a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/helper/TR069RequestProcessEngineHelper.java +++ b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/helper/TR069RequestProcessEngineHelper.java @@ -113,7 +113,7 @@ public class TR069RequestProcessEngineHelper { * @return */ protected TR069RequestProcessorData getTR069RequestProcessorData() { - return requestCacheUtil.get(); + return TR069RequestProcessorCacheUtil.get(); } /** diff --git a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/TR069EventNotificationService.java b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/TR069EventNotificationService.java index b6025f0..634f9df 100644 --- a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/TR069EventNotificationService.java +++ b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/TR069EventNotificationService.java @@ -23,6 +23,7 @@ import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.NBI_OP_RE import org.commscope.tr069adapter.acs.common.DeviceInform; import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.commscope.tr069adapter.acs.common.dto.CustomOperationCode; import org.commscope.tr069adapter.acs.common.dto.TR069InformType; import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode; import org.slf4j.Logger; @@ -68,11 +69,19 @@ public class TR069EventNotificationService { String deviceId = deviceRPCResponse.getDeviceDetails().getDeviceId(); try { MDC.put(CLIENT_STR, deviceId); - TR069OperationCode operCode = - (TR069OperationCode) deviceRPCResponse.getOperationResponse().getOperationCode(); - String opCodeName = operCode.name(); - logger.debug("Device RPC Response received for operation: '{}' with operation ID: {}", - opCodeName, deviceRPCResponse.getOperationId()); + if (deviceRPCResponse.getOperationResponse() + .getOperationCode() instanceof TR069OperationCode) { + TR069OperationCode operCode = + (TR069OperationCode) deviceRPCResponse.getOperationResponse().getOperationCode(); + logger.debug("Device RPC Response received for operation: '" + operCode.name() + + "' with operation ID:" + deviceRPCResponse.getOperationId()); + } else if (deviceRPCResponse.getOperationResponse() + .getOperationCode() instanceof CustomOperationCode) { + CustomOperationCode operCode = + (CustomOperationCode) deviceRPCResponse.getOperationResponse().getOperationCode(); + logger.debug("Device RPC Response received for operation: '" + operCode.getJndiName() + + "' with operation ID:" + deviceRPCResponse.getOperationId()); + } jmsTemplate.convertAndSend(NBI_OP_RESULT_Q, deviceRPCResponse); logger.debug("Successfully posted the operation result event to DM to forward to NBI"); } catch (Exception e) { diff --git a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/TR069RequestProcessEngine.java b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/TR069RequestProcessEngine.java index 8ad7f2b..91dacb3 100644 --- a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/TR069RequestProcessEngine.java +++ b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/impl/TR069RequestProcessEngine.java @@ -28,6 +28,7 @@ import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; import org.commscope.tr069adapter.acs.common.OperationCode; import org.commscope.tr069adapter.acs.common.OperationDetails; +import org.commscope.tr069adapter.acs.common.OperationResponse; import org.commscope.tr069adapter.acs.common.dto.CustomOperationCode; import org.commscope.tr069adapter.acs.common.dto.DeviceOperationRequestDetails; import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails; @@ -99,7 +100,11 @@ public class TR069RequestProcessEngine extends TR069RequestProcessEngineHelper { deviceId = deviceRPCRequest.getDeviceDetails().getDeviceId(); try { tr069DeviceDetails = deviceOperationInterface.getDeviceDetails(deviceId); - } catch (DeviceOperationException deo) { + deviceRPCResponse = checkForDeviceAvailabilityRequest(deviceRPCRequest, tr069DeviceDetails); + if (null != deviceRPCResponse) { + return; + } + } catch (DeviceOperationException | SessionManagerException deo) { logger.error(deo.getMessage()); deviceRPCResponse = tr069RequestProcessEngineUtility.buildAbortedOperationresult( tr069DeviceDetails, deviceRPCRequest, AcsFaultCode.FAULT_CODE_8000); @@ -152,6 +157,35 @@ public class TR069RequestProcessEngine extends TR069RequestProcessEngineHelper { } } + private DeviceRPCResponse checkForDeviceAvailabilityRequest(DeviceRPCRequest deviceRPCRequest, + TR069DeviceDetails tr069DeviceDetails) throws SessionManagerException { + DeviceRPCResponse deviceRPCResponse = null; + + if (!deviceRPCRequest.getOpDetails().getOpCode().equals(CustomOperationCode.CONNECT)) { + return deviceRPCResponse; + } + + SessionDTO sessionDTO = getSession(tr069DeviceDetails.getDeviceId()); + + if (null != sessionDTO && !SessionState.TERMINATED.equals(sessionDTO.getSessionState())) { + logger.debug("Device is reachable as device tr069 session is in {} state.", + sessionDTO.getSessionState()); + + deviceRPCResponse = new DeviceRPCResponse(); + deviceRPCResponse.setDeviceDetails(tr069DeviceDetails); + deviceRPCResponse.setOperationId(deviceRPCRequest.getOperationId()); + + OperationResponse operationResponse = new OperationResponse(); + // device reachable...change value 1 to some constant or enum + operationResponse.setStatus(TR069RequestProcessorUtility.DEVICE_REACHABLE_STATUS_CODE); + operationResponse.setOperationCode(deviceRPCRequest.getOpDetails().getOpCode()); + + deviceRPCResponse.setOperationResponse(operationResponse); + } + + return deviceRPCResponse; + } + /** * Common Step 1. Since there can exist only one Inform from any device, which will be the * initiator of the session, following steps to be followed a. Stop the session timer for this @@ -312,19 +346,8 @@ public class TR069RequestProcessEngine extends TR069RequestProcessEngineHelper { DeviceRPCRequest operationRequest = customOperationData.getDeviceRPCRequest(); deviceRPCResponse = customOperationData.getDeviceRPCResponse(); if (operationRequest != null) { - operationRequest.addContextParam(SESSION_ID, newSessionId); - updateSessionCurOpId(tr069RequestProcessorData, deviceRPCRequest.getOperationId()); - changeSessionState(tr069RequestProcessorData, SessionState.LOCKED); - updateSession(session); - if (deviceRPCResponse != null && operationRequest.getOperationId() != null - && !operationRequest.getOperationId() - .equals(deviceRPCResponse.getOperationId())) { - logger.debug( - "Sending the Device RPC response for a configure Multiple object prior operation"); - // Sending the operation response to NBI - tr069EventNotificationService.sendOperationResultToNBI(deviceRPCResponse); - } - return operationRequest; + return handleOperationRequest(deviceRPCResponse, session, deviceRPCRequest, + newSessionId, tr069RequestProcessorData, operationRequest); } else { logger.debug(PENDING_RPC_CHECK); deviceRPCRequest = @@ -368,6 +391,23 @@ public class TR069RequestProcessEngine extends TR069RequestProcessEngineHelper { return deviceRPCRequest; } + private DeviceRPCRequest handleOperationRequest(DeviceRPCResponse deviceRPCResponse, + SessionDTO session, DeviceRPCRequest deviceRPCRequest, String newSessionId, + TR069RequestProcessorData tr069RequestProcessorData, DeviceRPCRequest operationRequest) { + operationRequest.addContextParam(SESSION_ID, newSessionId); + updateSessionCurOpId(tr069RequestProcessorData, deviceRPCRequest.getOperationId()); + changeSessionState(tr069RequestProcessorData, SessionState.LOCKED); + updateSession(session); + if (deviceRPCResponse != null && operationRequest.getOperationId() != null + && !operationRequest.getOperationId().equals(deviceRPCResponse.getOperationId())) { + logger + .debug("Sending the Device RPC response for a configure Multiple object prior operation"); + // Sending the operation response to NBI + tr069EventNotificationService.sendOperationResultToNBI(deviceRPCResponse); + } + return operationRequest; + } + /** * * 1. Stop the request timer for this device using the session ID received in the cookie of the diff --git a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/util/TR069RequestProcessorUtility.java b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/util/TR069RequestProcessorUtility.java index 3c80090..9386a07 100644 --- a/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/util/TR069RequestProcessorUtility.java +++ b/acs/requestprocessor/src/main/java/org/commscope/tr069adapter/acs/requestprocessor/util/TR069RequestProcessorUtility.java @@ -47,6 +47,8 @@ public class TR069RequestProcessorUtility { protected static final int BLOCK_SIZE = 3999; protected static final int MAX_SIZE = 11998; + public static final int DEVICE_REACHABLE_STATUS_CODE = 100; + private TR069RequestProcessorUtility() { super(); diff --git a/common/src/main/java/org/commscope/tr069adapter/common/scheduler/ExecutionContext.java b/common/src/main/java/org/commscope/tr069adapter/common/scheduler/ExecutionContext.java index f3305d2..37a6ab6 100644 --- a/common/src/main/java/org/commscope/tr069adapter/common/scheduler/ExecutionContext.java +++ b/common/src/main/java/org/commscope/tr069adapter/common/scheduler/ExecutionContext.java @@ -83,7 +83,7 @@ public class ExecutionContext implements Serializable { return subSystemName; } - private Map context = new HashMap<>(); + private transient Map context = new HashMap<>(); /** * Can be used to get some job related data, at the time of job execution. diff --git a/config-data/pom.xml b/config-data/pom.xml index 18bbd49..6c70210 100644 --- a/config-data/pom.xml +++ b/config-data/pom.xml @@ -94,6 +94,11 @@ spring-boot-starter-test test + + org.commscope.tr069adapter.acs.common + acs-common + 1.0.0 + @@ -154,7 +159,7 @@ ${env.CONTAINER_PULL_REGISTRY} - ${docker.image.name} + ${docker.image.name}:${build.version} try ${basedir} diff --git a/config-data/src/main/java/org/commscope/tr069adapter/config/controllers/ConfugurationDataController.java b/config-data/src/main/java/org/commscope/tr069adapter/config/controllers/ConfugurationDataController.java index 84bab64..e6262e5 100644 --- a/config-data/src/main/java/org/commscope/tr069adapter/config/controllers/ConfugurationDataController.java +++ b/config-data/src/main/java/org/commscope/tr069adapter/config/controllers/ConfugurationDataController.java @@ -23,8 +23,8 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; +import org.commscope.tr069adapter.acs.common.dto.ConfigurationData; import org.commscope.tr069adapter.config.constants.ConfigurationServiceConstant; -import org.commscope.tr069adapter.config.dto.ConfigurationData; import org.commscope.tr069adapter.config.exceptions.InvalidConfigurationServiceException; import org.commscope.tr069adapter.config.model.ConfigFileContent; import org.commscope.tr069adapter.config.service.ConfigurationDataService; diff --git a/config-data/src/main/java/org/commscope/tr069adapter/config/parser/ConfigurationXMLDataParser.java b/config-data/src/main/java/org/commscope/tr069adapter/config/parser/ConfigurationXMLDataParser.java index 4be0ccf..35c689d 100644 --- a/config-data/src/main/java/org/commscope/tr069adapter/config/parser/ConfigurationXMLDataParser.java +++ b/config-data/src/main/java/org/commscope/tr069adapter/config/parser/ConfigurationXMLDataParser.java @@ -36,16 +36,14 @@ import javax.xml.validation.Validator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.commscope.tr069adapter.acs.common.dto.ConfigurationData; import org.commscope.tr069adapter.config.constants.ConfigurationServiceConstant; -import org.commscope.tr069adapter.config.dto.ConfigurationData; import org.commscope.tr069adapter.config.exceptions.InvalidConfigurationServiceException; import org.commscope.tr069adapter.config.model.ConfigFileContent; import org.springframework.stereotype.Component; import org.xml.sax.Attributes; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; -import org.xml.sax.SAXNotRecognizedException; -import org.xml.sax.SAXNotSupportedException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; @@ -113,7 +111,7 @@ public class ConfigurationXMLDataParser extends DefaultHandler { parser = factory.newSAXParser(); parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); - setProperty(parser); + setProperty(); parser.parse(xmlFileContentInputStream, this); @@ -269,9 +267,8 @@ public class ConfigurationXMLDataParser extends DefaultHandler { logger.debug("File is valid."); } - protected void setProperty(SAXParser parser) - throws SAXNotRecognizedException, SAXNotSupportedException { - logger.debug("property added."); + protected void setProperty() { + logger.debug("property added."); } } diff --git a/config-data/src/main/java/org/commscope/tr069adapter/config/service/ConfigurationDataService.java b/config-data/src/main/java/org/commscope/tr069adapter/config/service/ConfigurationDataService.java index 9717bf2..0987cde 100644 --- a/config-data/src/main/java/org/commscope/tr069adapter/config/service/ConfigurationDataService.java +++ b/config-data/src/main/java/org/commscope/tr069adapter/config/service/ConfigurationDataService.java @@ -21,8 +21,8 @@ package org.commscope.tr069adapter.config.service; import java.nio.charset.StandardCharsets; import java.util.Optional; +import org.commscope.tr069adapter.acs.common.dto.ConfigurationData; import org.commscope.tr069adapter.config.constants.Utility; -import org.commscope.tr069adapter.config.dto.ConfigurationData; import org.commscope.tr069adapter.config.exceptions.InvalidConfigurationServiceException; import org.commscope.tr069adapter.config.model.ConfigFileContent; import org.commscope.tr069adapter.config.parser.ConfigurationXMLDataParser; diff --git a/config-data/src/main/resources/log4j2.xml b/config-data/src/main/resources/log4j2.xml index 2d73ef5..a247797 100644 --- a/config-data/src/main/resources/log4j2.xml +++ b/config-data/src/main/resources/log4j2.xml @@ -1,109 +1,109 @@ - - - + + + - - %d{yyyy-MM-dd HH:mm:ss} %m%n - /logs - configurationServiceLogs - - - - - + + %d{yyyy-MM-dd HH:mm:ss} %m%n + /logs + configurationServiceLogs + + + + + - - - [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] - %-25.45c{1} %-5p: %m%n -
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
-
- - - - - - - - - - -
+ + + [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] + %-25.45c{1} %-5p: %m%n +
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
+
+ + + + + + + + + + +
- - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + -
+
- - - - - + + + + + - - - - + + + + - - - - + + + + - - -
+ + + diff --git a/config-data/src/main/resources/schema-mariadb.sql b/config-data/src/main/resources/schema-mariadb.sql index 5f36066..9634210 100644 --- a/config-data/src/main/resources/schema-mariadb.sql +++ b/config-data/src/main/resources/schema-mariadb.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS config_file_content - ( - macid varchar(255) not null, - file_content mediumtext not null, - primary key(macid) + ( + macid varchar(255) not null, + file_content mediumtext not null, + primary key(macid) ); \ No newline at end of file diff --git a/config-data/src/main/resources/xsd/ConfigurationData.xsd b/config-data/src/main/resources/xsd/ConfigurationData.xsd index 5f1673c..a4495a7 100644 --- a/config-data/src/main/resources/xsd/ConfigurationData.xsd +++ b/config-data/src/main/resources/xsd/ConfigurationData.xsd @@ -1,2744 +1,2744 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config-data/src/test/java/com/commscope/tr069adapter/config/ConfigDataApplicationTests.java b/config-data/src/test/java/com/commscope/tr069adapter/config/ConfigDataApplicationTests.java index 89b8ab9..8b2fe27 100644 --- a/config-data/src/test/java/com/commscope/tr069adapter/config/ConfigDataApplicationTests.java +++ b/config-data/src/test/java/com/commscope/tr069adapter/config/ConfigDataApplicationTests.java @@ -22,7 +22,7 @@ import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; -import org.commscope.tr069adapter.config.dto.ConfigurationData; +import org.commscope.tr069adapter.acs.common.dto.ConfigurationData; import org.commscope.tr069adapter.config.model.ConfigFileContent; import org.springframework.web.client.RestTemplate; diff --git a/config-data/src/test/resources/log4j2.xml b/config-data/src/test/resources/log4j2.xml new file mode 100644 index 0000000..bf8803e --- /dev/null +++ b/config-data/src/test/resources/log4j2.xml @@ -0,0 +1,109 @@ + + + + + + %d{yyyy-MM-dd HH:mm:ss} %m%n + ./target/test-logs + configurationServiceLogs + + + + + + + + + [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] + %-25.45c{1} %-5p: %m%n +
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
diff --git a/db/pom.xml b/db/pom.xml index af0d638..a093570 100644 --- a/db/pom.xml +++ b/db/pom.xml @@ -47,13 +47,13 @@ package build - save + save ${env.CONTAINER_PULL_REGISTRY} - ${docker.image.name} + ${docker.image.name}:${build.version} try ${basedir} diff --git a/factory/pom.xml b/factory/pom.xml index 424adb3..592c946 100644 --- a/factory/pom.xml +++ b/factory/pom.xml @@ -130,13 +130,13 @@ package build - save + save ${env.CONTAINER_PULL_REGISTRY} - ${docker.image.name} + ${docker.image.name}:${build.version} try ${basedir} diff --git a/factory/src/main/resources/log4j2.xml b/factory/src/main/resources/log4j2.xml index 8865221..e32737d 100644 --- a/factory/src/main/resources/log4j2.xml +++ b/factory/src/main/resources/log4j2.xml @@ -22,55 +22,55 @@ --> - - %d{yyyy-MM-dd HH:mm:ss} %m%n - /logs - factoryDataImportLogs - - - - - + + %d{yyyy-MM-dd HH:mm:ss} %m%n + /logs + factoryDataImportLogs + + + + + - - - [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] - %-25.45c{1} %-5p: %m%n -
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
-
- - - - - -
+ + + [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] + %-25.45c{1} %-5p: %m%n +
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
+
+ + + + + +
- - - - - - - + + + + + + + -
+
- - - - - + + + + + - - - - + + + + - - + +
diff --git a/factory/src/test/resources/application.properties b/factory/src/test/resources/application.properties new file mode 100644 index 0000000..3e7f4ec --- /dev/null +++ b/factory/src/test/resources/application.properties @@ -0,0 +1,19 @@ +# ============LICENSE_START======================================================================== +# ONAP : tr-069-adapter +# ================================================================================================= +# Copyright (C) 2020 CommScope Inc Intellectual Property. +# ================================================================================================= +# This tr-069-adapter software file is distributed by CommScope Inc +# 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 +# +# This file 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. +# ===============LICENSE_END======================================================================= + +server.port=8089 diff --git a/factory/src/test/resources/log4j2.xml b/factory/src/test/resources/log4j2.xml new file mode 100644 index 0000000..2f6fb35 --- /dev/null +++ b/factory/src/test/resources/log4j2.xml @@ -0,0 +1,76 @@ + + + + + + %d{yyyy-MM-dd HH:mm:ss} %m%n + ./target/test-logs + factoryDataImportLogs + + + + + + + + + [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] + %-25.45c{1} %-5p: %m%n +
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
+
+ + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + +
diff --git a/mapper/Dockerfile b/mapper/Dockerfile index 117d847..513522f 100644 --- a/mapper/Dockerfile +++ b/mapper/Dockerfile @@ -34,6 +34,10 @@ ENV VES_REST_HOST=tr069adapter-ves-notifier ENV VES_REST_PORT=8383 ENV netConfServerPort=17830 ENV netConfServerIP=localhost +ENV DB_SERVICE=tr069adapter-mariadb +ENV DB_NAME=dmsdb +ENV DB_USERNAME=root +ENV DB_PASSWORD=root WORKDIR /opt/CSAdapter/ diff --git a/mapper/mapper-schema/CustomYangModelMOmapping.txt b/mapper/mapper-schema/CustomYangModelMOmapping.txt new file mode 100644 index 0000000..376585f --- /dev/null +++ b/mapper/mapper-schema/CustomYangModelMOmapping.txt @@ -0,0 +1,4 @@ +TRMONAME,YANGMONAME,MOTYPE,TRDATATYPE,YANGNAMESPACE +heartbeat.,heartbeat,ScalarObject,object,urn:o-ran:heartbeat-management:1.0 +heartbeat.heartbeatPeriod,heartbeat.heartbeatPeriod,Scalar-ReadWrite,unsignedInt +heartbeat.countDownTimer,heartbeat.countDownTimer,Scalar-ReadWrite,unsignedInt \ No newline at end of file diff --git a/mapper/pom.xml b/mapper/pom.xml index e0fad64..cfce5a3 100644 --- a/mapper/pom.xml +++ b/mapper/pom.xml @@ -78,6 +78,14 @@ acs-common 1.0.0
+ + org.mariadb.jdbc + mariadb-java-client + + + org.springframework.boot + spring-boot-starter-data-jpa + commons-io commons-io @@ -99,6 +107,11 @@ spring-boot-starter-test test + + com.h2database + h2 + test + @@ -133,7 +146,7 @@ ${project.parent.basedir}/eclipse-formatter.xml + spotless:apply process-sources --> com.diffplug.spotless @@ -148,8 +161,8 @@ + mvn spotless:apply to rewrite source files use mvn spotless:check to validate + source files --> org.apache.maven.plugins @@ -179,7 +192,7 @@ ${env.CONTAINER_PULL_REGISTRY} - ${docker.image.name} + ${docker.image.name}:${build.version} try ${basedir} diff --git a/mapper/rpc_set_input.xml b/mapper/rpc_set_input.xml new file mode 100644 index 0000000..ddbe4cf --- /dev/null +++ b/mapper/rpc_set_input.xml @@ -0,0 +1,9 @@ + + + + sftp://root@10.208.224.201/root/vishal/BCRP_OneImage_4.3.00.158.signed.bin + + airvana123 + + + \ No newline at end of file diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/MapperConfigProperties.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/MapperConfigProperties.java index c3f3a0a..023617a 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/MapperConfigProperties.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/MapperConfigProperties.java @@ -42,6 +42,8 @@ public class MapperConfigProperties { private String alarmMORegex; + private String verConfigUri; + public String getRequesTimeout() { return requesTimeout; } @@ -121,4 +123,13 @@ public class MapperConfigProperties { public void setAlarmMORegex(String alarmMORegex) { this.alarmMORegex = alarmMORegex; } + + public String getVerConfigUri() { + return verConfigUri; + } + + public void setVerConfigUri(String verConfigUri) { + this.verConfigUri = verConfigUri; + } + } diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/Test.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/Test.java new file mode 100644 index 0000000..65aa033 --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/Test.java @@ -0,0 +1,42 @@ +package org.commscope.tr069adapter.mapper; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode; +import org.commscope.tr069adapter.mapper.util.MOMetaDataUtil; +import org.commscope.tr069adapter.mapper.util.NetconfToTr069MapperUtil; +import org.w3c.dom.Element; + +public class Test { + + public static final String INDEX_STR = "index"; + public static final String INDEX_REGEX = "[0-9]{1,}"; + + public static void main(String[] args) throws IOException { + File file = new File("rpc_set_input.xml"); + String requestXML = FileUtils.readFileToString(file, "UTF-8"); + + + StringBuilder buff = new StringBuilder(); + for (int i = 6400; i <= 9600; i++) { + buff.append(i).append(","); + } + System.out.println(buff.toString()); + + MOMetaDataUtil util = new MOMetaDataUtil(); + util.loadMetaData(); + Element el = NetconfToTr069MapperUtil.convertStringToDocument(requestXML); + + DeviceRPCRequest req = NetconfToTr069MapperUtil.prepareTR069Request("0005B9AAAAA3", el, "rpc", + TR069OperationCode.GET_PARAMETER_VALUES); + req.getOpDetails() + .setParmeters(util.getSupportedChildParameters(req.getOpDetails().getParmeters())); + + System.out.println(req); + + } + +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/acs/impl/ACSNotificationHandlerImpl.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/acs/impl/ACSNotificationHandlerImpl.java index 693f788..12e2761 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/acs/impl/ACSNotificationHandlerImpl.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/acs/impl/ACSNotificationHandlerImpl.java @@ -28,16 +28,23 @@ import org.commscope.tr069adapter.acs.common.ParameterDTO; import org.commscope.tr069adapter.acs.common.dto.TR069InformType; import org.commscope.tr069adapter.acs.common.inform.BootInform; import org.commscope.tr069adapter.acs.common.inform.BootstrapInform; +import org.commscope.tr069adapter.acs.common.inform.ConnectionRequestInform; import org.commscope.tr069adapter.acs.common.inform.PeriodicInform; +import org.commscope.tr069adapter.acs.common.inform.TransferCompleteInform; import org.commscope.tr069adapter.acs.common.inform.ValueChangeInform; import org.commscope.tr069adapter.mapper.MOMetaData; import org.commscope.tr069adapter.mapper.MapperConfigProperties; import org.commscope.tr069adapter.mapper.acs.ACSNotificationHandler; +import org.commscope.tr069adapter.mapper.dao.DeviceOperationsDAO; +import org.commscope.tr069adapter.mapper.entity.DeviceOperationDetails; +import org.commscope.tr069adapter.mapper.model.NetConfNotificationDTO; import org.commscope.tr069adapter.mapper.model.NetConfServerDetails; import org.commscope.tr069adapter.mapper.model.NetconfServerManagementError; import org.commscope.tr069adapter.mapper.netconf.NetConfNotificationSender; import org.commscope.tr069adapter.mapper.netconf.NetConfServerManager; import org.commscope.tr069adapter.mapper.sync.SynchronizedRequestHandler; +import org.commscope.tr069adapter.mapper.util.FirwareUpgradeErrorCode; +import org.commscope.tr069adapter.mapper.util.FirwareUpgradeStatus; import org.commscope.tr069adapter.mapper.util.MOMetaDataUtil; import org.commscope.tr069adapter.mapper.ves.VESNotificationSender; import org.slf4j.Logger; @@ -49,6 +56,7 @@ import org.springframework.stereotype.Component; public class ACSNotificationHandlerImpl implements ACSNotificationHandler { private static final Logger logger = LoggerFactory.getLogger(ACSNotificationHandlerImpl.class); + private static final String SOFT_MGMT_NS_URI = "urn:o-ran:software-management:1.0"; @Autowired SynchronizedRequestHandler syncHandler; @@ -71,6 +79,9 @@ public class ACSNotificationHandlerImpl implements ACSNotificationHandler { @Autowired NetConfServerManager netconfManager; + @Autowired + DeviceOperationsDAO deviceOperDAO; + @Override public void handleOperationResponse(DeviceRPCResponse opResult) { opResult.getOperationResponse().setParameterDTOs( @@ -85,6 +96,18 @@ public class ACSNotificationHandlerImpl implements ACSNotificationHandler { if (notification instanceof BootstrapInform) { logger.info("BootStrap notification received"); BootstrapInform bootstrapNotification = (BootstrapInform) notification; + + DeviceOperationDetails deviceDetails = + deviceOperDAO.findByDeviceId(notification.getDeviceDetails().getDeviceId()); + if (deviceDetails == null) { + deviceDetails = new DeviceOperationDetails(); + deviceDetails.setDeviceId(notification.getDeviceDetails().getDeviceId()); + deviceDetails.setSwVersion(notification.getDeviceDetails().getSoftwareVersion()); + deviceOperDAO.save(deviceDetails); + } + + checkForActivateNotification(notification); + // send request to create the netconf server instance for the bootstrap device // id NetConfServerDetails serverInfo = createNtConfServer(bootstrapNotification); @@ -103,6 +126,7 @@ public class ACSNotificationHandlerImpl implements ACSNotificationHandler { notiSender.sendNotification(bsInform); } else if (notification instanceof BootInform) { logger.info("Boot notification received"); + checkForActivateNotification(notification); BootInform bootNotification = (BootInform) notification; BootInform bInform = getDeviceBootNotification(bootNotification, TR069InformType.BOOT); if (bootNotification.getValueChangeNotification() != null) { @@ -117,9 +141,21 @@ public class ACSNotificationHandlerImpl implements ACSNotificationHandler { vesnotiSender.sendNotification(pINotificaiton, null); notiSender.sendNotification(pINotificaiton); logger.info("VC notification received"); + } else if (notification instanceof ConnectionRequestInform) { + ConnectionRequestInform crNotificaiton = (ConnectionRequestInform) notification; + vesnotiSender.sendNotification(crNotificaiton, null); + logger.info("ConnectionRequestInform notification received"); } else if (notification instanceof ValueChangeInform) { ValueChangeInform valueChgNotificaiton = (ValueChangeInform) notification; processVCNotification(valueChgNotificaiton, isAlarmVC); + } else if (notification instanceof TransferCompleteInform) { + TransferCompleteInform tfNotificaiton = (TransferCompleteInform) notification; + if (tfNotificaiton.getCommandKey() != null && tfNotificaiton.getCommandKey() + .equalsIgnoreCase(tfNotificaiton.getDeviceDetails().getDeviceId())) { + logger.debug("TransferCompleteInform is recevied at mapper"); + processTransferCompleteInform(tfNotificaiton); + logger.debug("TransferCompleteInform processing completed at mapper"); + } } pnpPreProvisioningHandler.onDeviceNotification(notification); @@ -263,4 +299,106 @@ public class ACSNotificationHandlerImpl implements ACSNotificationHandler { } return isIPv6; } + + private void processTransferCompleteInform(TransferCompleteInform notification) { + + try { + ArrayList paramList = new ArrayList(); + DeviceOperationDetails fwDetails = + deviceOperDAO.findByDeviceId(notification.getDeviceDetails().getDeviceId()); + if (fwDetails == null || fwDetails.getFileName() == null) { + logger.debug( + "TransferCompleteInform recevied for invaild device, there is no entry exist in the database"); + return; + } + if (fwDetails.getDownLoadStatus() == FirwareUpgradeStatus.DOWNLOAD_INTIATED.getStatus()) { + paramList.add(new ParameterDTO("download-event.file-name", fwDetails.getFileName())); + + String status = FirwareUpgradeErrorCode.getErrorCodeMapping(notification.getFaultCode()); + paramList.add(new ParameterDTO("download-event.status", status)); + if (notification.getFaultCode() != 0) { + fwDetails.setDownLoadStatus(FirwareUpgradeStatus.DOWNLOAD_FAILED.getStatus()); + paramList + .add(new ParameterDTO("download-event.error-message", notification.getFaultString())); + } else { + fwDetails.setDownLoadStatus(FirwareUpgradeStatus.DOWNLOAD_COMPLETED.getStatus()); + logger.debug("downloading file completed on the device successfully."); + } + deviceOperDAO.save(fwDetails); + + logger.debug("sending download-event notification to netconfserver"); + NetConfNotificationDTO netConfNotifDTO = + new NetConfNotificationDTO(notification.getDeviceDetails().getDeviceId(), null, true); + netConfNotifDTO.setParameters(paramList); + netConfNotifDTO.setUri(SOFT_MGMT_NS_URI); + + if (notiSender.sendCustomNotification(netConfNotifDTO).getStatusCode().is2xxSuccessful()) { + logger.debug("sending download-event notification to netconfserver sucess"); + } else { + logger.error("sending download-event notification to netconfserver failed"); + } + } else { + logger.debug( + "TransferCompleteInform recevied after boot is received; already software is activated"); + } + } catch (Exception e) { + logger.debug("Exception occured while processing TransferCompleteInform " + e.toString()); + } + } + + private void checkForActivateNotification(DeviceInform notification) { + + try { + ArrayList paramList = new ArrayList(); + DeviceOperationDetails devDetails = + deviceOperDAO.findByDeviceId(notification.getDeviceDetails().getDeviceId()); + + if (devDetails == null + || devDetails.getDownLoadStatus() == FirwareUpgradeStatus.NOT_STARTED.getStatus()) { + logger.debug("firmware upgrade is not in progress"); + return; + } + + if (!notification.getDeviceDetails().getSoftwareVersion() + .equalsIgnoreCase(devDetails.getSwVersion()) + && devDetails.getDownLoadStatus() == FirwareUpgradeStatus.DOWNLOAD_INTIATED.getStatus()) { + logger.debug("received the boot/bootstrap before the transfer complete recevied"); + TransferCompleteInform inform = new TransferCompleteInform(); + inform.setDeviceDetails(notification.getDeviceDetails()); + inform.setFaultCode(0); + processTransferCompleteInform(inform); + } + + devDetails = deviceOperDAO.findByDeviceId(notification.getDeviceDetails().getDeviceId()); + if (devDetails.getDownLoadStatus() == FirwareUpgradeStatus.DOWNLOAD_COMPLETED.getStatus()) { + paramList.add(new ParameterDTO("activation-event.slot-name", "Active-Partion")); + // check for software change + if (notification.getDeviceDetails().getSoftwareVersion() + .equalsIgnoreCase(devDetails.getSwVersion())) { + paramList.add(new ParameterDTO("activation-event.status", "APPLICATION_ERROR")); + devDetails.setDownLoadStatus(FirwareUpgradeStatus.ACTIVATION_ERROR.getStatus()); + } else { + devDetails.setSwVersion(notification.getDeviceDetails().getSoftwareVersion()); + devDetails.setDownLoadStatus(FirwareUpgradeStatus.ACTIVATION_COMPLETED.getStatus()); + paramList.add(new ParameterDTO("activation-event.status", "COMPLETED")); + } + deviceOperDAO.save(devDetails); + + logger.debug("sending activation-event notification to netconfserver"); + NetConfNotificationDTO netConfNotifDTO = + new NetConfNotificationDTO(notification.getDeviceDetails().getDeviceId(), null, true); + netConfNotifDTO.setParameters(paramList); + netConfNotifDTO.setUri(SOFT_MGMT_NS_URI); + + if (notiSender.sendCustomNotification(netConfNotifDTO).getStatusCode().is2xxSuccessful()) { + logger.debug("sending activation-event notification to netconfserver sucess"); + } else { + logger.error("sending activation-event notification to netconfserver failed"); + } + } + } catch (Exception e) { + logger.debug( + "Exception occured while processing ProcessFirmWareActivateNotification " + e.toString()); + } + } } diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/acs/impl/PnPPreProvisioningHandler.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/acs/impl/PnPPreProvisioningHandler.java index b6327ec..b7fee2d 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/acs/impl/PnPPreProvisioningHandler.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/acs/impl/PnPPreProvisioningHandler.java @@ -26,10 +26,8 @@ import java.util.Map; import org.commscope.tr069adapter.acs.common.DeviceInform; import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; -import org.commscope.tr069adapter.acs.common.OperationOptions; import org.commscope.tr069adapter.acs.common.ParameterDTO; import org.commscope.tr069adapter.acs.common.dto.ConfigurationData; -import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails; import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode; import org.commscope.tr069adapter.acs.common.dto.TR069OperationDetails; import org.commscope.tr069adapter.acs.common.inform.BootInform; @@ -38,6 +36,7 @@ import org.commscope.tr069adapter.mapper.MOMetaData; import org.commscope.tr069adapter.mapper.MapperConfigProperties; import org.commscope.tr069adapter.mapper.sync.SynchronizedRequestHandler; import org.commscope.tr069adapter.mapper.util.MOMetaDataUtil; +import org.commscope.tr069adapter.mapper.util.NetconfToTr069MapperUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -238,18 +237,9 @@ public class PnPPreProvisioningHandler { private DeviceRPCRequest createNBIOperationRequest(String deviceId, List params) { TR069OperationDetails opDetails = new TR069OperationDetails(); opDetails.setOpCode(TR069OperationCode.SET_PARAMETER_VALUES); - opDetails.setParmeters(params); - - DeviceRPCRequest deviceRPCRequest = new DeviceRPCRequest(); - TR069DeviceDetails tr069DeviceDetails = new TR069DeviceDetails(); - tr069DeviceDetails.setDeviceId(deviceId); - deviceRPCRequest.setOpDetails(opDetails); - deviceRPCRequest.setDeviceDetails(tr069DeviceDetails); - OperationOptions options = new OperationOptions(); - options.setExecutionTimeout(300l); - deviceRPCRequest.setOptions(options); - - return deviceRPCRequest; + + return NetconfToTr069MapperUtil.handleParamsOperation(params, opDetails, deviceId); + } /** diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/boot/MapperServiceBooter.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/boot/MapperServiceBooter.java index e5f0452..c189162 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/boot/MapperServiceBooter.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/boot/MapperServiceBooter.java @@ -20,14 +20,18 @@ package org.commscope.tr069adapter.mapper.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.web.client.RestTemplate; @SpringBootApplication @ComponentScan({"org.commscope.tr069adapter.mapper", "org.commscope.tr069adapter.mapper.acs", "org.commscope.tr069adapter.mapper.ves"}) +@EnableJpaRepositories("org.commscope.tr069adapter.mapper.dao") +@EntityScan("org.commscope.tr069adapter.mapper.entity") public class MapperServiceBooter { public static void main(String[] args) { diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/dao/DeviceOperationsDAO.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/dao/DeviceOperationsDAO.java new file mode 100644 index 0000000..fad7956 --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/dao/DeviceOperationsDAO.java @@ -0,0 +1,11 @@ +package org.commscope.tr069adapter.mapper.dao; + +import org.commscope.tr069adapter.mapper.entity.DeviceOperationDetails; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface DeviceOperationsDAO extends CrudRepository { + + public DeviceOperationDetails findByDeviceId(String deviceId); +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/entity/DeviceOperationDetails.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/entity/DeviceOperationDetails.java new file mode 100644 index 0000000..0c5a190 --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/entity/DeviceOperationDetails.java @@ -0,0 +1,72 @@ +package org.commscope.tr069adapter.mapper.entity; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; + +@Entity +@Table(name = "device_operation_details", + uniqueConstraints = @UniqueConstraint(columnNames = {"DEVICE_ID"})) +public class DeviceOperationDetails implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column(name = "DEVICE_ID", length = 30) + private String deviceId; + + @Column(name = "SW_VERSION", length = 30) + private String swVersion; + + @Column(name = "DOWN_LOAD_STATUS") + private int downLoadStatus; + + @Column(name = "FIRMWARE_FILE", length = 1024) + private String fileName; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getSwVersion() { + return swVersion; + } + + public void setSwVersion(String swVersion) { + this.swVersion = swVersion; + } + + public int getDownLoadStatus() { + return downLoadStatus; + } + + public void setDownLoadStatus(int downLoadStatus) { + this.downLoadStatus = downLoadStatus; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/model/NetConfNotificationDTO.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/model/NetConfNotificationDTO.java new file mode 100644 index 0000000..792ada1 --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/model/NetConfNotificationDTO.java @@ -0,0 +1,72 @@ +package org.commscope.tr069adapter.mapper.model; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +import java.io.Serializable; +import java.util.List; + +import org.commscope.tr069adapter.acs.common.ParameterDTO; + +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") +public class NetConfNotificationDTO implements Serializable { + + private static final long serialVersionUID = 4928942484595767042L; + private boolean isCustomNotification; + private String notificationType; + private List parameters; + private String uri; + private String deviceID; + + public NetConfNotificationDTO() { + super(); + } + + public NetConfNotificationDTO(String deviceID, String notificationType, + boolean isCustomNotification) { + super(); + this.isCustomNotification = isCustomNotification; + this.notificationType = notificationType; + this.deviceID = deviceID; + } + + public String getDeviceID() { + return deviceID; + } + + public void setDeviceID(String deviceID) { + this.deviceID = deviceID; + } + + public String getNotificationType() { + return notificationType; + } + + public void setNotificationType(String notificationType) { + this.notificationType = notificationType; + } + + public List getParameters() { + return parameters; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public boolean isCustomNotification() { + return isCustomNotification; + } + + public void setCustomNotification(boolean isCustomNotification) { + this.isCustomNotification = isCustomNotification; + } + +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/model/VESNotification.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/model/VESNotification.java index 61a465d..4c0f388 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/model/VESNotification.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/model/VESNotification.java @@ -23,10 +23,12 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import java.io.Serializable; import org.commscope.tr069adapter.acs.common.DeviceInform; +import org.commscope.tr069adapter.acs.common.OperationDetails; @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") public class VESNotification implements Serializable { private DeviceInform devnotification; + private OperationDetails operationDetails; private NetConfServerDetails netconfDetails; private String eNodeBName; @@ -38,6 +40,14 @@ public class VESNotification implements Serializable { this.devnotification = devnotification; } + public OperationDetails getOperationDetails() { + return operationDetails; + } + + public void setOperationDetails(OperationDetails operationDetails) { + this.operationDetails = operationDetails; + } + public NetConfServerDetails getNetconfDetails() { return netconfDetails; } diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/NetConfNotificationSender.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/NetConfNotificationSender.java index adb3267..5ec31e7 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/NetConfNotificationSender.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/NetConfNotificationSender.java @@ -25,6 +25,7 @@ import org.commscope.tr069adapter.acs.common.DeviceInform; import org.commscope.tr069adapter.acs.common.ParameterDTO; import org.commscope.tr069adapter.mapper.MOMetaData; import org.commscope.tr069adapter.mapper.MapperConfigProperties; +import org.commscope.tr069adapter.mapper.model.NetConfNotificationDTO; import org.commscope.tr069adapter.mapper.util.MOMetaDataUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,9 +59,13 @@ public class NetConfNotificationSender { try { LOG.debug("deviceInform : {} {}", deviceInform.getInformTypeList(), deviceInform.getParameters()); - convertTR069ToNetConfParams(deviceInform); + NetConfNotificationDTO netConfDTO = + new NetConfNotificationDTO(deviceInform.getDeviceDetails().getDeviceId(), + deviceInform.getInformType().toString(), false); + netConfDTO.setParameters(deviceInform.getParameters()); + convertTR069ToNetConfParams(netConfDTO); LOG.debug("Posting notification to netconf server"); - response = restTemplate.postForObject(uri, deviceInform, ResponseEntity.class); + response = restTemplate.postForObject(uri, netConfDTO, ResponseEntity.class); LOG.debug("Posting notification to netconf server completed "); } catch (Exception e) { LOG.error("Exception while sending the notification.", e); @@ -68,10 +73,23 @@ public class NetConfNotificationSender { return response; } - private void convertTR069ToNetConfParams(DeviceInform deviceInform) { + public ResponseEntity sendCustomNotification(NetConfNotificationDTO netConfDTO) { + ResponseEntity response = null; + final String uri = getUri(); + LOG.debug("Posting custom notification to netconf server " + uri); + try { + response = restTemplate.postForObject(uri, netConfDTO, ResponseEntity.class); + LOG.debug("Posting custom notification to netconf server sucessfull"); + } catch (Exception e) { + LOG.error("Exception while sending the custom notification.", e.toString()); + } + return response; + } + + private void convertTR069ToNetConfParams(NetConfNotificationDTO netConfDTO) { List removeList = new ArrayList<>(); - if (null != deviceInform) { - for (ParameterDTO param : deviceInform.getParameters()) { + if (null != netConfDTO) { + for (ParameterDTO param : netConfDTO.getParameters()) { if (param.getParamValue() == null || param.getParamValue().trim().length() <= 0) { continue; } @@ -85,8 +103,7 @@ public class NetConfNotificationSender { removeList.add(param); // unknown parameter found. } } - deviceInform.getParameters().removeAll(removeList); // remove unknown - // parameters + netConfDTO.getParameters().removeAll(removeList); } } diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/NetConfRequestHandler.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/NetConfRequestHandler.java index 7dbb5b0..575d24e 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/NetConfRequestHandler.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/NetConfRequestHandler.java @@ -33,4 +33,7 @@ public interface NetConfRequestHandler { public NetConfResponse handleDelConfigRequest(NetConfRequest request); public boolean handelRegisterEvent(NetConfServerDetails request); + + public NetConfResponse handleSWDownloadRequest(NetConfRequest request); + } diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/controller/NetConfRequestReceiver.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/controller/NetConfRequestReceiver.java index ada3692..ca5f15a 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/controller/NetConfRequestReceiver.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/controller/NetConfRequestReceiver.java @@ -74,8 +74,9 @@ public class NetConfRequestReceiver { @PostMapping("/softwareDowload") public NetConfResponse swDownloadRequest(@RequestBody NetConfRequest request) { LOG.info("Received request for SW-DOWNLOAD. Request : {}", request); + NetConfResponse response = handler.handleSWDownloadRequest(request); LOG.info("Processed SW-DOWNLOAD request. Response : "); - return null; + return response; } @PostMapping("/softwareActivate") diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/impl/NetConfRequestHandlerImpl.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/impl/NetConfRequestHandlerImpl.java index 834102e..4c06bf2 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/impl/NetConfRequestHandlerImpl.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/netconf/impl/NetConfRequestHandlerImpl.java @@ -20,13 +20,18 @@ package org.commscope.tr069adapter.mapper.netconf.impl; import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.commscope.tr069adapter.acs.common.OperationOptions; import org.commscope.tr069adapter.acs.common.ParameterDTO; +import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails; import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode; -import org.commscope.tr069adapter.mapper.ErrorCodeMetaData; +import org.commscope.tr069adapter.acs.common.dto.TR069OperationDetails; import org.commscope.tr069adapter.mapper.MOMetaData; +import org.commscope.tr069adapter.mapper.dao.DeviceOperationsDAO; +import org.commscope.tr069adapter.mapper.entity.DeviceOperationDetails; import org.commscope.tr069adapter.mapper.model.ErrorCodeDetails; import org.commscope.tr069adapter.mapper.model.NetConfRequest; import org.commscope.tr069adapter.mapper.model.NetConfResponse; @@ -34,7 +39,10 @@ import org.commscope.tr069adapter.mapper.model.NetConfServerDetails; import org.commscope.tr069adapter.mapper.netconf.NetConfRequestHandler; import org.commscope.tr069adapter.mapper.sync.SynchronizedRequestHandler; import org.commscope.tr069adapter.mapper.util.ErrorCodeUtil; +import org.commscope.tr069adapter.mapper.util.FirwareUpgradeStatus; import org.commscope.tr069adapter.mapper.util.MOMetaDataUtil; +import org.commscope.tr069adapter.mapper.util.MapperConstants; +import org.commscope.tr069adapter.mapper.util.MapperValidator; import org.commscope.tr069adapter.mapper.util.NetconfToTr069MapperUtil; import org.commscope.tr069adapter.mapper.ves.VESNotificationSender; import org.slf4j.Logger; @@ -42,6 +50,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; +import org.w3c.dom.Document; import org.w3c.dom.Element; @Component @@ -67,6 +76,9 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { @Autowired VESNotificationSender vesnotiSender; + @Autowired + DeviceOperationsDAO deviceOperDAO; + @Override public NetConfResponse handleSetConfigRequest(NetConfRequest netConfRequest) { Element el = NetconfToTr069MapperUtil.convertStringToDocument(netConfRequest.getRequestXml()); @@ -80,11 +92,16 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { } List requestParams = deviceRPCRequest.getOpDetails().getParmeters(); List filteredParams = new ArrayList<>(); + List vesRequestParams = new ArrayList<>(); + if (null != requestParams) { for (ParameterDTO param : requestParams) { if (null == param.getParamValue() || StringUtils.isEmpty(param.getParamValue())) { continue; } + if (isVesNotificationRequest(param)) { + vesRequestParams.add(param); + } filteredParams.add(param); } deviceRPCRequest.getOpDetails().setParmeters(filteredParams); @@ -106,12 +123,41 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { handleBooleanParametersReverse(deviceRPCRequest.getOpDetails().getParmeters()); LOG.debug("Prepared NBI request for edit-config {}", deviceRPCRequest); - DeviceRPCResponse deviceRPCResponse; - deviceRPCResponse = syncHandler.performDeviceOperation(deviceRPCRequest); + DeviceRPCResponse deviceRPCResponseVes = null; + List allParamList = deviceRPCRequest.getOpDetails().getParmeters(); + + if (!vesRequestParams.isEmpty()) { + if (!MapperValidator.isCountDownTimerValid(vesRequestParams)) { + return getErrorResponse(MapperConstants.INVALID_PARAM_VAL_ERROR_CODE, + MapperConstants.INVALID_COUNT_DOWN_TIMER_MSG); + } + + deviceRPCRequest.getOpDetails().setParmeters(vesRequestParams); + deviceRPCResponseVes = vesnotiSender.sendEditConfigNotification(deviceRPCRequest); + + if (null == deviceRPCResponseVes) { + return getTimeOutResponse(); + } + } + + allParamList.removeAll(vesRequestParams); + + DeviceRPCResponse deviceRPCResponseDevice = null; + if (null != allParamList && !allParamList.isEmpty()) { + deviceRPCRequest.getOpDetails().setParmeters(allParamList); + deviceRPCResponseDevice = syncHandler.performDeviceOperation(deviceRPCRequest); + + if (null == deviceRPCResponseDevice) { + return getTimeOutResponse(); + } + } + + DeviceRPCResponse deviceRPCResponse = + mergeSetConfigDeviceRPCResponse(deviceRPCResponseVes, deviceRPCResponseDevice); if (null == deviceRPCResponse) { return getTimeOutResponse(); } - response = mapperUtil.getNetconfResponse(deviceRPCResponse); + response = mapperUtil.getNetconfResponse(deviceRPCResponse, false); return response; } @@ -154,7 +200,7 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { if (null == opResult) { return getTimeOutResponse(); } - response = mapperUtil.getNetconfResponse(opResult); + response = mapperUtil.getNetconfResponse(opResult, false); return response; } @@ -186,7 +232,7 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { if (null == opResult) { return getTimeOutResponse(); } - response = mapperUtil.getNetconfResponse(opResult); + response = mapperUtil.getNetconfResponse(opResult, false); return response; } @@ -194,6 +240,14 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { public NetConfResponse handleGetConfigRequest(NetConfRequest netConfRequest) { Element el = NetconfToTr069MapperUtil.convertStringToDocument(netConfRequest.getRequestXml()); NetConfResponse response = null; + List vesRequestParams = new ArrayList<>(); + + boolean isSoftwareInventory = false; + if (netConfRequest.getRequestXml().contains("software-inventory")) { + LOG.info("XML Contains software-inventory"); + isSoftwareInventory = true; + } + DeviceRPCRequest request = NetconfToTr069MapperUtil.prepareTR069Request( netConfRequest.getDeviceId(), el, "filter", TR069OperationCode.GET_PARAMETER_VALUES); @@ -209,24 +263,59 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { LOG.debug("There are no supported device parameters found for get-config."); return getEmptyResponse(); } + for (ParameterDTO param : request.getOpDetails().getParmeters()) { + if (isVesNotificationRequest(param)) { + vesRequestParams.add(param); + } + } } LOG.debug("Prepared NBI request for get-config {}", request); - DeviceRPCResponse opResult; - opResult = syncHandler.performDeviceOperation(request); + DeviceRPCResponse opResultVes = null; + List allParamList = request.getOpDetails().getParmeters(); + + if (!vesRequestParams.isEmpty()) { + request.getOpDetails().setParmeters(vesRequestParams); + opResultVes = vesnotiSender.sendGetConfigNotification(request); + + if (null == opResultVes) { + return getTimeOutResponse(); + } + } + + + allParamList.removeAll(vesRequestParams); + + DeviceRPCResponse opResultDevice = null; + if (!allParamList.isEmpty()) { + request.getOpDetails().setParmeters(allParamList); + opResultDevice = syncHandler.performDeviceOperation(request); + + if (null == opResultDevice) { + return getTimeOutResponse(); + } + } + + DeviceRPCResponse opResult = mergeGetConfigDeviceRPCResponse(opResultVes, opResultDevice); + if (null == opResult) { return getTimeOutResponse(); } - LOG.debug("Received GPV response : FaultKey = {} FaultString = {} Parameters : {}", - opResult.getFaultKey(), opResult.getFaultString(), - opResult.getOperationResponse().getParameterDTOs()); + LOG.debug("Received GPV response : FaultKey = " + opResult.getFaultKey() + ", FaultString = " + + opResult.getFaultString() + ", Parameters :" + + opResult.getOperationResponse().getParameterDTOs()); if (null != opResult.getOperationResponse().getParameterDTOs()) handleBooleanParameters(opResult.getOperationResponse().getParameterDTOs()); - response = mapperUtil.getNetconfResponse(opResult); + + if (isSoftwareInventory) { + response = mapperUtil.getNetconfResponseForSoftwareInventory(opResult); + } else { + response = mapperUtil.getNetconfResponse(opResult, false); + } if (opResult.getFaultKey() != null && opResult.getFaultKey().equalsIgnoreCase("9005")) { // check for tabular - LOG.debug("Tabular Entry not exist in the device; we need to add it now"); + LOG.debug("Tabualr Entry not exist in the device; we need to add it now"); MOMetaData data = metaDataUtil .getMetaDataByTR69Name(request.getOpDetails().getParmeters().get(0).getParamName()); if (data.isTabluarObj()) { @@ -237,6 +326,148 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { return response; } + @Override + public NetConfResponse handleSWDownloadRequest(NetConfRequest request) { + LOG.debug("request received fro sw-download"); + Document d1 = NetconfToTr069MapperUtil.convertStringToDocumentXml(request.getRequestXml()); + NetConfResponse response = null; + Map map = + NetconfToTr069MapperUtil.extractRequestParamters(d1, "rpc", "software-download"); + if (map == null || map.size() <= 0) { + LOG.debug("There are no device parameters found for get."); + return getEmptyResponse(); + } + + TR069OperationDetails opDetails = new TR069OperationDetails(); + DeviceRPCRequest deviceRPCRequest = new DeviceRPCRequest(); + TR069DeviceDetails tr069DeviceDetails = new TR069DeviceDetails(); + tr069DeviceDetails.setDeviceId(request.getDeviceId()); + deviceRPCRequest.setOpDetails(opDetails); + deviceRPCRequest.setDeviceDetails(tr069DeviceDetails); + OperationOptions options = new OperationOptions(); + options.setExecutionTimeout(60l); + deviceRPCRequest.setOptions(options); + String fileName = map.get("rpc.software-download.remote-file-path"); + String password = map.get("rpc.software-download.password.password"); + + if (fileName == null || password == null || getDownloadFileURI(fileName) == null + || getDownloadUserName(fileName) == null) { + LOG.error( + "remote-file-path value is not as per yang model reference. Allowed pattern sftp://@[:]/path"); + return getOperationAbortedResponse( + "remote-file-path value is not as per yang model reference. Allowed pattern sftp://@[:]/path"); + } + + List paramDTOList = new ArrayList<>(); + paramDTOList.add(new ParameterDTO("FileType", "1 Firmware Upgrade Image")); + paramDTOList.add(new ParameterDTO("URL", getDownloadFileURI(fileName))); + paramDTOList.add(new ParameterDTO("Username", getDownloadUserName(fileName))); + paramDTOList.add(new ParameterDTO("Password", password)); + paramDTOList.add(new ParameterDTO("FileSize", "0")); + paramDTOList.add(new ParameterDTO("TargetFileName", "")); + paramDTOList.add(new ParameterDTO("DelaySeconds", "1")); + paramDTOList.add(new ParameterDTO("SuccessURL", "")); + paramDTOList.add(new ParameterDTO("FailureURL", "")); + + deviceRPCRequest.getOpDetails().setParmeters(paramDTOList); + deviceRPCRequest.getOpDetails().setOpCode(TR069OperationCode.DOWNLOAD); + + LOG.debug("Prepared NBI request for download " + deviceRPCRequest); + + DeviceOperationDetails fwDetails = deviceOperDAO.findByDeviceId(request.getDeviceId()); + if (fwDetails == null) { + String errorMsg = "TR069 device request has been aborted,due to device not identified"; + return getOperationAbortedResponse(errorMsg); + } + + if (fwDetails.getDownLoadStatus() != FirwareUpgradeStatus.DOWNLOAD_INTIATED.getStatus() + && fwDetails.getDownLoadStatus() != FirwareUpgradeStatus.DOWNLOAD_COMPLETED.getStatus()) { + + LOG.debug("persisting the fw details " + fwDetails.toString()); + + DeviceRPCResponse opResult; + opResult = syncHandler.performDeviceOperation(deviceRPCRequest); + if (null == opResult) { + return getTimeOutResponse(); + } + fwDetails.setFileName(fileName); + fwDetails.setDownLoadStatus(FirwareUpgradeStatus.DOWNLOAD_INTIATED.getStatus()); + deviceOperDAO.save(fwDetails); + ArrayList responseParamDTOList = new ArrayList<>(); + + if (opResult.getOperationResponse().getStatus() == 1) { + responseParamDTOList.add(new ParameterDTO("rpc-reply.ns1:status", "STARTED")); + } else { + responseParamDTOList.add(new ParameterDTO("rpc-reply.ns1:status", "FAILED")); + responseParamDTOList + .add(new ParameterDTO("rpc-reply.ns1:error-message", opResult.getFaultString())); + } + responseParamDTOList.add(new ParameterDTO("rpc-reply.ns1:notification-timeout", "1200")); + + opResult.getOperationResponse().setParameterDTOs(responseParamDTOList); + response = mapperUtil.getNetconfResponse(opResult, true); + + LOG.debug("update the status for fw details " + fwDetails.toString()); + } else { + LOG.debug("FirmWare Upgrade is in progress"); + String errorMsg = "TR069 device request has been aborted as Firmware Upgrade is inProgress"; + return getOperationAbortedResponse(errorMsg); + } + + return response; + } + + private DeviceRPCResponse mergeGetConfigDeviceRPCResponse(DeviceRPCResponse opResultVes, + DeviceRPCResponse opResultDevice) { + if (null == opResultVes) { + return opResultDevice; + } + + if (null == opResultDevice) { + return opResultVes; + } + + if (null != opResultVes.getFaultKey() + && !opResultVes.getFaultKey().equals(MapperConstants.RPC_SUCCESS)) { + return opResultVes; + } else if (null != opResultDevice.getFaultKey() + && !opResultDevice.getFaultKey().equals(MapperConstants.RPC_SUCCESS)) { + return opResultDevice; + } + + opResultDevice.getOperationResponse().getParameterDTOs() + .addAll(opResultVes.getOperationResponse().getParameterDTOs()); + return opResultDevice; + } + + private DeviceRPCResponse mergeSetConfigDeviceRPCResponse(DeviceRPCResponse opResultVes, + DeviceRPCResponse opResultDevice) { + if (null == opResultVes) { + return opResultDevice; + } + + if (null == opResultDevice) { + return opResultVes; + } + + return opResultDevice; + } + + private boolean isVesNotificationRequest(ParameterDTO param) { + if (null == param.getParamName() || param.getParamName().isEmpty()) { + return false; + } + + if (param.getParamName().toLowerCase().contains(MapperConstants.HEART_BEAT_PERIOD.toLowerCase()) + || param.getParamName().toLowerCase() + .contains(MapperConstants.COUNT_DOWN_TIMER.toLowerCase()) + || param.getParamName().toLowerCase().contains(MapperConstants.HEART_BEAT.toLowerCase())) { + return true; + } + + return false; + } + private void handleBooleanParameters(List parameterDTOs) { for (ParameterDTO param : parameterDTOs) { @@ -267,7 +498,7 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { private NetConfResponse getEmptyResponse() { NetConfResponse response = new NetConfResponse(); - ErrorCodeMetaData errorCodeMetaData = errorCodeUtil.getErrorCodeMetaData("0"); + ErrorCodeDetails errorCodeMetaData = errorCodeUtil.getErrorCodeMetaData("0"); ErrorCodeDetails errorCode = new ErrorCodeDetails(); errorCode.setFaultCode("0"); errorCode.setErrorMessage(errorCodeMetaData.getErrorMessage()); @@ -282,7 +513,7 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { // prepare timeout error response NetConfResponse timeOutErrorResponse = new NetConfResponse(); ErrorCodeDetails errorCode = new ErrorCodeDetails(); - ErrorCodeMetaData errorCodeMetaData = errorCodeUtil.getErrorCodeMetaData("8006"); + ErrorCodeDetails errorCodeMetaData = errorCodeUtil.getErrorCodeMetaData("8006"); errorCode.setFaultCode("8006"); errorCode.setErrorMessage(errorCodeMetaData.getErrorMessage()); @@ -294,6 +525,39 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { return timeOutErrorResponse; } + private NetConfResponse getErrorResponse(String errCode, String errorMsg) { + NetConfResponse errorResponse = new NetConfResponse(); + ErrorCodeDetails errorCode = new ErrorCodeDetails(); + ErrorCodeDetails errorCodeMetaData = errorCodeUtil.getErrorCodeMetaData("8006"); + if (errorCodeMetaData != null) { + errorCode.setFaultCode(errCode); + errorCode.setErrorMessage(errorCodeMetaData.getErrorMessage()); + errorCode.setErrorType(errorCodeMetaData.getErrorType()); + errorCode.setErrorTag(errorCodeMetaData.getErrorTag()); + errorCode.setErrorSeverity(errorCodeMetaData.getErrorSeverity()); + } + errorResponse.setErrorCode(errorCode); + errorResponse.setErrorMessage(errorMsg); + return errorResponse; + } + + private NetConfResponse getOperationAbortedResponse(String errorMessage) { + // prepare timeout error response + NetConfResponse timeOutErrorResponse = new NetConfResponse(); + ErrorCodeDetails errorCode = new ErrorCodeDetails(); + ErrorCodeDetails errorCodeMetaData = errorCodeUtil.getErrorCodeMetaData("8006"); + if (errorCode != null) { + errorCode.setFaultCode("8002"); + errorCode.setErrorMessage(errorCodeMetaData.getErrorMessage()); + errorCode.setErrorType(errorCodeMetaData.getErrorType()); + errorCode.setErrorTag(errorCodeMetaData.getErrorTag()); + errorCode.setErrorSeverity(errorCodeMetaData.getErrorSeverity()); + } + timeOutErrorResponse.setErrorCode(errorCode); + timeOutErrorResponse.setErrorMessage(errorMessage); + return timeOutErrorResponse; + } + public List filteredSetParameters(List parameters) { List result = new ArrayList<>(); for (ParameterDTO param : parameters) { @@ -327,4 +591,28 @@ public class NetConfRequestHandlerImpl implements NetConfRequestHandler { LOG.debug("processing the handelRegisterEvent completed"); return result; } + + private static String getDownloadFileURI(String filepath) { + + if (filepath.contains("@") && filepath.contains("//")) { + String[] str = filepath.split("@"); + String[] strForUserName = str[0].split("//"); + if (str.length > 1) { + String Url = strForUserName[0] + "//" + str[1]; + return Url; + } + } + return null; + } + + private static String getDownloadUserName(String filepath) { + + if (filepath.contains("@") && filepath.contains("//")) { + String[] str = filepath.split("@"); + String[] strForUserName = str[0].split("//"); + if (strForUserName.length > 1) + return strForUserName[1]; + } + return null; + } } diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/ErrorCodeUtil.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/ErrorCodeUtil.java index 13f9a6a..9537f9b 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/ErrorCodeUtil.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/ErrorCodeUtil.java @@ -30,7 +30,7 @@ import java.util.Map.Entry; import javax.annotation.PostConstruct; import org.apache.commons.io.FileUtils; -import org.commscope.tr069adapter.mapper.ErrorCodeMetaData; +import org.commscope.tr069adapter.mapper.model.ErrorCodeDetails; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -38,11 +38,10 @@ import org.springframework.stereotype.Component; @Component public class ErrorCodeUtil { - private static final Logger LOG = LoggerFactory.getLogger(ErrorCodeUtil.class); private static final String ERROR_CODE_FILE = "error-code-mapping.json"; - private static Map errorCodeMap; + private static Map errorCodeMap; @PostConstruct public static void loadErrorCodeData() { @@ -55,20 +54,20 @@ public class ErrorCodeUtil { } public void printErrorCodeMap() { - for (Entry entry : errorCodeMap.entrySet()) { + for (Entry entry : errorCodeMap.entrySet()) { LOG.debug("KEY= {}", entry.getKey()); LOG.debug("VALUE= {}", entry.getValue()); } } - private static Map getMetaDataAsMap(File file) throws IOException { + private static Map getMetaDataAsMap(File file) throws IOException { String json = FileUtils.readFileToString(file, StandardCharsets.UTF_8); - Map result = null; + Map result = null; ObjectMapper mapper = new ObjectMapper(); try { - result = mapper.readValue(json, new TypeReference>() {}); + result = mapper.readValue(json, new TypeReference>() {}); } catch (IOException e) { LOG.error("IOException while loading device model meta data {}", e.toString()); LOG.error("Exception : {}", e.getMessage()); @@ -76,7 +75,7 @@ public class ErrorCodeUtil { return result; } - public ErrorCodeMetaData getErrorCodeMetaData(String errorCode) { + public ErrorCodeDetails getErrorCodeMetaData(String errorCode) { return errorCodeMap.get(errorCode); } diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/FirwareUpgradeErrorCode.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/FirwareUpgradeErrorCode.java new file mode 100644 index 0000000..823aa7e --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/FirwareUpgradeErrorCode.java @@ -0,0 +1,25 @@ +package org.commscope.tr069adapter.mapper.util; + +import java.util.HashMap; +import java.util.Map; + +public class FirwareUpgradeErrorCode { + private static Map ErrorCodes = new HashMap();; + + static { + ErrorCodes.put(9019, "AUTHENTICATION_ERROR"); + ErrorCodes.put(9001, "AUTHENTICATION_ERROR"); + ErrorCodes.put(9016, "AUTHENTICATION_ERROR"); + ErrorCodes.put(9012, "AUTHENTICATION_ERROR"); + ErrorCodes.put(9015, "PROTOCOL_ERROR"); + ErrorCodes.put(9002, "APPLICATION_ERROR"); + ErrorCodes.put(9003, "APPLICATION_ERROR"); + ErrorCodes.put(9020, "TIMEOUT"); + ErrorCodes.put(0, "COMPLETED"); + } + + public static String getErrorCodeMapping(int errorCode) { + return ErrorCodes.get(errorCode) != null ? ErrorCodes.get(errorCode) : "APPLICATION_ERROR"; + } + +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/FirwareUpgradeStatus.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/FirwareUpgradeStatus.java new file mode 100644 index 0000000..918a413 --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/FirwareUpgradeStatus.java @@ -0,0 +1,16 @@ +package org.commscope.tr069adapter.mapper.util; + +public enum FirwareUpgradeStatus { + NOT_STARTED(0), DOWNLOAD_INTIATED(1), DOWNLOAD_FAILED(2), DOWNLOAD_COMPLETED(3), ACTIVATION_ERROR( + 4), ACTIVATION_COMPLETED(5); + + private int status; + + private FirwareUpgradeStatus(int status) { + this.status = status; + } + + public int getStatus() { + return status; + } +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MOMetaDataUtil.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MOMetaDataUtil.java index e2711c7..a038468 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MOMetaDataUtil.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MOMetaDataUtil.java @@ -49,7 +49,6 @@ public class MOMetaDataUtil { private Map metaDataMap; private Map metaDataReverseMap; public static final String ORAN_SW_MGMT_URI = "urn:o-ran:software-management:1.0"; - private static HashMap nameSpaces = new HashMap<>(); @PostConstruct public void loadMetaData() { @@ -79,47 +78,58 @@ public class MOMetaDataUtil { continue; } if (line != null && line.split(",").length >= 3) { - String[] split = line.split(","); - boolean isReadOnly = false; - boolean isTabluar = false; - boolean isTabObject = false; - String dataType = ""; - - if (split[2].contains("-")) { - String[] dataAttr = split[2].split("-"); - if ("Tabular".equalsIgnoreCase(dataAttr[0])) - isTabluar = true; - if ("ReadOnly".equalsIgnoreCase(dataAttr[1])) - isReadOnly = true; - } else if ("TabularObject".equalsIgnoreCase(split[2])) { - isTabObject = true; - } - if (split.length > 3) { - dataType = split[3]; - } - if (isTabObject) { - String logMessage = split[1].substring(0, split[1].length() - 5); - LOG.info("Adding Parent Objects {}", logMessage); - String substring = split[0].substring(0, split[0].length() - 4); - MOMetaData metaTabData = - new MOMetaData(substring, dataType, isReadOnly, isTabluar, isTabObject); - if ((split.length > 4 && split[4] != null) && split[4].trim().length() > 0) { - metaTabData.setURI(split[4]); - } - metaDataMap.put(logMessage, metaTabData); - } - MOMetaData metaData = - new MOMetaData(split[0], dataType, isReadOnly, isTabluar, isTabObject); - if ((split.length > 4 && split[4] != null) && split[4].trim().length() > 0) { - metaData.setURI(split[4]); - } - metaDataMap.put(split[1], metaData); - metaDataReverseMap.put(split[0], split[1]); + + parseMetaDataLine(line, metaDataMap, metaDataReverseMap); + } } } } + private static void parseMetaDataLine(String line, Map metaDataMap, + Map metaDataReverseMap) { + String[] split = line.split(","); + boolean isReadOnly = false; + boolean isTabluar = false; + boolean isTabObject = false; + if (split[2].contains("-")) { + String[] dataAttr = split[2].split("-"); + if ("Tabular".equalsIgnoreCase(dataAttr[0])) + isTabluar = true; + if ("ReadOnly".equalsIgnoreCase(dataAttr[1])) + isReadOnly = true; + } else if ("TabularObject".equalsIgnoreCase(split[2])) { + isTabObject = true; + } + prepareMOMetaData(isReadOnly, isTabluar, split, isTabObject, metaDataMap, metaDataReverseMap); + } + + private static void prepareMOMetaData(boolean isReadOnly, boolean isTabluar, String[] split, + boolean isTabObject, Map metaDataMap, + Map metaDataReverseMap) { + String dataType = ""; + if (split.length > 3) { + dataType = split[3]; + } + if (isTabObject) { + String logMessage = split[1].substring(0, split[1].length() - 5); + LOG.info("Adding Parent Objects {}", logMessage); + String substring = split[0].substring(0, split[0].length() - 4); + MOMetaData metaTabData = + new MOMetaData(substring, dataType, isReadOnly, isTabluar, isTabObject); + if ((split.length > 4 && split[4] != null) && split[4].trim().length() > 0) { + metaTabData.setURI(split[4]); + } + metaDataMap.put(logMessage, metaTabData); + } + MOMetaData metaData = new MOMetaData(split[0], dataType, isReadOnly, isTabluar, isTabObject); + if ((split.length > 4 && split[4] != null) && split[4].trim().length() > 0) { + metaData.setURI(split[4]); + } + metaDataMap.put(split[1], metaData); + metaDataReverseMap.put(split[0], split[1]); + } + public MOMetaData getMetaDataByNetConfName(String moName) { String moNameInGnrForm = moName.replaceAll(INDEX_REGEX, STRING_I); return metaDataMap.get(moNameInGnrForm); @@ -147,10 +157,6 @@ public class MOMetaDataUtil { return metaDataMap.keySet(); } - public String getNameSpace(String nodeName) { - return nameSpaces.get(nodeName); - } - public List getSupportedChildParameters(List parameters) { List result = new ArrayList<>(); Set allMatchedChilds = new HashSet<>(); diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MapperConstants.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MapperConstants.java new file mode 100644 index 0000000..5d358eb --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MapperConstants.java @@ -0,0 +1,18 @@ +package org.commscope.tr069adapter.mapper.util; + +public class MapperConstants { + public static final String HEART_BEAT_PERIOD = "heartbeatPeriod"; + public static final String HEART_BEAT = "heartbeat"; + public static final String COUNT_DOWN_TIMER = "countDownTimer"; + public static final String COUNT_DOWN_TIMER_SET_VAL = "0"; + public static final String INVALID_COUNT_DOWN_TIMER_MSG = + "Only 0 is allowed for countDownTimer value during set operation"; + public static final String INVALID_PARAM_VAL_ERROR_CODE = "9007"; + + public static final int DEVICE_REACHABLE_STATUS_CODE = 100; + public static final int DEVICE_REACHABILITY_OP_FAILURE_CODE = 101; + public static final String DEVICE_TIMEOUT_STATUS_CODE = "8006"; + public static final String DEVICE_REACHABLE_MSG = "Device is reachable"; + public static final String DEFAULT_OP_TIMEOUT_MSG = "Operation Timed out"; + public static final String RPC_SUCCESS = "0"; +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MapperValidator.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MapperValidator.java new file mode 100644 index 0000000..632b0e0 --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/MapperValidator.java @@ -0,0 +1,34 @@ +package org.commscope.tr069adapter.mapper.util; + +import java.util.List; + +import org.commscope.tr069adapter.acs.common.ParameterDTO; + +public class MapperValidator { + private MapperValidator() { + throw new IllegalStateException("Can't be instantiated as MapperValidator is utility class"); + } + + + public static boolean isCountDownTimerValid(List paramList) { + for (ParameterDTO param : paramList) { + if (Boolean.FALSE.equals(isNullOrEmpty(param.getParamName())) && param.getParamName() + .toLowerCase().contains(MapperConstants.COUNT_DOWN_TIMER.toLowerCase())) { + + return !isNullOrEmpty(param.getParamValue()) + && param.getParamValue().equalsIgnoreCase(MapperConstants.COUNT_DOWN_TIMER_SET_VAL); + } + } + return true; + } + + + + public static boolean isNullOrEmpty(String object) { + return (null == object || object.isEmpty()); + } + + public static Boolean isNullOrEmpty(List list) { + return (null == list || list.isEmpty()); + } +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/NetconfToTr069MapperUtil.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/NetconfToTr069MapperUtil.java index 680495e..02a87c1 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/NetconfToTr069MapperUtil.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/util/NetconfToTr069MapperUtil.java @@ -45,7 +45,6 @@ import org.commscope.tr069adapter.acs.common.ParameterDTO; import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails; import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode; import org.commscope.tr069adapter.acs.common.dto.TR069OperationDetails; -import org.commscope.tr069adapter.mapper.ErrorCodeMetaData; import org.commscope.tr069adapter.mapper.model.ErrorCodeDetails; import org.commscope.tr069adapter.mapper.model.NetConfResponse; import org.slf4j.Logger; @@ -96,6 +95,13 @@ public class NetconfToTr069MapperUtil { return null; } + public static Map extractRequestParamters(Document operationElement, + String netconfTag, String filterElement) { + Node requestDataNode = getParameterDataNode(operationElement, netconfTag, filterElement); + Map map = getParameterMapForNode(requestDataNode, -1); + return map; + } + public static DeviceRPCRequest prepareTR069Request(String deviceId, Element operationElement, String netconfTag, TR069OperationCode opCode) { Node requestDataNode = getDeviceDataNode(operationElement, netconfTag); @@ -126,6 +132,11 @@ public class NetconfToTr069MapperUtil { TR069OperationDetails opDetails = new TR069OperationDetails(); opDetails.setOpCode(opCode); + return handleParamsOperation(params, opDetails, deviceId); + } + + public static DeviceRPCRequest handleParamsOperation(List params, + TR069OperationDetails opDetails, String deviceId) { opDetails.setParmeters(params); DeviceRPCRequest deviceRPCRequest = new DeviceRPCRequest(); @@ -139,17 +150,16 @@ public class NetconfToTr069MapperUtil { return deviceRPCRequest; } - public NetConfResponse getNetconfResponse(DeviceRPCResponse opResult) { + public NetConfResponse getNetconfResponse(DeviceRPCResponse opResult, boolean isCustomparameter) { NetConfResponse netConfResponse = new NetConfResponse(); - ErrorCodeMetaData errorCodeMetaData = - errorCodeUtil.getErrorCodeMetaData(opResult.getFaultKey()); + ErrorCodeDetails errorCodeDetails = errorCodeUtil.getErrorCodeMetaData(opResult.getFaultKey()); ErrorCodeDetails errorCode = new ErrorCodeDetails(); - if (errorCodeMetaData != null) { + if (errorCodeDetails != null) { errorCode.setFaultCode(opResult.getFaultKey()); - errorCode.setErrorMessage(errorCodeMetaData.getErrorMessage()); - errorCode.setErrorType(errorCodeMetaData.getErrorType()); - errorCode.setErrorTag(errorCodeMetaData.getErrorTag()); - errorCode.setErrorSeverity(errorCodeMetaData.getErrorSeverity()); + errorCode.setErrorMessage(errorCodeDetails.getErrorMessage()); + errorCode.setErrorType(errorCodeDetails.getErrorType()); + errorCode.setErrorTag(errorCodeDetails.getErrorTag()); + errorCode.setErrorSeverity(errorCodeDetails.getErrorSeverity()); netConfResponse.setErrorCode(errorCode); netConfResponse.setErrorMessage(opResult.getFaultString()); } else if (opResult.getFaultKey() != null && opResult.getFaultString() != null) { @@ -161,12 +171,128 @@ public class NetconfToTr069MapperUtil { netConfResponse.setErrorCode(errorCode); netConfResponse.setErrorMessage(opResult.getFaultString()); } - netConfResponse.setNetconfResponseXml( - getNetconfResponseXML(opResult.getOperationResponse().getParameterDTOs())); + netConfResponse.setNetconfResponseXml(getNetconfResponseXML( + opResult.getOperationResponse().getParameterDTOs(), isCustomparameter)); + return netConfResponse; + } + + public NetConfResponse getNetconfResponseForSoftwareInventory(DeviceRPCResponse opResult) { + + NetConfResponse netConfResponse = new NetConfResponse(); + ErrorCodeDetails errorCodeDetails = errorCodeUtil.getErrorCodeMetaData(opResult.getFaultKey()); + ErrorCodeDetails errorCode = new ErrorCodeDetails(); + if (errorCodeDetails != null) { + errorCode.setFaultCode(opResult.getFaultKey()); + errorCode.setErrorMessage(errorCodeDetails.getErrorMessage()); + errorCode.setErrorType(errorCodeDetails.getErrorType()); + errorCode.setErrorTag(errorCodeDetails.getErrorTag()); + errorCode.setErrorSeverity(errorCodeDetails.getErrorSeverity()); + netConfResponse.setErrorCode(errorCode); + netConfResponse.setErrorMessage(opResult.getFaultString()); + return netConfResponse; + } else if (opResult.getFaultKey() != null && opResult.getFaultString() != null) { + errorCode.setFaultCode(opResult.getFaultKey()); + errorCode.setErrorMessage(opResult.getFaultString()); + errorCode.setErrorType("application"); + errorCode.setErrorTag("operation-failed"); + errorCode.setErrorSeverity("ERROR"); + netConfResponse.setErrorCode(errorCode); + netConfResponse.setErrorMessage(opResult.getFaultString()); + return netConfResponse; + } + List paramDTOList = new ArrayList<>(); + + String build = null; + String productClass = null; + for (ParameterDTO paramDto : opResult.getOperationResponse().getParameterDTOs()) { + if (paramDto.getParamName().equals("Device.DeviceInfo.SoftwareVersion")) + build = paramDto.getParamValue(); + else if (paramDto.getParamName().equals("Device.DeviceInfo.ProductClass")) + productClass = paramDto.getParamValue(); + } + + String[] arrOfBuild = build.split("\\."); + String buildId = arrOfBuild[arrOfBuild.length - 1]; + StringBuilder buildVersion = new StringBuilder(); + for (int i = 0; i < arrOfBuild.length - 1; i++) { + if (i == arrOfBuild.length - 2) { + buildVersion.append(arrOfBuild[i]); + } else { + buildVersion.append(arrOfBuild[i]); + buildVersion.append("."); + } + } + + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.name", "Active Partition")); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.status", "VALID")); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.active", "true")); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.running", "true")); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.access", "READ_ONLY")); + paramDTOList + .add(new ParameterDTO("software-inventory.software-slot.product-code", productClass)); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.vendor-code", "CS")); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.build-id", buildId)); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.build-version", + buildVersion.toString())); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.files.name", "BC_ONE")); + paramDTOList.add(new ParameterDTO("software-inventory.software-slot.files.integrity", "OK")); + + String XmlStr = getNetconfResponseXML(paramDTOList, true); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + Document doc = null; + try { + builder = factory.newDocumentBuilder(); + doc = builder.parse(new InputSource(new StringReader(XmlStr))); + } catch (Exception e) { + logger.error("Error while converting String to element" + e); + errorCode.setFaultCode("8002"); + errorCode.setErrorMessage("Operation Aborted"); + errorCode.setErrorType("application"); + errorCode.setErrorTag("operation-failed"); + errorCode.setErrorSeverity("ERROR"); + netConfResponse.setErrorCode(errorCode); + netConfResponse.setErrorMessage("Operation Aborted"); + return netConfResponse; + } + + Element originalDocumentElement = doc.getDocumentElement(); + Element newDocumentElement = doc.createElementNS("urn:o-ran:software-management:1.0", + originalDocumentElement.getNodeName()); + NodeList list = originalDocumentElement.getChildNodes(); + while (list.getLength() != 0) { + newDocumentElement.appendChild(list.item(0)); + } + // Replace the original element + doc.replaceChild(newDocumentElement, originalDocumentElement); + + String strxml = null; + try { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(new StringWriter()); + transformer.transform(source, result); + strxml = result.getWriter().toString(); + } catch (Exception e) { + logger.error("Error while converting Element to String" + e); + errorCode.setFaultCode("8002"); + errorCode.setErrorMessage("Operation Aborted"); + errorCode.setErrorType("application"); + errorCode.setErrorTag("operation-failed"); + errorCode.setErrorSeverity("ERROR"); + netConfResponse.setErrorCode(errorCode); + netConfResponse.setErrorMessage("Operation Aborted"); + return netConfResponse; + } + + netConfResponse.setNetconfResponseXml(strxml); + logger.debug("NetConf Response XML String for software inventory: " + strxml); return netConfResponse; } - private String getNetconfResponseXML(List parameters) { + private String getNetconfResponseXML(List parameters, boolean isCustomparameter) { if (null == parameters || parameters.isEmpty()) { return null; @@ -187,6 +313,9 @@ public class NetconfToTr069MapperUtil { for (ParameterDTO paramDto : parameters) { String paramName = metaDataUtil.getNetconfNameByTR69NameWithIndexes(paramDto.getParamName()); + if (paramName == null && isCustomparameter) { + paramName = paramDto.getParamName(); + } String paramValue = paramDto.getParamValue(); if (paramValue == null || paramValue.trim().isEmpty()) { logger.debug("Values is empty so skipping this parameter."); @@ -217,7 +346,7 @@ public class NetconfToTr069MapperUtil { bld.append("."); bld.append(nodeName); parentNodeKey = bld.toString(); - Element node = parentNodeMap.get(parentNodeKey); + Element node = parentNodeMap.computeIfPresent(parentNodeKey, (k, v) -> v); // create a tabular parent node if doesn't exit in MAP if (null == node) { @@ -322,28 +451,15 @@ public class NetconfToTr069MapperUtil { if (moRNode.getNodeType() == Node.ELEMENT_NODE) { NodeList childs = moRNode.getChildNodes(); boolean hasChildElements = false; - if (childs.getLength() > 0) { - int counter = 0; - for (int i = 0; i < childs.getLength(); i++) { - Node cNode = childs.item(i); - if (cNode != null && cNode.getNodeType() == Node.ELEMENT_NODE) { - counter++; - } - } - - for (int i = 0; i < childs.getLength(); i++) { - Node cNode = childs.item(i); - if (cNode != null && cNode.getNodeType() == Node.ELEMENT_NODE) { - hasChildElements = true; - Map subResult = getParameterMapForNode(cNode, counter); - result.putAll(subResult); - } - } - } + hasChildElements = checkMoreElements(result, childs, hasChildElements); if (!hasChildElements) { String moName = getMOName(moRNode); - if ((null != moName && !moName.endsWith("." + INDEX_STR)) - || (null != moName && numberOfChilds == 1)) { + if (moName.equals("software-inventory")) { + result.put("device.device-info.software-version", moRNode.getTextContent()); + result.put("device.device-info.product-class", moRNode.getTextContent()); + } else if (!moName.endsWith("." + INDEX_STR)) { + result.put(moName, moRNode.getTextContent()); + } else if (numberOfChilds == 1) { result.put(moName, moRNode.getTextContent()); } } @@ -352,6 +468,29 @@ public class NetconfToTr069MapperUtil { return result; } + private static boolean checkMoreElements(Map result, NodeList childs, + boolean hasChildElements) { + if (childs.getLength() > 0) { + int counter = 0; + for (int i = 0; i < childs.getLength(); i++) { + Node cNode = childs.item(i); + if (cNode != null && cNode.getNodeType() == Node.ELEMENT_NODE) { + counter++; + } + } + + for (int i = 0; i < childs.getLength(); i++) { + Node cNode = childs.item(i); + if (cNode != null && cNode.getNodeType() == Node.ELEMENT_NODE) { + hasChildElements = true; + Map subResult = getParameterMapForNode(cNode, counter); + result.putAll(subResult); + } + } + } + return hasChildElements; + } + private static String getMOName(Node moRNode) { String result = removeNS(moRNode.getNodeName()); Node pNode = moRNode; @@ -379,6 +518,21 @@ public class NetconfToTr069MapperUtil { } } + private static Node getParameterDataNode(Document el, String docStart, String filterElement) { + NodeList nodeList = el.getElementsByTagName(docStart); + if (nodeList.getLength() > 0) { + nodeList = nodeList.item(0).getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + String nodeName = removeNS(node.getNodeName()); + if (nodeName.equals(filterElement)) { + return node; + } + } + } + return null; + } + private static Node getDeviceDataNode(Element el, String filter) { try { NodeList nodeList = el.getElementsByTagName(filter); diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VESNotificationSender.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VESNotificationSender.java index 6ced95d..044d304 100644 --- a/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VESNotificationSender.java +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VESNotificationSender.java @@ -19,6 +19,8 @@ package org.commscope.tr069adapter.mapper.ves; import org.commscope.tr069adapter.acs.common.DeviceInform; +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; import org.commscope.tr069adapter.mapper.MapperConfigProperties; import org.commscope.tr069adapter.mapper.acs.impl.PnPPreProvisioningHandler; import org.commscope.tr069adapter.mapper.model.NetConfServerDetails; @@ -65,6 +67,19 @@ public class VESNotificationSender { return restTemplate.postForObject(uri, vesNotifi, VESNotificationResponse.class); } + public DeviceRPCResponse sendEditConfigNotification(DeviceRPCRequest deviceRPCRequest) { + final String uri = config.getVerConfigUri() + "/editConfig"; + LOG.debug("Posting edit config request to ves agent {}", uri); + return restTemplate.postForObject(uri, deviceRPCRequest, DeviceRPCResponse.class); + } + + public DeviceRPCResponse sendGetConfigNotification(DeviceRPCRequest deviceRPCRequest) { + final String uri = config.getVerConfigUri() + "/getConfig"; + LOG.debug("Posting get config request to ves agent {}", uri); + return restTemplate.postForObject(uri, deviceRPCRequest, DeviceRPCResponse.class); + } + + private String getUri() { return config.getVesUri(); } diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VesRequestHandler.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VesRequestHandler.java new file mode 100644 index 0000000..c610338 --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VesRequestHandler.java @@ -0,0 +1,9 @@ +package org.commscope.tr069adapter.mapper.ves; + +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; + +public interface VesRequestHandler { + + public DeviceRPCResponse handleDeviceConnectivityRequest(DeviceRPCRequest deviceRPCRequest); +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VesRequestReceiver.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VesRequestReceiver.java new file mode 100644 index 0000000..d417e5c --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/VesRequestReceiver.java @@ -0,0 +1,29 @@ +package org.commscope.tr069adapter.mapper.ves; + +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/tr069MapperVesNBI") +public class VesRequestReceiver { + + private static final Logger LOG = LoggerFactory.getLogger(VesRequestReceiver.class); + + @Autowired + VesRequestHandler handler; + + @PostMapping("/checkDeviceConnectivity") + public DeviceRPCResponse deviceConnectivityCheckRequest(@RequestBody DeviceRPCRequest request) { + LOG.info("Received request for Device Reachability check. Request : {}", request); + DeviceRPCResponse response = handler.handleDeviceConnectivityRequest(request); + LOG.info("Received request for Device Reachability check. Response : {}", response); + return response; + } +} diff --git a/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/impl/VesRequestHandlerImpl.java b/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/impl/VesRequestHandlerImpl.java new file mode 100644 index 0000000..4d84243 --- /dev/null +++ b/mapper/src/main/java/org/commscope/tr069adapter/mapper/ves/impl/VesRequestHandlerImpl.java @@ -0,0 +1,67 @@ +package org.commscope.tr069adapter.mapper.ves.impl; + +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.commscope.tr069adapter.acs.common.OperationResponse; +import org.commscope.tr069adapter.mapper.MapperConfigProperties; +import org.commscope.tr069adapter.mapper.model.ErrorCodeDetails; +import org.commscope.tr069adapter.mapper.sync.SynchronizedRequestHandler; +import org.commscope.tr069adapter.mapper.util.ErrorCodeUtil; +import org.commscope.tr069adapter.mapper.util.MapperConstants; +import org.commscope.tr069adapter.mapper.ves.VesRequestHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class VesRequestHandlerImpl implements VesRequestHandler { + + private static final Logger LOG = LoggerFactory.getLogger(VesRequestHandlerImpl.class); + + @Autowired + SynchronizedRequestHandler syncHandler; + + @Autowired + MapperConfigProperties config; + + @Autowired + private ErrorCodeUtil errorCodeUtil; + + + @Override + public DeviceRPCResponse handleDeviceConnectivityRequest(DeviceRPCRequest deviceRPCRequest) { + DeviceRPCResponse deviceRPCResponse = syncHandler.performDeviceOperation(deviceRPCRequest); + if (null == deviceRPCResponse) { + return getTimeOutResponse(deviceRPCRequest); + } + + return deviceRPCResponse; + } + + private DeviceRPCResponse getTimeOutResponse(DeviceRPCRequest deviceRPCRequest) { + DeviceRPCResponse timeOutErrorResponse = new DeviceRPCResponse(); + + timeOutErrorResponse.setDeviceDetails(deviceRPCRequest.getDeviceDetails()); + + OperationResponse operationResponse = new OperationResponse(); + operationResponse.setStatus(MapperConstants.DEVICE_REACHABILITY_OP_FAILURE_CODE);// device + // reachable...change + // value 1 to + // some + // constant or + // enum + operationResponse.setOperationCode(deviceRPCRequest.getOpDetails().getOpCode()); + + timeOutErrorResponse.setOperationResponse(operationResponse); + timeOutErrorResponse.setFaultKey(MapperConstants.DEVICE_TIMEOUT_STATUS_CODE); + ErrorCodeDetails errorCodeDetails = + errorCodeUtil.getErrorCodeMetaData(MapperConstants.DEVICE_TIMEOUT_STATUS_CODE); + if (null != errorCodeDetails) { + timeOutErrorResponse.setFaultString(errorCodeDetails.getErrorMessage()); + } else { + timeOutErrorResponse.setFaultString(MapperConstants.DEFAULT_OP_TIMEOUT_MSG); + } + return timeOutErrorResponse; + } +} diff --git a/mapper/src/main/resources/application.properties b/mapper/src/main/resources/application.properties index 0a5657e..c5c974f 100644 --- a/mapper/src/main/resources/application.properties +++ b/mapper/src/main/resources/application.properties @@ -27,5 +27,16 @@ config.configDBUri=http://${CONFIG_DB_REST_HOST}:${CONFIG_DB_REST_PORT}/getConfi config.nbiNotificationUri=http://${NBI_REST_HOST}:${NBI_REST_PORT}/netConfNotificationService/notification config.nbiServerManagerUri=http://${NBI_REST_HOST}:${NBI_REST_PORT}/netConfServerManagerService config.vesUri=http://${VES_REST_HOST}:${VES_REST_PORT}/vesagent/deviceEvent +config.verConfigUri=http://${VES_REST_HOST}:${VES_REST_PORT}/vesagent config.netConfServerIP=${netConfServerIP}; config.netConfServerPort=${netConfServerPort}; + +## Datasource properties +spring.datasource.platform=mariadb +spring.datasource.initialization-mode=always +spring.jpa.hibernate.ddl-auto=none +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PASSWORD} +spring.datasource.url=jdbc:mariadb://${DB_SERVICE}:3306/${DB_NAME} +spring.datasource.driver-class-name=org.mariadb.jdbc.Driver +spring.jpa.show-sql=true diff --git a/mapper/src/main/resources/log4j2.xml b/mapper/src/main/resources/log4j2.xml index b12df3b..7869f22 100644 --- a/mapper/src/main/resources/log4j2.xml +++ b/mapper/src/main/resources/log4j2.xml @@ -1,25 +1,25 @@ - - + + %d{yyyy-MM-dd HH:mm:ss} %m%n @@ -86,19 +86,19 @@ - - + + - - + + - - - + + + - + diff --git a/mapper/src/main/resources/schema-mariadb.sql b/mapper/src/main/resources/schema-mariadb.sql new file mode 100644 index 0000000..b680a21 --- /dev/null +++ b/mapper/src/main/resources/schema-mariadb.sql @@ -0,0 +1 @@ +CREATE TABLE IF NOT EXISTS device_operation_details (ID int null,DEVICE_ID varchar(30) not null, SW_VERSION varchar(30) not null, DOWN_LOAD_STATUS int default 0, FIRMWARE_FILE varchar(1024) ); \ No newline at end of file diff --git a/mapper/src/test/java/org/commscope/tr069adapter/mapper/NetconfToTr069MapperUtilTest.java b/mapper/src/test/java/org/commscope/tr069adapter/mapper/NetconfToTr069MapperUtilTest.java index 5dbc344..2d1fbb7 100644 --- a/mapper/src/test/java/org/commscope/tr069adapter/mapper/NetconfToTr069MapperUtilTest.java +++ b/mapper/src/test/java/org/commscope/tr069adapter/mapper/NetconfToTr069MapperUtilTest.java @@ -49,7 +49,7 @@ public class NetconfToTr069MapperUtilTest { OperationResponse opr = new OperationResponse(); opr.setParameterDTOs(getGeneralParams()); opResult.setOperationResponse(opr); - NetConfResponse netConfRes = mapUtil.getNetconfResponse(opResult); + NetConfResponse netConfRes = mapUtil.getNetconfResponse(opResult, false); Assert.assertNotNull(netConfRes); Assert.assertEquals("0", netConfRes.getErrorCode().getFaultCode()); Assert.assertEquals("Success", netConfRes.getErrorCode().getErrorMessage()); @@ -64,7 +64,7 @@ public class NetconfToTr069MapperUtilTest { OperationResponse opr = new OperationResponse(); opr.setParameterDTOs(getGeneralParams()); opResult.setOperationResponse(opr); - NetConfResponse netConfRes = mapUtil.getNetconfResponse(opResult); + NetConfResponse netConfRes = mapUtil.getNetconfResponse(opResult, false); Assert.assertNotNull(netConfRes); Assert.assertEquals("9001", netConfRes.getErrorCode().getFaultCode()); Assert.assertEquals("Request denied", netConfRes.getErrorCode().getErrorMessage()); @@ -77,7 +77,7 @@ public class NetconfToTr069MapperUtilTest { opResult.setDeviceDetails(new DeviceDetails()); OperationResponse opr = new OperationResponse(); opResult.setOperationResponse(opr); - NetConfResponse netConfRes = mapUtil.getNetconfResponse(opResult); + NetConfResponse netConfRes = mapUtil.getNetconfResponse(opResult, false); Assert.assertNotNull(netConfRes); Assert.assertEquals("0", netConfRes.getErrorCode().getFaultCode()); Assert.assertEquals("Success", netConfRes.getErrorCode().getErrorMessage()); diff --git a/mapper/src/test/resources/application.properties b/mapper/src/test/resources/application.properties index aaa7217..9223bf1 100644 --- a/mapper/src/test/resources/application.properties +++ b/mapper/src/test/resources/application.properties @@ -27,5 +27,14 @@ config.configDBUri=http://tr069adapter-acs-initialpnpdb:9000/getConfig/ config.nbiNotificationUri=http://tr069adapter-netconf-server:8181/netConfNotificationService/notification config.nbiServerManagerUri=http://tr069adapter-netconf-server:8181/netConfServerManagerService config.vesUri=http://tr069adapter-ves-notifier:9191/vesagent/deviceEvent +config.verConfigUri=http://tr069adapter-ves-notifier:9191/vesagent config.netConfServerIP=10.211.5.55 config.netConfServerPort=17830 + +## Datasource properties +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password=sa +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=create diff --git a/mapper/src/test/resources/log4j2.xml b/mapper/src/test/resources/log4j2.xml new file mode 100644 index 0000000..9e13a60 --- /dev/null +++ b/mapper/src/test/resources/log4j2.xml @@ -0,0 +1,104 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss} %m%n + ./target/test-logs + + + + + + + + + [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] %-25.45c{1} %-5p: %m%n +
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
diff --git a/netconf-server/Dockerfile b/netconf-server/Dockerfile index 471ac19..81c170d 100644 --- a/netconf-server/Dockerfile +++ b/netconf-server/Dockerfile @@ -23,7 +23,6 @@ ARG JAR ENV NETCONF_REST_PORT=8181 ENV MAPPER_REST_PORT=9999 ENV NETCONFSRVS_START_PORT=17830 -ENV NETCONFSRVS_END_PORT=18030 ENV NUM_SERVERS=200 ENV MAPPER_REST_HOST=tr069adapter-netconfig-mapper ENV DB_SERVICE=tr069adapter-mariadb @@ -31,6 +30,8 @@ ENV DB_NAME=dmsdb ENV DB_USERNAME=root ENV DB_PASSWORD=root ENV netConfServerIP=localhost +ENV VES_REST_HOST=tr069adapter-ves-notifier +ENV VES_REST_PORT=8383 WORKDIR /opt/CSAdapter/ diff --git a/netconf-server/pom.xml b/netconf-server/pom.xml index f355a95..3b09997 100644 --- a/netconf-server/pom.xml +++ b/netconf-server/pom.xml @@ -214,7 +214,7 @@ ${env.CONTAINER_PULL_REGISTRY} - ${docker.image.name} + ${docker.image.name}:${build.version} try ${basedir} diff --git a/netconf-server/schemas/bbf-tr-196-2-0-3-full.yang b/netconf-server/schemas/bbf-tr-196-2-0-3-full.yang index d9ba1d6..1785178 100644 --- a/netconf-server/schemas/bbf-tr-196-2-0-3-full.yang +++ b/netconf-server/schemas/bbf-tr-196-2-0-3-full.yang @@ -17,7 +17,7 @@ module bbf-tr-196-2-0-3-full { description "This module contains a collection of YANG definitions for managing radio access network (RAN) devices."; - revision 2020-06-23 { + revision 2020-06-24 { description "Initial version, used only for ONAP PoC 2018-06-25 diff --git a/netconf-server/schemas/iana-hardware.yang b/netconf-server/schemas/iana-hardware.yang new file mode 100644 index 0000000..9a16ac6 --- /dev/null +++ b/netconf-server/schemas/iana-hardware.yang @@ -0,0 +1,180 @@ +module iana-hardware { +yang-version 1.1; +namespace "urn:ietf:params:xml:ns:yang:iana-hardware"; +prefix ianahw; + +organization "IANA"; +contact + " Internet Assigned Numbers Authority + Postal: ICANN + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States of America + Tel: +1 310 301 5800 + E-Mail: iana@iana.org>"; + +description + "IANA-defined identities for hardware class. + The latest revision of this YANG module can be obtained from + the IANA website. + Requests for new values should be made to IANA via + email (iana@iana.org). + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + The initial version of this YANG module is part of RFC 8348; + see the RFC itself for full legal notices."; +reference + "https://www.iana.org/assignments/yang-parameters"; + +revision 2018-03-13 { + description + "Initial revision."; + reference + "RFC 8348: A YANG Data Model for Hardware Management"; +} + +/* + * Identities + */ + +identity hardware-class { + description + "This identity is the base for all hardware class + identifiers."; +} + +identity unknown { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is unknown + to the server."; +} + +identity chassis { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is an + overall container for networking equipment. Any class of + physical component, except a stack, may be contained within a + chassis; a chassis may only be contained within a stack."; +} + +identity backplane { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of device for aggregating and forwarding networking traffic, + such as a shared backplane in a modular ethernet switch. Note + that an implementation may model a backplane as a single + physical component, which is actually implemented as multiple + discrete physical components (within a chassis or stack)."; +} + +identity container { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is capable + of containing one or more removable physical entities, + possibly of different types. For example, each (empty or + full) slot in a chassis will be modeled as a container. Note + that all removable physical components should be modeled + within a container component, such as field-replaceable + modules, fans, or power supplies. Note that all known + containers should be modeled by the agent, including empty + containers."; +} + +identity power-supply { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is a + power-supplying component."; +} + +identity fan { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is a fan or + other heat-reduction component."; +} + +identity sensor { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of sensor, such as a temperature sensor within a router + chassis."; +} + +identity module { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of self-contained sub-system. If a module component is + removable, then it should be modeled within a container + component; otherwise, it should be modeled directly within + another physical component (e.g., a chassis or another + module)."; +} + +identity port { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of networking port capable of receiving and/or transmitting + networking traffic."; +} + +identity stack { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of super-container (possibly virtual) intended to group + together multiple chassis entities. A stack may be realized + by a virtual cable, a real interconnect cable attached to + multiple chassis, or multiple interconnect cables. A stack + should not be modeled within any other physical components, + but a stack may be contained within another stack. Only + chassis components should be contained within a stack."; +} + +identity cpu { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of central processing unit."; +} + +identity energy-object { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of energy object, i.e., it is a piece of equipment that is + part of or attached to a communications network that is + monitored, it is controlled, or it aids in the management of + another device for Energy Management."; +} + +identity battery { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of battery."; +} + +identity storage-drive { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of component with data storage capability as its main + functionality, e.g., hard disk drive (HDD), solid-state device + (SSD), solid-state hybrid drive (SSHD), object storage device + (OSD), or other."; +} +} diff --git a/netconf-server/schemas/ietf-crypto-types.yang b/netconf-server/schemas/ietf-crypto-types.yang new file mode 100644 index 0000000..836321e --- /dev/null +++ b/netconf-server/schemas/ietf-crypto-types.yang @@ -0,0 +1,1783 @@ +module ietf-crypto-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-crypto-types"; + prefix ct; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + Author: Kent Watsen + Author: Wang Haiguang "; + + description + "This module defines common YANG types for cryptographic + applications. + + Copyright (c) 2019 IETF Trust and the persons identified + as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with + or without modification, is permitted pursuant to, and + subject to the license terms contained in, the Simplified + BSD License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX + (https://www.rfc-editor.org/info/rfcXXXX); see the RFC + itself for full legal notices.; + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', + 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', + 'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document + are to be interpreted as described in BCP 14 (RFC 2119) + (RFC 8174) when, and only when, they appear in all + capitals, as shown here."; + + revision 2019-04-29 { + description + "Initial version"; + reference + "RFC XXXX: Common YANG Data Types for Cryptography"; + } + + /**************************************/ + /* Identities for Hash Algorithms */ + /**************************************/ + + identity hash-algorithm { + description + "A base identity for hash algorithm verification."; + } + + identity sha-224 { + base hash-algorithm; + description + "The SHA-224 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + identity sha-256 { + base hash-algorithm; + description + "The SHA-256 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + identity sha-384 { + base hash-algorithm; + description + "The SHA-384 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + identity sha-512 { + base hash-algorithm; + description + "The SHA-512 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + /***********************************************/ + /* Identities for Asymmetric Key Algorithms */ + /***********************************************/ + + identity asymmetric-key-algorithm { + description + "Base identity from which all asymmetric key + encryption Algorithm."; + } + + identity rsa1024 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 1024-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa2048 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 2048-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa3072 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 3072-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa4096 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 4096-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa7680 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 7680-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa15360 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 15360-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity secp192r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + identity secp224r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp256r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp384r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp521r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + /*************************************/ + /* Identities for MAC Algorithms */ + /*************************************/ + + identity mac-algorithm { + description + "A base identity for mac generation."; + } + + identity hmac-sha1 { + base mac-algorithm; + description + "Generating MAC using SHA1 hash function"; + reference + "RFC 3174: US Secure Hash Algorithm 1 (SHA1)"; + } + + identity hmac-sha1-96 { + base mac-algorithm; + description + "Generating MAC using SHA1 hash function"; + reference + "RFC 2404: The Use of HMAC-SHA-1-96 within ESP and AH"; + } + + identity hmac-sha2-224 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-256 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-256-128 { + base mac-algorithm; + description + "Generating a 256 bits MAC using SHA2 hash function and + truncate it to 128 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 + with IPsec"; + } + + identity hmac-sha2-384 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-384-192 { + base mac-algorithm; + description + "Generating a 384 bits MAC using SHA2 hash function and + truncate it to 192 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with + IPsec"; + } + + identity hmac-sha2-512 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-512-256 { + base mac-algorithm; + description + "Generating a 512 bits MAC using SHA2 hash function and + truncating it to 256 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with + IPsec"; + } + + identity aes-128-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-192-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-256-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-cmac-96 { + base mac-algorithm; + description + "Generating MAC using Advanced Encryption Standard (AES) + Cipher-based Message Authentication Code (CMAC)"; + reference + "RFC 4494: The AES-CMAC-96 Algorithm and its Use with IPsec"; + } + + identity aes-cmac-128 { + base mac-algorithm; + description + "Generating MAC using Advanced Encryption Standard (AES) + Cipher-based Message Authentication Code (CMAC)"; + reference + "RFC 4493: The AES-CMAC Algorithm"; + } + + /********************************************/ + /* Identities for Encryption Algorithms */ + /********************************************/ + + identity encryption-algorithm { + description + "A base identity for encryption algorithm."; + } + + identity aes-128-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 128 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-192-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 192 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-256-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 256 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-128-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 128 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + identity aes-192-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 192 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-256-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 256 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + /****************************************************/ + /* Identities for Encryption and MAC Algorithms */ + /****************************************************/ + + identity encryption-and-mac-algorithm { + description + "A base identity for encryption and MAC algorithm."; + } + + identity aes-128-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-192-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 192 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-256-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 256 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-128-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + + identity aes-192-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 192 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + + identity mac-aes-256-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + identity chacha20-poly1305 { + base encryption-and-mac-algorithm; + description + "Encrypt message with chacha20 algorithm and generate MAC with + POLY1305; it can also be used for generating MAC"; + reference + "RFC 8439: ChaCha20 and Poly1305 for IETF Protocols"; + } + + /******************************************/ + /* Identities for signature algorithm */ + /******************************************/ + + identity signature-algorithm { + description + "A base identity for asymmetric key encryption algorithm."; + } + + identity dsa-sha1 { + base signature-algorithm; + description + "The signature algorithm using DSA algorithm with SHA1 hash + algorithm"; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity rsassa-pkcs1-sha1 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the SHA1 + hash algorithm."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity rsassa-pkcs1-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA256 hash algorithm."; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell + (SSH) Protocol + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + identity rsassa-pkcs1-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA384 hash algorithm."; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pkcs1-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA512 hash algorithm."; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell + (SSH) Protocol + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA384 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA512 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp256r1-sha256 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp256r1 + and SHA256 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp384r1-sha384 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp384r1 + and SHA384 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp521r1-sha512 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp521r1 + and SHA512 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ed25519 { + base signature-algorithm; + description + "The signature algorithm using EdDSA as defined in RFC 8032 or + its successors."; + reference + "RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + + identity ed448 { + base signature-algorithm; + description + "The signature algorithm using EdDSA as defined in RFC 8032 or + its successors."; + reference + "RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + + identity eccsi { + base signature-algorithm; + description + "The signature algorithm using ECCSI signature as defined in + RFC 6507."; + reference + "RFC 6507: + Elliptic Curve-Based Certificateless Signatures for + Identity-based Encryption (ECCSI)"; + } + + /**********************************************/ + /* Identities for key exchange algorithms */ + /**********************************************/ + + identity key-exchange-algorithm { + description + "A base identity for Diffie-Hellman based key exchange + algorithm."; + } + + identity psk-only { + base key-exchange-algorithm; + description + "Using Pre-shared key for authentication and key exchange"; + reference + "RFC 4279: + Pre-Shared Key cipher suites for Transport Layer Security + (TLS)"; + } + + identity dhe-ffdhe2048 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 2048 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe3072 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 3072 bit finite + field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe4096 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 4096 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe6144 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 6144 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe8192 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 8192 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity psk-dhe-ffdhe2048 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE2048"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe3072 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE3072"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe4096 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE4096"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe6144 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE6144"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe8192 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE8192"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdhe-secp256r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp256r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-secp384r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp384r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-secp521r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp521r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-x25519 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve x25519"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-x448 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve x448"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity psk-ecdhe-secp256r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp256r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-secp384r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp384r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-secp521r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp521r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-x25519 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve x25519"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-x448 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve x448"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity diffie-hellman-group14-sha1 { + base key-exchange-algorithm; + description + "Using DH group14 and SHA1 for key exchange"; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity diffie-hellman-group14-sha256 { + base key-exchange-algorithm; + description + "Using DH group14 and SHA256 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group15-sha512 { + base key-exchange-algorithm; + description + "Using DH group15 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group16-sha512 { + base key-exchange-algorithm; + description + "Using DH group16 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group17-sha512 { + base key-exchange-algorithm; + description + "Using DH group17 and SHA512 for key exchange"; + + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group18-sha512 { + base key-exchange-algorithm; + description + "Using DH group18 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity ecdh-sha2-secp256r1 { + base key-exchange-algorithm; + description + "Elliptic curve-based Diffie Hellman key exchange over curve + secp256r1 and using SHA2 for MAC generation"; + reference + "RFC 6239: Suite B Cryptographic Suites for Secure Shell + (SSH)"; + } + + identity ecdh-sha2-secp384r1 { + base key-exchange-algorithm; + description + "Elliptic curve-based Diffie Hellman key exchange over curve + secp384r1 and using SHA2 for MAC generation"; + reference + "RFC 6239: Suite B Cryptographic Suites for Secure Shell + (SSH)"; + } + + identity rsaes-oaep { + base key-exchange-algorithm; + description + "RSAES-OAEP combines the RSAEP and RSADP primitives with the + EME-OAEP encoding method"; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsaes-pkcs1-v1_5 { + base key-exchange-algorithm; + description + " RSAES-PKCS1-v1_5 combines the RSAEP and RSADP primitives + with the EME-PKCS1-v1_5 encoding method"; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + /**********************************************************/ + /* Typedefs for identityrefs to above base identities */ + /**********************************************************/ + + typedef hash-algorithm-ref { + type identityref { + base hash-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'hash-algorithm' base identity."; + } + + typedef signature-algorithm-ref { + type identityref { + base signature-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'signature-algorithm' base identity."; + } + + typedef mac-algorithm-ref { + type identityref { + base mac-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'mac-algorithm' base identity."; + } + + typedef encryption-algorithm-ref { + type identityref { + base encryption-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'encryption-algorithm' + base identity."; + } + + typedef encryption-and-mac-algorithm-ref { + type identityref { + base encryption-and-mac-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'encryption-and-mac-algorithm' + base identity."; + } + + typedef asymmetric-key-algorithm-ref { + type identityref { + base asymmetric-key-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'asymmetric-key-algorithm' + base identity."; + } + + typedef key-exchange-algorithm-ref { + type identityref { + base key-exchange-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'key-exchange-algorithm' base identity."; + } + + /***************************************************/ + /* Typedefs for ASN.1 structures from RFC 5280 */ + /***************************************************/ + + typedef x509 { + type binary; + description + "A Certificate structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + typedef crl { + type binary; + description + "A CertificateList structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + /***********************************************/ + /* Typedefs for ASN.1 structures from 5652 */ + /***********************************************/ + + typedef cms { + type binary; + description + "A ContentInfo structure, as specified in RFC 5652, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5652: + Cryptographic Message Syntax (CMS) + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + typedef data-content-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + data content type, as described by Section 4 in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef signed-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + signed-data content type, as described by Section 5 in + RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef enveloped-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + enveloped-data content type, as described by Section 6 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef digested-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + digested-data content type, as described by Section 7 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef encrypted-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + encrypted-data content type, as described by Section 8 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef authenticated-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + authenticated-data content type, as described by Section 9 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + /***************************************************/ + /* Typedefs for structures related to RFC 4253 */ + /***************************************************/ + + typedef ssh-host-key { + type binary; + description + "The binary public key data for this SSH key, as + specified by RFC 4253, Section 6.6, i.e.: + + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + } + + /*********************************************************/ + /* Typedefs for ASN.1 structures related to RFC 5280 */ + /*********************************************************/ + + typedef trust-anchor-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a self-signed + root certificate."; + } + + typedef end-entity-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a certificate + that is neither self-signed nor having Basic constraint + CA true."; + } + + /*********************************************************/ + /* Typedefs for ASN.1 structures related to RFC 5652 */ + /*********************************************************/ + + typedef trust-anchor-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the chain of + X.509 certificates needed to authenticate the certificate + presented by a client or end-entity. + + The CMS MUST contain only a single chain of certificates. + The client or end-entity certificate MUST only authenticate + to last intermediate CA certificate listed in the chain. + + In all cases, the chain MUST include a self-signed root + certificate. In the case where the root certificate is + itself the issuer of the client or end-entity certificate, + only one certificate is present. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure that is commonly used to disseminate X.509 + certificates and revocation objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile."; + } + + typedef end-entity-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the end + entity certificate itself, and MAY contain any number + of intermediate certificates leading up to a trust + anchor certificate. The trust anchor certificate + MAY be included as well. + + The CMS MUST contain a single end entity certificate. + The CMS MUST NOT contain any spurious certificates. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure that is commonly used to disseminate X.509 + certificates and revocation objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile."; + } + + /**********************************************/ + /* Groupings for keys and/or certificates */ + /**********************************************/ + + grouping public-key-grouping { + description + "A public key. + + The 'algorithm' and 'public-key' nodes are not + mandatory because they MAY be defined in . + Implementations SHOULD assert that these values are + either configured or that they exist in ."; + leaf algorithm { + nacm:default-deny-write; + type asymmetric-key-algorithm-ref; + must '../public-key'; + description + "Identifies the key's algorithm. More specifically, + this leaf specifies how the 'public-key' binary leaf + is encoded."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf public-key { + nacm:default-deny-write; + type binary; + must '../algorithm'; + description + "A binary that contains the value of the public key. The + interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPublicKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented using the 'publicKey' described in + RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + } + + grouping asymmetric-key-pair-grouping { + description + "A private/public key pair. + The 'algorithm', 'public-key', and 'private-key' nodes are + not mandatory because they MAY be defined in . + Implementations SHOULD assert that these values are either + configured or that they exist in ."; + uses public-key-grouping; + leaf private-key { + nacm:default-deny-all; + type union { + type binary; + type enumeration { + enum permanently-hidden { + description + "The private key is inaccessible due to being + protected by the system (e.g., a cryptographic + hardware module). + + How such keys are backed-up and restored, if + at all, is implementation specific. + + Servers MUST fail any attempt by a client to + configure this value directly. This value is + not set by clients, but rather is set by the + 'generate-hidden-key' and 'install-hidden-key' + actions."; + } + } + } + must '../public-key'; + description + "A binary that contains the value of the private key. The + interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPrivateKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented as ECPrivateKey as defined in RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } // private-key + + action generate-hidden-key { + nacm:default-deny-all; + description + "Requests the device to generate a hidden key using the + specified asymmetric key algorithm. This action is + used to request the system to generate a key that is + 'permanently-hidden', perhaps protected by a cryptographic + hardware module. The resulting asymmetric key values are + considered operational state and hence present only in + and bound to the lifetime of the parent + 'config true' node. Subsequent invocations of this or + the 'install-hidden-key' action are denied with error-tag + 'data-exists'."; + input { + leaf algorithm { + type asymmetric-key-algorithm-ref; + mandatory true; + description + "The algorithm to be used when generating the + asymmetric key."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + } + } // generate-hidden-key + + action install-hidden-key { + nacm:default-deny-all; + description + "Requests the device to load the specified values into + a hidden key. The resulting asymmetric key values are + considered operational state and hence present only in + and bound to the lifetime of the parent + 'config true' node. Subsequent invocations of this + or the 'generate-hidden-key' action are denied with + error-tag 'data-exists'."; + input { + leaf algorithm { + type asymmetric-key-algorithm-ref; + mandatory true; + description + "The algorithm to be used when generating the + asymmetric key."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf public-key { + type binary; + description + "A binary that contains the value of the public key. + The interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an + RSA key is represented as RSAPublicKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented using the 'publicKey' described in + RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + leaf private-key { + type binary; + description + "A binary that contains the value of the private key. + The interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPrivateKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented as ECPrivateKey as defined in RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + } + } // install-hidden-key + } // asymmetric-key-pair-grouping + + + grouping trust-anchor-cert-grouping { + description + "A trust anchor certificate, and a notification for when + it is about to (or already has) expire."; + leaf cert { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping trust-anchor-certs-grouping { + description + "A list of trust anchor certificates, and a notification + for when one is about to (or already has) expire."; + leaf-list cert { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping end-entity-cert-grouping { + description + "An end entity certificate, and a notification for when + it is about to (or already has) expire."; + leaf cert { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping end-entity-certs-grouping { + description + "A list of end entity certificates, and a notification for + when one is about to (or already has) expire."; + leaf-list cert { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping asymmetric-key-pair-with-cert-grouping { + description + "A private/public key pair and an associated certificate."; + uses asymmetric-key-pair-grouping; + uses end-entity-cert-grouping; + + action generate-certificate-signing-request { + nacm:default-deny-all; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. The specified assertions need + to be appropriate for the certificate's use. For + example, an entity certificate for a TLS server + SHOULD have values that enable clients to satisfy + RFC 6125 processing."; + input { + leaf subject { + type binary; + mandatory true; + description + "The 'subject' field per the CertificationRequestInfo + structure as specified by RFC 2986, Section 4.1 + encoded using the ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + leaf attributes { + type binary; + description + "The 'attributes' field from the structure + CertificationRequestInfo as specified by RFC 2986, + Section 4.1 encoded using the ASN.1 distinguished + encoding rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + output { + leaf certificate-signing-request { + type binary; + mandatory true; + description + "A CertificationRequest structure as specified by + RFC 2986, Section 4.2 encoded using the ASN.1 + distinguished encoding rules (DER), as specified + in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + } // generate-certificate-signing-request + } // asymmetric-key-pair-with-cert-grouping + + + grouping asymmetric-key-pair-with-certs-grouping { + description + "A private/public key pair and associated certificates."; + uses asymmetric-key-pair-grouping; + container certificates { + nacm:default-deny-write; + description + "Certificates associated with this asymmetric key. + More than one certificate supports, for instance, + a TPM-protected asymmetric key that has both IDevID + and LDevID certificates associated."; + list certificate { + key "name"; + description + "A certificate for this asymmetric key."; + leaf name { + type string; + description + "An arbitrary name for the certificate. If the name + matches the name of a certificate that exists + independently in (i.e., an IDevID), + then the 'cert' node MUST NOT be configured."; + } + uses end-entity-cert-grouping; + } + } // certificates + + action generate-certificate-signing-request { + nacm:default-deny-all; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. The specified assertions need + to be appropriate for the certificate's use. For + example, an entity certificate for a TLS server + SHOULD have values that enable clients to satisfy + RFC 6125 processing."; + input { + leaf subject { + type binary; + mandatory true; + description + "The 'subject' field per the CertificationRequestInfo + structure as specified by RFC 2986, Section 4.1 + encoded using the ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + leaf attributes { + type binary; + description + "The 'attributes' field from the structure + CertificationRequestInfo as specified by RFC 2986, + Section 4.1 encoded using the ASN.1 distinguished + encoding rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + output { + leaf certificate-signing-request { + type binary; + mandatory true; + description + "A CertificationRequest structure as specified by + RFC 2986, Section 4.2 encoded using the ASN.1 + distinguished encoding rules (DER), as specified + in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + } // generate-certificate-signing-request + } // asymmetric-key-pair-with-certs-grouping +} diff --git a/netconf-server/schemas/ietf-hardware.yang b/netconf-server/schemas/ietf-hardware.yang new file mode 100644 index 0000000..d909018 --- /dev/null +++ b/netconf-server/schemas/ietf-hardware.yang @@ -0,0 +1,1141 @@ +module ietf-hardware { +yang-version 1.1; +namespace "urn:ietf:params:xml:ns:yang:ietf-hardware"; +prefix hw; + +import ietf-inet-types { + prefix inet; +} +import ietf-yang-types { + prefix yang; +} +import iana-hardware { + prefix ianahw; +} + +organization + "IETF NETMOD (Network Modeling) Working Group"; + +contact + "WG Web: + WG List: + Editor: Andy Bierman + + Editor: Martin Bjorklund + + Editor: Jie Dong + + Editor: Dan Romascanu + "; + +description + "This module contains a collection of YANG definitions for + managing hardware. + This data model is designed for the Network Management Datastore + Architecture (NMDA) defined in RFC 8342. + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 8348; see + the RFC itself for full legal notices."; + +revision 2018-03-13 { + description + "Initial revision."; + reference + "RFC 8348: A YANG Data Model for Hardware Management"; +} + +/* + * Features + */ + +feature entity-mib { + description + "This feature indicates that the device implements + the ENTITY-MIB."; + reference + "RFC 6933: Entity MIB (Version 4)"; +} + +feature hardware-state { + description + "Indicates that ENTITY-STATE-MIB objects are supported"; + reference + "RFC 4268: Entity State MIB"; +} + +feature hardware-sensor { + description + "Indicates that ENTITY-SENSOR-MIB objects are supported"; + reference + "RFC 3433: Entity Sensor Management Information Base"; +} + +/* + * Typedefs + */ + +typedef admin-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report administrative state."; + } + enum locked { + value 2; + description + "The resource is administratively prohibited from use."; + } + enum shutting-down { + value 3; + description + "The resource usage is administratively limited to current + instances of use."; + } + enum unlocked { + value 4; + description + "The resource is not administratively prohibited from + use."; + } + } + description + "Represents the various possible administrative states."; + reference + "RFC 4268: Entity State MIB - EntityAdminState"; +} + +typedef oper-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report its operational state."; + } + enum disabled { + value 2; + description + "The resource is totally inoperable."; + } + enum enabled { + value 3; + + description + "The resource is partially or fully operable."; + } + enum testing { + value 4; + description + "The resource is currently being tested and cannot + therefore report whether or not it is operational."; + } + } + description + "Represents the possible values of operational states."; + reference + "RFC 4268: Entity State MIB - EntityOperState"; +} + +typedef usage-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report usage state."; + } + enum idle { + value 2; + description + "The resource is servicing no users."; + } + enum active { + value 3; + description + "The resource is currently in use, and it has sufficient + spare capacity to provide for additional users."; + } + enum busy { + value 4; + description + "The resource is currently in use, but it currently has no + spare capacity to provide for additional users."; + } + } + description + "Represents the possible values of usage states."; + reference + "RFC 4268: Entity State MIB - EntityUsageState"; +} + +typedef alarm-state { + type bits { + bit unknown { + position 0; + description + "The resource is unable to report alarm state."; + } + bit under-repair { + position 1; + description + "The resource is currently being repaired, which, depending + on the implementation, may make the other values in this + bit string not meaningful."; + } + bit critical { + position 2; + description + "One or more critical alarms are active against the + resource."; + } + bit major { + position 3; + description + "One or more major alarms are active against the + resource."; + } + bit minor { + position 4; + description + "One or more minor alarms are active against the + resource."; + } + bit warning { + position 5; + description + "One or more warning alarms are active against the + resource."; + } + bit indeterminate { + position 6; + description + "One or more alarms of whose perceived severity cannot be + determined are active against this resource."; + } + } + description + "Represents the possible values of alarm states. An alarm is a + persistent indication of an error or warning condition. + When no bits of this attribute are set, then no active alarms + are known against this component and it is not under repair."; + reference + "RFC 4268: Entity State MIB - EntityAlarmStatus"; +} + +typedef standby-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report standby state."; + } + enum hot-standby { + value 2; + description + "The resource is not providing service, but it will be + immediately able to take over the role of the resource to + be backed up, without the need for initialization + activity, and will contain the same information as the + resource to be backed up."; + } + enum cold-standby { + value 3; + description + "The resource is to back up another resource, but it will + not be immediately able to take over the role of a + resource to be backed up and will require some + initialization activity."; + } + enum providing-service { + value 4; + description + "The resource is providing service."; + } + } + description + "Represents the possible values of standby states."; + reference + "RFC 4268: Entity State MIB - EntityStandbyStatus"; +} + +typedef sensor-value-type { + type enumeration { + enum other { + value 1; + description + "A measure other than those listed below."; + } + enum unknown { + value 2; + description + "An unknown measurement or arbitrary, relative numbers"; + } + enum volts-AC { + value 3; + description + "A measure of electric potential (alternating current)."; + } + enum volts-DC { + value 4; + description + "A measure of electric potential (direct current)."; + } + enum amperes { + value 5; + description + "A measure of electric current."; + } + enum watts { + value 6; + description + "A measure of power."; + } + enum hertz { + value 7; + description + "A measure of frequency."; + } + enum celsius { + value 8; + description + "A measure of temperature."; + } + enum percent-RH { + value 9; + description + "A measure of percent relative humidity."; + } + enum rpm { + value 10; + description + "A measure of shaft revolutions per minute."; + } + enum cmm { + value 11; + description + "A measure of cubic meters per minute (airflow)."; + } + enum truth-value { + value 12; + description + "Value is one of 1 (true) or 2 (false)"; + } + } + description + "A node using this data type represents the sensor measurement + data type associated with a physical sensor value. The actual + data units are determined by examining a node of this type + together with the associated sensor-value-scale node. + A node of this type SHOULD be defined together with nodes of + type sensor-value-scale and type sensor-value-precision. + These three types are used to identify the semantics of a node + of type sensor-value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorDataType"; +} + +typedef sensor-value-scale { + type enumeration { + enum yocto { + value 1; + description + "Data scaling factor of 10^-24."; + } + enum zepto { + value 2; + description + "Data scaling factor of 10^-21."; + } + enum atto { + value 3; + description + "Data scaling factor of 10^-18."; + } + enum femto { + value 4; + description + "Data scaling factor of 10^-15."; + } + enum pico { + value 5; + description + "Data scaling factor of 10^-12."; + } + enum nano { + value 6; + description + "Data scaling factor of 10^-9."; + } + enum micro { + value 7; + description + "Data scaling factor of 10^-6."; + } + enum milli { + value 8; + description + "Data scaling factor of 10^-3."; + } + enum units { + value 9; + description + "Data scaling factor of 10^0."; + } + enum kilo { + value 10; + description + "Data scaling factor of 10^3."; + } + enum mega { + value 11; + description + "Data scaling factor of 10^6."; + } + enum giga { + value 12; + description + "Data scaling factor of 10^9."; + } + enum tera { + value 13; + description + "Data scaling factor of 10^12."; + } + enum peta { + value 14; + description + "Data scaling factor of 10^15."; + } + enum exa { + value 15; + description + "Data scaling factor of 10^18."; + } + enum zetta { + value 16; + description + "Data scaling factor of 10^21."; + } + enum yotta { + value 17; + description + "Data scaling factor of 10^24."; + } + } + description + "A node using this data type represents a data scaling factor, + represented with an International System of Units (SI) prefix. + The actual data units are determined by examining a node of + this type together with the associated sensor-value-type. + A node of this type SHOULD be defined together with nodes of + type sensor-value-type and type sensor-value-precision. + Together, associated nodes of these three types are used to + identify the semantics of a node of type sensor-value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorDataScale"; +} + +typedef sensor-value-precision { + type int8 { + range "-8 .. 9"; + } + description + "A node using this data type represents a sensor value + precision range. + A node of this type SHOULD be defined together with nodes of + type sensor-value-type and type sensor-value-scale. Together, + associated nodes of these three types are used to identify the + semantics of a node of type sensor-value. + If a node of this type contains a value in the range 1 to 9, + it represents the number of decimal places in the fractional + part of an associated sensor-value fixed-point number. + If a node of this type contains a value in the range -8 to -1, + it represents the number of accurate digits in the associated + sensor-value fixed-point number. + The value zero indicates the associated sensor-value node is + not a fixed-point number. + Server implementers must choose a value for the associated + sensor-value-precision node so that the precision and accuracy + of the associated sensor-value node is correctly indicated. + For example, a component representing a temperature sensor + that can measure 0 to 100 degrees C in 0.1 degree + increments, +/- 0.05 degrees, would have a + sensor-value-precision value of '1', a sensor-value-scale + value of 'units', and a sensor-value ranging from '0' to + '1000'. The sensor-value would be interpreted as + 'degrees C * 10'."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorPrecision"; +} + +typedef sensor-value { + type int32 { + range "-1000000000 .. 1000000000"; + } + description + "A node using this data type represents a sensor value. + A node of this type SHOULD be defined together with nodes of + type sensor-value-type, type sensor-value-scale, and + type sensor-value-precision. Together, associated nodes of + those three types are used to identify the semantics of a node + of this data type. + The semantics of a node using this data type are determined by + the value of the associated sensor-value-type node. + If the associated sensor-value-type node is equal to 'voltsAC', + 'voltsDC', 'amperes', 'watts', 'hertz', 'celsius', or 'cmm', + then a node of this type MUST contain a fixed-point number + ranging from -999,999,999 to +999,999,999. The value + -1000000000 indicates an underflow error. The value + +1000000000 indicates an overflow error. The + sensor-value-precision indicates how many fractional digits + are represented in the associated sensor-value node. + If the associated sensor-value-type node is equal to + 'percentRH', then a node of this type MUST contain a number + ranging from 0 to 100. + If the associated sensor-value-type node is equal to 'rpm', + then a node of this type MUST contain a number ranging from + -999,999,999 to +999,999,999. + If the associated sensor-value-type node is equal to + 'truth-value', then a node of this type MUST contain either the + value 1 (true) or the value 2 (false). + If the associated sensor-value-type node is equal to 'other' or + 'unknown', then a node of this type MUST contain a number + ranging from -1000000000 to 1000000000."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorValue"; +} + +typedef sensor-status { + type enumeration { + enum ok { + value 1; + description + "Indicates that the server can obtain the sensor value."; + } + enum unavailable { + value 2; + description + "Indicates that the server presently cannot obtain the + sensor value."; + } + enum nonoperational { + value 3; + description + "Indicates that the server believes the sensor is broken. + The sensor could have a hard failure (disconnected wire) + or a soft failure such as out-of-range, jittery, or wildly + fluctuating readings."; + } + } + description + "A node using this data type represents the operational status + of a physical sensor."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorStatus"; +} + +/* + * Data nodes + */ + +container hardware { + description + "Data nodes representing components. + If the server supports configuration of hardware components, + then this data model is instantiated in the configuration + datastores supported by the server. The leaf-list 'datastore' + for the module 'ietf-hardware' in the YANG library provides + this information."; + + leaf last-change { + type yang:date-and-time; + config false; + description + "The time the '/hardware/component' list changed in the + operational state."; + } + + list component { + key name; + description + "List of components. + When the server detects a new hardware component, it + initializes a list entry in the operational state. + If the server does not support configuration of hardware + components, list entries in the operational state are + initialized with values for all nodes as detected by the + implementation. + Otherwise, this procedure is followed: + 1. If there is an entry in the '/hardware/component' list + in the intended configuration with values for the nodes + 'class', 'parent', and 'parent-rel-pos' that are equal + to the detected values, then the list entry in the + operational state is initialized with the configured + values, including the 'name'. + 2. Otherwise (i.e., there is no matching configuration + entry), the list entry in the operational state is + initialized with values for all nodes as detected by + the implementation. + If the '/hardware/component' list in the intended + configuration is modified, then the system MUST behave as if + it re-initializes itself and follow the procedure in (1)."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalEntry"; + + leaf name { + type string; + description + "The name assigned to this component. + This name is not required to be the same as + entPhysicalName."; + } + + leaf class { + type identityref { + base ianahw:hardware-class; + } + mandatory true; + description + "An indication of the general hardware type of the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalClass"; + } + + leaf physical-index { + if-feature entity-mib; + type int32 { + range "1..2147483647"; + } + config false; + description + "The entPhysicalIndex for the entPhysicalEntry represented + by this list entry."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalIndex"; + } + + leaf description { + type string; + config false; + description + "A textual description of the component. This node should + contain a string that identifies the manufacturer's name + for the component and should be set to a distinct value + for each version or model of the component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalDescr"; + } + + leaf parent { + type leafref { + path "../../component/name"; + require-instance false; + } + description + "The name of the component that physically contains this + component. + If this leaf is not instantiated, it indicates that this + component is not contained in any other component. + In the event that a physical component is contained by + more than one physical component (e.g., double-wide + modules), this node contains the name of one of these + components. An implementation MUST use the same name + every time this node is instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalContainedIn"; + } + + leaf parent-rel-pos { + type int32 { + range "0 .. 2147483647"; + } + description + "An indication of the relative position of this child + component among all its sibling components. Sibling + components are defined as components that: + o share the same value of the 'parent' node and + o share a common base identity for the 'class' node. + Note that the last rule gives implementations flexibility + in how components are numbered. For example, some + implementations might have a single number series for all + components derived from 'ianahw:port', while some others + might have different number series for different + components with identities derived from 'ianahw:port' (for + example, one for registered jack 45 (RJ45) and one for + small form-factor pluggable (SFP))."; + + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalParentRelPos"; + } + + leaf-list contains-child { + type leafref { + path "../../component/name"; + } + config false; + description + "The name of the contained component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalChildIndex"; + } + + leaf hardware-rev { + type string; + config false; + description + "The vendor-specific hardware revision string for the + component. The preferred value is the hardware revision + identifier actually printed on the component itself (if + present)."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalHardwareRev"; + } + + leaf firmware-rev { + type string; + config false; + description + "The vendor-specific firmware revision string for the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalFirmwareRev"; + } + + leaf software-rev { + type string; + config false; + + description + "The vendor-specific software revision string for the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalSoftwareRev"; + } + + leaf serial-num { + type string; + config false; + description + "The vendor-specific serial number string for the + component. The preferred value is the serial number + string actually printed on the component itself (if + present)."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalSerialNum"; + } + + leaf mfg-name { + type string; + config false; + description + "The name of the manufacturer of this physical component. + The preferred value is the manufacturer name string + actually printed on the component itself (if present). + Note that comparisons between instances of the + 'model-name', 'firmware-rev', 'software-rev', and + 'serial-num' nodes are only meaningful amongst components + with the same value of 'mfg-name'. + If the manufacturer name string associated with the + physical component is unknown to the server, then this + node is not instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgName"; + } + + leaf model-name { + type string; + config false; + description + "The vendor-specific model name identifier string + associated with this physical component. The preferred + value is the customer-visible part number, which may be + printed on the component itself. + If the model name string associated with the physical + component is unknown to the server, then this node is not + instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalModelName"; + } + + leaf alias { + type string; + description + "An 'alias' name for the component, as specified by a + network manager, that provides a non-volatile 'handle' for + the component. + If no configured value exists, the server MAY set the + value of this node to a locally unique value in the + operational state. + A server implementation MAY map this leaf to the + entPhysicalAlias MIB object. Such an implementation needs + to use some mechanism to handle the differences in size + and characters allowed between this leaf and + entPhysicalAlias. The definition of such a mechanism is + outside the scope of this document."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalAlias"; + } + + leaf asset-id { + type string; + description + "This node is a user-assigned asset tracking identifier for + the component. + A server implementation MAY map this leaf to the + entPhysicalAssetID MIB object. Such an implementation + needs to use some mechanism to handle the differences in + size and characters allowed between this leaf and + entPhysicalAssetID. The definition of such a mechanism is + outside the scope of this document."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalAssetID"; + } + + leaf is-fru { + type boolean; + config false; + + description + "This node indicates whether or not this component is + considered a 'field-replaceable unit' by the vendor. If + this node contains the value 'true', then this component + identifies a field-replaceable unit. For all components + that are permanently contained within a field-replaceable + unit, the value 'false' should be returned for this + node."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalIsFRU"; + } + + leaf mfg-date { + type yang:date-and-time; + config false; + description + "The date of manufacturing of the managed component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgDate"; + } + + leaf-list uri { + type inet:uri; + description + "This node contains identification information about the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalUris"; + } + + leaf uuid { + type yang:uuid; + config false; + description + "A Universally Unique Identifier of the component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalUUID"; + } + + container state { + if-feature hardware-state; + description + "State-related nodes"; + reference + "RFC 4268: Entity State MIB"; + + leaf state-last-changed { + type yang:date-and-time; + config false; + description + "The date and time when the value of any of the + admin-state, oper-state, usage-state, alarm-state, or + standby-state changed for this component. + If there has been no change since the last + re-initialization of the local system, this node + contains the date and time of local system + initialization. If there has been no change since the + component was added to the local system, this node + contains the date and time of the insertion."; + reference + "RFC 4268: Entity State MIB - entStateLastChanged"; + } + + leaf admin-state { + type admin-state; + description + "The administrative state for this component. + This node refers to a component's administrative + permission to service both other components within its + containment hierarchy as well other users of its + services defined by means outside the scope of this + module. + Some components exhibit only a subset of the remaining + administrative state values. Some components cannot be + locked; hence, this node exhibits only the 'unlocked' + state. Other components cannot be shut down gracefully; + hence, this node does not exhibit the 'shutting-down' + state."; + reference + "RFC 4268: Entity State MIB - entStateAdmin"; + } + + leaf oper-state { + type oper-state; + config false; + description + "The operational state for this component. + Note that this node does not follow the administrative + state. An administrative state of 'down' does not + predict an operational state of 'disabled'. + Note that some implementations may not be able to + accurately report oper-state while the admin-state node + has a value other than 'unlocked'. In these cases, this + node MUST have a value of 'unknown'."; + reference + "RFC 4268: Entity State MIB - entStateOper"; + } + + leaf usage-state { + type usage-state; + config false; + description + "The usage state for this component. + This node refers to a component's ability to service + more components in a containment hierarchy. + Some components will exhibit only a subset of the usage + state values. Components that are unable to ever + service any components within a containment hierarchy + will always have a usage state of 'busy'. In some + cases, a component will be able to support only one + other component within its containment hierarchy and + will therefore only exhibit values of 'idle' and + 'busy'."; + reference + "RFC 4268: Entity State MIB - entStateUsage"; + } + + leaf alarm-state { + type alarm-state; + config false; + description + "The alarm state for this component. It does not + include the alarms raised on child components within its + containment hierarchy."; + reference + "RFC 4268: Entity State MIB - entStateAlarm"; + } + + leaf standby-state { + type standby-state; + config false; + description + "The standby state for this component. + Some components will exhibit only a subset of the + remaining standby state values. If this component + cannot operate in a standby role, the value of this node + will always be 'providing-service'."; + reference + "RFC 4268: Entity State MIB - entStateStandby"; + } + } + + container sensor-data { + when 'derived-from-or-self(../class, + "ianahw:sensor")' { + description + "Sensor data nodes present for any component of type + 'sensor'"; + } + if-feature hardware-sensor; + config false; + + description + "Sensor-related nodes."; + reference + "RFC 3433: Entity Sensor Management Information Base"; + + leaf value { + type sensor-value; + description + "The most recent measurement obtained by the server + for this sensor. + A client that periodically fetches this node should also + fetch the nodes 'value-type', 'value-scale', and + 'value-precision', since they may change when the value + is changed."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValue"; + } + + leaf value-type { + type sensor-value-type; + description + "The type of data units associated with the + sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorType"; + } + leaf value-scale { + type sensor-value-scale; + description + "The (power of 10) scaling factor associated + with the sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorScale"; + } + + leaf value-precision { + type sensor-value-precision; + description + "The number of decimal places of precision + associated with the sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorPrecision"; + } + + leaf oper-status { + type sensor-status; + description + "The operational status of the sensor."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorOperStatus"; + } + + leaf units-display { + type string; + description + "A textual description of the data units that should be + used in the display of the sensor value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorUnitsDisplay"; + } + + leaf value-timestamp { + type yang:date-and-time; + description + "The time the status and/or value of this sensor was last + obtained by the server."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValueTimeStamp"; + } + leaf value-update-rate { + type uint32; + units "milliseconds"; + description + "An indication of the frequency that the server updates + the associated 'value' node, represented in + milliseconds. The value zero indicates: + - the sensor value is updated on demand (e.g., + when polled by the server for a get-request), + - the sensor value is updated when the sensor + value changes (event-driven), or + - the server does not know the update rate."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValueUpdateRate"; + } + } + } +} + +/* + * Notifications + */ + +notification hardware-state-change { + description + "A hardware-state-change notification is generated when the + value of /hardware/last-change changes in the operational + state."; + reference + "RFC 6933: Entity MIB (Version 4) - entConfigChange"; +} + +notification hardware-state-oper-enabled { + if-feature hardware-state; + description + "A hardware-state-oper-enabled notification signifies that a + component has transitioned into the 'enabled' state."; + + leaf name { + type leafref { + path "/hardware/component/name"; + } + + description + "The name of the component that has transitioned into the + 'enabled' state."; + } + leaf admin-state { + type leafref { + path "/hardware/component/state/admin-state"; + } + description + "The administrative state for the component."; + } + leaf alarm-state { + type leafref { + path "/hardware/component/state/alarm-state"; + } + description + "The alarm state for the component."; + } + reference + "RFC 4268: Entity State MIB - entStateOperEnabled"; +} + +notification hardware-state-oper-disabled { + if-feature hardware-state; + description + "A hardware-state-oper-disabled notification signifies that a + component has transitioned into the 'disabled' state."; + + leaf name { + type leafref { + path "/hardware/component/name"; + } + description + "The name of the component that has transitioned into the + 'disabled' state."; + } + leaf admin-state { + type leafref { + path "/hardware/component/state/admin-state"; + } + description + "The administrative state for the component."; + } + leaf alarm-state { + type leafref { + path "/hardware/component/state/alarm-state"; + } + + description + "The alarm state for the component."; + } + reference + "RFC 4268: Entity State MIB - entStateOperDisabled"; +} + +} diff --git a/netconf-server/schemas/ietf-inet-types.yang b/netconf-server/schemas/ietf-inet-types.yang new file mode 100644 index 0000000..b8e45c8 --- /dev/null +++ b/netconf-server/schemas/ietf-inet-types.yang @@ -0,0 +1,429 @@ +module ietf-inet-types { + +namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; +prefix "inet"; + +organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + +contact + "WG Web: + WG List: + WG Chair: David Kessens + + WG Chair: Juergen Schoenwaelder + + Editor: Juergen Schoenwaelder + "; + +description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + +revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; +} + +revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; +} + +/*** collection of types related to protocol fields ***/ + +typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; +} + +typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; +} + +typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; +} + +typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; +} + +/*** collection of types related to autonomous systems ***/ + +typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; +} + +/*** collection of types related to IP addresses and hostnames ***/ + +typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; +} + +typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + The canonical format for the zone index is the numerical + format"; +} + +typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; +} + +typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; +} + +typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; +} + +typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; +} + +typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; +} + +typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; +} + +typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; +} + +/*** collection of domain name and URI types ***/ + +typedef domain-name { + type string { + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; +} + +typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; +} + +typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; +} + +} diff --git a/netconf-server/schemas/ietf-netconf-acm.yang b/netconf-server/schemas/ietf-netconf-acm.yang new file mode 100644 index 0000000..46e5c48 --- /dev/null +++ b/netconf-server/schemas/ietf-netconf-acm.yang @@ -0,0 +1,440 @@ +module ietf-netconf-acm { + + namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"; + + prefix nacm; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + Author: Andy Bierman + + Author: Martin Bjorklund + "; + + description + "Network Configuration Access Control Model. + Copyright (c) 2012 - 2018 IETF Trust and the persons + identified as authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 8341; see + the RFC itself for full legal notices."; + + revision "2018-02-14" { + description + "Added support for YANG 1.1 actions and notifications tied to + data nodes. Clarified how NACM extensions can be used by + other data models."; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + revision "2012-02-22" { + description + "Initial version."; + reference + "RFC 6536: Network Configuration Protocol (NETCONF) + Access Control Model"; + } + + /* + * Extension statements + */ + + extension default-deny-write { + description + "Used to indicate that the data model node + represents a sensitive security system parameter. + If present, the NETCONF server will only allow the designated + 'recovery session' to have write access to the node. An + explicit access control rule is required for all other users. + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + The 'default-deny-write' extension MAY appear within a data + definition statement. It is ignored otherwise."; + } + + extension default-deny-all { + description + "Used to indicate that the data model node + controls a very sensitive security system parameter. + If present, the NETCONF server will only allow the designated + 'recovery session' to have read, write, or execute access to + the node. An explicit access control rule is required for all + other users. + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + The 'default-deny-all' extension MAY appear within a data + definition statement, 'rpc' statement, or 'notification' + statement. It is ignored otherwise."; + } + + /* + * Derived types + */ + + typedef user-name-type { + type string { + length "1..max"; + } + description + "General-purpose username string."; + } + + typedef matchall-string-type { + type string { + pattern '\*'; + } + description + "The string containing a single asterisk '*' is used + to conceptually represent all possible values + for the particular leaf using this data type."; + } + + typedef access-operations-type { + type bits { + bit create { + description + "Any protocol operation that creates a + new data node."; + } + bit read { + description + "Any protocol operation or notification that + returns the value of a data node."; + } + bit update { + description + "Any protocol operation that alters an existing + data node."; + } + bit delete { + description + "Any protocol operation that removes a data node."; + } + bit exec { + description + "Execution access to the specified protocol operation."; + } + } + description + "Access operation."; + } + + typedef group-name-type { + type string { + length "1..max"; + pattern '[^\*].*'; + } + description + "Name of administrative group to which + users can be assigned."; + } + + typedef action-type { + type enumeration { + enum permit { + description + "Requested action is permitted."; + } + enum deny { + description + "Requested action is denied."; + } + } + description + "Action taken by the server when a particular + rule matches."; + } + + typedef node-instance-identifier { + type yang:xpath1.0; + description + "Path expression used to represent a special + data node, action, or notification instance-identifier + string. + A node-instance-identifier value is an + unrestricted YANG instance-identifier expression. + All the same rules as an instance-identifier apply, + except that predicates for keys are optional. If a key + predicate is missing, then the node-instance-identifier + represents all possible server instances for that key. + This XML Path Language (XPath) expression is evaluated in the + following context: + o The set of namespace declarations are those in scope on + the leaf element where this type is used. + o The set of variable bindings contains one variable, + 'USER', which contains the name of the user of the + current session. + o The function library is the core function library, but + note that due to the syntax restrictions of an + instance-identifier, no functions are allowed. + o The context node is the root node in the data tree. + The accessible tree includes actions and notifications tied + to data nodes."; + } + + /* + * Data definition statements + */ + + container nacm { + nacm:default-deny-all; + + description + "Parameters for NETCONF access control model."; + + leaf enable-nacm { + type boolean; + default "true"; + description + "Enables or disables all NETCONF access control + enforcement. If 'true', then enforcement + is enabled. If 'false', then enforcement + is disabled."; + } + + leaf read-default { + type action-type; + default "permit"; + description + "Controls whether read access is granted if + no appropriate rule is found for a + particular read request."; + } + + leaf write-default { + type action-type; + default "deny"; + description + "Controls whether create, update, or delete access + is granted if no appropriate rule is found for a + particular write request."; + } + + leaf exec-default { + type action-type; + default "permit"; + description + "Controls whether exec access is granted if no appropriate + rule is found for a particular protocol operation request."; + } + + leaf enable-external-groups { + type boolean; + default "true"; + description + "Controls whether the server uses the groups reported by the + NETCONF transport layer when it assigns the user to a set of + NACM groups. If this leaf has the value 'false', any group + names reported by the transport layer are ignored by the + server."; + } + + leaf denied-operations { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request was denied."; + } + + leaf denied-data-writes { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request to alter + a configuration datastore was denied."; + } + + leaf denied-notifications { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that + a notification was dropped for a subscription because + access to the event type was denied."; + } + + container groups { + description + "NETCONF access control groups."; + + list group { + key name; + + description + "One NACM group entry. This list will only contain + configured entries, not any entries learned from + any transport protocols."; + + leaf name { + type group-name-type; + description + "Group name associated with this entry."; + } + + leaf-list user-name { + type user-name-type; + description + "Each entry identifies the username of + a member of the group associated with + this entry."; + } + } + } + + list rule-list { + key name; + ordered-by user; + description + "An ordered collection of access control rules."; + + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule-list."; + } + leaf-list group { + type union { + type matchall-string-type; + type group-name-type; + } + description + "List of administrative groups that will be + assigned the associated access rights + defined by the 'rule' list. + The string '*' indicates that all groups apply to the + entry."; + } + + list rule { + key name; + ordered-by user; + description + "One access control rule. + Rules are processed in user-defined order until a match is + found. A rule matches if 'module-name', 'rule-type', and + 'access-operations' match the request. If a rule + matches, the 'action' leaf determines whether or not + access is granted."; + + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule."; + } + + leaf module-name { + type union { + type matchall-string-type; + type string; + } + default "*"; + description + "Name of the module associated with this rule. + This leaf matches if it has the value '*' or if the + object being accessed is defined in the module with the + specified module name."; + } + choice rule-type { + description + "This choice matches if all leafs present in the rule + match the request. If no leafs are present, the + choice matches all requests."; + case protocol-operation { + leaf rpc-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if + its value equals the requested protocol operation + name."; + } + } + case notification { + leaf notification-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if its + value equals the requested notification name."; + } + } + + case data-node { + leaf path { + type node-instance-identifier; + mandatory true; + description + "Data node instance-identifier associated with the + data node, action, or notification controlled by + this rule. + Configuration data or state data + instance-identifiers start with a top-level + data node. A complete instance-identifier is + required for this type of path value. + The special value '/' refers to all possible + datastore contents."; + } + } + } + + leaf access-operations { + type union { + type matchall-string-type; + type access-operations-type; + } + default "*"; + description + "Access operations associated with this rule. + This leaf matches if it has the value '*' or if the + bit corresponding to the requested operation is set."; + } + + leaf action { + type action-type; + mandatory true; + description + "The access control action associated with the + rule. If a rule has been determined to match a + particular request, then this object is used + to determine whether to permit or deny the + request."; + } + + leaf comment { + type string; + description + "A textual description of the access rule."; + } + } + } + } +} diff --git a/netconf-server/schemas/ietf-netconf-monitoring-extension.yang b/netconf-server/schemas/ietf-netconf-monitoring-extension.yang new file mode 100644 index 0000000..91dc773 --- /dev/null +++ b/netconf-server/schemas/ietf-netconf-monitoring-extension.yang @@ -0,0 +1,31 @@ +module ietf-netconf-monitoring-extension { + + yang-version 1; + + namespace + "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring-extension"; + + prefix ncme; + + import ietf-netconf-monitoring { + prefix ncm; + } + + revision "2013-12-10" { + description "Initial revision."; + + } + + identity netconf-tcp { + base ncm:transport; + description + "NETCONF over TCP."; + } + + augment "/ncm:netconf-state/ncm:sessions/ncm:session" { + leaf session-identifier { + type string; + } + } + +} \ No newline at end of file diff --git a/netconf-server/schemas/ietf-netconf-monitoring.yang b/netconf-server/schemas/ietf-netconf-monitoring.yang new file mode 100644 index 0000000..8d167b8 --- /dev/null +++ b/netconf-server/schemas/ietf-netconf-monitoring.yang @@ -0,0 +1,596 @@ +module ietf-netconf-monitoring { + + yang-version 1; + + namespace + "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"; + + prefix ncm; + + import ietf-yang-types { + prefix yang; + revision-date "2013-07-15"; + } + + import ietf-inet-types { + prefix inet; + revision-date "2013-07-15"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: Mehmet Ersue + + + WG Chair: Bert Wijnen + + + Editor: Mark Scott + + + Editor: Martin Bjorklund + "; + + description + "NETCONF Monitoring Module. + All elements in this module are read-only. + + Copyright (c) 2010 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6022; see + the RFC itself for full legal notices."; + + revision "2010-10-04" { + description "Initial revision."; + reference + "RFC 6022: YANG Module for NETCONF Monitoring"; + + } + + + typedef netconf-datastore-type { + type enumeration { + enum "running" { + value 0; + } + enum "candidate" { + value 1; + } + enum "startup" { + value 2; + } + } + description + "Enumeration of possible NETCONF datastore types."; + reference + "RFC 4741: NETCONF Configuration Protocol"; + + } + + identity transport { + description + "Base identity for NETCONF transport types."; + } + + identity netconf-ssh { + base transport; + description + "NETCONF over Secure Shell (SSH)."; + reference + "RFC 4742: Using the NETCONF Configuration Protocol + over Secure SHell (SSH)"; + + } + + identity netconf-soap-over-beep { + base transport; + description + "NETCONF over Simple Object Access Protocol (SOAP) over + Blocks Extensible Exchange Protocol (BEEP)."; + reference + "RFC 4743: Using NETCONF over the Simple Object + Access Protocol (SOAP)"; + + } + + identity netconf-soap-over-https { + base transport; + description + "NETCONF over Simple Object Access Protocol (SOAP) + over Hypertext Transfer Protocol Secure (HTTPS)."; + reference + "RFC 4743: Using NETCONF over the Simple Object + Access Protocol (SOAP)"; + + } + + identity netconf-beep { + base transport; + description + "NETCONF over Blocks Extensible Exchange Protocol (BEEP)."; + reference + "RFC 4744: Using the NETCONF Protocol over the + Blocks Extensible Exchange Protocol (BEEP)"; + + } + + identity netconf-tls { + base transport; + description + "NETCONF over Transport Layer Security (TLS)."; + reference + "RFC 5539: NETCONF over Transport Layer Security (TLS)"; + + } + + identity schema-format { + description + "Base identity for data model schema languages."; + } + + identity xsd { + base schema-format; + description + "W3C XML Schema Definition."; + reference + "W3C REC REC-xmlschema-1-20041028: + XML Schema Part 1: Structures"; + + } + + identity yang { + base schema-format; + description + "The YANG data modeling language for NETCONF."; + reference + "RFC 6020: YANG - A Data Modeling Language for the + Network Configuration Protocol (NETCONF)"; + + } + + identity yin { + base schema-format; + description "The YIN syntax for YANG."; + reference + "RFC 6020: YANG - A Data Modeling Language for the + Network Configuration Protocol (NETCONF)"; + + } + + identity rng { + base schema-format; + description + "Regular Language for XML Next Generation (RELAX NG)."; + reference + "ISO/IEC 19757-2:2008: RELAX NG"; + + } + + identity rnc { + base schema-format; + description "Relax NG Compact Syntax"; + reference + "ISO/IEC 19757-2:2008: RELAX NG"; + + } + + grouping common-counters { + description + "Counters that exist both per session, and also globally, + accumulated from all sessions."; + leaf in-rpcs { + type yang:zero-based-counter32; + description + "Number of correct messages received."; + } + + leaf in-bad-rpcs { + type yang:zero-based-counter32; + description + "Number of messages received when an message was expected, + that were not correct messages. This includes XML parse + errors and errors on the rpc layer."; + } + + leaf out-rpc-errors { + type yang:zero-based-counter32; + description + "Number of messages sent that contained an + element."; + } + + leaf out-notifications { + type yang:zero-based-counter32; + description + "Number of messages sent."; + } + } // grouping common-counters + + container netconf-state { + config false; + description + "The netconf-state container is the root of the monitoring + data model."; + container capabilities { + description + "Contains the list of NETCONF capabilities supported by the + server."; + leaf-list capability { + type inet:uri; + description + "List of NETCONF capabilities supported by the server."; + } + } // container capabilities + + container datastores { + description + "Contains the list of NETCONF configuration datastores."; + list datastore { + key "name"; + description + "List of NETCONF configuration datastores supported by + the NETCONF server and related information."; + leaf name { + type netconf-datastore-type; + description + "Name of the datastore associated with this list entry."; + } + + container locks { + presence + "This container is present only if the datastore + is locked."; + description + "The NETCONF and operations allow + a client to lock specific resources in a datastore. The + NETCONF server will prevent changes to the locked + resources by all sessions except the one that acquired + the lock(s). + + Monitoring information is provided for each datastore + entry including details such as the session that acquired + the lock, the type of lock (global or partial) and the + list of locked resources. Multiple locks per datastore + are supported."; + grouping lock-info { + description + "Lock related parameters, common to both global and + partial locks."; + leaf locked-by-session { + type uint32; + mandatory true; + description + "The session ID of the session that has locked + this resource. Both a global lock and a partial + lock MUST contain the NETCONF session-id. + + If the lock is held by a session that is not managed + by the NETCONF server (e.g., a CLI session), a session + id of 0 (zero) is reported."; + reference + "RFC 4741: NETCONF Configuration Protocol"; + + } + + leaf locked-time { + type yang:date-and-time; + mandatory true; + description + "The date and time of when the resource was + locked."; + } + } // grouping lock-info + choice lock-type { + description + "Indicates if a global lock or a set of partial locks + are set."; + container global-lock { + description + "Present if the global lock is set."; + uses lock-info; + } // container global-lock + list partial-lock { + key "lock-id"; + description + "List of partial locks."; + reference + "RFC 5717: Partial Lock Remote Procedure Call (RPC) for + NETCONF"; + + leaf lock-id { + type uint32; + description + "This is the lock id returned in the + response."; + } + + uses lock-info; + + leaf-list select { + type yang:xpath1.0; + min-elements 1; + description + "The xpath expression that was used to request + the lock. The select expression indicates the + original intended scope of the lock."; + } + + leaf-list locked-node { + type instance-identifier; + description + "The list of instance-identifiers (i.e., the + locked nodes). + + The scope of the partial lock is defined by the list + of locked nodes."; + } + } // list partial-lock + } // choice lock-type + } // container locks + } // list datastore + } // container datastores + + container schemas { + description + "Contains the list of data model schemas supported by the + server."; + list schema { + key "identifier version format"; + description + "List of data model schemas supported by the server."; + leaf identifier { + type string; + description + "Identifier to uniquely reference the schema. The + identifier is used in the operation and may + be used for other purposes such as file retrieval. + + For modeling languages that support or require a data + model name (e.g., YANG module name) the identifier MUST + match that name. For YANG data models, the identifier is + the name of the module or submodule. In other cases, an + identifier such as a filename MAY be used instead."; + } + + leaf version { + type string; + description + "Version of the schema supported. Multiple versions MAY be + supported simultaneously by a NETCONF server. Each + version MUST be reported individually in the schema list, + i.e., with same identifier, possibly different location, + but different version. + + For YANG data models, version is the value of the most + recent YANG 'revision' statement in the module or + submodule, or the empty string if no 'revision' statement + is present."; + } + + leaf format { + type identityref { + base schema-format; + } + description + "The data modeling language the schema is written + in (currently xsd, yang, yin, rng, or rnc). + For YANG data models, 'yang' format MUST be supported and + 'yin' format MAY also be provided."; + } + + leaf namespace { + type inet:uri; + mandatory true; + description + "The XML namespace defined by the data model. + + For YANG data models, this is the module's namespace. + If the list entry describes a submodule, this field + contains the namespace of the module to which the + submodule belongs."; + } + + leaf-list location { + type union { + type enumeration { + enum "NETCONF" { + value 0; + } + } + type inet:uri; + } + description + "One or more locations from which the schema can be + retrieved. This list SHOULD contain at least one + entry per schema. + + A schema entry may be located on a remote file system + (e.g., reference to file system for ftp retrieval) or + retrieved directly from a server supporting the + operation (denoted by the value 'NETCONF')."; + } + } // list schema + } // container schemas + + container sessions { + description + "The sessions container includes session-specific data for + NETCONF management sessions. The session list MUST include + all currently active NETCONF sessions."; + list session { + key "session-id"; + description + "All NETCONF sessions managed by the NETCONF server + MUST be reported in this list."; + leaf session-id { + type uint32 { + range "1..max"; + } + description + "Unique identifier for the session. This value is the + NETCONF session identifier, as defined in RFC 4741."; + reference + "RFC 4741: NETCONF Configuration Protocol"; + + } + + leaf transport { + type identityref { + base transport; + } + mandatory true; + description + "Identifies the transport for each session, e.g., + 'netconf-ssh', 'netconf-soap', etc."; + } + + leaf username { + type string; + mandatory true; + description + "The username is the client identity that was authenticated + by the NETCONF transport protocol. The algorithm used to + derive the username is NETCONF transport protocol specific + and in addition specific to the authentication mechanism + used by the NETCONF transport protocol."; + } + + leaf source-host { + type inet:host; + description + "Host identifier of the NETCONF client. The value + returned is implementation specific (e.g., hostname, + IPv4 address, IPv6 address)"; + } + + leaf login-time { + type yang:date-and-time; + mandatory true; + description + "Time at the server at which the session was established."; + } + + uses common-counters { + description + "Per-session counters. Zero based with following reset + behaviour: + - at start of a session + - when max value is reached"; + } + } // list session + } // container sessions + + container statistics { + description + "Statistical data pertaining to the NETCONF server."; + leaf netconf-start-time { + type yang:date-and-time; + description + "Date and time at which the management subsystem was + started."; + } + + leaf in-bad-hellos { + type yang:zero-based-counter32; + description + "Number of sessions silently dropped because an + invalid message was received. This includes + messages with a 'session-id' attribute, bad namespace, and + bad capability declarations."; + } + + leaf in-sessions { + type yang:zero-based-counter32; + description + "Number of sessions started. This counter is incremented + when a message with a is sent. + + 'in-sessions' - 'in-bad-hellos' = + 'number of correctly started netconf sessions'"; + } + + leaf dropped-sessions { + type yang:zero-based-counter32; + description + "Number of sessions that were abnormally terminated, e.g., + due to idle timeout or transport close. This counter is not + incremented when a session is properly closed by a + operation, or killed by a + operation."; + } + + uses common-counters { + description + "Global counters, accumulated from all sessions. + Zero based with following reset behaviour: + - re-initialization of NETCONF server + - when max value is reached"; + } + } // container statistics + } // container netconf-state + + rpc get-schema { + description + "This operation is used to retrieve a schema from the + NETCONF server. + + Positive Response: + The NETCONF server returns the requested schema. + + Negative Response: + If requested schema does not exist, the is + 'invalid-value'. + + If more than one schema matches the requested parameters, the + is 'operation-failed', and is + 'data-not-unique'."; + input { + leaf identifier { + type string; + mandatory true; + description + "Identifier for the schema list entry."; + } + + leaf version { + type string; + description + "Version of the schema requested. If this parameter is not + present, and more than one version of the schema exists on + the server, a 'data-not-unique' error is returned, as + described above."; + } + + leaf format { + type identityref { + base schema-format; + } + description + "The data modeling language of the schema. If this + parameter is not present, and more than one formats of + the schema exists on the server, a 'data-not-unique' error + is returned, as described above."; + } + } + + output { + anyxml data { + description + "Contains the schema content."; + } + } + } // rpc get-schema +} // module diff --git a/netconf-server/schemas/ietf-yang-types.yang b/netconf-server/schemas/ietf-yang-types.yang new file mode 100644 index 0000000..b35286e --- /dev/null +++ b/netconf-server/schemas/ietf-yang-types.yang @@ -0,0 +1,435 @@ +module ietf-yang-types { + +namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; +prefix "yang"; + +organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + +contact + "WG Web: + WG List: + WG Chair: David Kessens + + WG Chair: Juergen Schoenwaelder + + Editor: Juergen Schoenwaelder + "; + +description + "This module contains a collection of generally useful derived + YANG data types. + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + +revision 2013-07-15 { + description + "This revision adds the following new data types: + - yang-identifier + - hex-string + - uuid + - dotted-quad"; + reference + "RFC 6991: Common YANG Data Types"; +} + +revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; +} + +/*** collection of counter and gauge types ***/ + +typedef counter32 { + type uint32; + description + "The counter32 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter32 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + The counter32 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter32. + In the value set and its semantics, this type is equivalent + to the Counter32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef zero-based-counter32 { + type yang:counter32; + default "0"; + description + "The zero-based-counter32 type represents a counter32 + that has the defined 'initial' value zero. + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter32 textual convention of the SMIv2."; + reference + "RFC 4502: Remote Network Monitoring Management Information + Base Version 2"; +} + +typedef counter64 { + type uint64; + description + "The counter64 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter64 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + The counter64 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter64. + In the value set and its semantics, this type is equivalent + to the Counter64 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef zero-based-counter64 { + type yang:counter64; + default "0"; + description + "The zero-based-counter64 type represents a counter64 that + has the defined 'initial' value zero. + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter64 textual convention of the SMIv2."; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; +} + +typedef gauge32 { + type uint32; + description + "The gauge32 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^32-1 (4294967295 decimal), and + the minimum value cannot be smaller than 0. The value of + a gauge32 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge32 also decreases (increases). + In the value set and its semantics, this type is equivalent + to the Gauge32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef gauge64 { + type uint64; + description + "The gauge64 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^64-1 (18446744073709551615), and + the minimum value cannot be smaller than 0. The value of + a gauge64 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge64 also decreases (increases). + In the value set and its semantics, this type is equivalent + to the CounterBasedGauge64 SMIv2 textual convention defined + in RFC 2856"; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; +} + +/*** collection of identifier-related types ***/ + +typedef object-identifier { + type string { + pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + + '(\.(0|([1-9]\d*)))*'; + } + description + "The object-identifier type represents administratively + assigned names in a registration-hierarchical-name tree. + Values of this type are denoted as a sequence of numerical + non-negative sub-identifier values. Each sub-identifier + value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers + are separated by single dots and without any intermediate + whitespace. + The ASN.1 standard restricts the value space of the first + sub-identifier to 0, 1, or 2. Furthermore, the value space + of the second sub-identifier is restricted to the range + 0 to 39 if the first sub-identifier is 0 or 1. Finally, + the ASN.1 standard requires that an object identifier + has always at least two sub-identifiers. The pattern + captures these restrictions. + Although the number of sub-identifiers is not limited, + module designers should realize that there may be + implementations that stick with the SMIv2 limit of 128 + sub-identifiers. + This type is a superset of the SMIv2 OBJECT IDENTIFIER type + since it is not restricted to 128 sub-identifiers. Hence, + this type SHOULD NOT be used to represent the SMIv2 OBJECT + IDENTIFIER type; the object-identifier-128 type SHOULD be + used instead."; + reference + "ISO9834-1: Information technology -- Open Systems + Interconnection -- Procedures for the operation of OSI + Registration Authorities: General procedures and top + arcs of the ASN.1 Object Identifier tree"; +} + +typedef object-identifier-128 { + type object-identifier { + pattern '\d*(\.\d*){1,127}'; + } + description + "This type represents object-identifiers restricted to 128 + sub-identifiers. + In the value set and its semantics, this type is equivalent + to the OBJECT IDENTIFIER type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef yang-identifier { + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; + pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; + } + description + "A YANG identifier string as defined by the 'identifier' + rule in Section 12 of RFC 6020. An identifier must + start with an alphabetic character or an underscore + followed by an arbitrary sequence of alphabetic or + numeric characters, underscores, hyphens, or dots. + A YANG identifier MUST NOT start with any possible + combination of the lowercase or uppercase character + sequence 'xml'."; + reference + "RFC 6020: YANG - A Data Modeling Language for the Network + Configuration Protocol (NETCONF)"; +} + +/*** collection of types related to date and time***/ + +typedef date-and-time { + type string { + pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + + '(Z|[\+\-]\d{2}:\d{2})'; + } + description + "The date-and-time type is a profile of the ISO 8601 + standard for representation of dates and times using the + Gregorian calendar. The profile is defined by the + date-time production in Section 5.6 of RFC 3339. + The date-and-time type is compatible with the dateTime XML + schema type with the following notable exceptions: + (a) The date-and-time type does not allow negative years. + (b) The date-and-time time-offset -00:00 indicates an unknown + time zone (see RFC 3339) while -00:00 and +00:00 and Z + all represent the same time zone in dateTime. + (c) The canonical format (see below) of data-and-time values + differs from the canonical format used by the dateTime XML + schema type, which requires all times to be in UTC using + the time-offset 'Z'. + This type is not equivalent to the DateAndTime textual + convention of the SMIv2 since RFC 3339 uses a different + separator between full-date and full-time and provides + higher resolution of time-secfrac. + The canonical format for date-and-time values with a known time + zone uses a numeric time zone offset that is calculated using + the device's configured known offset to UTC time. A change of + the device's offset to UTC time will cause date-and-time values + to change accordingly. Such changes might happen periodically + in case a server follows automatically daylight saving time + (DST) time zone offset changes. The canonical format for + date-and-time values with an unknown time zone (usually + referring to the notion of local time) uses the time-offset + -00:00."; + reference + "RFC 3339: Date and Time on the Internet: Timestamps + RFC 2579: Textual Conventions for SMIv2 + XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; +} + +typedef timeticks { + type uint32; + description + "The timeticks type represents a non-negative integer that + represents the time, modulo 2^32 (4294967296 decimal), in + hundredths of a second between two epochs. When a schema + node is defined that uses this type, the description of + the schema node identifies both of the reference epochs. + In the value set and its semantics, this type is equivalent + to the TimeTicks type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; +} + +typedef timestamp { + type yang:timeticks; + description + "The timestamp type represents the value of an associated + timeticks schema node at which a specific occurrence + happened. The specific occurrence must be defined in the + description of any schema node defined using this type. When + the specific occurrence occurred prior to the last time the + associated timeticks attribute was zero, then the timestamp + value is zero. Note that this requires all timestamp values + to be reset to zero when the value of the associated timeticks + attribute reaches 497+ days and wraps around to zero. + The associated timeticks schema node must be specified + in the description of any schema node using this type. + In the value set and its semantics, this type is equivalent + to the TimeStamp textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; +} + +/*** collection of generic address types ***/ + +typedef phys-address { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "Represents media- or physical-level addresses represented + as a sequence octets, each octet represented by two hexadecimal + numbers. Octets are separated by colons. The canonical + representation uses lowercase characters. + In the value set and its semantics, this type is equivalent + to the PhysAddress textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; +} + +typedef mac-address { + type string { + pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; + } + description + "The mac-address type represents an IEEE 802 MAC address. + The canonical representation uses lowercase characters. + In the value set and its semantics, this type is equivalent + to the MacAddress textual convention of the SMIv2."; + reference + "IEEE 802: IEEE Standard for Local and Metropolitan Area + Networks: Overview and Architecture + RFC 2579: Textual Conventions for SMIv2"; +} + +/*** collection of XML-specific types ***/ + +typedef xpath1.0 { + type string; + description + "This type represents an XPATH 1.0 expression. + When a schema node is defined that uses this type, the + description of the schema node MUST specify the XPath + context in which the XPath expression is evaluated."; + reference + "XPATH: XML Path Language (XPath) Version 1.0"; +} + +/*** collection of string types ***/ + +typedef hex-string { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + description + "A hexadecimal string with octets represented as hex digits + separated by colons. The canonical representation uses + lowercase characters."; +} + +typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lowercase characters. + The following is an example of a UUID in string representation: + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + "; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; +} + +typedef dotted-quad { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; + } + description + "An unsigned 32-bit number expressed in the dotted-quad + notation, i.e., four octets written as decimal numbers + and separated with the '.' (full stop) character."; +} +} diff --git a/netconf-server/schemas/o-ran-file-management.yang b/netconf-server/schemas/o-ran-file-management.yang new file mode 100644 index 0000000..27ab9ee --- /dev/null +++ b/netconf-server/schemas/o-ran-file-management.yang @@ -0,0 +1,213 @@ +module o-ran-file-management { + yang-version 1.1; + namespace "urn:o-ran:file-management:1.0"; + prefix "o-ran-file-mgmt"; + + import ietf-crypto-types { + prefix "ct"; + } + + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the configuration and operations for handling upload. + + Copyright 2019 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) backward compatible changes to correct sFTP Server Authentication . + 2) minor fixes according to lack of descriptions + 3) backward compatible changes to introduce groupings"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + grouping file-path-grouping { + description "Complete logical path of the file to upload/download + (no wildcard is allowed) ex : /o-RAN/log/syslog.1"; + + leaf local-logical-file-path { + type string; + mandatory true; + description "Local logical file path"; + } + + leaf remote-file-path { + type string; + mandatory true; + description "URI specifying the remote-file-path on O-DU/NMS. + Format:sftp://@[:port]/path"; + } + } + + grouping output-status-grouping { + description "Status grouping"; + + leaf status { + type enumeration { + enum SUCCESS { + description "";} + enum FAILURE { + description "";} + } + description "Operation status"; + } + + leaf reject-reason { + when "../status = 'FAILURE'"; + type string; + description ""; + } + } + + grouping credential-information { + description "Type of authentication to use for SFTP upload or download."; + choice credentials { + case password { + container password { + presence true; + leaf password { + type string; + mandatory true; + description + "password needed for O-RU authentication."; + } + description + "password for O-RU authentication method in use"; + } + container server { + list keys { + key algorithm; + ordered-by user; + uses ct:public-key-grouping; + description + "List of allowed algorithms with its keys"; + } + description + "Key for sFTP server authentication"; + } + } + case certificate { + container certificate { + presence true; + description + "certificate authentication method in use"; + } + } + description ""; + } + } + + grouping retrieve-input { + description "Grouping for information retrieval RPC input"; + leaf logical-path { + type string; + mandatory true; + description "O-RAN unit of which the files are to be listed. + ex : O-RAN/log, o-RAN/PM, O-RAN/transceiver"; + } + leaf file-name-filter { + type string; + description "Filter which are to be applied on the result list of file names (* is allowed as wild-card)."; + } + } + + grouping retrieve-output { + description "Grouping for information retrieval RPC output"; + uses output-status-grouping; + leaf-list file-list { + when "../status = 'SUCCESS'"; + type string; + description "List of files in the unit with the filter applied."; + } + } + +// RPCs + + rpc file-upload { + description "File upload over SFTP from equipment to NETCONF client"; + input { + uses file-path-grouping; + uses credential-information; + } + output { + uses output-status-grouping; + } + } + + rpc retrieve-file-list { + description "List all the files in the logical O-RAN unit (* is allowed as wild-card)."; + input { + uses retrieve-input; + + } + output { + uses retrieve-output; + } + } + + notification file-upload-notification { + uses file-path-grouping; + uses output-status-grouping; + description ""; + } + + rpc file-download { + description + "Management plane triggered to generate the download file of O-RU."; + input { + uses file-path-grouping; + uses credential-information; + } + output { + uses output-status-grouping; + } + } + + notification file-download-event { + uses file-path-grouping; + uses output-status-grouping; + description ""; + } +} diff --git a/netconf-server/schemas/o-ran-hardware.yang b/netconf-server/schemas/o-ran-hardware.yang new file mode 100644 index 0000000..0787ebb --- /dev/null +++ b/netconf-server/schemas/o-ran-hardware.yang @@ -0,0 +1,271 @@ +module o-ran-hardware { + yang-version 1.1; + namespace "urn:o-ran:hardware:1.0"; + prefix "o-ran-hw"; + + import ietf-hardware { + prefix hw; + } + import iana-hardware { + prefix ianahw; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the YANG definitions for managng the O-RAN hardware. + + Copyright 2019 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) added new identities to accommodate cross working group use of + o-ran-hardware and assoicated set of augmentations that are backwards + compatible to version 1.0.0"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + feature ENERGYSAVING { + description + "Indicates that the Radio Unit supports energy saving state."; + } + + // identity statements + identity O-RAN-RADIO { + base ianahw:module; + description + "Module used as it represents a self-contained sub-system + used in /hw:/hardware/hw:component/hw:class to represent + an O-RAN RU"; + } + + identity O-RAN-HW-COMPONENT { + base ianahw:module; + description + "Module used as it represents a self-contained sub-system + used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN hardware component"; + } + + identity O-DU-COMPONENT { + base O-RAN-HW-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN defined O-DU hardware component"; + } + + identity O-RU-COMPONENT { + base O-RAN-HW-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN defined O-RU hardware component, including a stand-alone + O-RU or an O-RU component integrated into a multi-module system."; + } + + // typedef statements + typedef energysaving-state { + type enumeration { + enum UNKNOWN { + description "The Radio Unit is unable to report energy saving state."; + } + enum SLEEPING { + description + "The Radio Unit is in a sleep state. The NETCONF management plane + connection is functioning. Other functions and hardware which are + not needed for management plane may be in energy saving mode."; + } + enum AWAKE { + description + "The Radio Unit is not in an energy saving state."; + } + } + description + "new typedef since ietf-hardware only covers pwer-state + for redundancy purposes and not power saving operations."; + } + + typedef availability-type { + type enumeration { + enum UNKNOWN { + description "The Radio Unit is unable to report its availability state."; + } + enum NORMAL { + description + "The equipment is functioning correctly."; + } + enum DEGRADED { + description + "The equipment may be reporting a major alarm or may be reporting a critical + alarm that is only impacting one or more subcomponent, but where the + equipment's implementation permit it to continue operation (server traffic) + in a degraded state. + + Used for example, when the equipment has M identical sub-components and + when a critical alarm is imapcting only N subcomponents, where N + + CommScope Inc + 1100 10th Ave Ct SE, + Hickory, + NC 28602, + USA"; + description + "This module defines operations and configuration for the heart beat event management."; + + revision 2020-06-30 { + description + "PLEASE READ BELOW NOTES BEFORE USING THE MODEL: + 1) All attributes of TR 196, 181 and OneCell extensions are all covered + in this same YANG File. In future this shall split into three + different yang models. + + 2) The reason for using single file is that the SDN-R Configuration APP + doesn't load the UI properly if the yang model uses augmentations. + Once the SDN-R Configuration App supports augmented yang files then + the model could be split into different files. + + 3) For tabular parameters, in yang model 'index' is used as a key and it + is introduced to indicate the row id/index value in table. "; + reference + "Subset of BBF TR-196, TR-181 and CommScope OneCell Vendor Extensions + Models"; + } + + container heartbeat { + + description + "This object contains parameters relating to HeartBeat parameters."; + leaf heartbeatPeriod { + type uint8 { + range "0 | 5..60"; + } + units "minutes"; + default "5"; + description + "It specifies the time between two emissions of heartbeat notifications. A value of zero implies there is no heartbeat emission. The unit is minute"; + } + leaf countDownTimer { + type uint8 { + range "0..60"; + } + units "minutes"; + default "0"; + description + "It represents the current value of a countdown timer. Heartbeat is emitted when value reaches or is set to 0. The unit is minute."; + reference + "count down timer to emit next heart beat pulse"; + } + } +} + diff --git a/netconf-server/schemas/o-ran-software-management.yang b/netconf-server/schemas/o-ran-software-management.yang new file mode 100644 index 0000000..ed84774 --- /dev/null +++ b/netconf-server/schemas/o-ran-software-management.yang @@ -0,0 +1,595 @@ +module o-ran-software-management { + yang-version 1.1; + namespace "urn:o-ran:software-management:1.0"; + prefix o-ran-swm; + + import ietf-inet-types { + prefix "inet"; + revision-date 2013-07-15; + } + + import ietf-hardware { + prefix "hw"; + } + + import o-ran-hardware { + prefix "o-ran-hw"; + } + + import o-ran-file-management { + prefix "o-ran-fm"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines operations and configuration for the management of software packages. + This module is derived out of opencpe-firmware-mgmt@2014-02-06.yang + + Copyright 2019 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2019-07-03" { + description + "version 1.0.2 + + 1) backward compatible changes to correct sFTP Server Authentication . + 2) simplifying file management and authentication to reuse from o-ran-file-management module + 3) minor fixes according to lack of descriptions + 4) removal of not used grouping + 5) backward compatible changes to introduce groupings."; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + // groupings + + grouping slot-group { + description + "Contains information about each software slot and its content."; + list software-slot { + key name; + min-elements 2; + + description + "Information about available software-slots and their software."; + + leaf name { + type string; + + description + "Name of the software package. This shall be unique to identify the software-slot."; + } + + leaf status { + type enumeration { + enum VALID { + description + "Slot Contains software build considered as proven valid"; + } + enum INVALID { + description + "software build is not currently used by O-RU. The software is considered by O-RU as damaged (e.g. wrong CRC)"; + } + enum EMPTY { + description + "W slot does not contain software package."; + } + } + config false; + mandatory true; + + description "Indicates the status of the software slot"; + } + + leaf active { + type boolean; + must "../status = 'VALID'"; + config false; + description + "informs if software stored in particular slot is activated at the moment"; + } + + leaf running { + type boolean; + must "../status = 'VALID'"; + config false; + description + "informs if software stored in particular slot is used at the moment"; + } + + leaf access { + type enumeration { + enum READ_ONLY { + description + "slot intended only for factory software, + activation of such software slot means getting back to factory defaults"; + } + enum READ_WRITE { + description + "slot used for updating software"; + } + } + default READ_WRITE; + config false; + + description + "Indicates the writability of the slot. + A Read-Only software slot is one which has a factory installed software-slot"; + } + + leaf product-code { + type leafref { + path "/hw:hardware/hw:component/o-ran-hw:product-code"; + } + config false; + + description "product code provided by the vendor, specific to the product. This is derived from manifest file."; + } + + leaf vendor-code { + type string { + length 1..2; + } + config false; + + description + "Unique code of the vendor. This is derived from manifest file."; + } + + leaf build-id { + type string; + config false; + + description + "Identity associated with the software build. This is derived from manifest file."; + } + + leaf build-name { + type string; + config false; + + description + "Name of the build. This is derived from manifest file."; + } + + leaf build-version { + type string; + description "The vendor-specific version string of the software build."; + } + + list files { + key "name"; + config false; + + description "List of all the files present in the software package."; + + leaf name { + type string; + + description + "Name of the file installed in the slot."; + } + + leaf version { + type string; + + description + "Version of the file installed in the slot"; + } + leaf local-path { + type string; + mandatory true; + + description + "Complete path of the file stored locally"; + } + + leaf integrity { + type enumeration { + enum OK { + description "OK - indicates that file integrity is correct"; + } + enum NOK { + description "NOK - indicates corrupted file"; + } + } + config false; + + description + "Result of the file integrity check (checksum calculation) during installation."; + } + } + } + } + + grouping download-input { + description + "Grouping for sw download rpc input"; + leaf remote-file-path { + type inet:uri; + mandatory true; + description + "URI of the software image including username. + The following format is possible: + sftp://@[:]/path"; + } + + uses o-ran-fm:credential-information; + } + + grouping download-output { + description + "Grouping for sw download rpc output"; + leaf status { + type enumeration { + enum STARTED { + description + "Operation has been started without error."; + } + enum FAILED { + description + "Operation cannot be started because of error, more detailed information can be found in error-message."; + } + } + mandatory true; + + description + "Status of the software files download"; + } + leaf error-message { + when "../status = 'FAILED'"; + type string; + + description + "Detailed error Message when the status is failed."; + } + + leaf notification-timeout { + type int32; + units seconds; + default 30; + + description + "Notification timeout is the time NETCONF client shall + wait for a 'download-event' notification from O-RU. If there is no + 'download-event' notification received within notification-timeout, + NETCONF client shall assume the download timeout/failure, and follow necessary steps."; + } + } + + grouping install-input { + description + "Grouping for sw installation rpc input"; + leaf slot-name { + type leafref { + path "/software-inventory/software-slot/name"; + } + must "/software-inventory/software-slot[name = current()][active = 'false' and running = 'false']" { + error-message "software-install may be requested only against active::false and running::false slot!"; + } + mandatory true; + + description + "software-slot to which the software shall be installed to."; + } + + leaf-list file-names { + type string; + + description + "Names of the files within software package to be installed"; + } + } + + grouping install-output { + description + "Grouping for sw installation rpc output"; + leaf status { + type enumeration { + enum STARTED { + description + "Operation has been started without error."; + } + enum FAILED { + description + "Operation cannot be started because of error, more detailed information can be found in error-message."; + } + } + mandatory true; + + description + "Status of the software package install."; + } + leaf error-message { + when "../status = 'FAILED'"; + type string; + + description + "Detailed error Message when the status is failed."; + } + } + + grouping activate-input { + description + "Grouping for sw activation rpc input"; + leaf slot-name { + type leafref { + path "/software-inventory/software-slot/name"; + } + must "/software-inventory/software-slot[name = current()][status = 'VALID']" { + error-message "software activation may be requested only on VALID slot!"; + } + mandatory true; + + description + "Slot name on which software has to be activated."; + } + } + + grouping activate-output { + description + "Grouping for sw activation rpc output"; + leaf status { + type enumeration { + enum STARTED { + description + "Operation has been started without error."; + } + enum FAILED { + description + "Operation cannot be started because of error, more detailed information can be found in error-message."; + } + } + mandatory true; + + description + "Status of the software files activation"; + } + leaf error-message { + when "../status = 'FAILED'"; + type string; + + description + "Detailed error Message when the status is failed."; + } + + leaf notification-timeout { + type int32; + units seconds; + default 30; + + description + "Timeout on client waiting for the activate event"; + } + } + + grouping download-notification { + description + "Grouping for notification event structure for download completion"; + leaf file-name { + type string; + mandatory true; + + description + "File name of downloaded software package"; + } + + leaf status { + type enumeration { + enum COMPLETED { + description + "Operation completed succesfully"; + } + enum AUTHENTICATION_ERROR { + description "source available, wrong credentials"; + } + enum PROTOCOL_ERROR { + description "SFTP errors"; + } + enum FILE_NOT_FOUND { + description "source not available."; + } + enum APPLICATION_ERROR { + description "Application related errors"; + } + enum TIMEOUT { + description "Timeout waiting for download"; + } + } + + description + "Status of finished operation execution"; + } + leaf error-message { + when "../status != 'COMPLETED'"; + type string; + + description + "Detailed description of faulty situation"; + } + } + + grouping install-notification { + description + "Grouping for notification event structure for installation completion"; + leaf slot-name { + type leafref { + path "/software-inventory/software-slot/name"; + } + + description + "Name of the slot to which software was installed."; + } + leaf status { + type enumeration { + enum COMPLETED { + description + "Operation completed succesfully"; + } + enum FILE_ERROR { + description "operation on the file resulted in in error, disk failure, not enough disk space, + incompatible file format"; + } + enum INTEGRITY_ERROR { + description "file is corrupted"; + } + enum APPLICATION_ERROR { + description "operation failed due to internal reason"; + } + } + + description + "Status of finished operation execution"; + } + leaf error-message { + when "../status != 'COMPLETED'"; + type string; + + description + "Detailed description of faulty situation"; + } + } + + grouping activation-notification { + description + "Grouping for notification event structure for activation completion"; + leaf slot-name { + type leafref { + path "/software-inventory/software-slot/name"; + } + + description + "Name of the slot which was activated"; + } + + leaf status { + type enumeration { + enum COMPLETED { + description + "Operation completed succesfully"; + } + enum APPLICATION_ERROR { + description + "Operation finished with error, more details can by found in error-message"; + } + } + + description + "Status of finished operation execution"; + } + leaf return-code { + type uint8; + + description + "status code return when the software is tried to activate"; + } + leaf error-message { + when "../status != 'COMPLETED'"; + type string; + + description + "Detailed description of faulty situation"; + } + } + + // top level container + + container software-inventory { + config false; + description + "Contains information about each software slot and its content."; + + uses slot-group; + + } + // rpc statements + + rpc software-download { + description + "Rpc needed to perform software download operation."; + + input { + uses download-input; + } + output { + uses download-output; + } + } + + rpc software-install { + description + "Install a previously downloaded software package."; + + input { + uses install-input; + } + output { + uses install-output; + } + } + + rpc software-activate { + description + "Activate a previously installed software."; + input { + uses activate-input; + } + output { + uses activate-output; + } + } + + // notification definitions + notification download-event { + description "Notification event structure for download completion"; + uses download-notification; + + } + + notification install-event { + description "Notification event structure for installation completion"; + uses install-notification; + } + + notification activation-event { + description "Notification event structure for activation completion"; + uses activation-notification; + } +} diff --git a/netconf-server/schemas/tr-181-2-12-0-cwmp-full.yang b/netconf-server/schemas/tr-181-2-12-0-cwmp-full.yang index f692039..549fcc5 100644 --- a/netconf-server/schemas/tr-181-2-12-0-cwmp-full.yang +++ b/netconf-server/schemas/tr-181-2-12-0-cwmp-full.yang @@ -27,7 +27,7 @@ module tr-181-2-12-0-cwmp-full { See the License for the specific language governing permissions and limitations under the License."; - revision 2020-06-23 { + revision 2020-06-24 { description "Initial version, used only for ONAP PoC 2018-06-25"; reference diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/config/NetConfServerProperties.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/config/NetConfServerProperties.java index 738f4a9..e1f6efb 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/config/NetConfServerProperties.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/config/NetConfServerProperties.java @@ -32,10 +32,10 @@ public class NetConfServerProperties { private String mapperPath; private String netconfServerRestPort; private String netconfServersStartPort; - private String netconfServersEndPort; private String maxNumOfNetconfServers; private String netconfServerIP; private String schemaDirPath; + private String vesURI; public String getRequestTimeOut() { return requestTimeOut; @@ -77,14 +77,6 @@ public class NetConfServerProperties { this.netconfServersStartPort = netconfServersStartPort; } - public String getNetconfServersEndPort() { - return netconfServersEndPort; - } - - public void setNetconfServersEndPort(String netconfServersEndPort) { - this.netconfServersEndPort = netconfServersEndPort; - } - public Integer getDefaultNetconfStartPort() { return defaultNetconfStartPort; } @@ -117,4 +109,11 @@ public class NetConfServerProperties { this.schemaDirPath = schemaDirPath; } + public String getVesURI() { + return vesURI; + } + + public void setVesURI(String vesURI) { + this.vesURI = vesURI; + } } diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/notification/NetConfSessionUtil.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/notification/NetConfSessionUtil.java index 046db19..416df8f 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/notification/NetConfSessionUtil.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/notification/NetConfSessionUtil.java @@ -1,21 +1,3 @@ -/* - * ============LICENSE_START======================================================================== - * ONAP : tr-069-adapter - * ================================================================================================= - * Copyright (C) 2020 CommScope Inc Intellectual Property. - * ================================================================================================= - * This tr-069-adapter software file is distributed by CommScope Inc 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 - * - * This file 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. - * ===============LICENSE_END======================================================================= - */ - package org.commscope.tr069adapter.netconf.notification; import java.io.IOException; @@ -27,7 +9,6 @@ import java.util.List; import java.util.Map; import java.util.StringTokenizer; -import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -36,8 +17,8 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import org.commscope.tr069adapter.acs.common.DeviceInform; import org.commscope.tr069adapter.acs.common.ParameterDTO; +import org.commscope.tr069adapter.mapper.model.NetConfNotificationDTO; import org.commscope.tr069adapter.netconf.rpc.CreateSubscription; import org.opendaylight.netconf.api.NetconfMessage; import org.opendaylight.netconf.api.xml.XmlNetconfConstants; @@ -58,37 +39,39 @@ public class NetConfSessionUtil { private static final String INDEX_REGEX = "[0-9]{1,}"; private static final String NS_URI = "urn:onf:otcc:wireless:yang:tr069-notification"; - public void sendNetConfNotification(DeviceInform notification) { - NetconfMessage netconfMessage = convertToNetConfMessage(notification); - LOG.debug("Notification converted to NetConf format {}", netconfMessage); - CreateSubscription.sendNotification(netconfMessage, - notification.getDeviceDetails().getDeviceId()); + public void sendNetConfNotification(NetConfNotificationDTO netConNotifDTO) { + NetconfMessage netconfMessage = convertToNetConfMessage(netConNotifDTO); + LOG.debug("Notification converted to NetConf format" + netconfMessage); + CreateSubscription.sendNotification(netconfMessage, netConNotifDTO.getDeviceID()); } - private NetconfMessage convertToNetConfMessage(DeviceInform notification) { + private NetconfMessage convertToNetConfMessage(NetConfNotificationDTO netConNotifDTO) { try { - String netConfXmlMsg = getNetconfResponseXML(notification); - if (netConfXmlMsg == null) - throw new IllegalArgumentException("There are no parameters found in the response"); - return new NetconfMessage(XmlUtil.readXmlToDocument(netConfXmlMsg)); + String nameSpace = ""; + if (netConNotifDTO.getUri() != null) { + nameSpace = netConNotifDTO.getUri(); + } else { + nameSpace = NS_URI; + } + return new NetconfMessage( + XmlUtil.readXmlToDocument(getNetconfResponseXML(netConNotifDTO, nameSpace))); } catch (SAXException | IOException e) { throw new IllegalArgumentException("Cannot parse notifications", e); } } - private static String getNetconfResponseXML(DeviceInform notification) { - if (notification == null || notification.getParameters().isEmpty()) { + private static String getNetconfResponseXML(NetConfNotificationDTO netConNotifDTO, + String nameSpace) { + if (netConNotifDTO == null || netConNotifDTO.getParameters().isEmpty()) { LOG.debug("There are no parameters found in the response."); return null; } - List parameters = notification.getParameters(); + List parameters = netConNotifDTO.getParameters(); String result = null; try { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); - docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Document doc = docBuilder.newDocument(); @@ -100,35 +83,38 @@ public class NetConfSessionUtil { String paramValue = paramDto.getParamValue(); StringTokenizer tokenizer = new StringTokenizer(paramName, "."); String parentNodeName = null; - StringBuilder parentNodeKey = null; + String parentNodeKey = null; Element parentNode = null; while (tokenizer.hasMoreElements()) { String nodeName = (String) tokenizer.nextElement(); if (null == parentNodeName) { // construct first node or // Device node parentNodeName = nodeName; - parentNodeKey = new StringBuilder(nodeName); + parentNodeKey = nodeName; // check if the node already exists in parentNodeMap - parentNode = parentNodeMap.get(parentNodeKey.toString()); + parentNode = parentNodeMap.get(parentNodeKey); if (null == dataNode) { dataNode = parentNode; } + continue; } else if (nodeName.matches(INDEX_REGEX)) { // construct // tabular and // index nodes // get parent tabular node from parent MAP - parentNodeKey = parentNodeKey.append(".").append(nodeName); - Element node = parentNodeMap.get(parentNodeKey.toString()); + parentNodeKey = parentNodeKey + "." + nodeName; + Element node = parentNodeMap.get(parentNodeKey); // create a tabular parent node if doesn't exit in MAP if (null == node) { node = doc.createElement(parentNodeName); - parentNodeMap.put(parentNodeKey.toString(), node); + parentNodeMap.put(parentNodeKey, node); // update current tabular parent node. if (null != parentNode) parentNode.appendChild(node); + else + parentNode = node; // prepare and add index node to tabular parent node Element indexNode = doc.createElement(INDEX_STR); @@ -145,23 +131,23 @@ public class NetConfSessionUtil { // attribute // is // found - parentNodeKey = parentNodeKey.append(".").append(nodeName); + parentNodeKey = parentNodeKey + "." + nodeName; parentNodeName = nodeName; } else { // construct intermediate nodes - Element node = parentNodeMap.get(parentNodeKey.toString()); + Element node = parentNodeMap.get(parentNodeKey); if (null == node) { if (null == dataNode) { - node = doc.createElementNS(NS_URI, parentNodeName); + node = doc.createElementNS(nameSpace, parentNodeName); dataNode = node; } else { node = doc.createElement(parentNodeName); } - parentNodeMap.put(parentNodeKey.toString(), node); + parentNodeMap.put(parentNodeKey, node); if (null != parentNode) parentNode.appendChild(node); } - parentNodeKey = parentNodeKey.append(".").append(nodeName); + parentNodeKey = parentNodeKey + "." + nodeName; parentNodeName = nodeName; parentNode = node; } @@ -169,8 +155,7 @@ public class NetConfSessionUtil { // construct leaf node Element leafNode = doc.createElement(parentNodeName); leafNode.setTextContent(paramValue); - if (null != parentNode) - parentNode.appendChild(leafNode); + parentNode.appendChild(leafNode); } if (null != dataNode) { @@ -178,16 +163,21 @@ public class NetConfSessionUtil { final Element eventTime = doc.createElement(XmlNetconfConstants.EVENT_TIME); eventTime .setTextContent(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date())); - - final Element evtTypeElement = - doc.createElementNS(NS_URI, notification.getInformTypeList().get(0).toString()); - evtTypeElement.appendChild(dataNode); element.appendChild(element.getOwnerDocument().importNode(eventTime, true)); - element.appendChild(element.getOwnerDocument().importNode(evtTypeElement, true)); + + if (netConNotifDTO.getNotificationType() != null) { + final Element evtTypeElement = + doc.createElementNS(nameSpace, netConNotifDTO.getNotificationType()); + evtTypeElement.appendChild(dataNode); + element.appendChild(element.getOwnerDocument().importNode(evtTypeElement, true)); + } else { + element.appendChild(element.getOwnerDocument().importNode(dataNode, true)); + } + result = convertDocumentToString(element); } } catch (ParserConfigurationException pce) { - LOG.error("Error while getNetconfResponseXML {}", pce.toString()); + pce.printStackTrace(); } return result; @@ -197,17 +187,15 @@ public class NetConfSessionUtil { String strxml = null; try { TransformerFactory transformerFactory = TransformerFactory.newInstance(); - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(element); StreamResult result = new StreamResult(new StringWriter()); transformer.transform(source, result); strxml = result.getWriter().toString(); } catch (Exception e) { - LOG.error("Error while converting Element to String {}", e.toString()); + LOG.error("Error while converting Element to String" + e); } - LOG.debug("Converted XML is : {}", strxml); + LOG.debug("Converted XML is : " + strxml); return strxml; } diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/notification/NotificationHandler.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/notification/NotificationHandler.java index 24192f2..71197d0 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/notification/NotificationHandler.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/notification/NotificationHandler.java @@ -18,7 +18,7 @@ package org.commscope.tr069adapter.netconf.notification; -import org.commscope.tr069adapter.acs.common.DeviceInform; +import org.commscope.tr069adapter.mapper.model.NetConfNotificationDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -32,9 +32,9 @@ public class NotificationHandler { @Autowired NetConfSessionUtil netConfSessionUtil; - public void handleNetConfNotification(DeviceInform notification) { - LOG.debug("processing netconf notification {}", notification); - netConfSessionUtil.sendNetConfNotification(notification); + public void handleNetConfNotification(NetConfNotificationDTO netConNotifDTO) { + LOG.debug("processing netconf notification " + netConNotifDTO); + netConfSessionUtil.sendNetConfNotification(netConNotifDTO); } } diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/restapi/NetConfServerManagerRestApi.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/restapi/NetConfServerManagerRestApi.java index c05e4ad..7f60040 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/restapi/NetConfServerManagerRestApi.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/restapi/NetConfServerManagerRestApi.java @@ -59,14 +59,14 @@ public class NetConfServerManagerRestApi { } @PostMapping("/unregisterServer") - public boolean unregisterNetConfServerInstance(@RequestParam String deviceId, + public String unregisterNetConfServerInstance(@RequestParam String deviceId, @RequestParam String enodeBName) { - LOG.info("Received request for Unregister NetConf Server for deviceID: {}, enodeBName: {}", + LOG.info("Received request for Unregister NetConf Server for deviceID: {}, enodeBName: {} ", deviceId, enodeBName); - boolean status = manager.unregister(deviceId, enodeBName); - LOG.info("Unregister request is processed. NetConf Server for deviceID: {} , unregistered= {}", - deviceId, status); - return status; + String result = manager.unregister(deviceId, enodeBName); + LOG.info("Unregister request is processed. NetConf Server for deviceID: {} , unregisted= {}", + deviceId, result); + return result; } } diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/restapi/NotificationReceiverService.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/restapi/NotificationReceiverService.java index 47a794c..e2863e1 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/restapi/NotificationReceiverService.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/restapi/NotificationReceiverService.java @@ -1,24 +1,6 @@ -/* - * ============LICENSE_START======================================================================== - * ONAP : tr-069-adapter - * ================================================================================================= - * Copyright (C) 2020 CommScope Inc Intellectual Property. - * ================================================================================================= - * This tr-069-adapter software file is distributed by CommScope Inc 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 - * - * This file 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. - * ===============LICENSE_END======================================================================= - */ - package org.commscope.tr069adapter.netconf.restapi; -import org.commscope.tr069adapter.acs.common.DeviceInform; +import org.commscope.tr069adapter.mapper.model.NetConfNotificationDTO; import org.commscope.tr069adapter.netconf.notification.NotificationHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,10 +20,11 @@ public class NotificationReceiverService { NotificationHandler handler; @PostMapping("/notification") - public void processNotification(@RequestBody DeviceInform notification) { - LOG.debug("Received NetConf Notification : {}", notification); - handler.handleNetConfNotification(notification); - LOG.debug("Processed NetConf Notification for :{}", notification); + public void processNotification(@RequestBody NetConfNotificationDTO netConNotifDTO) { + System.out.println("Received NetConf Notification :" + netConNotifDTO); + LOG.debug("Received NetConf Notification :" + netConNotifDTO); + handler.handleNetConfNotification(netConNotifDTO); + LOG.debug("Processed NetConf Notification for :" + netConNotifDTO); + System.out.println("Processed NetConf Notification for :" + netConNotifDTO); } - } diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/rpc/SoftwareDownloadOperation.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/rpc/SoftwareDownloadOperation.java index b6f4dc9..00bf175 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/rpc/SoftwareDownloadOperation.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/rpc/SoftwareDownloadOperation.java @@ -18,9 +18,19 @@ package org.commscope.tr069adapter.netconf.rpc; +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.commscope.tr069adapter.mapper.model.ErrorCodeDetails; +import org.commscope.tr069adapter.mapper.model.NetConfResponse; import org.commscope.tr069adapter.netconf.boot.NetConfServiceBooter; import org.commscope.tr069adapter.netconf.config.NetConfServerProperties; import org.opendaylight.netconf.api.DocumentedException; +import org.opendaylight.netconf.api.DocumentedException.ErrorSeverity; +import org.opendaylight.netconf.api.DocumentedException.ErrorTag; +import org.opendaylight.netconf.api.DocumentedException.ErrorType; import org.opendaylight.netconf.api.xml.XmlElement; import org.opendaylight.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.netconf.mapping.api.HandlingPriority; @@ -29,6 +39,7 @@ import org.opendaylight.netconf.mapping.api.NetconfOperationChainedExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; +import org.xml.sax.InputSource; public class SoftwareDownloadOperation implements NetconfOperation { private static final Logger logger = LoggerFactory.getLogger(SoftwareDownloadOperation.class); @@ -52,18 +63,48 @@ public class SoftwareDownloadOperation implements NetconfOperation { public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws DocumentedException { - logger.debug("sw-download rpc recevied in netconf server"); + logger.debug("soft-ware download rpc is received in netconfserver"); + final XmlElement requestElement = XmlElement.fromDomDocument(requestMessage); + final String msgId = requestElement.getAttribute(XmlNetconfConstants.MESSAGE_ID); String requestXml = XmlUtility.convertDocumentToString(requestElement); - logger.debug("sw-download rpc recevied requestXml = {}", requestXml); + logger.debug("soft-ware download rpc requestXml=" + requestXml); + NetConfServerProperties config = NetConfServiceBooter.getApplicationContext().getBean(NetConfServerProperties.class); final String baseUrl = config.getMapperPath() + "/softwareDowload"; - XmlUtility.invokeMapperCall(baseUrl, requestXml, deviceID); + NetConfResponse restResponse = XmlUtility.invokeMapperCall(baseUrl, requestXml, deviceID); + + Document document = null; + + ErrorCodeDetails errorCode = restResponse.getErrorCode(); + if (errorCode != null && errorCode.getFaultCode() != null + && !errorCode.getFaultCode().equalsIgnoreCase("0")) { + logger.error("Error recevied : " + errorCode); + throw new DocumentedException(errorCode.getErrorMessage(), + ErrorType.from(errorCode.getErrorType()), ErrorTag.from(errorCode.getErrorTag()), + ErrorSeverity.from(errorCode.getErrorSeverity())); + } else if (restResponse != null && restResponse.getNetconfResponseXml() != null) { + logger.debug("soft-ware download rpc response received from mapper " + + restResponse.getNetconfResponseXml()); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + document = + builder.parse(new InputSource(new StringReader(restResponse.getNetconfResponseXml()))); + document.getDocumentElement().setAttribute("xmlns:ns1", getOperationNamespace()); + document.getDocumentElement().setAttribute("xmlns", + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + document.getDocumentElement().setAttribute(XmlNetconfConstants.MESSAGE_ID, msgId); + } catch (Exception e) { + logger.error("while contruscting the response; ", e.toString()); + } + } - return null; + return document; } protected HandlingPriority canHandle(final String operationName, @@ -107,4 +148,12 @@ public class SoftwareDownloadOperation implements NetconfOperation { return XmlElement.fromDomElementWithExpected(message.getDocumentElement(), XmlNetconfConstants.RPC_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); } + + protected String getOperationNamespace() { + return "urn:o-ran:software-management:1.0"; + } + + protected String getOperationName() { + return "software-download"; + } } diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/rpc/XmlUtility.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/rpc/XmlUtility.java index 8432ee1..5d09eb0 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/rpc/XmlUtility.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/rpc/XmlUtility.java @@ -70,6 +70,7 @@ public class XmlUtility { } return strxml; + } public static Element convertStringToDocument(String xmlStr) { diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetConfServerManagerImpl.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetConfServerManagerImpl.java index eee8db6..ed1164e 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetConfServerManagerImpl.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetConfServerManagerImpl.java @@ -24,15 +24,24 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.commscope.tr069adapter.acs.common.OperationDetails; +import org.commscope.tr069adapter.acs.common.ParameterDTO; +import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode; import org.commscope.tr069adapter.mapper.model.NetConfServerDetails; import org.commscope.tr069adapter.mapper.model.NetconfServerManagementError; +import org.commscope.tr069adapter.mapper.model.VESNotification; +import org.commscope.tr069adapter.mapper.model.VESNotificationResponse; import org.commscope.tr069adapter.netconf.config.NetConfServerProperties; import org.commscope.tr069adapter.netconf.dao.NetConfServerDetailsRepository; import org.commscope.tr069adapter.netconf.entity.NetConfServerDetailsEntity; import org.commscope.tr069adapter.netconf.error.RetryFailedException; import org.commscope.tr069adapter.netconf.error.ServerPortAllocationException; import org.commscope.tr069adapter.netconf.server.helper.ServerPortAllocationHelper; +import org.commscope.tr069adapter.netconf.server.utils.NetConfServerConstants; +import org.commscope.tr069adapter.netconf.server.ves.VESNotificationSender; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -61,21 +70,26 @@ public class NetConfServerManagerImpl { @Autowired RestartNetconfServerHandler restartServersHandler; + @Autowired + VESNotificationSender vesNotificationSender; + + ExecutorService executorService = Executors.newFixedThreadPool(10); + public void restartServers() { LOG.debug("Restarting all netconf servers during startup..."); Iterable entities = netconfDAO.findAll(); - List serverDetailsList = new ArrayList<>(); - for (NetConfServerDetailsEntity entity : entities) { - serverDetailsList.add(entity); - } - restartServersOnStartup(serverDetailsList); - if (!serverDetailsList.isEmpty()) { - LOG.debug("Attempting to start failed netconf servers {}", serverDetailsList); - try { - restartServersHandler.restart(serverDetailsList); - } catch (RetryFailedException e) { - LOG.error("Failed to restart all netconf servers. {}", e.toString()); + for (NetConfServerDetailsEntity entity : entities) { + boolean isReserved = serverPortAllocator.checkAndReserveServerPort(entity.getListenPort()); + if (isReserved) { + ServerStartTask task = new ServerStartTask(entity, this); + executorService.execute(task); + } else { + try { + restartServersHandler.restart(entity); + } catch (RetryFailedException e) { + e.printStackTrace(); + } } } LOG.debug("Restarting netconf servers during startup is completed."); @@ -110,17 +124,25 @@ public class NetConfServerManagerImpl { try { String port = serverPortAllocator.reserveServerPort(); - LOG.debug("Successfully reserved a port for deviceID={} ,port={}", deviceId, port); - - // start the server - boolean isServerStarted = ncServerStarter.startServer(port, deviceId); - boolean isPortInUse = serverPortAllocator.isServerPortInUse(port); - - if (!isServerStarted || !isPortInUse) { + if (port == null) { + result.setError(NetconfServerManagementError.PORT_NOT_AVAILBLE); LOG.error( - "Failed to start netconf server for deviceID: {}, at port:{} , isServerStarted={} ,isPortInUse={}", - deviceId, port, isServerStarted, isPortInUse); - return null; + "All ports are exhausted. Hence cannot allocate a port to start new netconf server"); + return result; + } else { + LOG.debug("Successfully reserved a port for deviceID={} ,port={}", deviceId, port); + + // start the server + boolean isServerStarted = ncServerStarter.startServer(port, deviceId); + boolean isPortInUse = serverPortAllocator.isServerPortInUse(port); + + if (!isServerStarted || !isPortInUse) { + LOG.error( + "Failed to start netconf server for deviceID: {}, at port:{} , isServerStarted={} ,isPortInUse={}", + deviceId, port, isServerStarted, isPortInUse); + result.setError(NetconfServerManagementError.PORT_IN_USE); + return result; + } } // save the record in db @@ -150,52 +172,41 @@ public class NetConfServerManagerImpl { return result; } - public void restartServersOnStartup(List serverDetailsList) { - - List startedServers = new ArrayList<>(); - for (NetConfServerDetailsEntity entity : serverDetailsList) { + public boolean restartServersOnStartup(NetConfServerDetailsEntity entity) { + boolean isSuccess = false; - serverPortAllocator.checkAndReserveServerPort(entity.getListenPort()); + boolean isServerStarted = + ncServerStarter.startServer(entity.getListenPort(), entity.getDeviceId()); + if (isServerStarted) { + LOG.info("Successfully restarted NETCONF server {} on port {} upon application startup.", + entity.getDeviceId(), entity.getListenPort()); + // we need to push the pnfEntry for IP updated + NetConfServerDetails details = getNetConfServerDetails(entity.getDeviceId(), entity); - serverPortAllocator.isServerPortInUse(entity.getListenPort()); - boolean isServerStarted = - ncServerStarter.startServer(entity.getListenPort(), entity.getDeviceId()); - - if (isServerStarted) { - LOG.info("Successfully restarted NETCONF server {} on port {} upon application startup.", - entity.getDeviceId(), entity.getListenPort()); - // we need to push the pnfEntry for IP updated - NetConfServerDetails details = getNetConfServerDetails(entity.getDeviceId(), entity); - - final String baseUrl = config.getMapperPath() + "/registerNetconfServer"; - URI uri = null; - try { - uri = new URI(baseUrl); - } catch (URISyntaxException e) { - LOG.error("error while contructing the URI {}", e.toString()); - } - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - HttpEntity httpentity = new HttpEntity<>(details, headers); - boolean isSuccess = false; - if (uri != null) { - isSuccess = restTemplate.postForObject(uri, httpentity, Boolean.class); - } + final String baseUrl = config.getMapperPath() + "/registerNetconfServer"; + URI uri = null; + try { + uri = new URI(baseUrl); + } catch (URISyntaxException e) { + LOG.error("error while contructing the URI {}", e.toString()); + } + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + HttpEntity httpentity = new HttpEntity<>(details, headers); + if (uri != null) { + isSuccess = restTemplate.postForObject(uri, httpentity, Boolean.class); + } - if (!isSuccess) { - LOG.error("Netconf Register request is failed update the updated host details.."); - } else { - LOG.debug("successfully started the server"); - } - startedServers.add(entity); + if (!isSuccess) { + LOG.error("Netconf Register request is failed update the updated host details.."); } else { - LOG.error("Failed to restart NETCONF server {} on port {} upon application startup.", - entity.getDeviceId(), entity.getListenPort()); + LOG.debug("successfully started the server"); } + } else { + LOG.error("Failed to restart NETCONF server {} on port {} upon application startup.", + entity.getDeviceId(), entity.getListenPort()); } - if (!serverDetailsList.isEmpty()) { - serverDetailsList.removeAll(startedServers); - } + return isSuccess; } private NetConfServerDetails getNetConfServerDetails(String deviceId, @@ -213,9 +224,67 @@ public class NetConfServerManagerImpl { return result; } - public boolean unregister(String deviceId, String enodeBName) { - LOG.debug("Unregister is not yet supported deviceId={} enodeBName={}", deviceId, enodeBName); - return false; + public String unregister(String deviceId, String enodeBName) { + String resultMsg = null; + NetConfServerDetailsEntity entity = null; + if (deviceId != null) { + entity = this.netconfDAO.findByDeviceId(deviceId); + } else if (enodeBName != null) { + entity = this.netconfDAO.findByEnodeBName(enodeBName); + } else { + LOG.error( + "Both deviceID and enodeBName are null. Hence failed to unregister the netconf server."); + resultMsg = "Failed to unregister the device " + deviceId + ", enodeBName=" + enodeBName + + ". Invalid deviceId/enodeBName specified."; + } + if (entity == null) { + resultMsg = "Failed to unregister the device " + deviceId + ", enodeBName=" + enodeBName + + ". Invalid deviceId/enodeBName specified."; + LOG.info(resultMsg); + } + boolean result = this.ncServerStarter.stopServer(deviceId); + if (result) { + resultMsg = + "Successfully unregistered the device " + deviceId + " and enodeBName=" + enodeBName; + this.serverPortAllocator.unReserveServerPort(entity.getListenPort()); + this.netconfDAO.delete(entity); + LOG.info(resultMsg); + delteHeartBeatTimer(deviceId); + } else { + resultMsg = "Failed to unregister the device " + deviceId + ", enodeBName=" + enodeBName; + LOG.error(resultMsg); + } + + return resultMsg; + } + + private void delteHeartBeatTimer(String deviceId) { + VESNotification vesNotification = new VESNotification(); + + vesNotification.seteNodeBName(deviceId); + + ParameterDTO paramDTO = new ParameterDTO(); + paramDTO.setParamName(NetConfServerConstants.HEART_BEAT); + + List paramDTOList = new ArrayList<>(); + paramDTOList.add(paramDTO); + + OperationDetails opDetails = new OperationDetails(); + opDetails.setOpCode(TR069OperationCode.DELETE_OBJECT); + opDetails.setParmeters(paramDTOList); + + vesNotification.setOperationDetails(opDetails); + + VESNotificationResponse response = + vesNotificationSender.sendDeleteConfigNotification(vesNotification); + + if (response.getStatusCode() == NetConfServerConstants.SUCCESS) { + LOG.info("Heart beat timer is deleted successfully for device {}", deviceId); + } else { + LOG.error("Failed to delete heart beat timer for device {}. ErrorMsg : {}", deviceId, + response.getResponseMsg()); + } + } public List getServersInfo() { @@ -247,4 +316,29 @@ public class NetConfServerManagerImpl { } return null; } + + class ServerStartTask implements Runnable { + + NetConfServerDetailsEntity entity; + NetConfServerManagerImpl netconfServerManager; + + public ServerStartTask(NetConfServerDetailsEntity entity, + NetConfServerManagerImpl netconfServerManager) { + this.entity = entity; + this.netconfServerManager = netconfServerManager; + } + + @Override + public void run() { + boolean isSuccess = netconfServerManager.restartServersOnStartup(entity); + if (isSuccess) { + try { + netconfServerManager.restartServersHandler.restart(entity); + } catch (RetryFailedException e) { + e.printStackTrace();// TODO: logg + } + } + } + + } } diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetconfServerStarter.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetconfServerStarter.java index 39e4e3b..c438ee5 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetconfServerStarter.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetconfServerStarter.java @@ -18,16 +18,21 @@ package org.commscope.tr069adapter.netconf.server; +import com.google.common.base.Preconditions; + import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; + import org.commscope.tr069adapter.netconf.config.NetConfServerProperties; import org.commscope.tr069adapter.netconf.operations.CustomOperationsCreator; import org.opendaylight.netconf.test.tool.NetconfDeviceSimulator; @@ -39,7 +44,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -import com.google.common.base.Preconditions; @Component @Scope("singleton") @@ -47,6 +51,8 @@ public class NetconfServerStarter { private static final Logger LOG = LoggerFactory.getLogger(NetconfServerStarter.class); + private static Map serversMap = new HashMap<>(); + @Autowired NetConfServerProperties config; @@ -95,13 +101,14 @@ public class NetconfServerStarter { return false; } - try(final NetconfDevice netconfDevice = new NetconfDevice(configuration)){ + try (final NetconfDevice netconfDevice = new NetconfDevice(configuration)) { final List openDevices = netconfDevice.start(); if (openDevices.isEmpty()) { LOG.debug("Failed to start netconf server instance {}", macID); return false; } netconfDevice.setAutoClose(false); + serversMap.put(macID, netconfDevice); } catch (RuntimeException e) { LOG.error("Unhandled exception. Failed to start the server", e); return false; @@ -110,6 +117,22 @@ public class NetconfServerStarter { return true; } + public boolean stopServer(String macID) { + try { + LOG.debug("Stopping Netconf server for MACID {}", macID); + NetconfDevice netconf = serversMap.get(macID); + netconf.setAutoClose(true); + netconf.close(); + LOG.debug("Completed stopping Netconf server for MACID {}", macID); + return true; + } catch (Exception e) { + LOG.debug("Error while stopping Netconf server for MACID {}; error message {}", macID, + e.getMessage()); + } + + return false; + } + private boolean loadSchemas(File schemasDir) { if (schemasDir != null) { if (!schemasDir.exists() || !schemasDir.isDirectory() || !schemasDir.canRead()) { diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/RestartNetconfServerHandler.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/RestartNetconfServerHandler.java index 57e3602..6f7f9f2 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/RestartNetconfServerHandler.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/RestartNetconfServerHandler.java @@ -18,10 +18,9 @@ package org.commscope.tr069adapter.netconf.server; -import java.util.List; - import org.commscope.tr069adapter.netconf.entity.NetConfServerDetailsEntity; import org.commscope.tr069adapter.netconf.error.RetryFailedException; +import org.commscope.tr069adapter.netconf.server.helper.ServerPortAllocationHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -38,32 +37,33 @@ public class RestartNetconfServerHandler { @Autowired NetConfServerManagerImpl manager; + @Autowired + ServerPortAllocationHelper serverPortAllocator; + @Retryable(value = {RetryFailedException.class}, maxAttempts = 100, backoff = @Backoff(delay = 15000)) - public void restart(List serverDetailsList) - throws RetryFailedException { + public void restart(NetConfServerDetailsEntity entity) throws RetryFailedException { + boolean isSucess = false; try { // restart netconf servers - manager.restartServersOnStartup(serverDetailsList); + serverPortAllocator.checkAndReserveServerPort(entity.getListenPort()); + isSucess = manager.restartServersOnStartup(entity); } catch (Exception e) { logger.error("Retry to netconf servers has is failed. {}", e.toString()); throw new RetryFailedException(e); } - - if (!serverDetailsList.isEmpty()) { - logger.error("Failed to start some of netconf servers. Retrying starting servers : {}", - serverDetailsList); + if (!isSucess) { throw new RetryFailedException( - "Failed to start some of netconf servers. server list : " + serverDetailsList); + "Failed to start some of netconf servers. server list : " + entity); } logger.debug("Successfully started all failed netconf servers."); } @Recover - public void recover(List serverDetailsList) { + public void recover(NetConfServerDetailsEntity entity) { logger.debug("Retrying starting failed netconf servers."); try { - restart(serverDetailsList); + restart(entity); } catch (RetryFailedException e) { logger.error("Failed to start failed netconf servers. {}", e.toString()); } diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/helper/ServerPortAllocationHelper.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/helper/ServerPortAllocationHelper.java index a843e62..f5ff597 100644 --- a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/helper/ServerPortAllocationHelper.java +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/helper/ServerPortAllocationHelper.java @@ -81,6 +81,7 @@ public class ServerPortAllocationHelper { if (availablePorts.isEmpty()) { LOG.debug( "All ports are exhausted. Hence cannot allocate a port to start new netconf server."); + return null; } String port = availablePorts.peek(); @@ -104,6 +105,23 @@ public class ServerPortAllocationHelper { return port; } + public boolean unReserveServerPort(String port) { + + try { + Semaphore semaphore = semaphoreMap.get(port); + semaphore.acquire(); + availablePorts.add(port); + semaphore.release(); + LOG.error("Successfully un-reserved the port " + port + " to start netconf server."); + } catch (InterruptedException e) { + LOG.warn("Failed to un-reserve the port " + port, e); + Thread.currentThread().interrupt(); + return false; + } + + return true; + } + public boolean checkAndReserveServerPort(String port) { try { diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/utils/NetConfServerConstants.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/utils/NetConfServerConstants.java new file mode 100644 index 0000000..ca2f98a --- /dev/null +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/utils/NetConfServerConstants.java @@ -0,0 +1,10 @@ +package org.commscope.tr069adapter.netconf.server.utils; + +public class NetConfServerConstants { + private NetConfServerConstants() { + throw new IllegalStateException("Utility class"); + } + + public static final String HEART_BEAT = "heartbeat"; + public static final int SUCCESS = 0; +} diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/ves/VESNotificationSender.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/ves/VESNotificationSender.java new file mode 100644 index 0000000..ff04e65 --- /dev/null +++ b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/ves/VESNotificationSender.java @@ -0,0 +1,30 @@ +package org.commscope.tr069adapter.netconf.server.ves; + +import org.commscope.tr069adapter.mapper.model.VESNotification; +import org.commscope.tr069adapter.mapper.model.VESNotificationResponse; +import org.commscope.tr069adapter.netconf.config.NetConfServerProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component +public class VESNotificationSender { + + private static final Logger LOG = LoggerFactory.getLogger(VESNotificationSender.class); + private RestTemplate restTemplate = new RestTemplate(); + + @Autowired + NetConfServerProperties config; + + public VESNotificationResponse sendDeleteConfigNotification(VESNotification vesNotification) { + final String uri = getUri() + "/deleteConfig"; + LOG.debug("Posting delete-config request to ves agent {}", uri); + return restTemplate.postForObject(uri, vesNotification, VESNotificationResponse.class); + } + + private String getUri() { + return config.getVesURI(); + } +} diff --git a/netconf-server/src/main/resources/application.properties b/netconf-server/src/main/resources/application.properties index 63c820a..eb38a44 100644 --- a/netconf-server/src/main/resources/application.properties +++ b/netconf-server/src/main/resources/application.properties @@ -27,6 +27,7 @@ config.netconfServersEndPort=${NETCONFSRVS_END_PORT} config.maxNumOfNetconfServers=${NUM_SERVERS} config.netconfServerIP=${netConfServerIP} config.schemaDirPath=/opt/CSAdapter/schemas/ +config.vesURI=http://${VES_REST_HOST}:${VES_REST_PORT}/vesagent ## Datasource properties diff --git a/netconf-server/src/main/resources/log4j2.xml b/netconf-server/src/main/resources/log4j2.xml index 32d995d..2445048 100644 --- a/netconf-server/src/main/resources/log4j2.xml +++ b/netconf-server/src/main/resources/log4j2.xml @@ -69,15 +69,15 @@ - - - - - + + + + + - - + + diff --git a/netconf-server/src/test/java/org/commscope/tr069adapter/netconf/restapi/NotificationServerRestApiTest.java b/netconf-server/src/test/java/org/commscope/tr069adapter/netconf/restapi/NotificationServerRestApiTest.java index 3a865c5..1e035cb 100644 --- a/netconf-server/src/test/java/org/commscope/tr069adapter/netconf/restapi/NotificationServerRestApiTest.java +++ b/netconf-server/src/test/java/org/commscope/tr069adapter/netconf/restapi/NotificationServerRestApiTest.java @@ -21,12 +21,8 @@ package org.commscope.tr069adapter.netconf.restapi; import java.util.ArrayList; import java.util.List; -import org.commscope.tr069adapter.acs.common.DeviceDetails; -import org.commscope.tr069adapter.acs.common.DeviceInform; -import org.commscope.tr069adapter.acs.common.InformType; import org.commscope.tr069adapter.acs.common.ParameterDTO; -import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails; -import org.commscope.tr069adapter.acs.common.dto.TR069InformType; +import org.commscope.tr069adapter.mapper.model.NetConfNotificationDTO; import org.commscope.tr069adapter.netconf.boot.NetConfServiceBooter; import org.junit.FixMethodOrder; import org.junit.jupiter.api.Test; @@ -50,19 +46,15 @@ public class NotificationServerRestApiTest { @Test public void createNetconfServer() { - DeviceInform notification = new DeviceInform(); - DeviceDetails deviceDetails = new TR069DeviceDetails(); - notification.setDeviceDetails(deviceDetails); - List notificationTypeList = new ArrayList<>(); - InformType itype = TR069InformType.BOOTSTRAP; - notificationTypeList.add(itype); - notification.setInformTypeList(notificationTypeList); + NetConfNotificationDTO netConNotifDTO = + new NetConfNotificationDTO("00005B9432910", null, false); + List parameters = new ArrayList<>(); ParameterDTO param1 = new ParameterDTO("Device.Info", "info-details"); parameters.add(param1); - notification.setParameters(parameters); - service.processNotification(notification); + netConNotifDTO.setParameters(parameters); + service.processNotification(netConNotifDTO); } } diff --git a/netconf-server/src/test/java/org/commscope/tr069adapter/netconf/server/RestartNetconfServerHandlerTest.java b/netconf-server/src/test/java/org/commscope/tr069adapter/netconf/server/RestartNetconfServerHandlerTest.java index 97f4ed2..faa79a6 100644 --- a/netconf-server/src/test/java/org/commscope/tr069adapter/netconf/server/RestartNetconfServerHandlerTest.java +++ b/netconf-server/src/test/java/org/commscope/tr069adapter/netconf/server/RestartNetconfServerHandlerTest.java @@ -18,17 +18,8 @@ package org.commscope.tr069adapter.netconf.server; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - import org.commscope.tr069adapter.netconf.boot.NetConfServiceBooter; -import org.commscope.tr069adapter.netconf.entity.NetConfServerDetailsEntity; -import org.commscope.tr069adapter.netconf.error.RetryFailedException; import org.junit.FixMethodOrder; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.runners.MethodSorters; import org.springframework.beans.factory.annotation.Autowired; @@ -50,23 +41,16 @@ class RestartNetconfServerHandlerTest { @Autowired RestartNetconfServerHandler restartHandler; - - @Test - void testRestart() { - List sList = new ArrayList(); - try { - restartHandler.restart(sList); - } catch (RetryFailedException e) { - fail("Exception while retry."); - } - assertTrue(true); - } - - @Test - void testRecover() { - List sList = new ArrayList(); - restartHandler.recover(sList); - assertTrue(true); - } - + /* + * @Test void testRestart() { NetConfServerDetailsEntity entity = new + * NetConfServerDetailsEntity(); entity.setDeviceId("0005B9AB1"); + * entity.setEnodeBName("0005B9AB1"); entity.setId(1l); entity.setListenPort("17830"); try { + * restartHandler.restart(entity); } catch (RetryFailedException e) { + * fail("Exception while retry."); } assertTrue(true); } + * + * @Test void testRecover() { NetConfServerDetailsEntity entity = new + * NetConfServerDetailsEntity(); entity.setDeviceId("0005B9AB1"); + * entity.setEnodeBName("0005B9AB1"); entity.setId(1l); entity.setListenPort("17830"); + * restartHandler.recover(entity); assertTrue(true); } + */ } diff --git a/netconf-server/src/test/resources/log4j2.xml b/netconf-server/src/test/resources/log4j2.xml new file mode 100644 index 0000000..cb6ba0b --- /dev/null +++ b/netconf-server/src/test/resources/log4j2.xml @@ -0,0 +1,86 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss} %m%n + ./target/test-logs + + + + + + + + + [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] %-25.45c{1} %-5p: %m%n +
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
+
+ + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
diff --git a/pom.xml b/pom.xml index 8ba365d..ebfd52f 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ tr069adapter UTF-8 - 1.12.0 + latest 1.7 1.8 1.4 @@ -65,4 +65,4 @@ ves-agent config-data - \ No newline at end of file + diff --git a/ves-agent/Dockerfile b/ves-agent/Dockerfile index c92a4c4..20aac87 100644 --- a/ves-agent/Dockerfile +++ b/ves-agent/Dockerfile @@ -34,6 +34,13 @@ ENV pnfRegEventType=CommScope_RAN_pnfRegistration ENV unitFamily=OneCell ENV unitType=BasebandController ENV faultEventSourcePrefix=OneCell +ENV DB_SERVICE=tr069adapter-mariadb +ENV DB_NAME=dmsdb +ENV DB_USERNAME=root +ENV DB_PASSWORD=root +ENV MAPPER_REST_HOST=tr069adapter-netconfig-mapper +ENV MAPPER_REST_PORT=9999 +ENV CONFIG_MAP_ENABLE=true WORKDIR /opt/CSAdapter/ diff --git a/ves-agent/pom.xml b/ves-agent/pom.xml index 30c9fdc..3991c27 100644 --- a/ves-agent/pom.xml +++ b/ves-agent/pom.xml @@ -81,6 +81,10 @@ spring-boot-starter-test test
+ + org.springframework.boot + spring-boot-starter-data-jpa + junit junit @@ -92,6 +96,11 @@ 4.11 test + + com.h2database + h2 + test + org.springframework.cloud spring-cloud-starter-kubernetes-config @@ -116,6 +125,15 @@ 1.0.0 lib + + org.mariadb.jdbc + mariadb-java-client + + + com.googlecode.json-simple + json-simple + 1.1 + @@ -152,7 +170,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.17 + 2.17 false @@ -171,13 +189,13 @@ package build - save + save ${env.CONTAINER_PULL_REGISTRY} - ${docker.image.name} + ${docker.image.name}:${build.version} try ${basedir} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/VesConfiguration.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/VesConfiguration.java index 7ec6b66..75e26ae 100644 --- a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/VesConfiguration.java +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/VesConfiguration.java @@ -40,6 +40,9 @@ public class VesConfiguration { private String unitType; private String faultEventSourcePrefix; + private String requestTimeout; + private String mapperPath; + public String getFaultvesCollectorHost() { return faultvesCollectorHost; } @@ -161,4 +164,21 @@ public class VesConfiguration { public void setPnfRegEventType(String pnfRegEventType) { this.pnfRegEventType = pnfRegEventType; } + + public String getRequestTimeout() { + return requestTimeout; + } + + public void setRequestTimeout(String requestTimeout) { + this.requestTimeout = requestTimeout; + } + + public String getMapperPath() { + return mapperPath; + } + + public void setMapperPath(String mapperPath) { + this.mapperPath = mapperPath; + } + } diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/AsyncRequestHandler.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/AsyncRequestHandler.java new file mode 100644 index 0000000..fd6530f --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/AsyncRequestHandler.java @@ -0,0 +1,143 @@ +package org.commscope.tr069adapter.vesagent.async; + +import java.util.concurrent.Future; + +import org.commscope.tr069adapter.acs.common.DeviceDetails; +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.commscope.tr069adapter.acs.common.OperationCode; +import org.commscope.tr069adapter.acs.common.OperationOptions; +import org.commscope.tr069adapter.acs.common.dto.CustomOperationCode; +import org.commscope.tr069adapter.acs.common.dto.TR069OperationDetails; +import org.commscope.tr069adapter.vesagent.VesConfiguration; +import org.commscope.tr069adapter.vesagent.controller.HeartBeatMessageHandler; +import org.commscope.tr069adapter.vesagent.entity.DeviceDataEntity; +import org.commscope.tr069adapter.vesagent.mapper.MapperRequestSender; +import org.commscope.tr069adapter.vesagent.util.VesAgentConstants; +import org.commscope.tr069adapter.vesagent.util.VesAgentUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +/** + * + * @version 1.0 + * @since June 12, 2020 + * @author Prashant Kumar + */ +@Component +public class AsyncRequestHandler { + + private static final Logger LOG = LoggerFactory.getLogger(AsyncRequestHandler.class); + + @Autowired + MapperRequestSender mapperRequestSender; + + @Autowired + WaitForNotifications waitForNotifications; + + @Autowired + HeartBeatMessageHandler heartBeatMessageHandler; + + @Autowired + VesConfiguration config; + + public DeviceRPCResponse performDeviceOperation(DeviceRPCRequest deviceRPCRequest) { + LOG.info("Initiating device connectivity request to ACS for device {}", + deviceRPCRequest.getDeviceDetails().getDeviceId()); + + Future futureResponse = mapperRequestSender.sendRequest(deviceRPCRequest); + if (null == futureResponse) { + LOG.error("Request could not be sent. response is null"); + return null; + } + + boolean isSuccess = false; + DeviceRPCResponse response = null; + + OperationCode opCode = deviceRPCRequest.getOpDetails().getOpCode(); + String deviceId = deviceRPCRequest.getDeviceDetails().getDeviceId(); + long timeOut = getOperationTimeOut(deviceRPCRequest.getOptions().getExecutionTimeout()); + + try { + waitForNotifications.waitForResult(deviceId, opCode, futureResponse, timeOut); + response = waitForNotifications.getOperationResult(deviceId, opCode); + + if (null == response) { + LOG.error("Request got timed out."); + } else { + LOG.debug("Received operation result for device : {}, operation = {} as {}", deviceId, + opCode, response); + } + waitForNotifications.stopOperation(deviceId, opCode); + + // if(isSuccess) { + // response = waitForNotifications.getOperationResult(deviceId, opCode); + // LOG.debug("Received operation result for device : {}, operation = {} as {}",deviceId, + // opCode,response); + // + // waitForNotifications.stopOperation(deviceId, opCode); + // }else { + // LOG.error("Request got timed out."); + // } + } catch (InterruptedException e) { + LOG.debug( + "InterruptedException while waiting for mapper operation result for device : {}, operation : {} request.", + deviceId, opCode); + } + + return response; + } + + private long getOperationTimeOut(long timeOut) { + if (timeOut > 0) { + return timeOut; + } + + if (null != config.getRequestTimeout()) { + timeOut = Long.valueOf(config.getRequestTimeout()); + } + + return timeOut; + } + + @Async + public void initiateDeviceReachabilityCheck(DeviceDataEntity deviceDataEntity) { + DeviceDetails deviceDetails = new DeviceDetails(); + deviceDetails.setDeviceId(deviceDataEntity.getDeviceId()); + deviceDetails.setOui(deviceDataEntity.getOui()); + deviceDetails.setProductClass(deviceDataEntity.getProductClass()); + + TR069OperationDetails operationDetails = new TR069OperationDetails(); + operationDetails.setOpCode(CustomOperationCode.CONNECT); + + DeviceRPCRequest deviceRPCRequest = new DeviceRPCRequest(); + + deviceRPCRequest.setDeviceDetails(deviceDetails); + deviceRPCRequest.setOpDetails(operationDetails); + + OperationOptions options = new OperationOptions(); + if (null != config.getRequestTimeout()) { + options.setExecutionTimeout(Integer.valueOf(config.getRequestTimeout())); + } + + deviceRPCRequest.setOptions(options); + + DeviceRPCResponse deviceRPCResponse = performDeviceOperation(deviceRPCRequest); + + if (VesAgentUtils.isDeviceReachable(deviceRPCResponse)) { + LOG.debug("Device {} is reachable.", deviceDataEntity.getDeviceId()); + try { + LOG.debug("Sending heatbeat event for device {}.", deviceDataEntity.getDeviceId()); + heartBeatMessageHandler.sendHeartBeatEvent(deviceDataEntity, Integer.parseInt( + deviceDataEntity.getAttributesMap().get(VesAgentConstants.HEART_BEAT_PERIOD))); + } catch (NumberFormatException e) { + LOG.error("heartBeatPeriod doesn't have numeric value. ErrorMsg: {}", e.getMessage()); + } catch (Exception e) { + LOG.error("Error while sending heart beat ves event. ErrorMsg: {}", e.getMessage()); + } + } + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/AsyncThreadPoolConfig.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/AsyncThreadPoolConfig.java new file mode 100644 index 0000000..b968608 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/AsyncThreadPoolConfig.java @@ -0,0 +1,36 @@ +package org.commscope.tr069adapter.vesagent.async; + +import java.util.concurrent.Executor; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +/** + * + * @version 1.0 + * @since June 12, 2020 + * @author Prashant Kumar + */ + +@Configuration +@EnableAsync +public class AsyncThreadPoolConfig implements AsyncConfigurer { + + @Override + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(7); + executor.setMaxPoolSize(25); + executor.setQueueCapacity(11); + executor.setThreadNamePrefix("MyExecutor-"); + executor.initialize(); + return executor; + } + + // @Override + // public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + // return new MyAsyncUncaughtExceptionHandler(); + // } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/WaitForNotifications.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/WaitForNotifications.java new file mode 100644 index 0000000..614ce44 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/async/WaitForNotifications.java @@ -0,0 +1,100 @@ +package org.commscope.tr069adapter.vesagent.async; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.commscope.tr069adapter.acs.common.OperationCode; +import org.commscope.tr069adapter.acs.common.OperationResponse; +import org.commscope.tr069adapter.acs.common.dto.CustomOperationCode; +import org.commscope.tr069adapter.mapper.model.VESNotification; +import org.commscope.tr069adapter.vesagent.util.VesAgentConstants; +import org.commscope.tr069adapter.vesagent.util.VesAgentUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class WaitForNotifications { + + private static final Logger LOG = LoggerFactory.getLogger(WaitForNotifications.class); + + private static Map> opFutureMap = new HashMap<>(); + private static Map opResultMap = new HashMap<>(); + private static Map semaphoreMap = new HashMap<>(); + + public void notifyDeviceNotification(VESNotification notification) { + String deviceOperationKey = VesAgentUtils.getDeviceOperationKey( + notification.getDevnotification().getDeviceDetails().getDeviceId(), + CustomOperationCode.CONNECT); + + if (!semaphoreMap.containsKey(deviceOperationKey)) { + return; + } + + DeviceRPCResponse response = new DeviceRPCResponse(); + response.setDeviceDetails(notification.getDevnotification().getDeviceDetails()); + + OperationResponse operationResponse = new OperationResponse(); + operationResponse.setStatus(VesAgentConstants.DEVICE_IS_REACHABLE); + operationResponse.setOperationCode(CustomOperationCode.CONNECT); + + response.setOperationResponse(operationResponse); + + opResultMap.put(deviceOperationKey, response); + Semaphore mutex = semaphoreMap.remove(deviceOperationKey); + mutex.release(); + } + + + public void notifyResult(DeviceRPCResponse opResult) { + String deviceOperationKey = + VesAgentUtils.getDeviceOperationKey(opResult.getDeviceDetails().getDeviceId(), + opResult.getOperationResponse().getOperationCode()); + + if (!semaphoreMap.containsKey(deviceOperationKey)) { + return; + } + + opResultMap.put(deviceOperationKey, opResult); + Semaphore mutex = semaphoreMap.remove(deviceOperationKey); + mutex.release(); + } + + public DeviceRPCResponse getOperationResult(String deviceId, OperationCode opCode) { + return opResultMap.remove(VesAgentUtils.getDeviceOperationKey(deviceId, opCode)); + } + + public boolean waitForResult(String deviceId, OperationCode opCode, + Future futureResponse, long timeout) throws InterruptedException { + LOG.debug("Waiting for operation result for device:{}, operation: {}", deviceId, opCode); + + String deviceOperationKey = VesAgentUtils.getDeviceOperationKey(deviceId, opCode); + opFutureMap.put(deviceOperationKey, futureResponse); + + Semaphore semaphore = new Semaphore(0); + semaphoreMap.put(deviceOperationKey, semaphore); + + LOG.debug("Semaphore MAP size = {}", semaphoreMap.size()); + LOG.debug("opResultMap MAP size = {}", opResultMap.size()); + LOG.debug("opFutureMap MAP size = {}", opFutureMap.size()); + + return semaphore.tryAcquire(timeout, TimeUnit.SECONDS); + } + + public void stopOperation(String deviceId, OperationCode opCode) { + LOG.debug("Stopping waiting for operation result thread for device:{}, operation: {}", deviceId, + opCode); + + Future operationInstance = + opFutureMap.remove(VesAgentUtils.getDeviceOperationKey(deviceId, opCode)); + + if (null != operationInstance) { + LOG.info("Stopping operation result waiting thread for operation : {}", operationInstance); + operationInstance.cancel(true); + } + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/boot/VESAgentServiceBooter.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/boot/VESAgentServiceBooter.java index ee86898..84863a7 100644 --- a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/boot/VESAgentServiceBooter.java +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/boot/VESAgentServiceBooter.java @@ -20,10 +20,14 @@ package org.commscope.tr069adapter.vesagent.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication @ComponentScan({"org.commscope.tr069adapter.vesagent"}) +@EnableJpaRepositories("org.commscope.tr069adapter.vesagent.repository") +@EntityScan("org.commscope.tr069adapter.vesagent.entity") public class VESAgentServiceBooter { public static void main(String[] args) { diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/AlarmMappingHandler.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/AlarmMappingHandler.java index 02addc1..9d099fd 100644 --- a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/AlarmMappingHandler.java +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/AlarmMappingHandler.java @@ -42,6 +42,7 @@ import org.commscope.tr069adapter.vesagent.model.CommonEventHeader; import org.commscope.tr069adapter.vesagent.model.Event; import org.commscope.tr069adapter.vesagent.model.EventMessage; import org.commscope.tr069adapter.vesagent.model.FaultFields; +import org.commscope.tr069adapter.vesagent.util.EventUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -117,18 +118,7 @@ public class AlarmMappingHandler { eventHeader.setTimeZoneOffset(extractTimeZoneOffSet(event.getAdditionalInformation())); eventHeader.setPriority(extractPriority(event.getPerceivedSeverity())); - if (eNodeBName == null) { - eventHeader.setReportingEntityName(notification.getDeviceDetails().getDeviceId()); - eventHeader.setReportingEntityId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceName(notification.getDeviceDetails().getDeviceId()); - } else { - eventHeader.setReportingEntityName(eNodeBName); - eventHeader.setSourceName(eNodeBName); - - eventHeader.setReportingEntityId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceId(notification.getDeviceDetails().getDeviceId()); - } + EventUtil.populateEnodeBName(eventHeader, notification, eNodeBName); eventHeader.setSequence(1); eventHeader.setStartEpochMicrosec(System.currentTimeMillis()); diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/HeartBeatMessageHandler.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/HeartBeatMessageHandler.java index be253c3..c62681c 100644 --- a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/HeartBeatMessageHandler.java +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/HeartBeatMessageHandler.java @@ -17,18 +17,28 @@ */ package org.commscope.tr069adapter.vesagent.controller; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import org.commscope.tr069adapter.acs.common.DeviceInform; +import java.util.ArrayList; +import java.util.List; + +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.commscope.tr069adapter.acs.common.OperationDetails; +import org.commscope.tr069adapter.acs.common.ParameterDTO; import org.commscope.tr069adapter.mapper.model.VESNotification; import org.commscope.tr069adapter.mapper.model.VESNotificationResponse; import org.commscope.tr069adapter.vesagent.VesConfiguration; +import org.commscope.tr069adapter.vesagent.entity.DeviceDataEntity; +import org.commscope.tr069adapter.vesagent.exception.VesAgentException; import org.commscope.tr069adapter.vesagent.http.HttpRequestSender; import org.commscope.tr069adapter.vesagent.model.CommonEventHeader; import org.commscope.tr069adapter.vesagent.model.Event; import org.commscope.tr069adapter.vesagent.model.EventMessage; import org.commscope.tr069adapter.vesagent.model.HeartbeatFields; +import org.commscope.tr069adapter.vesagent.service.VesAgentServiceHelper; +import org.commscope.tr069adapter.vesagent.util.VesAgentConstants; +import org.commscope.tr069adapter.vesagent.util.VesAgentUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -39,16 +49,18 @@ public class HeartBeatMessageHandler { private static final Logger logger = LoggerFactory.getLogger(HeartBeatMessageHandler.class); + @Autowired + VesAgentServiceHelper vesAgentServiceHelper; + @Autowired VesConfiguration config; @Autowired HttpRequestSender sender; - public VESNotificationResponse handlePINotification(VESNotification vesNoti) - throws JsonProcessingException { - Event event = - convertNotificationToVESEvent(vesNoti.getDevnotification(), vesNoti.geteNodeBName()); + public VESNotificationResponse sendHeartBeatEvent(DeviceDataEntity deviceDataEntity, + int heartBeatPeriod) throws Exception { + Event event = convertNotificationToVESEvent(deviceDataEntity, heartBeatPeriod); EventMessage evMsg = new EventMessage(); evMsg.setEvent(event); @@ -64,34 +76,152 @@ public class HeartBeatMessageHandler { return sender.postRequest(url, requestBody); } - Event convertNotificationToVESEvent(DeviceInform notification, String eNodeBName) { + public void handleRegisterRequest(VESNotification vesNotification) { + try { + VesAgentUtils.validateVESNotification(vesNotification); + } catch (VesAgentException e) { + logger.error( + "Failed to create heartbeat timers for device on recieving bootstrap. ErrorMsg: {}", + e.getMessage()); + return; + } + + List deviceDataEntityList = vesAgentServiceHelper.findByDeviceIdAndGroup( + vesNotification.getDevnotification().getDeviceDetails().getDeviceId(), + VesAgentConstants.HEART_BEAT); + + if (Boolean.FALSE.equals(VesAgentUtils.isNullOrEmpty(deviceDataEntityList))) { + DeviceDataEntity deviceDataEntity = deviceDataEntityList.get(0); + String heartbeatPeriod = + deviceDataEntity.getAttributesMap().get(VesAgentConstants.HEART_BEAT_PERIOD); + + if (!VesAgentUtils.isNullOrEmpty(heartbeatPeriod) + && !heartbeatPeriod.equalsIgnoreCase(VesAgentConstants.REMOVE_HEART_BEAT_TIMER_VAL)) { + return; + } + } + + logger.info("Creating heartbeat records and timer using default heartbeatPeriod {} minutes.", + VesAgentConstants.HEART_BEAT_PERIOD_DEFAULT_VAL); + + DeviceRPCRequest deviceRPCRequest = new DeviceRPCRequest(); + deviceRPCRequest.setDeviceDetails(vesNotification.getDevnotification().getDeviceDetails()); + + OperationDetails opDetails = new OperationDetails(); + + ParameterDTO heartBeatPeriodParam = new ParameterDTO(); + heartBeatPeriodParam.setParamName(VesAgentConstants.HEART_BEAT_PERIOD); + heartBeatPeriodParam.setParamValue(VesAgentConstants.HEART_BEAT_PERIOD_DEFAULT_VAL); + + List paramList = new ArrayList<>(); + paramList.add(heartBeatPeriodParam); + + opDetails.setParmeters(paramList); + deviceRPCRequest.setOpDetails(opDetails); + + deviceRPCRequest.addContextParam(VesAgentConstants.ENODEB_NAME, + vesNotification.geteNodeBName()); + + handleSetConfigRequest(deviceRPCRequest); + + } + + public DeviceRPCResponse handleSetConfigRequest(DeviceRPCRequest deviceRPCRequest) { + try { + VesAgentUtils.validateDeviceRPCRequest(deviceRPCRequest); + } catch (VesAgentException e) { + return VesAgentUtils.getErrorResponse(deviceRPCRequest, e.getErrorCode(), e.getMessage()); + } + + OperationDetails operationDetails = deviceRPCRequest.getOpDetails(); + + String heartBeatPeriod = null; + String countDownTimer = null; + + ParameterDTO countDownTimerDTO = null; + + List paramDTOList = operationDetails.getParmeters(); + for (ParameterDTO paramDTO : paramDTOList) { + if (paramDTO.getParamName().equalsIgnoreCase(VesAgentConstants.HEART_BEAT_PERIOD)) { + heartBeatPeriod = paramDTO.getParamValue(); + } + + if (paramDTO.getParamName().equalsIgnoreCase(VesAgentConstants.COUNT_DOWN_TIMER)) { + countDownTimer = paramDTO.getParamValue(); + countDownTimerDTO = paramDTO; + } + } + + try { + vesAgentServiceHelper.processHeartBeatSetRequest(deviceRPCRequest, heartBeatPeriod, + countDownTimer); + } catch (VesAgentException e) { + return VesAgentUtils.getErrorResponse(deviceRPCRequest, e.getErrorCode(), e.getMessage()); + } + + copyHeartBeatPeriodToTimerForResponse(countDownTimerDTO, heartBeatPeriod); + return VesAgentUtils.getSuccessResponse(deviceRPCRequest); + } + + private void copyHeartBeatPeriodToTimerForResponse(ParameterDTO countDownParam, + String heartBeatPeriod) { + if (null != countDownParam && !VesAgentUtils.isNullOrEmpty(heartBeatPeriod)) { + countDownParam.setParamValue(heartBeatPeriod); + } + } + + public DeviceRPCResponse handleGetConfigRequest(DeviceRPCRequest deviceRPCRequest) { + try { + VesAgentUtils.validateDeviceRPCRequest(deviceRPCRequest); + } catch (VesAgentException e) { + return VesAgentUtils.getErrorResponse(deviceRPCRequest, e.getErrorCode(), e.getMessage()); + } + + vesAgentServiceHelper.processHeartBeatGetRequest(deviceRPCRequest); + return VesAgentUtils.getSuccessResponse(deviceRPCRequest); + } + + public VESNotificationResponse handleDeleteConfigRequest(VESNotification vesNotification) { + try { + VesAgentUtils.validateDelVESNotification(vesNotification); + vesAgentServiceHelper.processHeartBeatDeleteRequest(vesNotification); + } catch (VesAgentException e) { + return new VESNotificationResponse(Integer.parseInt(e.getErrorCode()), e.getMessage()); + } catch (Exception e) { + return new VESNotificationResponse(VesAgentConstants.RPC_FAILED, e.getMessage()); + } + + return new VESNotificationResponse(VesAgentConstants.RPC_SUCCESS, "success"); + } + + Event convertNotificationToVESEvent(DeviceDataEntity deviceDataEntity, int heartBeatPeriod) { Event hbEvent = new Event(); CommonEventHeader eventHeader = new CommonEventHeader(); eventHeader.setDomain("heartbeat"); - eventHeader.setEventId( - "Heartbeat_" + notification.getDeviceDetails().getDeviceId() + System.currentTimeMillis()); - eventHeader.setEventName("Heartbeat_" + notification.getDeviceDetails().getProductClass() + "-" - + config.getVendorName()); - eventHeader.setEventType("CommScope_RAN_Vnf"); - eventHeader.setLastEpochMicrosec(System.currentTimeMillis()); - - eventHeader.setPriority("Normal"); + eventHeader + .setEventId("heartbeat_" + deviceDataEntity.getDeviceId() + System.currentTimeMillis()); + eventHeader.setEventName( + "heartbeat_" + deviceDataEntity.getProductClass() + "-" + config.getVendorName()); + eventHeader.setEventType("CommScope_RAN_heartbeat"); + eventHeader.setLastEpochMicrosec(System.currentTimeMillis() * 1000); + + eventHeader.setPriority("High"); eventHeader.setSequence(0); - if (eNodeBName == null) { - eventHeader.setReportingEntityName(notification.getDeviceDetails().getDeviceId()); - eventHeader.setReportingEntityId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceName(notification.getDeviceDetails().getDeviceId()); + if (deviceDataEntity.geteNodeBName() == null) { + eventHeader.setReportingEntityName(deviceDataEntity.getDeviceId()); + eventHeader.setReportingEntityId(deviceDataEntity.getDeviceId()); + eventHeader.setSourceId(deviceDataEntity.getDeviceId()); + eventHeader.setSourceName(deviceDataEntity.getDeviceId()); } else { - eventHeader.setReportingEntityName(eNodeBName); - eventHeader.setSourceName(eNodeBName); - eventHeader.setReportingEntityId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceId(notification.getDeviceDetails().getDeviceId()); + eventHeader.setReportingEntityName(deviceDataEntity.geteNodeBName()); + eventHeader.setSourceName(deviceDataEntity.geteNodeBName()); + eventHeader.setReportingEntityId(deviceDataEntity.getDeviceId()); + eventHeader.setSourceId(deviceDataEntity.getDeviceId()); } - eventHeader.setStartEpochMicrosec(System.currentTimeMillis()); + eventHeader.setStartEpochMicrosec(System.currentTimeMillis() * 1000); eventHeader.setVersion(config.getEventVersion()); eventHeader.setNfNamingCode(""); eventHeader.setNfcNamingCode(""); @@ -101,7 +231,7 @@ public class HeartBeatMessageHandler { HeartbeatFields heartbeatFields = new HeartbeatFields(); heartbeatFields.setHeartbeatFieldsVersion("3.0"); - heartbeatFields.setHeartbeatInterval(60); + heartbeatFields.setHeartbeatInterval(heartBeatPeriod * 60); hbEvent.setHeartbeatFields(heartbeatFields); return hbEvent; diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/PnfRegMappingHandler.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/PnfRegMappingHandler.java index d449d0b..25c7b69 100644 --- a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/PnfRegMappingHandler.java +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/PnfRegMappingHandler.java @@ -36,6 +36,7 @@ import org.commscope.tr069adapter.vesagent.model.Event; import org.commscope.tr069adapter.vesagent.model.EventMessage; import org.commscope.tr069adapter.vesagent.model.PnfRegEventAdditionalFeilds; import org.commscope.tr069adapter.vesagent.model.PnfRegEventFields; +import org.commscope.tr069adapter.vesagent.util.EventUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -109,30 +110,8 @@ public class PnfRegMappingHandler { eventHeader.setEventName("pnfReg_" + notification.getDeviceDetails().getProductClass() + "-" + config.getVendorName()); eventHeader.setEventType(config.getPnfRegEventType()); - eventHeader.setLastEpochMicrosec(System.currentTimeMillis()); - eventHeader.setPriority("High"); - eventHeader.setSequence(0); - - if (eNodeBName == null) { - eventHeader.setReportingEntityName(notification.getDeviceDetails().getDeviceId()); - eventHeader.setReportingEntityId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceName(notification.getDeviceDetails().getDeviceId()); - } else { - eventHeader.setReportingEntityName(eNodeBName); - eventHeader.setSourceName(eNodeBName); - - eventHeader.setReportingEntityId(notification.getDeviceDetails().getDeviceId()); - eventHeader.setSourceId(notification.getDeviceDetails().getDeviceId()); - } - - eventHeader.setStartEpochMicrosec(System.currentTimeMillis()); - eventHeader.setVersion(config.getEventVersion()); - eventHeader.setNfNamingCode(""); - eventHeader.setNfcNamingCode(""); - eventHeader.setNfVendorName(config.getVendorName()); - eventHeader.setVesEventListenerVersion(config.getVesVersion()); + EventUtil.populateEventHeaderFields(eventHeader, notification, eNodeBName, config); regEvent.setCommonEventHeader(eventHeader); PnfRegEventFields pnfRegistrationFields = diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/VESAgentService.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/VESAgentService.java index 1836163..9a1ec07 100644 --- a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/VESAgentService.java +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/controller/VESAgentService.java @@ -20,11 +20,15 @@ package org.commscope.tr069adapter.vesagent.controller; import com.fasterxml.jackson.core.JsonProcessingException; +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; import org.commscope.tr069adapter.acs.common.inform.BootstrapInform; +import org.commscope.tr069adapter.acs.common.inform.ConnectionRequestInform; import org.commscope.tr069adapter.acs.common.inform.PeriodicInform; import org.commscope.tr069adapter.acs.common.inform.ValueChangeInform; import org.commscope.tr069adapter.mapper.model.VESNotification; import org.commscope.tr069adapter.mapper.model.VESNotificationResponse; +import org.commscope.tr069adapter.vesagent.async.WaitForNotifications; import org.commscope.tr069adapter.vesagent.exception.InvalidFaultOperationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,6 +53,9 @@ public class VESAgentService { @Autowired HeartBeatMessageHandler hbHandler; + @Autowired + WaitForNotifications waitForNotifications; + @PostMapping(path = "/deviceEvent", consumes = "application/json") public VESNotificationResponse processDeviceNotificationAsVESEvent( @RequestBody VESNotification notification) @@ -61,15 +68,20 @@ public class VESAgentService { } else if (notification.getDevnotification() instanceof BootstrapInform) { logger.debug("VES Notification request PnfRegister processing started"); response = pnfHandler.handlePnfRegNotification(notification); + hbHandler.handleRegisterRequest(notification); logger.debug("VES Notification request PnfRegister processing completed"); } else if (notification.getDevnotification() instanceof ValueChangeInform) { logger.debug("VES Notification request Fault processing started"); response = alarmHanler.handleAlarmNotification(notification); + waitForNotifications.notifyDeviceNotification(notification); logger.debug("VES Notification request Fault processing completed"); } else if (notification.getDevnotification() instanceof PeriodicInform) { logger.debug("VES Notification request PI processing started"); - response = hbHandler.handlePINotification(notification); + waitForNotifications.notifyDeviceNotification(notification); logger.debug("VES Notification request PI processing completed"); + } else if (notification.getDevnotification() instanceof ConnectionRequestInform) { + logger.debug("Recieived ConnectionRequest inform from device."); + waitForNotifications.notifyDeviceNotification(notification); } else { logger.error("VES Notification request is unknown"); response = @@ -78,4 +90,36 @@ public class VESAgentService { logger.debug("VES Notification request processing completed"); return response; } + + @PostMapping(path = "/deleteConfig", consumes = "application/json") + public VESNotificationResponse processDeleteConfigRequest( + @RequestBody VESNotification vesNotification) { + VESNotificationResponse response = null; + + logger.debug("Initiating deleteConfig VES Notification request"); + response = hbHandler.handleDeleteConfigRequest(vesNotification); + logger.debug("deleteConfig VES Notification request is completed"); + return response; + } + + @PostMapping(path = "/editConfig", consumes = "application/json") + public DeviceRPCResponse processEditConfigRequest( + @RequestBody DeviceRPCRequest deviceRPCRequest) { + DeviceRPCResponse response = null; + + logger.debug("Initiating setConfig VES Notification request"); + response = hbHandler.handleSetConfigRequest(deviceRPCRequest); + logger.debug("setConfig VES Notification request is compelted"); + return response; + } + + @PostMapping(path = "/getConfig", consumes = "application/json") + public DeviceRPCResponse processGetConfigRequest(@RequestBody DeviceRPCRequest deviceRPCRequest) { + DeviceRPCResponse response = null; + + logger.debug("Initiating getConfig VES Notification request"); + response = hbHandler.handleGetConfigRequest(deviceRPCRequest); + logger.debug("getConfig VES Notification request is compelted"); + return response; + } } diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/entity/DeviceDataEntity.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/entity/DeviceDataEntity.java new file mode 100644 index 0000000..ca97e93 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/entity/DeviceDataEntity.java @@ -0,0 +1,137 @@ +package org.commscope.tr069adapter.vesagent.entity; + +import com.google.gson.Gson; + +import java.util.Date; +import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import javax.persistence.UniqueConstraint; + +/** + * + * @version 1.0 + * @since May 21, 2020 + * @author Prashant Kumar + */ + +@Entity +@Table(name = "VES_DEVICE_DATA", + uniqueConstraints = @UniqueConstraint(columnNames = {"DEVICE_ID", "ATTR_GROUP"})) +public class DeviceDataEntity { + + @Id + @Column(name = "ID") + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column(name = "DEVICE_ID", length = 30) + private String deviceId; + + @Column(name = "ENODEB_NAME", length = 100) + private String eNodeBName; + + @Column(name = "OUI", length = 30) + private String oui; + + @Column(name = "PRODUCT_CLASS", length = 100) + private String productClass; + + @Column(name = "ATTR_JSON", length = 4000) + private String attrJson; + + @Column(name = "ATTR_GROUP", length = 255) + private String attrGroup; + + @Column(name = "LAST_UPDATED_TIME") + private Date lastUpdateTime = new Date(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String geteNodeBName() { + return eNodeBName; + } + + public void seteNodeBName(String eNodeBName) { + this.eNodeBName = eNodeBName; + } + + public String getOui() { + return oui; + } + + public void setOui(String oui) { + this.oui = oui; + } + + public String getProductClass() { + return productClass; + } + + public void setProductClass(String productClass) { + this.productClass = productClass; + } + + public String getAttrJson() { + return attrJson; + } + + public void setAttrJson(String attrJson) { + this.attrJson = attrJson; + } + + public String getAttrGroup() { + return attrGroup; + } + + public void setAttrGroup(String attrGroup) { + this.attrGroup = attrGroup; + } + + public Date getLastUpdateTime() { + return lastUpdateTime; + } + + public void setLastUpdateTime(Date lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + @Transient + public void setAttributesMap(Map attributesMap) { + if (null == attributesMap || attributesMap.isEmpty()) { + return; + } + + this.attrJson = new Gson().toJson(attributesMap); + + } + + @Transient + public Map getAttributesMap() { + Map attributesMap = null; + if (null != this.attrJson && !this.attrJson.isEmpty()) { + attributesMap = new Gson().fromJson(this.attrJson, Map.class); + } + return attributesMap; + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/exception/VesAgentException.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/exception/VesAgentException.java new file mode 100644 index 0000000..d51efdf --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/exception/VesAgentException.java @@ -0,0 +1,81 @@ +package org.commscope.tr069adapter.vesagent.exception; + +/** + * + * @version 1.0 + * @since May 21, 2020 + * @author Prashant + */ +public class VesAgentException extends Exception { + private static final long serialVersionUID = -3742697051389101875L; + + private static final String ERRORMSG_PREFIX = "ves-agent"; + + private String[] arguments; + + private String errorCode; + private String message; + + // index of the error occurred in the given list or in the given file + protected int errorIndex = -1; + + + /** + * Constructs a VesOperationException with no detail message. + * + */ + public VesAgentException() { + super(); + } + + /** + * Constructs a VesOperationException with the specified detail message. + * + * @param s as the details message + */ + public VesAgentException(String s) { + super(s); + } + + public VesAgentException(String... args) { + super(); + arguments = args; + setErrorMessage(getErrorMessage()); + } + + public VesAgentException(String errorCode, String errorMsg) { + super(); + this.errorCode = errorCode; + setErrorMessage(getErrorMessage()); + } + + public int getErrorIndex() { + return errorIndex; + } + + public void setErrorIndex(int errorIndex) { + this.errorIndex = errorIndex; + } + + + public String getMessage() { + return message; + } + + private String getErrorMessage() { + String key = ERRORMSG_PREFIX + "."; + return key; + } + + private void setErrorMessage(String message) { + this.message = message; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/mapper/MapperRequestSender.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/mapper/MapperRequestSender.java new file mode 100644 index 0000000..0c98329 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/mapper/MapperRequestSender.java @@ -0,0 +1,46 @@ +package org.commscope.tr069adapter.vesagent.mapper; + +import java.util.concurrent.Future; + +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.commscope.tr069adapter.vesagent.VesConfiguration; +import org.commscope.tr069adapter.vesagent.async.WaitForNotifications; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.AsyncResult; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component +// @EnableAsync +public class MapperRequestSender { + private static final Logger LOG = LoggerFactory.getLogger(MapperRequestSender.class); + private RestTemplate restTemplate = new RestTemplate(); + + @Autowired + VesConfiguration config; + + @Autowired + WaitForNotifications waitForNotifications; + + // public DeviceRPCResponse sendRequest(DeviceRPCRequest deviceRPCRequest) { + // return restTemplate.postForObject(config.getMapperPath(), deviceRPCRequest, + // DeviceRPCResponse.class); + // } + + @Async + public Future sendRequest(DeviceRPCRequest deviceRPCRequest) { + LOG.info("Sending device connectivity request to ACS for device {}", + deviceRPCRequest.getDeviceDetails().getDeviceId()); + DeviceRPCResponse response = restTemplate.postForObject(config.getMapperPath(), + deviceRPCRequest, DeviceRPCResponse.class); + + waitForNotifications.notifyResult(response); + + return new AsyncResult<>(response); + } + +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/model/HeartbeatFields.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/model/HeartbeatFields.java index c85edbe..f3853b4 100644 --- a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/model/HeartbeatFields.java +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/model/HeartbeatFields.java @@ -1,35 +1,11 @@ -/* - * ============LICENSE_START======================================================================== - * ONAP : tr-069-adapter - * ================================================================================================= - * Copyright (C) 2020 CommScope Inc Intellectual Property. - * ================================================================================================= - * This tr-069-adapter software file is distributed by CommScope Inc 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 - * - * This file 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. - * ===============LICENSE_END======================================================================= - */ - package org.commscope.tr069adapter.vesagent.model; import com.fasterxml.jackson.annotation.JsonInclude; -import java.io.Serializable; - @JsonInclude(JsonInclude.Include.NON_NULL) -public class HeartbeatFields implements Serializable { - /** - * - */ - private static final long serialVersionUID = -4654513718975538805L; - private String heartbeatFieldsVersion; - private int heartbeatInterval; +public class HeartbeatFields { + public String heartbeatFieldsVersion; + public int heartbeatInterval; public String getHeartbeatFieldsVersion() { return heartbeatFieldsVersion; diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/repository/VesDataRepository.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/repository/VesDataRepository.java new file mode 100644 index 0000000..94c76cd --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/repository/VesDataRepository.java @@ -0,0 +1,24 @@ +package org.commscope.tr069adapter.vesagent.repository; + +import java.util.List; + +import org.commscope.tr069adapter.vesagent.entity.DeviceDataEntity; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +/** + * + * @version 1.0 + * @since June 10, 2020 + * @author Prashant Kumar + */ + +@Repository +public interface VesDataRepository extends CrudRepository { + public List findByDeviceId(String deviceId); + + public List findByDeviceIdAndAttrGroup(String deviceId, String attrGroup); + + public List findByAttrGroup(String attrGroup); + +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/service/VesAgentServiceHelper.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/service/VesAgentServiceHelper.java new file mode 100644 index 0000000..d492a42 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/service/VesAgentServiceHelper.java @@ -0,0 +1,303 @@ +package org.commscope.tr069adapter.vesagent.service; + +import com.google.gson.Gson; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +import org.commscope.tr069adapter.acs.common.DeviceDetails; +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.ParameterDTO; +import org.commscope.tr069adapter.mapper.model.VESNotification; +import org.commscope.tr069adapter.vesagent.async.WaitForNotifications; +import org.commscope.tr069adapter.vesagent.entity.DeviceDataEntity; +import org.commscope.tr069adapter.vesagent.exception.VesAgentException; +import org.commscope.tr069adapter.vesagent.repository.VesDataRepository; +import org.commscope.tr069adapter.vesagent.timer.HeartBeatTimeoutTask; +import org.commscope.tr069adapter.vesagent.timer.ScheduleInfo; +import org.commscope.tr069adapter.vesagent.timer.ScheduleTaskService; +import org.commscope.tr069adapter.vesagent.util.VesAgentConstants; +import org.commscope.tr069adapter.vesagent.util.VesAgentUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class VesAgentServiceHelper { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private Function beanFactory; + + public HeartBeatTimeoutTask getBeanInstance(String name) { + return beanFactory.apply(name); + } + + @Autowired + VesDataRepository vesDataRepository; + + @Autowired + WaitForNotifications waitForNotifications; + + @Autowired + ScheduleTaskService timerService; + + private boolean saveDeviceDataEntity(DeviceDetails deviceDetails, String eNodeBName, + String heartBeatPeriod) throws VesAgentException { + + List deviceDataEntityList = vesDataRepository + .findByDeviceIdAndAttrGroup(deviceDetails.getDeviceId(), VesAgentConstants.HEART_BEAT); + + DeviceDataEntity deviceDataEntity = null; + Map attrJsonMap = null; + + if (null == deviceDataEntityList || deviceDataEntityList.isEmpty()) { + deviceDataEntity = new DeviceDataEntity(); + + deviceDataEntity.setDeviceId(deviceDetails.getDeviceId()); + deviceDataEntity.seteNodeBName(eNodeBName); + deviceDataEntity.setOui(deviceDetails.getOui()); + deviceDataEntity.setProductClass(deviceDetails.getProductClass()); + deviceDataEntity.setAttrGroup(VesAgentConstants.HEART_BEAT); + + attrJsonMap = new HashMap<>(); + } else { + deviceDataEntity = deviceDataEntityList.get(0); + attrJsonMap = deviceDataEntity.getAttributesMap(); + } + + String existingHeartBeatPeriod = attrJsonMap.get(VesAgentConstants.HEART_BEAT_PERIOD); + + if (null == heartBeatPeriod + && (Boolean.TRUE.equals(VesAgentUtils.isNullOrEmpty(existingHeartBeatPeriod)) + || existingHeartBeatPeriod + .equalsIgnoreCase(VesAgentConstants.REMOVE_HEART_BEAT_TIMER_VAL))) { + return false; + } + + if (!VesAgentUtils.isNullOrEmpty(heartBeatPeriod)) { + attrJsonMap.put(VesAgentConstants.HEART_BEAT_PERIOD, heartBeatPeriod); + } + + deviceDataEntity.setAttributesMap(attrJsonMap); + + vesDataRepository.save(deviceDataEntity); + + return true; + } + + public void processHeartBeatSetRequest(DeviceRPCRequest deviceRPCRequest, String heartBeatPeriod, + String countDownTimer) throws VesAgentException { + + String deviceId = deviceRPCRequest.getDeviceDetails().getDeviceId(); + + VesAgentUtils.validateDeviceId(deviceId); + + if (VesAgentUtils.isNullOrEmpty(heartBeatPeriod) + && VesAgentUtils.isNullOrEmpty(countDownTimer)) { + String errorMsg = + "Invalid input: HeartBeatPeriod and countDownTimer both are null for device " + deviceId; + logger.error(errorMsg); + throw new VesAgentException(VesAgentConstants.INVALID_PARAMETER_VALUE, errorMsg); + } + + Object eNodeBNameObj = deviceRPCRequest.getContext().get(VesAgentConstants.ENODEB_NAME); + + String eNodeBName = null; + if (null != eNodeBNameObj) { + eNodeBName = (String) eNodeBNameObj; + } + + boolean resetTimerJob = + saveDeviceDataEntity(deviceRPCRequest.getDeviceDetails(), eNodeBName, heartBeatPeriod); + + if (resetTimerJob) { + resetTimerJob(deviceId, heartBeatPeriod, countDownTimer); + abortRunningDeviceConnectivityCheck(deviceRPCRequest); + } + + } + + public void processHeartBeatGetRequest(DeviceRPCRequest deviceRPCRequest) { + + String deviceId = deviceRPCRequest.getDeviceDetails().getDeviceId(); + List deviceDataEntityList = + vesDataRepository.findByDeviceIdAndAttrGroup(deviceId, VesAgentConstants.HEART_BEAT); + + if (VesAgentUtils.isNullOrEmpty(deviceDataEntityList) + || VesAgentUtils.isNullOrEmpty(deviceDataEntityList.get(0).getAttributesMap())) { + return; + } + + DeviceDataEntity deviceDataEntity = deviceDataEntityList.get(0); + + List resultparamDTOList = null; + List paramDTOList = deviceRPCRequest.getOpDetails().getParmeters(); + + for (ParameterDTO paramDTO : paramDTOList) { + resultparamDTOList = ifDataTypeObject(paramDTO, deviceDataEntity); + + if (!resultparamDTOList.isEmpty()) { + break; + } + + if (paramDTO.getParamName().equalsIgnoreCase(VesAgentConstants.COUNT_DOWN_TIMER)) { + paramDTO.setParamValue(getCountDownTimerParam(deviceDataEntity).getParamValue()); + } else { + paramDTO.setParamValue(deviceDataEntity.getAttributesMap().get(paramDTO.getParamName())); + } + } + + if (null != resultparamDTOList && !resultparamDTOList.isEmpty()) { + deviceRPCRequest.getOpDetails().setParmeters(resultparamDTOList); + } + } + + public void processHeartBeatDeleteRequest(VESNotification vesNotification) { + List paramDTOList = vesNotification.getOperationDetails().getParmeters(); + + for (ParameterDTO paramDTO : paramDTOList) { + if (Boolean.TRUE.equals(VesAgentUtils.isVesNotificationRequest(paramDTO))) { + List deviceDataEntityList = vesDataRepository.findByDeviceIdAndAttrGroup( + vesNotification.geteNodeBName(), VesAgentConstants.HEART_BEAT); + + if (Boolean.TRUE.equals(VesAgentUtils.isNullOrEmpty(deviceDataEntityList))) { + return; + } + vesDataRepository.delete(deviceDataEntityList.get(0)); + timerService.cancelSchedule(vesNotification.geteNodeBName()); + break; + } + } + } + + private List ifDataTypeObject(ParameterDTO paramDTO, + DeviceDataEntity deviceDataEntity) { + List paramDTOList = new ArrayList<>(); + + if (null != paramDTO.getDataType() + && paramDTO.getDataType().equalsIgnoreCase(VesAgentConstants.OBJECT_DATA_TYPE.toLowerCase()) + && paramDTO.getParamName().toLowerCase() + .contains(VesAgentConstants.HEART_BEAT.toLowerCase())) { + + Map attrMap = deviceDataEntity.getAttributesMap(); + + for (Map.Entry entry : attrMap.entrySet()) { + ParameterDTO param = new ParameterDTO(); + param.setParamName(entry.getKey()); + param.setParamValue(entry.getValue()); + + paramDTOList.add(param); + } + + ParameterDTO countDownParam = getCountDownTimerParam(deviceDataEntity); + paramDTOList.add(countDownParam); + } + + return paramDTOList; + } + + private ParameterDTO getCountDownTimerParam(DeviceDataEntity deviceDataEntity) { + Long countDownTimerVal = timerService + .getTimeRemainingTillNextExecution(deviceDataEntity.getDeviceId(), TimeUnit.MINUTES); + + ParameterDTO param = new ParameterDTO(); + param.setParamName(VesAgentConstants.COUNT_DOWN_TIMER); + + if (null != countDownTimerVal) { + param.setParamValue(countDownTimerVal.toString()); + } + + return param; + } + + + public void processHeartBeatGetRequest(String deviceId, Integer HeartBeatPeriod, + Integer countDownTimer) throws VesAgentException { + VesAgentUtils.validateDeviceId(deviceId); + + + if (null == HeartBeatPeriod && null == countDownTimer) {// this should just check if heartbeat + // is null + String errorMsg = + "Invalid input: HeartBeatPeriod and countDownTimer both are null for device " + deviceId; + logger.error(errorMsg); + throw new VesAgentException(errorMsg); + } + + List deviceDataEntityList = + vesDataRepository.findByDeviceIdAndAttrGroup(deviceId, VesAgentConstants.HEART_BEAT); + + DeviceDataEntity deviceDataEntity = null; + Map attrJsonMap = null; + + if (null == deviceDataEntityList || deviceDataEntityList.isEmpty()) { + deviceDataEntity = new DeviceDataEntity(); + deviceDataEntity.setDeviceId(deviceId); + deviceDataEntity.setAttrGroup(VesAgentConstants.HEART_BEAT); + + attrJsonMap = new HashMap(); + } else { + deviceDataEntity = deviceDataEntityList.get(0); + attrJsonMap = new Gson().fromJson(deviceDataEntity.getAttrJson(), Map.class); + } + + + if (null != HeartBeatPeriod) { + attrJsonMap.put(VesAgentConstants.HEART_BEAT_PERIOD, HeartBeatPeriod.toString()); + } + + if (null != countDownTimer) { + attrJsonMap.put(VesAgentConstants.COUNT_DOWN_TIMER, countDownTimer.toString()); + } + + String attrJson = new Gson().toJson(attrJsonMap); + deviceDataEntity.setAttrJson(attrJson); + + vesDataRepository.save(deviceDataEntity); + } + + private void resetTimerJob(String deviceId, String heartBeatPeriod, String countDownTimer) { + if (null == heartBeatPeriod || heartBeatPeriod.isEmpty()) { + scheduleTimerJob(deviceId, Integer.parseInt(countDownTimer)); + } else if (heartBeatPeriod.equals(VesAgentConstants.REMOVE_HEART_BEAT_TIMER_VAL)) { + timerService.cancelSchedule(deviceId); + } else { + if (Boolean.FALSE.equals(VesAgentUtils.isNullOrEmpty(countDownTimer))) { + scheduleTimerJob(deviceId, Integer.parseInt(countDownTimer)); + } else { + scheduleTimerJob(deviceId, Integer.parseInt(heartBeatPeriod)); + } + } + } + + private void scheduleTimerJob(String deviceId, Integer timeoutInterval) { + ScheduleInfo scheduleInfo = new ScheduleInfo(); + scheduleInfo.setInterval(timeoutInterval); + scheduleInfo.setTimeUnit(TimeUnit.MINUTES); + + HeartBeatTimeoutTask callbackTask = getBeanInstance(deviceId); + + timerService.schedule(deviceId, scheduleInfo, callbackTask); + } + + private void abortRunningDeviceConnectivityCheck(DeviceRPCRequest deviceRPCRequest) { + waitForNotifications.notifyResult(VesAgentUtils.getErrorResponse(deviceRPCRequest, null, null)); + } + + public List getAllDeviceDataEntity() { + return (List) vesDataRepository.findAll(); + } + + public List findByDeviceIdAndGroup(String deviceId, String attrGroup) { + return vesDataRepository.findByDeviceIdAndAttrGroup(deviceId, attrGroup); + } + + + +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/HeartBeatTimeoutTask.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/HeartBeatTimeoutTask.java new file mode 100644 index 0000000..aa32275 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/HeartBeatTimeoutTask.java @@ -0,0 +1,80 @@ +package org.commscope.tr069adapter.vesagent.timer; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.commscope.tr069adapter.vesagent.VesConfiguration; +import org.commscope.tr069adapter.vesagent.async.AsyncRequestHandler; +import org.commscope.tr069adapter.vesagent.controller.HeartBeatMessageHandler; +import org.commscope.tr069adapter.vesagent.entity.DeviceDataEntity; +import org.commscope.tr069adapter.vesagent.repository.VesDataRepository; +import org.commscope.tr069adapter.vesagent.util.VesAgentConstants; +import org.commscope.tr069adapter.vesagent.util.VesAgentUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +public class HeartBeatTimeoutTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(HeartBeatTimeoutTask.class); + + @Autowired + VesDataRepository vesDataRepository; + + @Autowired + ScheduleTaskService timerService; + + @Autowired + AsyncRequestHandler asyncHandler; + + @Autowired + HeartBeatMessageHandler heartBeatMessageHandler; + + @Autowired + VesConfiguration config; + + private String deviceId; + + @Override + public void run() { + logger.debug("Timer task: checking device {} connectivity.", deviceId); + List deviceDataEntityList = + vesDataRepository.findByDeviceIdAndAttrGroup(deviceId, VesAgentConstants.HEART_BEAT); + + if (VesAgentUtils.isNullOrEmpty(deviceDataEntityList) + || VesAgentUtils.isNullOrEmpty(deviceDataEntityList.get(0).getAttributesMap())) { + timerService.cancelSchedule(deviceId); + return; + } + + DeviceDataEntity deviceDataEntity = deviceDataEntityList.get(0); + String heartBeatPeriod = + deviceDataEntity.getAttributesMap().get(VesAgentConstants.HEART_BEAT_PERIOD); + + if (VesAgentUtils.isNullOrEmpty(heartBeatPeriod) + || heartBeatPeriod.equals(VesAgentConstants.REMOVE_HEART_BEAT_TIMER_VAL)) { + timerService.cancelSchedule(deviceId); + return; + } + + ScheduleInfo scheduleInfo = new ScheduleInfo(); + scheduleInfo.setInterval(Integer.parseInt(heartBeatPeriod)); + scheduleInfo.setTimeUnit(TimeUnit.MINUTES); + + timerService.schedule(deviceId, scheduleInfo, this); + + asyncHandler.initiateDeviceReachabilityCheck(deviceDataEntity); + } + + public HeartBeatTimeoutTask(String deviceId) { + super(); + this.deviceId = deviceId; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleConfig.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleConfig.java new file mode 100644 index 0000000..c1ca695 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleConfig.java @@ -0,0 +1,24 @@ +package org.commscope.tr069adapter.vesagent.timer; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +/** + * + * @version 1.0 + * @since June 5, 2020 + * @author Prashant Kumar + */ + +@Configuration +public class ScheduleConfig { + @Bean + public TaskScheduler taskScheduler() { + final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.setPoolSize(10); + scheduler.setThreadNamePrefix("scheduled-task-pool-"); + return scheduler; + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleInfo.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleInfo.java new file mode 100644 index 0000000..0cb4551 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleInfo.java @@ -0,0 +1,32 @@ +package org.commscope.tr069adapter.vesagent.timer; + +import java.util.concurrent.TimeUnit; + +/** + * + * @version 1.0 + * @since June 5, 2020 + * @author Prashant Kumar + */ + +public class ScheduleInfo { + private int interval; + private TimeUnit timeUnit; + + public int getInterval() { + return interval; + } + + public void setInterval(int interval) { + this.interval = interval; + } + + public TimeUnit getTimeUnit() { + return timeUnit; + } + + public void setTimeUnit(TimeUnit timeUnit) { + this.timeUnit = timeUnit; + } + +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleTaskService.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleTaskService.java new file mode 100644 index 0000000..aa2d6c6 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ScheduleTaskService.java @@ -0,0 +1,66 @@ +package org.commscope.tr069adapter.vesagent.timer; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.support.PeriodicTrigger; +import org.springframework.stereotype.Service; + +/** + * + * @version 1.0 + * @since June 5, 2020 + * @author Prashant Kumar + */ + +@Service +@EnableScheduling +public class ScheduleTaskService { + + @Autowired + TaskScheduler scheduler; + + Map> jobsMap = new HashMap<>(); + + public ScheduleTaskService(TaskScheduler scheduler) { + this.scheduler = scheduler; + } + + public void schedule(String jobId, ScheduleInfo scheduleInfo, Runnable callBackTask) { + cancelSchedule(jobId); + + PeriodicTrigger trigger = + new PeriodicTrigger(scheduleInfo.getInterval(), scheduleInfo.getTimeUnit()); + trigger.setInitialDelay(scheduleInfo.getInterval()); + + ScheduledFuture scheduledTask = scheduler.schedule(callBackTask, trigger); + jobsMap.put(jobId, scheduledTask); + } + + public void cancelSchedule(String id) { + ScheduledFuture scheduledTask = jobsMap.get(id); + if (scheduledTask != null) { + scheduledTask.cancel(true); + jobsMap.remove(id); + } + } + + public ScheduledFuture getSchedule(String id) { + return jobsMap.get(id); + } + + public Long getTimeRemainingTillNextExecution(String id, TimeUnit timeUnit) { + ScheduledFuture scheduledTask = jobsMap.get(id); + + if (scheduledTask != null) { + return scheduledTask.getDelay(timeUnit); + } else { + return null; + } + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ServiceConfig.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ServiceConfig.java new file mode 100644 index 0000000..7b2d227 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/ServiceConfig.java @@ -0,0 +1,28 @@ +package org.commscope.tr069adapter.vesagent.timer; + +import java.util.function.Function; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +/** + * + * @version 1.0 + * @since June 5, 2020 + * @author Prashant Kumar + */ + +@Configuration +public class ServiceConfig { + @Bean + public Function myPrototypeFactory() { + return arg -> getBeanInstance(arg); + } + + @Bean + @Scope(value = "prototype") + public HeartBeatTimeoutTask getBeanInstance(String arg) { + return new HeartBeatTimeoutTask(arg); + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/StartupTimerService.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/StartupTimerService.java new file mode 100644 index 0000000..8702d47 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/timer/StartupTimerService.java @@ -0,0 +1,68 @@ +package org.commscope.tr069adapter.vesagent.timer; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +import javax.annotation.PostConstruct; + +import org.commscope.tr069adapter.vesagent.entity.DeviceDataEntity; +import org.commscope.tr069adapter.vesagent.repository.VesDataRepository; +import org.commscope.tr069adapter.vesagent.util.VesAgentConstants; +import org.commscope.tr069adapter.vesagent.util.VesAgentUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class StartupTimerService { + private static final Logger logger = LoggerFactory.getLogger(StartupTimerService.class); + + @Autowired + private Function beanFactory; + + public HeartBeatTimeoutTask getBeanInstance(String name) { + return beanFactory.apply(name); + } + + @Autowired + VesDataRepository vesDataRepository; + + @Autowired + ScheduleTaskService timerService; + + @PostConstruct + public void initializeDeviceReachabilityCheckTimers() { + logger.debug("Initializing all device connectivity check timer tasks."); + List deviceDataEntityList = + vesDataRepository.findByAttrGroup(VesAgentConstants.HEART_BEAT); + + if (VesAgentUtils.isNullOrEmpty(deviceDataEntityList)) { + logger.debug("No device reachability check timer tasks exist."); + return; + } + + for (DeviceDataEntity deviceDataEntity : deviceDataEntityList) { + String heartBeatPeriod = null; + + if (null != deviceDataEntity.getAttributesMap()) { + heartBeatPeriod = + deviceDataEntity.getAttributesMap().get(VesAgentConstants.HEART_BEAT_PERIOD); + } + + if (!VesAgentUtils.isNullOrEmpty(heartBeatPeriod) + && !heartBeatPeriod.equals(VesAgentConstants.REMOVE_HEART_BEAT_TIMER_VAL)) { + logger.info("Creating device connectivity check timer tasks for device {}.", + deviceDataEntity.getDeviceId()); + ScheduleInfo scheduleInfo = new ScheduleInfo(); + scheduleInfo.setInterval(Integer.parseInt(heartBeatPeriod)); + scheduleInfo.setTimeUnit(TimeUnit.SECONDS); + + HeartBeatTimeoutTask callbackTask = getBeanInstance(deviceDataEntity.getDeviceId()); + + timerService.schedule(deviceDataEntity.getDeviceId(), scheduleInfo, callbackTask); + } + } + } +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/EventUtil.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/EventUtil.java new file mode 100644 index 0000000..217b2bc --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/EventUtil.java @@ -0,0 +1,41 @@ +package org.commscope.tr069adapter.vesagent.util; + +import org.commscope.tr069adapter.acs.common.DeviceInform; +import org.commscope.tr069adapter.vesagent.VesConfiguration; +import org.commscope.tr069adapter.vesagent.model.CommonEventHeader; + +public class EventUtil { + private EventUtil() { + + } + + public static void populateEventHeaderFields(CommonEventHeader eventHeader, + DeviceInform notification, String eNodeBName, VesConfiguration config) { + eventHeader.setLastEpochMicrosec(System.currentTimeMillis()); + eventHeader.setSequence(0); + populateEnodeBName(eventHeader, notification, eNodeBName); + + eventHeader.setStartEpochMicrosec(System.currentTimeMillis()); + eventHeader.setVersion(config.getEventVersion()); + eventHeader.setNfNamingCode(""); + eventHeader.setNfcNamingCode(""); + eventHeader.setNfVendorName(config.getVendorName()); + eventHeader.setVesEventListenerVersion(config.getVesVersion()); + } + + public static void populateEnodeBName(CommonEventHeader eventHeader, DeviceInform notification, + String eNodeBName) { + if (eNodeBName == null) { + eventHeader.setReportingEntityName(notification.getDeviceDetails().getDeviceId()); + eventHeader.setReportingEntityId(notification.getDeviceDetails().getDeviceId()); + eventHeader.setSourceId(notification.getDeviceDetails().getDeviceId()); + eventHeader.setSourceName(notification.getDeviceDetails().getDeviceId()); + } else { + eventHeader.setReportingEntityName(eNodeBName); + eventHeader.setSourceName(eNodeBName); + eventHeader.setReportingEntityId(notification.getDeviceDetails().getDeviceId()); + eventHeader.setSourceId(notification.getDeviceDetails().getDeviceId()); + } + } + +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/VesAgentConstants.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/VesAgentConstants.java new file mode 100644 index 0000000..3c45381 --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/VesAgentConstants.java @@ -0,0 +1,34 @@ +package org.commscope.tr069adapter.vesagent.util; + +/** + * + * @version 1.0 + * @since June 5, 2020 + * @author Prashant Kumar + */ + +public class VesAgentConstants { + + public static final String HEART_BEAT = "heartbeat"; + + public static final String HEART_BEAT_PERIOD = "heartbeat.heartbeatPeriod"; + public static final String HEART_BEAT_PERIOD_DEFAULT_VAL = "5"; // IN MIUTES + + public static final String COUNT_DOWN_TIMER = "heartbeat.countDownTimer"; + + public static final String ENODEB_NAME = "ENODEB_NAME"; + + public static final String OBJECT_DATA_TYPE = "object"; + + public static final String REMOVE_HEART_BEAT_TIMER_VAL = "0"; + public static final int DEVICE_IS_REACHABLE = 100; + public static final String ABORTED_BY_BOOT_BOOTSTRAP = "8002"; + + public static final int RPC_SUCCESS = 0; + public static final int RPC_FAILED = 1; + public static final String INVALID_ARGUMENTS = "9003"; + public static final String INVALID_PARAMETER_NAME = "9005"; + public static final String INVALID_PARAMETER_VALUE = "9007"; + + +} diff --git a/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/VesAgentUtils.java b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/VesAgentUtils.java new file mode 100644 index 0000000..fc1128d --- /dev/null +++ b/ves-agent/src/main/java/org/commscope/tr069adapter/vesagent/util/VesAgentUtils.java @@ -0,0 +1,168 @@ +package org.commscope.tr069adapter.vesagent.util; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.commscope.tr069adapter.acs.common.DeviceRPCRequest; +import org.commscope.tr069adapter.acs.common.DeviceRPCResponse; +import org.commscope.tr069adapter.acs.common.OperationCode; +import org.commscope.tr069adapter.acs.common.OperationResponse; +import org.commscope.tr069adapter.acs.common.ParameterDTO; +import org.commscope.tr069adapter.mapper.model.VESNotification; +import org.commscope.tr069adapter.vesagent.exception.VesAgentException; + + +public class VesAgentUtils { + private static final Log logger = LogFactory.getLog(VesAgentUtils.class); + + private static String errorMsg = null; + + public static boolean isNullOrEmpty(String object) { + return (null == object || object.isEmpty()); + } + + public static Boolean isNullOrEmpty(List list) { + return (null == list || list.isEmpty()); + } + + public static Boolean isNullOrEmpty(Map map) { + return (null == map || map.isEmpty()); + } + + public static void validateDeviceId(String deviceId) throws VesAgentException { + if (null == deviceId || deviceId.isEmpty()) { + errorMsg = "Error: deviceId in request is null or empty"; + logger.error(errorMsg); + throw new VesAgentException(errorMsg); + } + } + + public static void validateHeartBeatPeriod(Integer heartBeatPeriod) throws VesAgentException { + if (null == heartBeatPeriod) { + errorMsg = "Error: heartBeatPeriod in request is null or empty"; + logger.error(errorMsg); + throw new VesAgentException(errorMsg); + } + } + + + public static void validateCountDownTimer(Integer countDownTimer) throws VesAgentException { + if (null == countDownTimer) { + errorMsg = "Error: countDownTimer in request is null or empty"; + logger.error(errorMsg); + throw new VesAgentException(errorMsg); + } + } + + public static void validateDeviceRPCRequest(DeviceRPCRequest deviceRPCRequest) + throws VesAgentException { + if (null == deviceRPCRequest || null == deviceRPCRequest.getOpDetails() + || null == deviceRPCRequest.getOpDetails().getParmeters() + || deviceRPCRequest.getOpDetails().getParmeters().isEmpty()) { + errorMsg = "Error: Input parameter list is null or empty"; + logger.error(errorMsg); + throw new VesAgentException(VesAgentConstants.INVALID_ARGUMENTS, errorMsg); + } + + if (null == deviceRPCRequest.getDeviceDetails() + || null == deviceRPCRequest.getDeviceDetails().getDeviceId() + || deviceRPCRequest.getDeviceDetails().getDeviceId().isEmpty()) { + errorMsg = "Error: Input deviceId is null or empty"; + logger.error(errorMsg); + throw new VesAgentException(VesAgentConstants.INVALID_ARGUMENTS, errorMsg); + } + } + + public static void validateVESNotification(VESNotification notification) + throws VesAgentException { + if (null == notification || null == notification.getDevnotification() + || null == notification.getDevnotification().getDeviceDetails() + || null == notification.getDevnotification().getDeviceDetails().getDeviceId() + || notification.getDevnotification().getDeviceDetails().getDeviceId().isEmpty()) { + + errorMsg = "Error: Input device details is null or empty"; + logger.error(errorMsg); + throw new VesAgentException(VesAgentConstants.INVALID_ARGUMENTS, errorMsg); + } + } + + public static void validateDelVESNotification(VESNotification notification) + throws VesAgentException { + if (null == notification || null == notification.getOperationDetails() + || null == notification.getOperationDetails().getParmeters() + || notification.getOperationDetails().getParmeters().isEmpty()) { + errorMsg = "Error: Input parameter list is null or empty"; + logger.error(errorMsg); + throw new VesAgentException(VesAgentConstants.INVALID_ARGUMENTS, errorMsg); + } + + if (null == notification.geteNodeBName() || notification.geteNodeBName().isEmpty()) { + errorMsg = "Error: Input deviceId/enodeBName is null or empty"; + logger.error(errorMsg); + throw new VesAgentException(VesAgentConstants.INVALID_ARGUMENTS, errorMsg); + } + } + + + public static DeviceRPCResponse getErrorResponse(DeviceRPCRequest deviceRPCRequest, + String faultCode, String faultMessage) { + DeviceRPCResponse errorResponse = new DeviceRPCResponse(); + + errorResponse.setDeviceDetails(deviceRPCRequest.getDeviceDetails()); + + OperationResponse operationResponse = new OperationResponse(); + operationResponse.setStatus(VesAgentConstants.RPC_FAILED);// device reachable...change value 1 + // to some constant or enum + operationResponse.setOperationCode(deviceRPCRequest.getOpDetails().getOpCode()); + + errorResponse.setOperationResponse(operationResponse); + errorResponse.setFaultKey(faultCode); + errorResponse.setFaultString(faultMessage); + + return errorResponse; + } + + public static DeviceRPCResponse getSuccessResponse(DeviceRPCRequest deviceRPCRequest) { + DeviceRPCResponse response = new DeviceRPCResponse(); + + response.setDeviceDetails(deviceRPCRequest.getDeviceDetails()); + + OperationResponse operationResponse = new OperationResponse(); + operationResponse.setStatus(VesAgentConstants.RPC_SUCCESS); + operationResponse.setOperationCode(deviceRPCRequest.getOpDetails().getOpCode()); + operationResponse.setParameterDTOs(deviceRPCRequest.getOpDetails().getParmeters()); + + response.setOperationResponse(operationResponse); + return response; + } + + public static boolean isDeviceReachable(DeviceRPCResponse deviceRPCResponse) { + if (null == deviceRPCResponse || null == deviceRPCResponse.getOperationResponse()) { + return false; + } + + if (deviceRPCResponse.getOperationResponse() + .getStatus() == VesAgentConstants.DEVICE_IS_REACHABLE) { + return true; + } + + return (null != deviceRPCResponse.getFaultKey() && deviceRPCResponse.getFaultKey() + .equalsIgnoreCase(VesAgentConstants.ABORTED_BY_BOOT_BOOTSTRAP)); + } + + public static Boolean isVesNotificationRequest(ParameterDTO param) { + if (null == param.getParamName() || param.getParamName().isEmpty()) { + return false; + } + + return param.getParamName().toLowerCase().contains(VesAgentConstants.HEART_BEAT.toLowerCase()); + } + + + public static String getDeviceOperationKey(String deviceId, OperationCode opCode) { + return deviceId + "-" + opCode; + } + +} diff --git a/ves-agent/src/main/resources/application.properties b/ves-agent/src/main/resources/application.properties index b4827c2..ea43f9b 100644 --- a/ves-agent/src/main/resources/application.properties +++ b/ves-agent/src/main/resources/application.properties @@ -19,14 +19,15 @@ # Spring boot application properties spring.application.name=${CONFIG_MAP_NAME} spring.cloud.kubernetes.config.namespace=${CONFIG_NAME_SPACE} -spring.cloud.kubernetes.reload.enabled=true -management.endpoint.restart.enabled=true +spring.cloud.kubernetes.reload.enabled=${CONFIG_MAP_ENABLE} +management.endpoint.restart.enabled=${CONFIG_MAP_ENABLE} spring.cloud.kubernetes.reload.strategy=refresh -management.endpoint.refresh.enabled=true +management.endpoint.refresh.enabled=${CONFIG_MAP_ENABLE} spring.cloud.kubernetes.reload.mode=polling spring.cloud.kubernetes.reload.period=${CONFIG_RELOAD_TIME} #spring.cloud.kubernetes.reload.monitoring-config-maps=true server.port=${VES_REST_PORT} +config.requestTimeout=120 config.vendorName=${vendorName} config.vesVersion=7.0.1 config.eventVersion=4.0.1 @@ -40,4 +41,14 @@ config.pnfregvesCollectorHost=${pnfregvesCollectorHost} config.pnfregvesCollectorPort=${pnfregvesCollectorPort} config.unitFamily=${unitFamily} config.unitType=${unitType} -config.faultEventSourcePrefix=${faultEventSourcePrefix} \ No newline at end of file +config.faultEventSourcePrefix=${faultEventSourcePrefix} +config.MapperPath=http://${MAPPER_REST_HOST}:${MAPPER_REST_PORT}/tr069MapperVesNBI/checkDeviceConnectivity/ + +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PASSWORD} +spring.datasource.url=jdbc:mariadb://${DB_SERVICE}:3306/${DB_NAME} +spring.datasource.driver-class-name=org.mariadb.jdbc.Driver +spring.datasource.platform=mariadb +spring.datasource.initialization-mode=always +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=none \ No newline at end of file diff --git a/ves-agent/src/main/resources/log4j2.xml b/ves-agent/src/main/resources/log4j2.xml index 4dcef81..3ce4544 100644 --- a/ves-agent/src/main/resources/log4j2.xml +++ b/ves-agent/src/main/resources/log4j2.xml @@ -1,26 +1,26 @@ - - - + + + %d{yyyy-MM-dd HH:mm:ss} %m%n @@ -85,19 +85,19 @@ - - - - - + + + + + - - - + + + - + diff --git a/ves-agent/src/main/resources/schema-mariadb.sql b/ves-agent/src/main/resources/schema-mariadb.sql new file mode 100644 index 0000000..3540aad --- /dev/null +++ b/ves-agent/src/main/resources/schema-mariadb.sql @@ -0,0 +1,15 @@ + +CREATE TABLE IF NOT EXISTS ves_device_data + ( + ID bigint null, + DEVICE_ID varchar(30) not null, + ENODEB_NAME varchar(100), + OUI varchar(30), + PRODUCT_CLASS varchar(100), + ATTR_JSON varchar(4000), + ATTR_GROUP varchar(256) not null, + LAST_UPDATED_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(DEVICE_ID,ATTR_GROUP) +); + + diff --git a/ves-agent/src/test/java/org/commscope/tr069adapter/vesagent/test/VESAgentServiceRestTest.java b/ves-agent/src/test/java/org/commscope/tr069adapter/vesagent/test/VESAgentServiceRestTest.java index f44ff94..b68b1b5 100644 --- a/ves-agent/src/test/java/org/commscope/tr069adapter/vesagent/test/VESAgentServiceRestTest.java +++ b/ves-agent/src/test/java/org/commscope/tr069adapter/vesagent/test/VESAgentServiceRestTest.java @@ -28,7 +28,6 @@ import org.commscope.tr069adapter.acs.common.InformType; import org.commscope.tr069adapter.acs.common.ParameterDTO; import org.commscope.tr069adapter.acs.common.dto.TR069InformType; import org.commscope.tr069adapter.acs.common.inform.BootstrapInform; -import org.commscope.tr069adapter.acs.common.inform.PeriodicInform; import org.commscope.tr069adapter.acs.common.inform.ValueChangeInform; import org.commscope.tr069adapter.mapper.model.NetConfServerDetails; import org.commscope.tr069adapter.mapper.model.VESNotification; @@ -209,58 +208,35 @@ public class VESAgentServiceRestTest { } } - @Test - public void processHBEventTest() { - try { - VESNotificationResponse res = - new VESNotificationResponse(HttpStatus.ACCEPTED.value(), "Sucess"); - Mockito.when(sender.postRequest(Mockito.anyString(), Mockito.anyString())).thenReturn(res); - VESNotification ves = new VESNotification(); - ves.seteNodeBName("0005B9A1"); - ves.setNetconfDetails(getNetConfDetails()); - DeviceInform inform = new PeriodicInform(); - inform.setDeviceDetails(getDeviceDetails()); - ArrayList list = new ArrayList<>(); - list.add(TR069InformType.PERIODIC); - inform.setInformTypeList(list); - inform.setParameters(getGeneralParams()); - ves.setDevnotification(inform); - - VESNotificationResponse vesResponse = agent.processDeviceNotificationAsVESEvent(ves); - Assert.assertNotNull(vesResponse); - Assert.assertEquals(HttpStatus.ACCEPTED.value(), vesResponse.getStatusCode()); - res.getStatusCode(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void processHBEventWhenEnbNullTest() { - try { - VESNotificationResponse res = - new VESNotificationResponse(HttpStatus.ACCEPTED.value(), "Sucess"); - Mockito.when(sender.postRequest(Mockito.anyString(), Mockito.anyString())).thenReturn(res); - VESNotification ves = new VESNotification(); - ves.seteNodeBName(null); - ves.setNetconfDetails(getNetConfDetails()); - DeviceInform inform = new PeriodicInform(); - inform.setDeviceDetails(getDeviceDetails()); - ArrayList list = new ArrayList<>(); - list.add(TR069InformType.PERIODIC); - inform.setInformTypeList(list); - inform.setParameters(getGeneralParams()); - ves.setDevnotification(inform); - - VESNotificationResponse vesResponse = agent.processDeviceNotificationAsVESEvent(ves); - Assert.assertNotNull(vesResponse); - Assert.assertEquals(HttpStatus.ACCEPTED.value(), vesResponse.getStatusCode()); - res.getStatusCode(); - } catch (Exception e) { - e.printStackTrace(); - } - } - + /* + * @Test public void processHBEventTest() { try { VESNotificationResponse res = new + * VESNotificationResponse(HttpStatus.ACCEPTED.value(), "Sucess"); + * Mockito.when(sender.postRequest(Mockito.anyString(), Mockito.anyString())).thenReturn(res); + * VESNotification ves = new VESNotification(); ves.seteNodeBName("0005B9A1"); + * ves.setNetconfDetails(getNetConfDetails()); DeviceInform inform = new PeriodicInform(); + * inform.setDeviceDetails(getDeviceDetails()); ArrayList list = new ArrayList<>(); + * list.add(TR069InformType.PERIODIC); inform.setInformTypeList(list); + * inform.setParameters(getGeneralParams()); ves.setDevnotification(inform); + * + * VESNotificationResponse vesResponse = agent.processDeviceNotificationAsVESEvent(ves); + * Assert.assertNotNull(vesResponse); Assert.assertEquals(HttpStatus.ACCEPTED.value(), + * vesResponse.getStatusCode()); res.getStatusCode(); } catch (Exception e) { e.printStackTrace(); + * } } + * + * @Test public void processHBEventWhenEnbNullTest() { try { VESNotificationResponse res = new + * VESNotificationResponse(HttpStatus.ACCEPTED.value(), "Sucess"); + * Mockito.when(sender.postRequest(Mockito.anyString(), Mockito.anyString())).thenReturn(res); + * VESNotification ves = new VESNotification(); ves.seteNodeBName(null); + * ves.setNetconfDetails(getNetConfDetails()); DeviceInform inform = new PeriodicInform(); + * inform.setDeviceDetails(getDeviceDetails()); ArrayList list = new ArrayList<>(); + * list.add(TR069InformType.PERIODIC); inform.setInformTypeList(list); + * inform.setParameters(getGeneralParams()); ves.setDevnotification(inform); + * + * VESNotificationResponse vesResponse = agent.processDeviceNotificationAsVESEvent(ves); + * Assert.assertNotNull(vesResponse); Assert.assertEquals(HttpStatus.ACCEPTED.value(), + * vesResponse.getStatusCode()); res.getStatusCode(); } catch (Exception e) { e.printStackTrace(); + * } } + */ @Test public void processOnRestartEventTest() { try { diff --git a/ves-agent/src/test/resources/application.properties b/ves-agent/src/test/resources/application.properties index d75fe21..2336e79 100644 --- a/ves-agent/src/test/resources/application.properties +++ b/ves-agent/src/test/resources/application.properties @@ -40,4 +40,14 @@ config.pnfregvesCollectorHost=10.211.5.55 config.pnfregvesCollectorPort=30325 config.unitFamily=ORAN config.unitType=TR069 -config.faultEventSourcePrefix=faultEventSourcePrefix \ No newline at end of file +config.faultEventSourcePrefix=faultEventSourcePrefix + +config.MapperPath=http://${MAPPER_REST_HOST}:${MAPPER_REST_PORT}/tr069MapperVesNBI/checkDeviceConnectivity/ + +## Datasource properties +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password=sa +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=create diff --git a/ves-agent/src/test/resources/log4j2.xml b/ves-agent/src/test/resources/log4j2.xml new file mode 100644 index 0000000..ac227c7 --- /dev/null +++ b/ves-agent/src/test/resources/log4j2.xml @@ -0,0 +1,103 @@ + + + + + + %d{yyyy-MM-dd HH:mm:ss} %m%n + ./target/test-logs + + + + + + + + + [%d{yyyy-MM-dd HH:mm:ss:SSS}] [%X{client}] [%.-40t] %-25.45c{1} %-5p: %m%n +
Debug Log started at: $${date:yyyy-MM-dd HH:mm:ss}
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
-- 2.16.6