diff options
Diffstat (limited to 'netconfsimulator/src/main/java/org')
24 files changed, 1329 insertions, 0 deletions
diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java new file mode 100644 index 0000000..92e5b23 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator; + +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.springframework.context.annotation.Bean; + +@org.springframework.context.annotation.Configuration +public class Configuration { + + @Bean + public HttpClient httpClient() { + return HttpClientBuilder.create().build(); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java new file mode 100644 index 0000000..e2a0ed0 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. 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.onap.netconfsimulator; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java new file mode 100644 index 0000000..2e9df99 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@EnableSwagger2 +@Configuration +class SwaggerConfig { + + @Bean + Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("org.onap.netconfsimulator")) + .paths(PathSelectors.any()) + .build(); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java new file mode 100644 index 0000000..9ae5641 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.kafka; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.onap.netconfsimulator.kafka.listener.KafkaListenerHandler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; + +@Configuration +@EnableKafka +class Config { + + @Value("${spring.kafka.bootstrap-servers}") + private String bootstrapServer; + + @Value("${spring.kafka.consumer.auto-offset-reset}") + private String offsetReset; + + @Bean + ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(ConsumerFactory<String, String> consumerFactory) { + ConcurrentKafkaListenerContainerFactory<String, String> containerFactory = new ConcurrentKafkaListenerContainerFactory<>(); + containerFactory.setConsumerFactory(consumerFactory); + return containerFactory; + } + + @Bean + ConsumerFactory<String, String> consumerFactory() { + Map<String, Object> props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServer); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, offsetReset); + return new DefaultKafkaConsumerFactory<>(props); + } + + + @Bean + KafkaListenerHandler kafkaListenerHandler(ConsumerFactory<String, String> consumerFactory) { + return new KafkaListenerHandler(consumerFactory); + } + +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java new file mode 100644 index 0000000..4311cd6 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.kafka; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +class MessageDTO { + private long timestamp; + private String configuration; +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java new file mode 100644 index 0000000..33bbdf7 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.kafka; + +import java.util.List; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +@RequestMapping("/store") +public class StoreController { + + private StoreService service; + + @Autowired + public StoreController(StoreService service) { + this.service = service; + } + + @GetMapping("/ping") + String ping() { + return "pong"; + } + + @GetMapping("cm-history") + List<MessageDTO> getAllConfigurationChanges() { + return service.getAllMessages(); + } + + @GetMapping("/less") + List<MessageDTO> less(@RequestParam(value = "offset", required = false, defaultValue = "${spring.kafka.default-offset}") long offset) { + return service.getLastMessages(offset); + } + +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java new file mode 100644 index 0000000..5fddff5 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.kafka; + +import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.common.TopicPartition; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.stereotype.Service; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Slf4j +@Service +public class StoreService { + + private static final String CONFIG_TOPIC = "config"; + private static final long CONSUMING_DURATION_IN_MS = 1000; + + private ConsumerFactory<String, String> consumerFactory; + static final List<String> TOPICS_TO_SUBSCRIBE = Collections.singletonList(CONFIG_TOPIC); + + @Autowired + StoreService(ConsumerFactory<String, String> consumerFactory) { + this.consumerFactory = consumerFactory; + } + + List<MessageDTO> getAllMessages() { + List<MessageDTO> messages = new ArrayList<>(); + String clientID = Long.toString(Instant.now().getEpochSecond()); + try (Consumer<String, String> consumer = consumerFactory.createConsumer(clientID, clientID)) { + consumer.subscribe(TOPICS_TO_SUBSCRIBE); + ConsumerRecords<String, String> consumerRecords = consumer.poll(CONSUMING_DURATION_IN_MS); + consumerRecords.forEach( + consumerRecord -> + messages.add(new MessageDTO(consumerRecord.timestamp(), consumerRecord.value()))); + log.debug(String.format("consumed %d messages", consumerRecords.count())); + } + return messages; + } + + List<MessageDTO> getLastMessages(long offset) { + List<MessageDTO> messages = new ArrayList<>(); + try (Consumer<String, String> consumer = createConsumer(offset)) { + ConsumerRecords<String, String> consumerRecords = consumer.poll(CONSUMING_DURATION_IN_MS); + consumerRecords.forEach(consumerRecord -> + messages.add(new MessageDTO(consumerRecord.timestamp(), consumerRecord.value()))); + } + return messages; + } + + private Consumer<String, String> createConsumer(long offsetFromLastIndex) { + String clientID = Long.toString(Instant.now().getEpochSecond()); + Consumer<String, String> consumer = consumerFactory.createConsumer(clientID, clientID); + consumer.subscribe(TOPICS_TO_SUBSCRIBE); + seekConsumerTo(consumer, offsetFromLastIndex); + return consumer; + } + + private void seekConsumerTo(Consumer<String, String> consumer, long offsetFromLastIndex) { + consumer.seekToEnd(consumer.assignment()); + consumer.poll(CONSUMING_DURATION_IN_MS); + TopicPartition topicPartition = consumer.assignment().iterator().next(); + long topicCurrentSize = consumer.position(topicPartition); + long indexToSeek = offsetFromLastIndex > topicCurrentSize ? 0 : topicCurrentSize - offsetFromLastIndex; + consumer.seek(topicPartition, indexToSeek); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java new file mode 100644 index 0000000..e3c04c9 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.kafka.listener; + +import lombok.Getter; +import org.springframework.kafka.listener.AbstractMessageListenerContainer; + +@Getter +public class KafkaListenerEntry { + + private String clientId; + private AbstractMessageListenerContainer listenerContainer; + + public KafkaListenerEntry(String clientId, AbstractMessageListenerContainer listenerContainer) { + this.clientId = clientId; + this.listenerContainer = listenerContainer; + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java new file mode 100644 index 0000000..604315d --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.kafka.listener; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.ConsumerFactory; + +import org.springframework.kafka.listener.ContainerProperties; +import org.springframework.kafka.listener.KafkaMessageListenerContainer; +import org.springframework.kafka.listener.MessageListener; + + +import org.springframework.kafka.support.TopicPartitionInitialOffset; + +import java.time.Instant; + +public class KafkaListenerHandler { + + private static final int PARTITION = 0; + private static final long NUMBER_OF_HISTORICAL_MESSAGES_TO_SHOW = -10L; + private static final boolean RELATIVE_TO_CURRENT = false; + private ConsumerFactory<String, String> consumerFactory; + + + @Autowired + public KafkaListenerHandler(ConsumerFactory<String, String> consumerFactory) { + this.consumerFactory = consumerFactory; + } + + + public KafkaListenerEntry createKafkaListener(MessageListener messageListener, String topicName) { + String clientId = Long.toString(Instant.now().getEpochSecond()); + ContainerProperties containerProperties = new ContainerProperties(topicName); + containerProperties.setGroupId(clientId); + KafkaMessageListenerContainer<String, String> listenerContainer = createListenerContainer(containerProperties, + topicName); + + listenerContainer.setupMessageListener(messageListener); + return new KafkaListenerEntry(clientId, listenerContainer); + } + + + KafkaMessageListenerContainer<String, String> createListenerContainer(ContainerProperties containerProperties, + String topicName) { + TopicPartitionInitialOffset config = new TopicPartitionInitialOffset(topicName, PARTITION, + NUMBER_OF_HISTORICAL_MESSAGES_TO_SHOW, RELATIVE_TO_CURRENT); + return new KafkaMessageListenerContainer<>(consumerFactory, containerProperties, config); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java new file mode 100644 index 0000000..90f283a --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.kafka.model; + +import lombok.Getter; + +@Getter +public class KafkaMessage { + private long timestamp; + private String configuration; + + public KafkaMessage(long timestamp, String configuration) { + this.timestamp = timestamp; + this.configuration = configuration; + } + + KafkaMessage() { + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java new file mode 100644 index 0000000..cdb4a8f --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java @@ -0,0 +1,111 @@ +/* + * ============LICENSE_START======================================================= + * NETCONF-CONTROLLER + * ================================================================================ + * Copyright (C) 2018 Nokia. 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.onap.netconfsimulator.netconfcore; + +import com.tailf.jnc.JNCException; + +import java.io.IOException; + +import lombok.extern.slf4j.Slf4j; +import org.onap.netconfsimulator.netconfcore.configuration.NetconfConfigurationService; +import org.onap.netconfsimulator.netconfcore.model.LoadModelResponse; +import org.onap.netconfsimulator.netconfcore.model.NetconfModelLoaderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +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.RequestPart; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@Slf4j +@RestController +@RequestMapping("netconf") +class NetconfController { + + private final NetconfConfigurationService netconfService; + private final NetconfModelLoaderService netconfModelLoaderService; + + @Autowired + NetconfController(NetconfConfigurationService netconfService, + NetconfModelLoaderService netconfModelLoaderService) { + this.netconfService = netconfService; + this.netconfModelLoaderService = netconfModelLoaderService; + } + + @GetMapping(value = "get", produces = "application/xml") + ResponseEntity<String> getNetconfConfiguration() throws IOException, JNCException { + return ResponseEntity.ok(netconfService.getCurrentConfiguration()); + } + + @GetMapping(value = "get/{model}/{container}", produces = "application/xml") + ResponseEntity<String> getNetconfConfiguration(@PathVariable String model, + @PathVariable String container) + throws IOException { + ResponseEntity<String> entity; + try { + entity = ResponseEntity.ok(netconfService.getCurrentConfiguration(model, container)); + } catch (JNCException exception) { + log.error("Get configuration for model {} and container {} failed.", model, container, + exception); + entity = ResponseEntity.badRequest().body(exception.toString()); + } + return entity; + } + + @PostMapping(value = "edit-config", produces = "application/xml") + @ResponseStatus(HttpStatus.ACCEPTED) + ResponseEntity<String> editConfig(@RequestPart("editConfigXml") MultipartFile editConfig) + throws IOException, JNCException { + log.info("Loading updated configuration"); + if (editConfig == null || editConfig.isEmpty()) { + throw new IllegalArgumentException("No XML file with proper name: editConfigXml found."); + } + return ResponseEntity + .status(HttpStatus.ACCEPTED) + .body(netconfService.editCurrentConfiguration(editConfig)); + } + + @PostMapping("model/{moduleName}") + ResponseEntity<String> loadNewYangModel(@RequestBody MultipartFile yangModel, + @RequestBody MultipartFile initialConfig, @PathVariable String moduleName) + throws IOException { + LoadModelResponse response = netconfModelLoaderService.loadYangModel(yangModel, initialConfig, moduleName); + return ResponseEntity + .status(response.getStatusCode()) + .body(response.getMessage()); + } + + @DeleteMapping("model/{modelName}") + ResponseEntity<String> deleteYangModel(@PathVariable String modelName) + throws IOException { + LoadModelResponse response = netconfModelLoaderService.deleteYangModel(modelName); + return ResponseEntity + .status(response.getStatusCode()) + .body(response.getMessage()); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java new file mode 100644 index 0000000..d90c60d --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java @@ -0,0 +1,60 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. 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.onap.netconfsimulator.netconfcore.configuration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +class NetconfBeanConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfBeanConfiguration.class); + + @Value("${netconf.port}") + private Integer netconfPort; + + @Value("${netconf.address}") + private String netconfAddress; + + @Value("${netconf.user}") + private String netconfUser; + + @Value("${netconf.password}") + private String netconfPassword; + + @Bean + NetconfConfigurationReader configurationReader() { + NetconfConnectionParams params = new NetconfConnectionParams(netconfAddress, netconfPort, netconfUser, netconfPassword); + LOGGER.info("Configuration params are : {}", params); + return new NetconfConfigurationReader(params, new NetconfSessionHelper()); + } + + @Bean + NetconfConfigurationEditor configurationEditor() { + NetconfConnectionParams params = + new NetconfConnectionParams(netconfAddress, netconfPort, netconfUser, netconfPassword); + return new NetconfConfigurationEditor(params, new NetconfSessionHelper()); + } + +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java new file mode 100644 index 0000000..992c88d --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. 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.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.Element; +import com.tailf.jnc.JNCException; +import com.tailf.jnc.NetconfSession; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +public class NetconfConfigurationEditor { + + private NetconfConnectionParams params; + private NetconfSessionHelper netconfSessionHelper; + + public NetconfConfigurationEditor(NetconfConnectionParams params, NetconfSessionHelper netconfSessionHelper) { + this.params = params; + this.netconfSessionHelper = netconfSessionHelper; + } + + void editConfig(Element configurationXmlElement) throws JNCException, IOException { + log.debug("New configuration passed to simulator: {}", configurationXmlElement.toXMLString()); + NetconfSession session = netconfSessionHelper.createNetconfSession(params); + session.editConfig(configurationXmlElement); + session.closeSession(); + + log.info("Successfully updated configuration"); + } + +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java new file mode 100644 index 0000000..10fe40e --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. 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.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.JNCException; +import com.tailf.jnc.NetconfSession; +import com.tailf.jnc.NodeSet; +import java.io.IOException; +import java.util.Objects; + +class NetconfConfigurationReader { + + private NetconfConnectionParams params; + private NetconfSessionHelper netconfSessionHelper; + + NetconfConfigurationReader(NetconfConnectionParams params, NetconfSessionHelper netconfSessionHelper) { + this.params = params; + this.netconfSessionHelper = netconfSessionHelper; + } + + String getRunningConfig() throws IOException, JNCException { + NetconfSession session = netconfSessionHelper.createNetconfSession(params); + String config = session.getConfig().toXMLString(); + session.closeSession(); + return config; + } + + String getRunningConfig(String modelPath) throws IOException, JNCException { + NetconfSession session = netconfSessionHelper.createNetconfSession(params); + NodeSet config = session.getConfig(modelPath); + if (Objects.isNull(config) || Objects.isNull(config.first())) { + throw new JNCException(JNCException.ELEMENT_MISSING, modelPath); + } + session.closeSession(); + return config.first().toXMLString(); + } + + +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java new file mode 100644 index 0000000..248aec4 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java @@ -0,0 +1,76 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. 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.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.Element; +import com.tailf.jnc.JNCException; +import com.tailf.jnc.XMLParser; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import org.xml.sax.InputSource; + +@Service +public class NetconfConfigurationService { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfConfigurationService.class); + private static final String CONFIGURATION_HAS_BEEN_ACTIVATED = "New configuration has been activated"; + + private final NetconfConfigurationReader netconfConfigurationReader; + private NetconfConfigurationEditor configurationEditor; + private XMLParser parser; + + @Autowired + public NetconfConfigurationService(NetconfConfigurationReader netconfConfigurationReader, + NetconfConfigurationEditor netconfConfigurationEditor) throws JNCException { + this.netconfConfigurationReader = netconfConfigurationReader; + this.configurationEditor = netconfConfigurationEditor; + this.parser = new XMLParser(); + } + + public String getCurrentConfiguration() throws IOException, JNCException { + return netconfConfigurationReader.getRunningConfig(); + } + + public String getCurrentConfiguration(String model, String container) throws IOException, JNCException { + String path = String.format("/%s:%s", model, container); + return netconfConfigurationReader.getRunningConfig(path); + } + + public String editCurrentConfiguration(MultipartFile newConfiguration) throws IOException, JNCException { + Element configurationElement = convertMultipartToXmlElement(newConfiguration); + configurationEditor.editConfig(configurationElement); + + LOGGER.debug("Loading new configuration: \n{}", configurationElement.toXMLString()); + return CONFIGURATION_HAS_BEEN_ACTIVATED; + } + + private Element convertMultipartToXmlElement(MultipartFile editConfig) throws IOException, JNCException { + InputSource inputSourceUpdateConfig = new InputSource(new ByteArrayInputStream(editConfig.getBytes())); + return parser.parse(inputSourceUpdateConfig); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java new file mode 100644 index 0000000..e43ff69 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. 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.onap.netconfsimulator.netconfcore.configuration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class NetconfConfigurationTO { + + private String configuration; + +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java new file mode 100644 index 0000000..ace0ee0 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. 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.onap.netconfsimulator.netconfcore.configuration; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@AllArgsConstructor +@ToString +@Getter +class NetconfConnectionParams { + + private final String address; + private final int port; + private final String user; + private final String password; + +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java new file mode 100644 index 0000000..69fda7d --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.JNCException; +import com.tailf.jnc.NetconfSession; +import com.tailf.jnc.SSHConnection; +import com.tailf.jnc.SSHSession; +import java.io.IOException; + +class NetconfSessionHelper { + + NetconfSession createNetconfSession(NetconfConnectionParams params) throws IOException, JNCException { + SSHConnection sshConnection = new SSHConnection(params.getAddress(), params.getPort()); + sshConnection.authenticateWithPassword(params.getUser(), params.getPassword()); + return new NetconfSession(new SSHSession(sshConnection)); + } + +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java new file mode 100644 index 0000000..a6e292f --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.netconfcore.model; + +public class LoadModelResponse { + + private Integer statusCode; + private String message; + + public LoadModelResponse(Integer statusCode, String message) { + this.statusCode = statusCode; + this.message = message; + } + + public Integer getStatusCode() { + return this.statusCode; + } + + public String getMessage() { + return this.message; + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java new file mode 100644 index 0000000..7e07395 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.netconfcore.model; + +import java.io.IOException; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class NetconfModelLoaderService { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfModelLoaderService.class); + + @Value("${netconf.address}") + private String netconfIp; + + @Value("${netconf.model-loader.port}") + private String modelLoaderPort; + + private final HttpClient httpClient; + + @Autowired + public NetconfModelLoaderService(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public LoadModelResponse deleteYangModel(String yangModelName) throws IOException { + String uri = getDeleteAddress(yangModelName); + HttpDelete httpDelete = new HttpDelete(uri); + HttpResponse httpResponse = httpClient.execute(httpDelete); + return parseResponse(httpResponse); + } + + public LoadModelResponse loadYangModel(MultipartFile yangModel, MultipartFile initialConfig, String moduleName) + throws IOException { + HttpPost httpPost = new HttpPost(getBackendAddress()); + HttpEntity httpEntity = MultipartEntityBuilder.create() + .addBinaryBody("yangModel", yangModel.getInputStream(), ContentType.MULTIPART_FORM_DATA, + yangModel.getOriginalFilename()) + .addBinaryBody("initialConfig", initialConfig.getInputStream(), ContentType.MULTIPART_FORM_DATA, + initialConfig.getOriginalFilename()) + .addTextBody("moduleName", moduleName) + .build(); + httpPost.setEntity(httpEntity); + HttpResponse response = httpClient.execute(httpPost); + return parseResponse(response); + } + + String getBackendAddress() { + return String.format("http://%s:%s/model", netconfIp, modelLoaderPort); + } + + String getDeleteAddress(String yangModelName) { + return String.format("%s?yangModelName=%s", getBackendAddress(), yangModelName); + } + + + private LoadModelResponse parseResponse(HttpResponse response) throws IOException { + int statusCode = response.getStatusLine().getStatusCode(); + String responseBody = EntityUtils.toString(response.getEntity()); + + logResponse(statusCode, responseBody); + return new LoadModelResponse(statusCode, responseBody); + } + + private void logResponse(int statusCode, String responseBody) { + if (statusCode >= HttpStatus.BAD_REQUEST.value()) { + LOGGER.error(responseBody); + } else { + LOGGER.info(responseBody); + } + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java new file mode 100644 index 0000000..4eaa850 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.websocket; + +import java.util.Collections; +import org.onap.netconfsimulator.websocket.message.NetconfMessageEncoder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; +import org.springframework.web.socket.server.standard.ServerEndpointRegistration; + +@Configuration +class EndpointConfig { + + @Bean + ServerEndpointRegistration endpointRegistration() { + ServerEndpointRegistration serverEndpointRegistration = new ServerEndpointRegistration("/netconf", + NetconfEndpoint.class); + serverEndpointRegistration.setEncoders(Collections.singletonList(NetconfMessageEncoder.class)); + return serverEndpointRegistration; + } + + @Bean + ServerEndpointExporter endpointExporter() { + return new ServerEndpointExporter(); + } +} + diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java new file mode 100644 index 0000000..5870ee1 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.websocket; + + +import java.util.Optional; +import javax.websocket.CloseReason; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.RemoteEndpoint; +import javax.websocket.Session; + +import org.onap.netconfsimulator.kafka.listener.KafkaListenerEntry; +import org.onap.netconfsimulator.kafka.listener.KafkaListenerHandler; +import org.onap.netconfsimulator.websocket.message.NetconfMessageListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.listener.AbstractMessageListenerContainer; +import org.springframework.kafka.listener.MessageListener; +import org.springframework.stereotype.Component; + +//instance of this class is created every each websocket request +@Component +class NetconfEndpoint extends Endpoint { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfEndpoint.class); + private static final String TOPIC_NAME = "config"; + + private KafkaListenerHandler kafkaListenerHandler; + + public Optional<KafkaListenerEntry> getEntry() { + return entry; + } + + public void setEntry(Optional<KafkaListenerEntry> entry) { + this.entry = entry; + } + + private Optional<KafkaListenerEntry> entry = Optional.empty(); + + + @Autowired + NetconfEndpoint(KafkaListenerHandler listenerHandler) { + this.kafkaListenerHandler = listenerHandler; + } + + @Override + public void onOpen(Session session, EndpointConfig endpointConfig) { + RemoteEndpoint.Basic basicRemote = session.getBasicRemote(); + + addKafkaListener(basicRemote); + entry.ifPresent(x -> LOGGER.info("Session with client: {} established", x.getClientId())); + } + + @Override + public void onError(Session session, Throwable throwable) { + LOGGER.error("Unexpected error occurred", throwable); + } + + @Override + public void onClose(Session session, CloseReason closeReason) { + entry.ifPresent(x -> x.getListenerContainer().stop()); + entry.ifPresent(x -> LOGGER.info("Closing connection for client: {}", x.getClientId())); + } + + + private void addKafkaListener(RemoteEndpoint.Basic remoteEndpoint) { + MessageListener messageListener = new NetconfMessageListener(remoteEndpoint); + + KafkaListenerEntry kafkaListener = kafkaListenerHandler.createKafkaListener(messageListener, TOPIC_NAME); + + AbstractMessageListenerContainer listenerContainer = kafkaListener.getListenerContainer(); + listenerContainer.start(); + entry = Optional.of(kafkaListener); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java new file mode 100644 index 0000000..349b7e2 --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.websocket.message; + +import org.onap.netconfsimulator.kafka.model.KafkaMessage; +import org.springframework.web.socket.adapter.standard.ConvertingEncoderDecoderSupport; + +public class NetconfMessageEncoder extends ConvertingEncoderDecoderSupport.TextEncoder<KafkaMessage> { + + private static final String MESSAGE_FORMAT = "%s: %s"; + + @Override + public String encode(KafkaMessage netconfMessage) { + return String.format(MESSAGE_FORMAT, netconfMessage.getTimestamp(), netconfMessage.getConfiguration()); + } +} diff --git a/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java new file mode 100644 index 0000000..61610de --- /dev/null +++ b/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. 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.onap.netconfsimulator.websocket.message; + +import java.io.IOException; +import javax.websocket.EncodeException; +import javax.websocket.RemoteEndpoint; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.onap.netconfsimulator.kafka.model.KafkaMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.kafka.listener.MessageListener; + +public class NetconfMessageListener implements MessageListener<String, String> { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfMessageListener.class); + private RemoteEndpoint.Basic remoteEndpoint; + + public NetconfMessageListener(RemoteEndpoint.Basic remoteEndpoint) { + this.remoteEndpoint = remoteEndpoint; + } + + @Override + public void onMessage(ConsumerRecord<String, String> message) { + LOGGER.debug("Attempting to send message to {}", remoteEndpoint); + try { + remoteEndpoint + .sendObject(new KafkaMessage(message.timestamp(), message.value())); + } catch (IOException | EncodeException exception) { + LOGGER.error("Error during sending message to remote", exception); + } + } +} |