From 204d666f85db71b0cff4f8508350524dde492f08 Mon Sep 17 00:00:00 2001 From: "Claudio D. Gasparini" Date: Mon, 3 May 2021 13:24:18 +0200 Subject: [PATCH] OAM NF Adopter SNMP Manager - SNMP to VES Issue-ID: OAM-205 Signed-off-by: Claudio D. Gasparini Change-Id: Id18af5c8074288fe5d9ee1c52dde8aa0663b438b --- ves-nf-oam-adopter/pom.xml | 1 + .../ves-nf-oam-adopter-artifacts/pom.xml | 5 + .../ves-nf-oam-adopter-parent/pom.xml | 34 +++++- .../ves-nf-oam-adopter-snmp-manager/pom.xml | 90 +++++++++++++++ .../oam/adopter/snmp/manager/SnmpManagerImpl.java | 50 +++++++++ .../manager/SnmpMappingConfigurationProvider.java | 84 ++++++++++++++ .../oam/adopter/snmp/manager/SnmpTrapListener.java | 115 +++++++++++++++++++ .../snmp/manager/api/TimeZoneOffsetService.java | 31 ++++++ .../manager/configurations/SnmpManagerConfig.java | 57 ++++++++++ .../manager/mapper/CommonEventHeaderHandler.java | 123 +++++++++++++++++++++ .../snmp/manager/mapper/FaultFieldsHandler.java | 79 +++++++++++++ .../adopter/snmp/manager/mapper/SnmpMapper.java | 42 +++++++ .../snmp/manager/mapper/SnmpMapperImpl.java | 83 ++++++++++++++ .../manager/pojos/TrapsMappingConfiguration.java | 55 +++++++++ .../manager/pojos/VesMappingConfiguration.java | 40 +++++++ .../manager/properties/SnmpManagerProperties.java | 34 ++++++ 16 files changed, 922 insertions(+), 1 deletion(-) create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/pom.xml create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpManagerImpl.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpMappingConfigurationProvider.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpTrapListener.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/api/TimeZoneOffsetService.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/configurations/SnmpManagerConfig.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/CommonEventHeaderHandler.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/FaultFieldsHandler.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/SnmpMapper.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/SnmpMapperImpl.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/pojos/TrapsMappingConfiguration.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/pojos/VesMappingConfiguration.java create mode 100644 ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/properties/SnmpManagerProperties.java diff --git a/ves-nf-oam-adopter/pom.xml b/ves-nf-oam-adopter/pom.xml index 29a80df..0ce9d8b 100644 --- a/ves-nf-oam-adopter/pom.xml +++ b/ves-nf-oam-adopter/pom.xml @@ -48,5 +48,6 @@ ves-nf-oam-adopter-spotbugs ves-nf-oam-adopter-api ves-nf-oam-adopter-event-notifier + ves-nf-oam-adopter-snmp-manager \ No newline at end of file diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-artifacts/pom.xml b/ves-nf-oam-adopter/ves-nf-oam-adopter-artifacts/pom.xml index ebcc70e..0307a2e 100644 --- a/ves-nf-oam-adopter/ves-nf-oam-adopter-artifacts/pom.xml +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-artifacts/pom.xml @@ -56,6 +56,11 @@ ves-nf-oam-adopter-event-notifier ${project.version} + + ${project.groupId} + ves-nf-oam-adopter-snmp-manager + ${project.version} + \ No newline at end of file diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-parent/pom.xml b/ves-nf-oam-adopter/ves-nf-oam-adopter-parent/pom.xml index f99ff9c..a44b348 100644 --- a/ves-nf-oam-adopter/ves-nf-oam-adopter-parent/pom.xml +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-parent/pom.xml @@ -41,15 +41,22 @@ ../ves-nf-oam-adopter-event-notifier/target/site/jacoco-ut/jacoco.xml, ../ves-nf-oam-adopter-event-notifier/target/site/jacoco-aggregate/jacoco.xml + ../ves-nf-oam-adopter-snmp-manager/target/site/jacoco-ut/jacoco.xml, + ../ves-nf-oam-adopter-snmp-manager/target/site/jacoco-aggregate/jacoco.xml + 2.7 + 2.6 + 1.9.4 2.8.6 5.0.3 - 1.18.20 2.2.600 + 1.18.20 3.0.12 4.2.3 2.4.5 + 3.4.4 + 4.2.3 3.8.0.2131 8.41 @@ -94,6 +101,31 @@ lombok ${lombok.version} + + org.snmp4j + snmp4j + ${snmp4j.version} + + + org.apache.commons + commons-configuration2 + ${commons-configuration2.version} + + + commons-io + commons-io + ${commons-io.version} + + + commons-beanutils + commons-beanutils + ${commons-beanutils.version} + + + com.github.spotbugs + spotbugs-annotations + ${spotbugs.version} + org.springframework.boot spring-boot-starter diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/pom.xml b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/pom.xml new file mode 100644 index 0000000..42f4847 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/pom.xml @@ -0,0 +1,90 @@ + + + + 4.0.0 + + + org.o-ran-sc.oam + ves-nf-oam-adopter-parent + 1.0.0-SNAPSHOT + ../ves-nf-oam-adopter-parent/pom.xml + + + ves-nf-oam-adopter-snmp-manager + + + + ${project.groupId} + ves-nf-oam-adopter-api + + + com.github.spotbugs + spotbugs-annotations + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + + + org.snmp4j + snmp4j + + + io.reactivex.rxjava3 + rxjava + + + org.slf4j + slf4j-api + + + org.springframework.boot + spring-boot-starter + + + org.projectlombok + lombok + + + org.apache.commons + commons-configuration2 + + + commons-io + commons-io + + + commons-beanutils + commons-beanutils + + + \ No newline at end of file diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpManagerImpl.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpManagerImpl.java new file mode 100644 index 0000000..fdd7a7b --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpManagerImpl.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager; + +import javax.annotation.PostConstruct; +import org.o.ran.oam.nf.oam.adopter.api.VesEventNotifier; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.api.TimeZoneOffsetService; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.mapper.SnmpMapper; + +public class SnmpManagerImpl implements AutoCloseable { + private static final String SNMP_MANAGER_THREAD = "SnmpManager"; + private final Thread snmpThread; + + /** + * Default constructor. + */ + public SnmpManagerImpl(final String host, final int port, final SnmpMapper mapper, + final VesEventNotifier vesEventNotifier, final TimeZoneOffsetService timeZoneOffsetService) { + final SnmpTrapListener trapListener = + new SnmpTrapListener(host, port, mapper, vesEventNotifier, timeZoneOffsetService); + this.snmpThread = new Thread(trapListener, SNMP_MANAGER_THREAD); + } + + @PostConstruct + public void init() { + snmpThread.start(); + } + + @Override + public void close() { + snmpThread.interrupt(); + } +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpMappingConfigurationProvider.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpMappingConfigurationProvider.java new file mode 100644 index 0000000..ac2a810 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpMappingConfigurationProvider.java @@ -0,0 +1,84 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager; + +import static java.util.Objects.requireNonNull; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import java.io.IOException; +import java.io.StringWriter; +import java.net.URI; +import java.nio.file.Paths; +import javax.annotation.PostConstruct; +import org.apache.commons.configuration2.YAMLConfiguration; +import org.apache.commons.configuration2.builder.ConfigurationBuilderEvent; +import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder; +import org.apache.commons.configuration2.builder.fluent.Parameters; +import org.apache.commons.configuration2.event.EventListener; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.pojos.VesMappingConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * Reads and listens for changes on snmp mapping configuration. + */ +@Service +public class SnmpMappingConfigurationProvider { + private static final Logger LOG = LoggerFactory.getLogger(SnmpMappingConfigurationProvider.class); + + private static final ObjectMapper YAML_READER = new ObjectMapper(new YAMLFactory()); + @Value("${snmp-manager.mapping-config-path:#{null}}") + private String mappingFilePath; + private ReloadingFileBasedConfigurationBuilder builder; + + /** + * Initialize service. + * @throws IOException on error + */ + @PostConstruct + public void init() throws IOException, ConfigurationException { + requireNonNull(mappingFilePath); + final URI filePath = Paths.get(mappingFilePath).toUri(); + builder = new ReloadingFileBasedConfigurationBuilder<>(YAMLConfiguration.class) + .configure(new Parameters().hierarchical().setURL(filePath.toURL())); + builder.addEventListener(ConfigurationBuilderEvent.CONFIGURATION_REQUEST, (EventListener) event -> { + builder.getReloadingController().checkForReloading(null); + LOG.info("Reloading {}", filePath); + }); + //Test initial configuration + builder.getConfiguration(); + } + + /** + * Reads VesMappingConfiguration from yaml file. + * + * @return Ves Mapping Configuration + */ + public VesMappingConfiguration getVesMappingConfiguration() throws ConfigurationException, IOException { + final YAMLConfiguration configuration = builder.getConfiguration(); + final StringWriter output = new StringWriter(); + configuration.write(output); + return YAML_READER.readValue(output.toString(), VesMappingConfiguration.class); + } +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpTrapListener.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpTrapListener.java new file mode 100644 index 0000000..d0bf916 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/SnmpTrapListener.java @@ -0,0 +1,115 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager; + +import com.google.gson.Gson; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Optional; +import org.o.ran.oam.nf.oam.adopter.api.VesEventNotifier; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.api.TimeZoneOffsetService; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.mapper.SnmpMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.snmp4j.CommandResponder; +import org.snmp4j.CommandResponderEvent; +import org.snmp4j.MessageDispatcher; +import org.snmp4j.MessageDispatcherImpl; +import org.snmp4j.PDU; +import org.snmp4j.Snmp; +import org.snmp4j.mp.MPv2c; +import org.snmp4j.smi.UdpAddress; +import org.snmp4j.transport.DefaultUdpTransportMapping; +import org.snmp4j.util.MultiThreadedMessageDispatcher; +import org.snmp4j.util.ThreadPool; + +final class SnmpTrapListener implements CommandResponder, Runnable { + + private static final Logger LOG = LoggerFactory.getLogger(SnmpTrapListener.class); + private static final int THREADS_SIZE = 2; + private final String hostPortAddress; + private final SnmpMapper mapper; + private final VesEventNotifier vesEventNotifier; + private final Gson gson = new Gson(); + private final TimeZoneOffsetService timeZoneOffsetService; + + public SnmpTrapListener(final String host, final Integer port, final SnmpMapper mapper, + final VesEventNotifier vesEventNotifier, final TimeZoneOffsetService timeZoneOffsetService) { + LOG.info("SnmpTrapListener listening on {}:{}", host, port); + this.hostPortAddress = host + "/" + port; + this.mapper = mapper; + this.vesEventNotifier = vesEventNotifier; + this.timeZoneOffsetService = timeZoneOffsetService; + } + + @SuppressFBWarnings("WA_NOT_IN_LOOP") + @Override + public synchronized void run() { + try { + final UdpAddress udpAddress = new UdpAddress(hostPortAddress); + final DefaultUdpTransportMapping snmpTarget = new DefaultUdpTransportMapping(udpAddress); + final ThreadPool threadPool = ThreadPool.create("SNMP_V2_Listener", THREADS_SIZE); + final MessageDispatcher dispatcher = + new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl()); + dispatcher.addMessageProcessingModel(new MPv2c()); + + final Snmp snmp = new Snmp(dispatcher, snmpTarget); + snmp.addCommandResponder(this); + + snmpTarget.listen(); + LOG.debug("Listening on {}", snmpTarget); + try { + wait(); + } catch (final InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } catch (final IOException e) { + LOG.error("Error occurred while listening to SNMP messages: {}", e.getMessage()); + } + } + + /** + * This method will be called whenever a pdu is received on the given port + * specified in the listen() method. + */ + @Override + public synchronized void processPdu(final CommandResponderEvent cmdRespEvent) { + LOG.info("Received PDU"); + final PDU pdu = cmdRespEvent.getPDU(); + if (pdu == null) { + LOG.warn("Ignoring PDU."); + return; + } + + final UdpAddress address = (UdpAddress) cmdRespEvent.getPeerAddress(); + final ZoneId optZoneId = timeZoneOffsetService.getTimeZone(address.getInetAddress().getHostAddress()); + final String timeZone = Optional.ofNullable(optZoneId) + .map(zoneId -> "UTC" + LocalDateTime.now().atZone(zoneId).getOffset() + .toString()).orElse(null); + + mapper.toEvent(address, timeZone, pdu) + .flatMapCompletable(vesEventNotifier::notifyEvents) + .doOnSubscribe(result -> LOG.debug("SNMP Trap processing started")) + .doOnComplete(() -> LOG.debug("SNMP Trap processed successfully")) + .doOnError(error -> LOG.error("Failed to process SNMP Trap", error)).subscribe(); + } +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/api/TimeZoneOffsetService.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/api/TimeZoneOffsetService.java new file mode 100644 index 0000000..5f4a02a --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/api/TimeZoneOffsetService.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.api; + +import java.time.ZoneId; +import org.eclipse.jdt.annotation.Nullable; + +public interface TimeZoneOffsetService { + + /** + * Returns Time zone of specific device if present. + */ + @Nullable ZoneId getTimeZone(String host); +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/configurations/SnmpManagerConfig.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/configurations/SnmpManagerConfig.java new file mode 100644 index 0000000..a39a52f --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/configurations/SnmpManagerConfig.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.configurations; + +import org.o.ran.oam.nf.oam.adopter.api.VesEventNotifier; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.SnmpManagerImpl; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.api.TimeZoneOffsetService; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.mapper.SnmpMapper; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.properties.SnmpManagerProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties +public class SnmpManagerConfig { + private final SnmpManagerProperties snmpManagerProperties; + private final SnmpMapper snmpMapper; + private final VesEventNotifier vesEventNotifier; + private final TimeZoneOffsetService timeZoneOffsetService; + + /** + * Snmp Manager Configuration Constructor. + */ + @Autowired + public SnmpManagerConfig(final SnmpManagerProperties snmpManagerProperties, final SnmpMapper snmpMapper, + final VesEventNotifier vesEventNotifier, final TimeZoneOffsetService timeZoneOffsetService) { + this.snmpManagerProperties = snmpManagerProperties; + this.snmpMapper = snmpMapper; + this.vesEventNotifier = vesEventNotifier; + this.timeZoneOffsetService = timeZoneOffsetService; + } + + @Bean + public SnmpManagerImpl getSnmpManagerService() { + return new SnmpManagerImpl(snmpManagerProperties.getHost(), snmpManagerProperties.getPort(), snmpMapper, + vesEventNotifier, timeZoneOffsetService); + } +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/CommonEventHeaderHandler.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/CommonEventHeaderHandler.java new file mode 100644 index 0000000..c2d052c --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/CommonEventHeaderHandler.java @@ -0,0 +1,123 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.mapper; + +import java.util.Optional; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.o.ran.oam.nf.oam.adopter.api.CommonEventHeader; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.pojos.TrapsMappingConfiguration; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.pojos.VesMappingConfiguration; +import org.snmp4j.PDU; +import org.snmp4j.smi.OID; +import org.snmp4j.smi.UdpAddress; +import org.snmp4j.smi.Variable; + +/** + * Follows + * https://docs.onap.org/projects/onap-vnfrqts-requirements/en/latest/Chapter8/ves7_1spec.html#datatype-commoneventheader + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +final class CommonEventHeaderHandler { + static CommonEventHeader toCommonEventHeader(final UdpAddress peerAddress, + final VesMappingConfiguration vesMappingConfig, final TrapsMappingConfiguration mappingConfiguration, + final PDU pdu, final String timeZone) { + final CommonEventHeader header = new CommonEventHeader(); + setMandatoryFields(header, peerAddress, vesMappingConfig, mappingConfiguration, pdu); + setOptionalFields(header, vesMappingConfig, mappingConfiguration, pdu, timeZone); + return header; + } + + private static void setOptionalFields(final CommonEventHeader header, + final VesMappingConfiguration vesMappingConfig, final TrapsMappingConfiguration mappingConfiguration, + final PDU pdu, final String timeZone) { + header.setNfVendorName(vesMappingConfig.getNfVendorName()); + final String oidEntityId = mappingConfiguration.getOidReportingEntityID(); + if (oidEntityId != null) { + final Variable uuid = pdu.getVariable(new OID(oidEntityId)); + header.setReportingEntityId(uuid == null ? null : uuid.toString()); + } + header.setNfNamingCode(null); //NOP + header.setNfcNamingCode(null); //NOP + if (timeZone != null) { + header.setTimeZoneOffset(timeZone); + } + } + + private static void setMandatoryFields(final CommonEventHeader header, final UdpAddress peerAddress, + final VesMappingConfiguration vesMappingConfig, final TrapsMappingConfiguration mappingConfiguration, + final PDU pdu) { + header.setDomain(CommonEventHeader.Domain.FAULT); + + final Optional eventIdOid = Optional.ofNullable(mappingConfiguration.getOidEventId()).map(OID::new); + final Optional eventIdValue = eventIdOid.map(pdu::getVariable); + final String eventId = eventIdValue.map(Variable::toString).orElse(pdu.getRequestID().toString()); + header.setEventId(eventId); + header.setEventName( + CommonEventHeader.Domain.FAULT.name() + "_" + vesMappingConfig.getReportingEntityName() + "_" + + mappingConfiguration.getName()); + + final String oidStartEpoch = mappingConfiguration.getEventStartEpochMicrosec(); + if (oidStartEpoch != null) { + final Variable uuid = pdu.getVariable(new OID(oidStartEpoch)); + header.setStartEpochMicrosec(uuid == null ? null : Long.valueOf(uuid.toString())); + } else { + header.setStartEpochMicrosec(System.currentTimeMillis()); + } + + final String oidLastEpoch = mappingConfiguration.getEventLastEpochMicrosec(); + if (oidLastEpoch != null) { + final Variable uuid = pdu.getVariable(new OID(oidLastEpoch)); + header.setLastEpochMicrosec(uuid == null ? null : Long.valueOf(uuid.toString())); + } else { + header.setLastEpochMicrosec(System.currentTimeMillis()); + } + header.setPriority(CommonEventHeader.Priority.HIGH); + header.setReportingEntityName(vesMappingConfig.getReportingEntityName()); + header.setReportingEntityId(vesMappingConfig.getReportingEntityId()); + header.setSequence(extractEventSequence(mappingConfiguration, pdu)); + final String oidSourceName = mappingConfiguration.getOidSourceName(); + if (oidSourceName != null) { + final Variable sourceName = pdu.getVariable(new OID(oidSourceName)); + header.setSourceName(sourceName.toString()); + } else { + header.setSourceName(peerAddress.getInetAddress().getHostAddress()); + } + header.setVersion(CommonEventHeader.Version._4_0); + header.setVesEventListenerVersion(Optional.ofNullable(vesMappingConfig.getVesEventListenerVersion()) + .map(CommonEventHeader.VesEventListenerVersion::fromValue) + .orElse(CommonEventHeader.VesEventListenerVersion._7_1)); + } + + private static long extractEventSequence(final TrapsMappingConfiguration mappingConfiguration, final PDU pdu) { + final Optional optEventSequenceOid = Optional.ofNullable(mappingConfiguration.getOidEventSequence()); + if (optEventSequenceOid.isPresent()) { + final String eventSequenceOid = optEventSequenceOid.get(); + if (!eventSequenceOid.contains(".")) { + return Long.parseLong(eventSequenceOid); + } + final Optional optValue = Optional.ofNullable(pdu.getVariable(new OID(eventSequenceOid))); + if (optValue.isPresent()) { + return optValue.get().toLong(); + } + } + return 0L; + } +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/FaultFieldsHandler.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/FaultFieldsHandler.java new file mode 100644 index 0000000..600f503 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/FaultFieldsHandler.java @@ -0,0 +1,79 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.mapper; + +import static org.o.ran.oam.nf.oam.adopter.snmp.manager.mapper.SnmpMapperImpl.DEFAULT; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.o.ran.oam.nf.oam.adopter.api.FaultFields; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.pojos.TrapsMappingConfiguration; +import org.snmp4j.PDU; +import org.snmp4j.smi.OID; +import org.snmp4j.smi.Variable; +import org.snmp4j.smi.VariableBinding; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +final class FaultFieldsHandler { + private static final String SNMP_FAULT = "SNMP_Fault"; + private static final String SNMP_UNKNOWN = "Unknown"; + + public static FaultFields toFaultFields(final TrapsMappingConfiguration trapsDescription, final PDU pdu) { + final FaultFields faultFields = new FaultFields(); + setMandatoryFields(faultFields, trapsDescription, pdu); + setOptionalFields(faultFields, trapsDescription, pdu); + return faultFields; + } + + private static void setMandatoryFields(final FaultFields faultFields, + final TrapsMappingConfiguration trapsDescription, final PDU pdu) { + faultFields.setAlarmCondition(trapsDescription.getName()); + faultFields.setEventSeverity(FaultFields.EventSeverity.fromValue(trapsDescription.getOidEventSeverity())); + faultFields.setEventSourceType(Optional.ofNullable(trapsDescription.getEventSourceType()).orElse(SNMP_UNKNOWN)); + faultFields.setFaultFieldsVersion(FaultFields.FaultFieldsVersion._4_0); + final String descOid = trapsDescription.getOidSpecificProblemDesc(); + faultFields.setSpecificProblem(SNMP_FAULT); + if (descOid != null && !DEFAULT.equals(descOid)) { + final Variable desc = pdu.getVariable(new OID(descOid)); + faultFields.setSpecificProblem(desc == null ? SNMP_FAULT : desc.toString()); + } + faultFields.setVfStatus(FaultFields.VfStatus.ACTIVE); + } + + private static void setOptionalFields(final FaultFields faultFields, + final TrapsMappingConfiguration trapsDescription, final PDU pdu) { + final List variables = pdu.getVariableBindings(); + final Map map = variables.stream() + .collect(Collectors.toMap(x -> x.getOid().toString(), x -> x.getVariable().toString())); + + faultFields.setAlarmAdditionalInformation(map.isEmpty() ? null : map); + final String interfaceOid = trapsDescription.getOidAlarmInterfaceName(); + if (interfaceOid != null) { + final Variable desc = pdu.getVariable(new OID(interfaceOid)); + faultFields.setAlarmInterfaceA(desc == null ? SNMP_FAULT : desc.toString()); + } + final String eCategory = trapsDescription.getEventCategory(); + faultFields.setEventCategory(eCategory); + } +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/SnmpMapper.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/SnmpMapper.java new file mode 100644 index 0000000..7e588f6 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/SnmpMapper.java @@ -0,0 +1,42 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.mapper; + +import io.reactivex.rxjava3.core.Maybe; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.o.ran.oam.nf.oam.adopter.api.CommonEventFormat302ONAP; +import org.snmp4j.PDU; +import org.snmp4j.smi.UdpAddress; + +public interface SnmpMapper { + /** + * Translate SNMP protocol data unit to ONAP Event. + * + * @param peerAddress sender address + * @param timeZone sender time zone in UTC Format (E.g. UTC+02:00 + * @param pdu SNMP protocol data unit + * @return event or null if translation not supported + */ + @NonNull Maybe toEvent( + @NonNull UdpAddress peerAddress, + @Nullable String timeZone, + @NonNull PDU pdu); +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/SnmpMapperImpl.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/SnmpMapperImpl.java new file mode 100644 index 0000000..125e37d --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/mapper/SnmpMapperImpl.java @@ -0,0 +1,83 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.mapper; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import io.reactivex.rxjava3.core.Maybe; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import org.o.ran.oam.nf.oam.adopter.api.CommonEventFormat302ONAP; +import org.o.ran.oam.nf.oam.adopter.api.Event; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.SnmpMappingConfigurationProvider; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.pojos.TrapsMappingConfiguration; +import org.o.ran.oam.nf.oam.adopter.snmp.manager.pojos.VesMappingConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.snmp4j.PDU; +import org.snmp4j.smi.OID; +import org.snmp4j.smi.UdpAddress; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SnmpMapperImpl implements SnmpMapper { + private static final Logger LOG = LoggerFactory.getLogger(SnmpMapperImpl.class); + public static final String DEFAULT = "default"; + public static final OID SNMP_TRAP_OID = new OID("1.3.6.1.6.3.1.1.4.1.0"); + private final SnmpMappingConfigurationProvider snmpMappingConfigurationProvider; + + @Autowired + public SnmpMapperImpl(final SnmpMappingConfigurationProvider snmpMappingConfigurationProvider) { + this.snmpMappingConfigurationProvider = snmpMappingConfigurationProvider; + } + + @Override + @SuppressFBWarnings("REC_CATCH_EXCEPTION") + public Maybe toEvent(final UdpAddress peerAddress, final String timeZone, final PDU pdu) { + try { + final int eventType = pdu.getType(); + if (pdu.getType() != PDU.NOTIFICATION) { + LOG.warn("SNMP Event type {} not supported, ignoring event.", eventType); + return Maybe.empty(); + } + LOG.info("Starting Mapping of SNMP Event type {}.", eventType); + LOG.trace("Pdu received {}.", pdu); + final Event event = new Event(); + final String trapOidVariable = pdu.getVariable(SNMP_TRAP_OID).toString(); + final VesMappingConfiguration vesMappingConfig = + snmpMappingConfigurationProvider.getVesMappingConfiguration(); + final Map trapsDescriptions = vesMappingConfig.getTraps().stream() + .collect(Collectors.toMap(TrapsMappingConfiguration::getOid, trapsDescription -> trapsDescription)); + final TrapsMappingConfiguration trapsDescription = + Optional.ofNullable(trapsDescriptions.get(trapOidVariable)).orElse(trapsDescriptions.get(DEFAULT)); + event.setCommonEventHeader(CommonEventHeaderHandler.toCommonEventHeader(peerAddress, vesMappingConfig, + trapsDescription, pdu, timeZone)); + event.setFaultFields(FaultFieldsHandler.toFaultFields(trapsDescription, pdu)); + final CommonEventFormat302ONAP eventFormat = new CommonEventFormat302ONAP(); + eventFormat.setEvent(event); + eventFormat.setEventList(null); + LOG.info("Mapping of SNMP Event type {} finished.", eventType); + return Maybe.just(eventFormat); + } catch (final Exception e) { + return Maybe.error(e); + } + } +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/pojos/TrapsMappingConfiguration.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/pojos/TrapsMappingConfiguration.java new file mode 100644 index 0000000..00599d3 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/pojos/TrapsMappingConfiguration.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.pojos; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class TrapsMappingConfiguration { + @JsonProperty("oid") + private String oid; + @JsonProperty("name") + private String name; + @JsonProperty("oid-event-id") + private String oidEventId; + @JsonProperty("event-severity") + private String oidEventSeverity; + @JsonProperty("oid-specific-problem-desc") + private String oidSpecificProblemDesc; + @JsonProperty("oid-source-name") + private String oidSourceName; + @JsonProperty("oid-reporting-entity-id") + private String oidReportingEntityID; + @JsonProperty("oid-alarm-interface-name") + private String oidAlarmInterfaceName; + @JsonProperty("event-category") + private String eventCategory; + @JsonProperty("event-source-type") + private String eventSourceType; + @JsonProperty("oid-event-sequence") + private String oidEventSequence; + @JsonProperty("oid-start-epoch-microsec") + private String eventStartEpochMicrosec; + @JsonProperty("oid-last-epoch-microsec") + private String eventLastEpochMicrosec; +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/pojos/VesMappingConfiguration.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/pojos/VesMappingConfiguration.java new file mode 100644 index 0000000..dc4f9a4 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/pojos/VesMappingConfiguration.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.pojos; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class VesMappingConfiguration { + @JsonProperty("reporting-entity-name") + private String reportingEntityName; + @JsonProperty("reporting-entity-id") + private String reportingEntityId; + @JsonProperty("nf-vendor-name") + private String nfVendorName; + @JsonProperty("traps") + private List traps; + @JsonProperty("ves-event-listener-version") + private String vesEventListenerVersion; +} diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/properties/SnmpManagerProperties.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/properties/SnmpManagerProperties.java new file mode 100644 index 0000000..8d48cc6 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-snmp-manager/src/main/java/org/o/ran/oam/nf/oam/adopter/snmp/manager/properties/SnmpManagerProperties.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.o.ran.oam.nf.oam.adopter.snmp.manager.properties; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "snmp-manager") +@Data +@NoArgsConstructor +public class SnmpManagerProperties { + private String host; + private int port; +} -- 2.16.6