diff options
Diffstat (limited to 'so-cnf-adapter-application/src/main/java')
10 files changed, 637 insertions, 15 deletions
diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudApiUrl.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudApiUrl.java index d21b97a..617eef7 100644 --- a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudApiUrl.java +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudApiUrl.java @@ -13,7 +13,11 @@ class MulticloudApiUrl { } String apiUrl(String instanceId) { - return multicloudConfiguration.getMulticloudUrl() + "/v1/instance/" + instanceId; + String url = multicloudConfiguration.getMulticloudUrl() + "/v1/instance"; + if (!instanceId.isEmpty()) { + url += "/" + instanceId; + } + return url; } }
\ No newline at end of file diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudClient.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudClient.java index 5edb34c..0f5df15 100644 --- a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudClient.java +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudClient.java @@ -23,11 +23,13 @@ package org.onap.so.adapters.cnf.client; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import org.onap.so.adapters.cnf.MulticloudConfiguration; +import org.onap.so.adapters.cnf.model.InstanceResponse; import org.onap.so.adapters.cnf.model.MulticloudInstanceRequest; import org.onap.so.adapters.cnf.model.healthcheck.K8sRbInstanceHealthCheck; import org.onap.so.adapters.cnf.model.healthcheck.K8sRbInstanceHealthCheckSimple; import org.onap.so.adapters.cnf.model.statuscheck.K8sRbInstanceStatus; +import org.onap.so.adapters.cnf.model.synchronization.SubscriptionRequest; +import org.onap.so.adapters.cnf.model.synchronization.SubscriptionResponse; import org.onap.so.client.exception.BadResponseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,9 +39,11 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.springframework.http.HttpMethod.DELETE; @@ -61,6 +65,78 @@ public class MulticloudClient { this.objectMapper = new ObjectMapper(); } + public List<InstanceResponse> getAllInstances() throws BadResponseException { + String endpoint = multicloudApiUrl.apiUrl(""); + ResponseEntity<String> result = restTemplate.exchange(endpoint, GET, getHttpEntity(), String.class); + checkResponseStatusCode(result); + log.info("getAllInstances response status: {}", result.getStatusCode()); + String body = result.getBody(); + log.debug("getAllInstances response body: {}", body); + + try { + return Arrays.asList(objectMapper.readValue(body, InstanceResponse[].class)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public SubscriptionResponse registerSubscription(String instanceId, SubscriptionRequest subscriptionRequest) throws BadResponseException { + String endpoint = multicloudApiUrl.apiUrl(instanceId) + "/status/subscription"; + ResponseEntity<String> result = restTemplate.exchange(endpoint, POST, getHttpEntity(subscriptionRequest), String.class); + checkResponseStatusCode(result); + log.info("registerSubscription response status: {}", result.getStatusCode()); + String body = result.getBody(); + log.debug("registerSubscription response body: {}", body); + + try { + return objectMapper.readValue(body, SubscriptionResponse.class); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public Boolean hasSubscription(String instanceId, String subscriptionId) throws BadResponseException { + String endpoint = multicloudApiUrl.apiUrl(instanceId) + "/status/subscription/" + subscriptionId; + try { + ResponseEntity<String> result = restTemplate.exchange(endpoint, GET, getHttpEntity(), String.class); + checkResponseStatusCode(result); + log.info("hasSubscription response status: {}", result.getStatusCode()); + return true; + } catch (HttpServerErrorException e) { + if (e.getMessage().contains("no documents")) { + log.info("hasSubscription response status: {}", 500); + return false; + } else + throw e; + } + } + + public SubscriptionResponse getSubscription(String instanceId, String subscriptionId) throws BadResponseException { + String endpoint = multicloudApiUrl.apiUrl(instanceId) + "/status/subscription/" + subscriptionId; + try { + ResponseEntity<String> result = restTemplate.exchange(endpoint, GET, getHttpEntity(), String.class); + checkResponseStatusCode(result); + log.info("getSubscription response status: {}", result.getStatusCode()); + String body = result.getBody(); + log.debug("getSubscription response body: {}", body); + return objectMapper.readValue(body, SubscriptionResponse.class); + } catch (HttpServerErrorException e) { + if (e.getMessage().contains("no documents")) { + throw new BadResponseException("Multicloud response status error 404"); + } else + throw e; + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public void deleteSubscription(String instanceId, String subscriptionId) throws BadResponseException { + String endpoint = multicloudApiUrl.apiUrl(instanceId) + "/status/subscription/" + subscriptionId; + ResponseEntity<String> result = restTemplate.exchange(endpoint, DELETE, getHttpEntity(), String.class); + checkResponseStatusCode(result); + log.info("deleteSubscription response status: {}", result.getStatusCode()); + } + public String upgradeInstance(String instanceId, MulticloudInstanceRequest upgradeRequest) throws BadResponseException { String endpoint = multicloudApiUrl.apiUrl(instanceId) + "/upgrade"; ResponseEntity<String> result = restTemplate.exchange(endpoint, POST, getHttpEntity(upgradeRequest), String.class); diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/NotificationRequest.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/NotificationRequest.java new file mode 100644 index 0000000..e0b021f --- /dev/null +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/NotificationRequest.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * ================================================================================ + * 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.so.adapters.cnf.model.synchronization; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.onap.so.adapters.cnf.model.aai.AaiRequest; + +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(value = "true") +public class NotificationRequest { + + @JsonProperty("instance-id") + private String instanceId; + @JsonProperty("subscription-name") + private String subscriptionName; + @JsonProperty("metadata") + private AaiRequest metadata; + + public NotificationRequest() { } + + public String getInstanceId() { + return instanceId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + public String getSubscriptionName() { + return subscriptionName; + } + + public void setSubscriptionName(String subscriptionName) { + this.subscriptionName = subscriptionName; + } + + public AaiRequest getMetadata() { + return metadata; + } + + public void setMetadata(AaiRequest metadata) { + this.metadata = metadata; + } + + @Override + public String toString() { + return "NotificationRequest{" + + "instanceId='" + instanceId + '\'' + + ", subscriptionName='" + subscriptionName + '\'' + + ", metadata=" + metadata + + '}'; + } +} diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/SubscriptionRequest.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/SubscriptionRequest.java new file mode 100644 index 0000000..238eef5 --- /dev/null +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/SubscriptionRequest.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * ================================================================================ + * 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.so.adapters.cnf.model.synchronization; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.onap.so.adapters.cnf.model.aai.AaiRequest; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(value = "true") +public class SubscriptionRequest { + + @JsonProperty(value = "name") + private String name; + + @JsonProperty(value = "callback-url") + private String callbackUrl; + + @JsonProperty(value = "min-notify-interval") + private int minNotifyInterval; + + @JsonProperty(value = "metadata") + private AaiRequest metadata; + + public String getCallbackUrl() { + return callbackUrl; + } + + public void setCallbackUrl(String callbackUrl) { + this.callbackUrl = callbackUrl; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getMinNotifyInterval() { + return minNotifyInterval; + } + + public void setMinNotifyInterval(int minNotifyInterval) { + this.minNotifyInterval = minNotifyInterval; + } + + public AaiRequest getMetadata() { + return metadata; + } + + public void setMetadata(AaiRequest metadata) { + this.metadata = metadata; + } + + @Override + public String toString() { + return "SubscriptionRequest{" + + "callbackUrl='" + callbackUrl + '\'' + + ", name='" + name + '\'' + + ", minNotifyInterval=" + minNotifyInterval + + ", metadata='" + metadata + '\'' + + '}'; + } +} diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/SubscriptionResponse.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/SubscriptionResponse.java new file mode 100644 index 0000000..5f05126 --- /dev/null +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/synchronization/SubscriptionResponse.java @@ -0,0 +1,118 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * ================================================================================ + * 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.so.adapters.cnf.model.synchronization; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Date; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class SubscriptionResponse { + + @JsonProperty("callback-url") + private String callbackUrl; + @JsonProperty("name") + private String name; + @JsonProperty("last-update-time") + private Date lastUpdateTime; + @JsonProperty("last-notify-time") + private Date lastNotifyTime; + @JsonProperty("last-notify-status") + private int lastNotifyStatus; + @JsonProperty("min-notify-interval") + private int minNotifyInterval; + @JsonProperty("metadata ") + private String metadata; + + public SubscriptionResponse() { } + + public String getCallbackUrl() { + return callbackUrl; + } + + public void setCallbackUrl(String callbackUrl) { + this.callbackUrl = callbackUrl; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getLastUpdateTime() { + return lastUpdateTime; + } + + public void setLastUpdateTime(Date lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + public Date getLastNotifyTime() { + return lastNotifyTime; + } + + public void setLastNotifyTime(Date lastNotifyTime) { + this.lastNotifyTime = lastNotifyTime; + } + + public int getLastNotifyStatus() { + return lastNotifyStatus; + } + + public void setLastNotifyStatus(int lastNotifyStatus) { + this.lastNotifyStatus = lastNotifyStatus; + } + + public int getMinNotifyInterval() { + return minNotifyInterval; + } + + public void setMinNotifyInterval(int minNotifyInterval) { + this.minNotifyInterval = minNotifyInterval; + } + + public String getMetadata() { + return metadata; + } + + public void setMetadata(String metadata) { + this.metadata = metadata; + } + + @Override + public String toString() { + return "SubscriptionResponse{" + + "callbackUrl='" + callbackUrl + '\'' + + ", name='" + name + '\'' + + ", lastUpdateTime=" + lastUpdateTime + + ", lastNotifyTime=" + lastNotifyTime + + ", lastNotifyStatus=" + lastNotifyStatus + + ", minNotifyInterval=" + minNotifyInterval + + ", metadata='" + metadata + '\'' + + '}'; + } +} diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/CnfAdapterRest.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/CnfAdapterRest.java index 3272ad9..df674f8 100644 --- a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/CnfAdapterRest.java +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/CnfAdapterRest.java @@ -59,6 +59,7 @@ import org.onap.so.adapters.cnf.service.CnfAdapterService; import org.onap.so.adapters.cnf.service.aai.AaiService; import org.onap.so.adapters.cnf.service.healthcheck.HealthCheckService; import org.onap.so.adapters.cnf.service.statuscheck.SimpleStatusCheckService; +import org.onap.so.adapters.cnf.service.synchrornization.SynchronizationService; import org.onap.so.adapters.cnf.service.upgrade.InstanceUpgradeService; import org.onap.so.client.exception.BadResponseException; import org.slf4j.Logger; @@ -89,6 +90,7 @@ public class CnfAdapterRest { private final CnfAdapterService cnfAdapterService; private final SoCallbackClient callbackClient; private final AaiService aaiService; + private final SynchronizationService synchronizationService; private final String uri; @Autowired @@ -98,6 +100,7 @@ public class CnfAdapterRest { CnfAdapterService cnfAdapterService, SoCallbackClient callbackClient, AaiService aaiService, + SynchronizationService synchronizationService, MulticloudConfiguration multicloudConfiguration) { this.simpleStatusCheckService = simpleStatusCheckService; this.healthCheckService = healthCheckService; @@ -105,6 +108,7 @@ public class CnfAdapterRest { this.cnfAdapterService = cnfAdapterService; this.aaiService = aaiService; this.callbackClient = callbackClient; + this.synchronizationService = synchronizationService; this.uri = multicloudConfiguration.getMulticloudUrl(); } @@ -154,6 +158,7 @@ public class CnfAdapterRest { AaiCallbackResponse callbackResponse = new AaiCallbackResponse(); try { aaiService.aaiUpdate(aaiRequest); + synchronizationService.createSubscriptionIfNotExists(aaiRequest); callbackResponse.setCompletionStatus(AaiCallbackResponse.CompletionStatus.COMPLETED); } catch (Exception e) { logger.warn("Failed to create resource in AAI", e); @@ -178,6 +183,7 @@ public class CnfAdapterRest { logger.info("Processing aai delete"); AaiCallbackResponse callbackResponse = new AaiCallbackResponse(); try { + synchronizationService.deleteSubscriptionIfExists(aaiRequest); aaiService.aaiDelete(aaiRequest); callbackResponse.setCompletionStatus(AaiCallbackResponse.CompletionStatus.COMPLETED); } catch (Exception e) { @@ -218,9 +224,7 @@ public class CnfAdapterRest { @ResponseBody @RequestMapping(value = {"/api/cnf-adapter/v1/instance"}, method = RequestMethod.POST, produces = "application/json", consumes = "application/json") - public String createInstance(@RequestBody BpmnInstanceRequest bpmnInstanceRequest) - throws JsonParseException, JsonMappingException, IOException { - + public String createInstance(@RequestBody BpmnInstanceRequest bpmnInstanceRequest) throws BadResponseException { logger.info("createInstance called."); return cnfAdapterService.createInstance(bpmnInstanceRequest); } @@ -294,8 +298,7 @@ public class CnfAdapterRest { @ResponseBody @RequestMapping(value = {"/api/cnf-adapter/v1/instance/{instID}"}, method = RequestMethod.DELETE, produces = "application/json") - public String deleteInstanceByInstanceId(@PathVariable("instID") String instanceID) - throws JsonParseException, JsonMappingException, IOException { + public String deleteInstanceByInstanceId(@PathVariable("instID") String instanceID) throws BadResponseException { logger.info("deleteInstanceByInstanceId called."); if (instanceID == null || instanceID.isEmpty() || instanceID.equals("null")) { diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/SubscriptionNotifyController.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/SubscriptionNotifyController.java new file mode 100644 index 0000000..88df42b --- /dev/null +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/SubscriptionNotifyController.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * ================================================================================ + * 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.so.adapters.cnf.rest; + + +import com.google.gson.Gson; +import org.onap.so.adapters.cnf.model.aai.AaiRequest; +import org.onap.so.adapters.cnf.model.synchronization.NotificationRequest; +import org.onap.so.adapters.cnf.service.aai.AaiService; +import org.onap.so.adapters.cnf.service.synchrornization.SynchronizationService; +import org.onap.so.client.exception.BadResponseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +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.RestController; + +import java.util.Map; + +@RestController +public class SubscriptionNotifyController { + + private static final Logger logger = LoggerFactory.getLogger(SubscriptionNotifyController.class); + private final static Gson gson = new Gson(); + + private final AaiService aaiService; + private final SynchronizationService synchronizationService; + + public SubscriptionNotifyController(AaiService aaiService, SynchronizationService synchronizationService) { + this.aaiService = aaiService; + this.synchronizationService = synchronizationService; + } + + @PostMapping(value = "/api/cnf-adapter/v1/instance/{instanceId}/status/notify") + public ResponseEntity subscriptionNotifyEndpoint(@PathVariable String instanceId, + @RequestBody NotificationRequest body) throws BadResponseException { + String subscriptionName = synchronizationService.getSubscriptionName(instanceId); + boolean isSubscriptionActive = synchronizationService.isSubscriptionActive(subscriptionName); + if (isSubscriptionActive) { + logger.info("AAI update- START"); + aaiService.aaiUpdate(body.getMetadata()); + return ResponseEntity + .accepted() + .build(); + } else { + return ResponseEntity + .badRequest() + .body(String.format("Cannot handle notification. Subscription %s not exists", subscriptionName)); + } + } + + private AaiRequest convertMetadataToAaiRequest(Map<String, Object> metadata) { + String json = gson.toJsonTree(metadata) + .getAsJsonObject() + .get("metadata") + .toString(); + + return gson.fromJson(json, AaiRequest.class); + } + +} diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/CnfAdapterService.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/CnfAdapterService.java index 7e667a0..6d84911 100644 --- a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/CnfAdapterService.java +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/CnfAdapterService.java @@ -24,14 +24,15 @@ package org.onap.so.adapters.cnf.service; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.gson.Gson; import org.apache.http.HttpStatus; +import org.json.JSONObject; import org.onap.so.adapters.cnf.MulticloudConfiguration; import org.onap.so.adapters.cnf.model.BpmnInstanceRequest; -import org.onap.so.adapters.cnf.model.CheckInstanceRequest; import org.onap.so.adapters.cnf.model.MulticloudInstanceRequest; -import org.onap.so.adapters.cnf.model.healthcheck.HealthCheckResponse; -import org.onap.so.adapters.cnf.service.healthcheck.HealthCheckService; -import org.onap.so.adapters.cnf.service.statuscheck.SimpleStatusCheckService; +import org.onap.so.adapters.cnf.model.aai.AaiRequest; +import org.onap.so.adapters.cnf.service.synchrornization.SynchronizationService; +import org.onap.so.client.exception.BadResponseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -66,8 +67,7 @@ public class CnfAdapterService { this.uri = multicloudConfiguration.getMulticloudUrl(); } - public String createInstance(BpmnInstanceRequest bpmnInstanceRequest) - throws JsonParseException, JsonMappingException, IOException { + public String createInstance(BpmnInstanceRequest bpmnInstanceRequest) { try { logger.info("CnfAdapterService createInstance called"); MulticloudInstanceRequest multicloudInstanceRequest = new MulticloudInstanceRequest(); @@ -262,8 +262,7 @@ public class CnfAdapterService { } } - public String deleteInstanceByInstanceId(String instanceId) - throws JsonParseException, JsonMappingException, IOException { + public String deleteInstanceByInstanceId(String instanceId) { logger.info("CnfAdapterService deleteInstanceByInstanceId called"); ResponseEntity<String> result = null; @@ -278,6 +277,7 @@ public class CnfAdapterService { logger.info("request: " + requestEntity); result = restTemplate.exchange(endpoint, HttpMethod.DELETE, requestEntity, String.class); logger.info("response: " + result); + return result.getBody(); } catch (HttpClientErrorException e) { logger.error("Error Calling Multicloud, e"); diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/synchrornization/SubscriptionsRecoveryProvider.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/synchrornization/SubscriptionsRecoveryProvider.java new file mode 100644 index 0000000..68b49a8 --- /dev/null +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/synchrornization/SubscriptionsRecoveryProvider.java @@ -0,0 +1,29 @@ +package org.onap.so.adapters.cnf.service.synchrornization; + +import org.onap.so.adapters.cnf.client.MulticloudClient; +import org.onap.so.adapters.cnf.model.InstanceResponse; +import org.onap.so.client.exception.BadResponseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.Set; +import java.util.stream.Collectors; + +@Component +public class SubscriptionsRecoveryProvider { + + private final MulticloudClient multicloudClient; + + public SubscriptionsRecoveryProvider(MulticloudClient multicloudClient) { + this.multicloudClient = multicloudClient; + } + + public Set<String> getInstanceList() throws BadResponseException { + Set<String> instanceIds; + instanceIds = multicloudClient.getAllInstances().stream() + .map(InstanceResponse::getId) + .collect(Collectors.toSet()); + return instanceIds; + } +} diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/synchrornization/SynchronizationService.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/synchrornization/SynchronizationService.java new file mode 100644 index 0000000..643977e --- /dev/null +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/synchrornization/SynchronizationService.java @@ -0,0 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * ================================================================================ + * 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.so.adapters.cnf.service.synchrornization; + +import org.apache.http.client.utils.URIBuilder; +import org.onap.so.adapters.cnf.client.MulticloudClient; +import org.onap.so.adapters.cnf.model.InstanceResponse; +import org.onap.so.adapters.cnf.model.aai.AaiRequest; +import org.onap.so.adapters.cnf.model.synchronization.SubscriptionRequest; +import org.onap.so.client.exception.BadResponseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.net.URISyntaxException; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +public class SynchronizationService { + + private static final Logger logger = LoggerFactory.getLogger(SynchronizationService.class); + + private static final String PROTOCOL = "http"; + private static final String HOST = "so-cnf-adapter"; + private static final int PORT = 8090; + + private final Set<String> subscriptions = new HashSet<>(); + private final MulticloudClient multicloudClient; + private final SubscriptionsRecoveryProvider recoveryProvider; + + public SynchronizationService(MulticloudClient multicloudClient, SubscriptionsRecoveryProvider recoveryProvider) { + this.multicloudClient = multicloudClient; + this.recoveryProvider = recoveryProvider; + } + + @PostConstruct + private void postConstruct() { + recoverSubscriptions(); + } + + private void recoverSubscriptions() { + if (subscriptions.isEmpty()) { + Set<String> instanceIds; + try { + + instanceIds = recoveryProvider.getInstanceList(); + + instanceIds.forEach(this::addSubscriptionIfSubscriptionFound); + } catch (BadResponseException e) { + logger.error("Instances not found", e); + } + } + } + + private void addSubscriptionIfSubscriptionFound(String instanceId) { + String subscriptionName = getSubscriptionName(instanceId); + try { + if (multicloudClient.hasSubscription(instanceId, subscriptionName)) + subscriptions.add(subscriptionName); + } catch (BadResponseException e) { + logger.warn("Subscriptions not found instanceId={} subscriptionName={}", instanceId, subscriptionName); + } + } + + public void createSubscriptionIfNotExists(AaiRequest aaiRequest) throws BadResponseException { + logger.debug("createSubscriptionIfNotExists- START"); + String instanceId = aaiRequest.getInstanceId(); + String subscriptionName = getSubscriptionName(instanceId); + String callbackUrl = generateCallbackUrl(instanceId); + + if (isSubscriptionActive(subscriptionName)) { + logger.info("Subscription: {} already exits", subscriptionName); + } else { + multicloudClient.registerSubscription(instanceId, getSubscriptionRequest(subscriptionName, callbackUrl, aaiRequest)); + subscriptions.add(subscriptionName); + logger.info("Subscription: {} registered", subscriptionName); + } + logger.debug("createSubscriptionIfNotExists- END"); + } + + public void deleteSubscriptionIfExists(AaiRequest aaiRequest) throws BadResponseException { + logger.debug("deleteSubscriptionIfExists - START"); + String instanceId = aaiRequest.getInstanceId(); + String subscriptionName = getSubscriptionName(instanceId); + + if (isSubscriptionActive(subscriptionName)) { + multicloudClient.deleteSubscription(instanceId, subscriptionName); + subscriptions.remove(subscriptionName); + logger.info("Subscription: {} removed", subscriptionName); + } else { + logger.info("Subscription: {} already removed or was not present", subscriptionName); + } + logger.debug("deleteSubscriptionIfExists - END"); + } + + public boolean isSubscriptionActive(String subscriptionName) { + return subscriptions.contains(subscriptionName); + } + + public String getSubscriptionName(String instanceId) { + return instanceId + "-cnf-adapter"; + } + + private SubscriptionRequest getSubscriptionRequest(String name, String endpoint, AaiRequest aaiRequest) { + SubscriptionRequest subscriptionRequest = new SubscriptionRequest(); + + subscriptionRequest.setName(name); + subscriptionRequest.setCallbackUrl(endpoint); + subscriptionRequest.setMinNotifyInterval(30); + + return subscriptionRequest; + } + + private String generateCallbackUrl(String instanceId) { + String path = String.format("/api/cnf-adapter/v1/instance/%s/status/notify", instanceId); + + URIBuilder uriBuilder = new URIBuilder(); + try { + return uriBuilder + .setScheme(PROTOCOL) + .setHost(HOST) + .setPort(PORT) + .setPath(path) + .build() + .toString(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } +} |