From 97a9001fe632b0eaed48d324dc8d6c2c3c630f8c Mon Sep 17 00:00:00 2001 From: PatrikBuhr Date: Fri, 26 Mar 2021 17:25:13 +0100 Subject: PMS Persistent storage of policies and type definitions - A1 Istanbul Policy types and type definitions are stored persistently to survive a restart of PMS. Change-Id: Ideae4dae5b6f9de2b82127e65ce5184d615c8fd4 Issue-ID: CCSDK-3256 Signed-off-by: PatrikBuhr --- .../a1policymanagementservice/BeanFactory.java | 26 +-- .../clients/CcsdkA1AdapterClient.java | 10 +- .../clients/OscA1Client.java | 9 +- .../clients/StdA1ClientVersion1.java | 9 +- .../clients/StdA1ClientVersion2.java | 10 +- .../configuration/ApplicationConfig.java | 6 +- .../controllers/v1/PolicyController.java | 54 +++--- .../controllers/v1/ServiceController.java | 7 +- .../controllers/v2/PolicyController.java | 54 +++--- .../controllers/v2/ServiceController.java | 7 +- .../dmaap/DmaapMessageConsumer.java | 8 +- .../dmaap/DmaapMessageHandler.java | 24 +-- .../dmaap/DmaapRequestMessage.java | 32 ++-- .../dmaap/DmaapResponseMessage.java | 26 +-- .../repository/MultiMap.java | 65 ++++++++ .../repository/Policies.java | 184 +++++++++++++++++---- .../repository/Policy.java | 26 +-- .../repository/PolicyType.java | 14 +- .../repository/PolicyTypes.java | 78 ++++++++- .../a1policymanagementservice/repository/Ric.java | 2 +- .../tasks/RefreshConfigTask.java | 3 + .../tasks/RicSynchronizationTask.java | 5 +- .../tasks/ServiceSupervision.java | 10 +- 23 files changed, 458 insertions(+), 211 deletions(-) create mode 100644 a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/MultiMap.java (limited to 'a1-policy-management/src/main/java/org') diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java index 54a5edaa..4b5c2f09 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java @@ -25,10 +25,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.catalina.connector.Connector; import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Services; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.server.ServletWebServerFactory; @@ -36,20 +35,14 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration -class BeanFactory { - private final ApplicationConfig applicationConfig = new ApplicationConfig(); +public class BeanFactory { @Value("${server.http-port}") private int httpPort = 0; @Bean - public Policies getPolicies() { - return new Policies(); - } - - @Bean - public PolicyTypes getPolicyTypes() { - return new PolicyTypes(); + public ApplicationConfig getApplicationConfig() { + return new ApplicationConfig(); } @Bean @@ -58,18 +51,13 @@ class BeanFactory { } @Bean - public ApplicationConfig getApplicationConfig() { - return this.applicationConfig; - } - - @Bean - Services getServices() { + public Services getServices() { return new Services(); } @Bean - A1ClientFactory getA1ClientFactory() { - return new A1ClientFactory(this.applicationConfig); + public A1ClientFactory getA1ClientFactory(@Autowired ApplicationConfig applicationConfig) { + return new A1ClientFactory(applicationConfig); } @Bean diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java index 448b7b61..c3f00407 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java @@ -168,14 +168,14 @@ public class CcsdkA1AdapterClient implements A1Client { @Override public Mono putPolicy(Policy policy) { - String ricUrl = - getUriBuilder().createPutPolicyUri(policy.type().id(), policy.id(), policy.statusNotificationUri()); - return post("putA1Policy", ricUrl, Optional.of(policy.json())); + String ricUrl = getUriBuilder().createPutPolicyUri(policy.getType().getId(), policy.getId(), + policy.getStatusNotificationUri()); + return post("putA1Policy", ricUrl, Optional.of(policy.getJson())); } @Override public Mono deletePolicy(Policy policy) { - return deletePolicyById(policy.type().id(), policy.id()); + return deletePolicyById(policy.getType().getId(), policy.getId()); } @Override @@ -210,7 +210,7 @@ public class CcsdkA1AdapterClient implements A1Client { @Override public Mono getPolicyStatus(Policy policy) { - String ricUrl = getUriBuilder().createGetPolicyStatusUri(policy.type().id(), policy.id()); + String ricUrl = getUriBuilder().createGetPolicyStatusUri(policy.getType().getId(), policy.getId()); return post("getA1PolicyStatus", ricUrl, Optional.empty()); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/OscA1Client.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/OscA1Client.java index 402a73b4..7ded8ac9 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/OscA1Client.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/OscA1Client.java @@ -165,13 +165,14 @@ public class OscA1Client implements A1Client { @Override public Mono putPolicy(Policy policy) { - String policyUri = this.uri.createPutPolicyUri(policy.type().id(), policy.id(), policy.statusNotificationUri()); - return restClient.put(policyUri, policy.json()); + String policyUri = this.uri.createPutPolicyUri(policy.getType().getId(), policy.getId(), + policy.getStatusNotificationUri()); + return restClient.put(policyUri, policy.getJson()); } @Override public Mono deletePolicy(Policy policy) { - return deletePolicyById(policy.type().id(), policy.id()); + return deletePolicyById(policy.getType().getId(), policy.getId()); } @Override @@ -188,7 +189,7 @@ public class OscA1Client implements A1Client { @Override public Mono getPolicyStatus(Policy policy) { - String statusUri = uri.createGetPolicyStatusUri(policy.type().id(), policy.id()); + String statusUri = uri.createGetPolicyStatusUri(policy.getType().getId(), policy.getId()); return restClient.get(statusUri); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/StdA1ClientVersion1.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/StdA1ClientVersion1.java index ba18afea..130f5500 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/StdA1ClientVersion1.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/StdA1ClientVersion1.java @@ -113,8 +113,9 @@ public class StdA1ClientVersion1 implements A1Client { @Override public Mono putPolicy(Policy policy) { - return restClient.put(uri.createPutPolicyUri(policy.type().id(), policy.id(), policy.statusNotificationUri()), - policy.json()); + return restClient.put( + uri.createPutPolicyUri(policy.getType().getId(), policy.getId(), policy.getStatusNotificationUri()), + policy.getJson()); } @Override @@ -129,7 +130,7 @@ public class StdA1ClientVersion1 implements A1Client { @Override public Mono deletePolicy(Policy policy) { - return deletePolicyById(policy.id()); + return deletePolicyById(policy.getId()); } @Override @@ -146,7 +147,7 @@ public class StdA1ClientVersion1 implements A1Client { @Override public Mono getPolicyStatus(Policy policy) { - return restClient.get(uri.createGetPolicyStatusUri(policy.type().id(), policy.id())); + return restClient.get(uri.createGetPolicyStatusUri(policy.getType().getId(), policy.getId())); } private Flux getPolicyIds() { diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/StdA1ClientVersion2.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/StdA1ClientVersion2.java index 471b3c4d..d79b2e72 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/StdA1ClientVersion2.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/StdA1ClientVersion2.java @@ -169,14 +169,14 @@ public class StdA1ClientVersion2 implements A1Client { @Override public Mono putPolicy(Policy policy) { - String policyUri = - this.uriBuiler.createPutPolicyUri(policy.type().id(), policy.id(), policy.statusNotificationUri()); - return restClient.put(policyUri, policy.json()); + String policyUri = this.uriBuiler.createPutPolicyUri(policy.getType().getId(), policy.getId(), + policy.getStatusNotificationUri()); + return restClient.put(policyUri, policy.getJson()); } @Override public Mono deletePolicy(Policy policy) { - return deletePolicyById(policy.type().id(), policy.id()); + return deletePolicyById(policy.getType().getId(), policy.getId()); } @Override @@ -193,7 +193,7 @@ public class StdA1ClientVersion2 implements A1Client { @Override public Mono getPolicyStatus(Policy policy) { - String statusUri = uriBuiler.createGetPolicyStatusUri(policy.type().id(), policy.id()); + String statusUri = uriBuiler.createGetPolicyStatusUri(policy.getType().getId(), policy.getId()); return restClient.get(statusUri); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java index 6449e48b..5bfe677e 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java @@ -32,18 +32,20 @@ import lombok.Getter; import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientConfig.HttpProxyConfig; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import reactor.core.publisher.Flux; @EnableConfigurationProperties -@ConfigurationProperties() public class ApplicationConfig { @NotEmpty @Getter @Value("${app.filepath}") private String localConfigurationFilePath; + @Getter + @Value("${app.vardata-directory:null}") + private String vardataDirectory; + @Value("${server.ssl.key-store-type}") private String sslKeyStoreType = ""; diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/PolicyController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/PolicyController.java index 1f5f7ca9..c2f6a48a 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/PolicyController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/PolicyController.java @@ -44,7 +44,6 @@ import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.VoidResponse; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2.ErrorResponse; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.ImmutablePolicy; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock.LockType; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; @@ -135,7 +134,7 @@ public class PolicyController { description = "The identity of the policy type to get the definition for.") // @RequestParam(name = "id", required = true) String id) throws EntityNotFoundException { PolicyType type = policyTypes.getType(id); - return new ResponseEntity<>(type.schema(), HttpStatus.OK); + return new ResponseEntity<>(type.getSchema(), HttpStatus.OK); } @GetMapping("/policy_types") @@ -175,7 +174,7 @@ public class PolicyController { @Parameter(name = "id", required = true, description = "The identity of the policy instance.") // @RequestParam(name = "id", required = true) String id) throws EntityNotFoundException { Policy p = policies.getPolicy(id); - return new ResponseEntity<>(p.json(), HttpStatus.OK); + return new ResponseEntity<>(p.getJson(), HttpStatus.OK); } @DeleteMapping("/policy") @@ -197,11 +196,11 @@ public class PolicyController { @Parameter(name = "id", required = true, description = "The identity of the policy instance.") // @RequestParam(name = "id", required = true) String id) throws EntityNotFoundException { Policy policy = policies.getPolicy(id); - keepServiceAlive(policy.ownerServiceId()); - Ric ric = policy.ric(); + keepServiceAlive(policy.getOwnerServiceId()); + Ric ric = policy.getRic(); return ric.getLock().lock(LockType.SHARED) // .flatMap(notUsed -> assertRicStateIdle(ric)) // - .flatMap(notUsed -> a1ClientFactory.createA1Client(policy.ric())) // + .flatMap(notUsed -> a1ClientFactory.createA1Client(policy.getRic())) // .doOnNext(notUsed -> policies.remove(policy)) // .flatMap(client -> client.deletePolicy(policy)) // .doOnNext(notUsed -> ric.getLock().unlockBlocking()) // @@ -252,7 +251,7 @@ public class PolicyController { if (ric == null || type == null) { return Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND)); } - Policy policy = ImmutablePolicy.builder() // + Policy policy = Policy.builder() // .id(instanceId) // .json(jsonString) // .type(type) // @@ -263,7 +262,7 @@ public class PolicyController { .statusNotificationUri("") // .build(); - final boolean isCreate = this.policies.get(policy.id()) == null; + final boolean isCreate = this.policies.get(policy.getId()) == null; return ric.getLock().lock(LockType.SHARED) // .flatMap(notUsed -> assertRicStateIdle(ric)) // @@ -298,11 +297,11 @@ public class PolicyController { private Mono validateModifiedPolicy(Policy policy) { // Check that ric is not updated - Policy current = this.policies.get(policy.id()); - if (current != null && !current.ric().id().equals(policy.ric().id())) { - RejectionException e = new RejectionException("Policy cannot change RIC, policyId: " + current.id() + // - ", RIC name: " + current.ric().id() + // - ", new name: " + policy.ric().id(), HttpStatus.CONFLICT); + Policy current = this.policies.get(policy.getId()); + if (current != null && !current.getRic().id().equals(policy.getRic().id())) { + RejectionException e = new RejectionException("Policy cannot change RIC, policyId: " + current.getId() + // + ", RIC name: " + current.getRic().id() + // + ", new name: " + policy.getRic().id(), HttpStatus.CONFLICT); logger.debug("Request rejected, {}", e.getMessage()); return Mono.error(e); } @@ -310,10 +309,10 @@ public class PolicyController { } private Mono checkSupportedType(Ric ric, PolicyType type) { - if (!ric.isSupportingType(type.id())) { + if (!ric.isSupportingType(type.getId())) { logger.debug("Request rejected, type not supported, RIC: {}", ric); - RejectionException e = new RejectionException("Type: " + type.id() + " not supported by RIC: " + ric.id(), - HttpStatus.NOT_FOUND); + RejectionException e = new RejectionException( + "Type: " + type.getId() + " not supported by RIC: " + ric.id(), HttpStatus.NOT_FOUND); return Mono.error(e); } return Mono.just("OK"); @@ -405,7 +404,7 @@ public class PolicyController { throws EntityNotFoundException { Policy policy = policies.getPolicy(id); - return a1ClientFactory.createA1Client(policy.ric()) // + return a1ClientFactory.createA1Client(policy.getRic()) // .flatMap(client -> client.getPolicyStatus(policy)) // .flatMap(status -> Mono.just(new ResponseEntity<>(status, HttpStatus.OK))) .onErrorResume(this::handleException); @@ -428,7 +427,8 @@ public class PolicyController { } List filtered = new ArrayList<>(); for (Policy p : collection) { - if (include(type, p.type().id()) && include(ric, p.ric().id()) && include(service, p.ownerServiceId())) { + if (include(type, p.getType().getId()) && include(ric, p.getRic().id()) + && include(service, p.getOwnerServiceId())) { filtered.add(p); } } @@ -451,12 +451,12 @@ public class PolicyController { List v = new ArrayList<>(policies.size()); for (Policy p : policies) { PolicyInfo policyInfo = new PolicyInfo(); - policyInfo.id = p.id(); - policyInfo.json = fromJson(p.json()); - policyInfo.ric = p.ric().id(); - policyInfo.type = p.type().id(); - policyInfo.service = p.ownerServiceId(); - policyInfo.lastModified = p.lastModified().toString(); + policyInfo.id = p.getId(); + policyInfo.json = fromJson(p.getJson()); + policyInfo.ric = p.getRic().id(); + policyInfo.type = p.getType().getId(); + policyInfo.service = p.getOwnerServiceId(); + policyInfo.lastModified = p.getLastModified().toString(); if (!policyInfo.validate()) { logger.error("BUG, all fields must be set"); } @@ -478,7 +478,7 @@ public class PolicyController { result.append(","); } first = false; - result.append(t.schema()); + result.append(t.getSchema()); } result.append("]"); return result.toString(); @@ -487,7 +487,7 @@ public class PolicyController { private String toPolicyTypeIdsJson(Collection types) { List v = new ArrayList<>(types.size()); for (PolicyType t : types) { - v.add(t.id()); + v.add(t.getId()); } return gson.toJson(v); } @@ -495,7 +495,7 @@ public class PolicyController { private String toPolicyIdsJson(Collection policies) { List v = new ArrayList<>(policies.size()); for (Policy p : policies) { - v.add(p.id()); + v.add(p.getId()); } return gson.toJson(v); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ServiceController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ServiceController.java index b4b7dca4..4e42550c 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ServiceController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ServiceController.java @@ -141,12 +141,11 @@ public class ServiceController { } } - @Operation(summary = "Delete a service") + @Operation(summary = "Unregisters a service") @ApiResponses(value = { // - @ApiResponse(responseCode = "204", description = "Service deleted"), - @ApiResponse(responseCode = "204", description = "Not used", + @ApiResponse(responseCode = "204", description = "Service unregisterred", // content = @Content(schema = @Schema(implementation = VoidResponse.class))), - @ApiResponse(responseCode = "404", description = "Service not found", + @ApiResponse(responseCode = "404", description = "Service not found", // content = @Content(schema = @Schema(implementation = String.class)))}) @DeleteMapping("/services") public ResponseEntity deleteService(// diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java index 1f0e1603..ab9b6692 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java @@ -42,7 +42,6 @@ import lombok.Getter; import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.VoidResponse; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.ImmutablePolicy; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock.LockType; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; @@ -115,7 +114,7 @@ public class PolicyController { public ResponseEntity getPolicyType( // @PathVariable("policytype_id") String policyTypeId) throws EntityNotFoundException { PolicyType type = policyTypes.getType(policyTypeId); - PolicyTypeInfo info = new PolicyTypeInfo(type.schema()); + PolicyTypeInfo info = new PolicyTypeInfo(type.getSchema()); return new ResponseEntity<>(gson.toJson(info), HttpStatus.OK); } @@ -177,12 +176,12 @@ public class PolicyController { public Mono> deletePolicy( // @PathVariable(Consts.POLICY_ID_PARAM) String policyId) throws EntityNotFoundException { Policy policy = policies.getPolicy(policyId); - keepServiceAlive(policy.ownerServiceId()); - Ric ric = policy.ric(); + keepServiceAlive(policy.getOwnerServiceId()); + Ric ric = policy.getRic(); return ric.getLock().lock(LockType.SHARED) // .flatMap(notUsed -> assertRicStateIdle(ric)) // - .flatMap(notUsed -> a1ClientFactory.createA1Client(policy.ric())) // + .flatMap(notUsed -> a1ClientFactory.createA1Client(policy.getRic())) // .doOnNext(notUsed -> policies.remove(policy)) // .flatMap(client -> client.deletePolicy(policy)) // .doOnNext(notUsed -> ric.getLock().unlockBlocking()) // @@ -219,7 +218,7 @@ public class PolicyController { if (ric == null || type == null) { throw new EntityNotFoundException("Near-RT RIC or policy type not found"); } - Policy policy = ImmutablePolicy.builder() // + Policy policy = Policy.builder() // .id(policyInfo.policyId) // .json(jsonString) // .type(type) // @@ -230,7 +229,7 @@ public class PolicyController { .statusNotificationUri(policyInfo.statusNotificationUri == null ? "" : policyInfo.statusNotificationUri) // .build(); - final boolean isCreate = this.policies.get(policy.id()) == null; + final boolean isCreate = this.policies.get(policy.getId()) == null; return ric.getLock().lock(LockType.SHARED) // .flatMap(notUsed -> assertRicStateIdle(ric)) // @@ -259,11 +258,11 @@ public class PolicyController { private Mono validateModifiedPolicy(Policy policy) { // Check that ric is not updated - Policy current = this.policies.get(policy.id()); - if (current != null && !current.ric().id().equals(policy.ric().id())) { - RejectionException e = new RejectionException("Policy cannot change RIC, policyId: " + current.id() + // - ", RIC ID: " + current.ric().id() + // - ", new ID: " + policy.ric().id(), HttpStatus.CONFLICT); + Policy current = this.policies.get(policy.getId()); + if (current != null && !current.getRic().id().equals(policy.getRic().id())) { + RejectionException e = new RejectionException("Policy cannot change RIC, policyId: " + current.getId() + // + ", RIC ID: " + current.getRic().id() + // + ", new ID: " + policy.getRic().id(), HttpStatus.CONFLICT); logger.debug("Request rejected, {}", e.getMessage()); return Mono.error(e); } @@ -271,10 +270,10 @@ public class PolicyController { } private Mono checkSupportedType(Ric ric, PolicyType type) { - if (!ric.isSupportingType(type.id())) { + if (!ric.isSupportingType(type.getId())) { logger.debug("Request rejected, type not supported, RIC: {}", ric); - RejectionException e = new RejectionException("Type: " + type.id() + " not supported by RIC: " + ric.id(), - HttpStatus.NOT_FOUND); + RejectionException e = new RejectionException( + "Type: " + type.getId() + " not supported by RIC: " + ric.id(), HttpStatus.NOT_FOUND); return Mono.error(e); } return Mono.just("{}"); @@ -376,7 +375,7 @@ public class PolicyController { @PathVariable(Consts.POLICY_ID_PARAM) String policyId) throws EntityNotFoundException { Policy policy = policies.getPolicy(policyId); - return a1ClientFactory.createA1Client(policy.ric()) // + return a1ClientFactory.createA1Client(policy.getRic()) // .flatMap(client -> client.getPolicyStatus(policy).onErrorResume(e -> Mono.just("{}"))) // .flatMap(status -> createPolicyStatus(policy, status)) // .onErrorResume(this::handleException); @@ -384,7 +383,7 @@ public class PolicyController { } private Mono> createPolicyStatus(Policy policy, String statusFromNearRic) { - PolicyStatusInfo info = new PolicyStatusInfo(policy.lastModified(), fromJson(statusFromNearRic)); + PolicyStatusInfo info = new PolicyStatusInfo(policy.getLastModified(), fromJson(statusFromNearRic)); String str = gson.toJson(info); return Mono.just(new ResponseEntity<>(str, HttpStatus.OK)); } @@ -406,7 +405,8 @@ public class PolicyController { } List filtered = new ArrayList<>(); for (Policy p : collection) { - if (include(type, p.type().id()) && include(ric, p.ric().id()) && include(service, p.ownerServiceId())) { + if (include(type, p.getType().getId()) && include(ric, p.getRic().id()) + && include(service, p.getOwnerServiceId())) { filtered.add(p); } } @@ -427,14 +427,14 @@ public class PolicyController { private PolicyInfo toPolicyInfo(Policy p) { PolicyInfo policyInfo = new PolicyInfo(); - policyInfo.policyId = p.id(); - policyInfo.policyData = fromJson(p.json()); - policyInfo.ricId = p.ric().id(); - policyInfo.policyTypeId = p.type().id(); - policyInfo.serviceId = p.ownerServiceId(); + policyInfo.policyId = p.getId(); + policyInfo.policyData = fromJson(p.getJson()); + policyInfo.ricId = p.getRic().id(); + policyInfo.policyTypeId = p.getType().getId(); + policyInfo.serviceId = p.getOwnerServiceId(); policyInfo.isTransient = p.isTransient(); - if (!p.statusNotificationUri().isEmpty()) { - policyInfo.statusNotificationUri = p.statusNotificationUri(); + if (!p.getStatusNotificationUri().isEmpty()) { + policyInfo.statusNotificationUri = p.getStatusNotificationUri(); } if (!policyInfo.validate()) { logger.error("BUG, all mandatory fields must be set"); @@ -459,7 +459,7 @@ public class PolicyController { private String toPolicyTypeIdsJson(Collection types) { List v = new ArrayList<>(types.size()); for (PolicyType t : types) { - v.add(t.id()); + v.add(t.getId()); } PolicyTypeIdList ids = new PolicyTypeIdList(v); return gson.toJson(ids); @@ -468,7 +468,7 @@ public class PolicyController { private String toPolicyIdsJson(Collection policies) { List v = new ArrayList<>(policies.size()); for (Policy p : policies) { - v.add(p.id()); + v.add(p.getId()); } return gson.toJson(new PolicyIdList(v)); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java index d3ff999a..a1106192 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java @@ -150,17 +150,16 @@ public class ServiceController { } } + @DeleteMapping(Consts.V2_API_ROOT + "/services/{service_id:.+}") @Operation(summary = "Unregister a service") @ApiResponses(value = { // @ApiResponse(responseCode = "204", description = "Service unregistered"), - @ApiResponse(responseCode = "200", description = "Not used", + @ApiResponse(responseCode = "200", description = "Not used", // content = @Content(schema = @Schema(implementation = VoidResponse.class))), - @ApiResponse(responseCode = "404", description = "Service not found", + @ApiResponse(responseCode = "404", description = "Service not found", // content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) }) - - @DeleteMapping(Consts.V2_API_ROOT + "/services/{service_id:.+}") public ResponseEntity deleteService(// @PathVariable("service_id") String serviceId) { try { diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java index 56765232..bc67e663 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java @@ -25,13 +25,10 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; -import com.google.gson.TypeAdapterFactory; import java.time.Duration; import java.util.ArrayList; import java.util.List; -import java.util.Optional; -import java.util.ServiceLoader; import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClient; import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClientFactory; @@ -115,7 +112,6 @@ public class DmaapMessageConsumer { public DmaapMessageConsumer(ApplicationConfig applicationConfig) { this.applicationConfig = applicationConfig; GsonBuilder gsonBuilder = new GsonBuilder(); - ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory); this.gson = gsonBuilder.create(); this.restClientFactory = new AsyncRestClientFactory(applicationConfig.getWebClientConfig()); } @@ -199,12 +195,12 @@ public class DmaapMessageConsumer { protected Mono sendErrorResponse(String response) { logger.debug("sendErrorResponse {}", response); - DmaapRequestMessage fakeRequest = ImmutableDmaapRequestMessage.builder() // + DmaapRequestMessage fakeRequest = DmaapRequestMessage.builder() // .apiVersion("") // .correlationId("") // .operation(DmaapRequestMessage.Operation.PUT) // .originatorId("") // - .payload(Optional.empty()) // + .payload(null) // .requestId("") // .target("") // .timestamp("") // diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageHandler.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageHandler.java index c77087a5..d0354174 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageHandler.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageHandler.java @@ -24,8 +24,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; -import java.util.Optional; - import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClient; import org.onap.ccsdk.oran.a1policymanagementservice.dmaap.DmaapRequestMessage.Operation; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; @@ -89,8 +87,8 @@ public class DmaapMessageHandler { } private Mono> invokePolicyManagementService(DmaapRequestMessage dmaapRequestMessage) { - DmaapRequestMessage.Operation operation = dmaapRequestMessage.operation(); - String uri = dmaapRequestMessage.url(); + DmaapRequestMessage.Operation operation = dmaapRequestMessage.getOperation(); + String uri = dmaapRequestMessage.getUrl(); if (operation == Operation.DELETE) { return pmsClient.deleteForEntity(uri); @@ -106,9 +104,9 @@ public class DmaapMessageHandler { } private String payload(DmaapRequestMessage message) { - Optional payload = message.payload(); - if (payload.isPresent()) { - return gson.toJson(payload.get()); + JsonObject payload = message.getPayload(); + if (payload != null) { + return gson.toJson(payload); } else { logger.warn("Expected payload in message from DMAAP: {}", message); return ""; @@ -127,14 +125,16 @@ public class DmaapMessageHandler { private Mono createDmaapResponseMessage(DmaapRequestMessage dmaapRequestMessage, String response, HttpStatus status) { - DmaapResponseMessage dmaapResponseMessage = ImmutableDmaapResponseMessage.builder() // + DmaapResponseMessage dmaapResponseMessage = DmaapResponseMessage.builder() // .status(status.toString()) // .message(response == null ? "" : response) // .type("response") // - .correlationId(dmaapRequestMessage.correlationId() == null ? "" : dmaapRequestMessage.correlationId()) // - .originatorId(dmaapRequestMessage.originatorId() == null ? "" : dmaapRequestMessage.originatorId()) // - .requestId(dmaapRequestMessage.requestId() == null ? "" : dmaapRequestMessage.requestId()) // - .timestamp(dmaapRequestMessage.timestamp() == null ? "" : dmaapRequestMessage.timestamp()) // + .correlationId( + dmaapRequestMessage.getCorrelationId() == null ? "" : dmaapRequestMessage.getCorrelationId()) // + .originatorId( + dmaapRequestMessage.getOriginatorId() == null ? "" : dmaapRequestMessage.getOriginatorId()) // + .requestId(dmaapRequestMessage.getRequestId() == null ? "" : dmaapRequestMessage.getRequestId()) // + .timestamp(dmaapRequestMessage.getTimestamp() == null ? "" : dmaapRequestMessage.getTimestamp()) // .build(); String str = gson.toJson(dmaapResponseMessage); return Mono.just(str); diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapRequestMessage.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapRequestMessage.java index f41c51c5..10dc981e 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapRequestMessage.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapRequestMessage.java @@ -22,34 +22,34 @@ package org.onap.ccsdk.oran.a1policymanagementservice.dmaap; import com.google.gson.JsonObject; -import java.util.Optional; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; -import org.immutables.gson.Gson; -import org.immutables.value.Value; - -@Value.Immutable -@Gson.TypeAdapters -public interface DmaapRequestMessage { +@Getter +@Builder +@EqualsAndHashCode +public class DmaapRequestMessage { public enum Operation { PUT, GET, DELETE, POST } - String correlationId(); + String correlationId; - String target(); + String target; - String timestamp(); + String timestamp; - String apiVersion(); + String apiVersion; - String originatorId(); + String originatorId; - String requestId(); + String requestId; - Operation operation(); + Operation operation; - String url(); + String url; - Optional payload(); + JsonObject payload; } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapResponseMessage.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapResponseMessage.java index 04024742..64778551 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapResponseMessage.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapResponseMessage.java @@ -20,24 +20,26 @@ package org.onap.ccsdk.oran.a1policymanagementservice.dmaap; -import org.immutables.gson.Gson; -import org.immutables.value.Value; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; -@Value.Immutable -@Gson.TypeAdapters -public interface DmaapResponseMessage { +@Getter +@Builder +@EqualsAndHashCode +public class DmaapResponseMessage { - String type(); + String type; - String correlationId(); + String correlationId; - String timestamp(); + String timestamp; - String originatorId(); + String originatorId; - String requestId(); + String requestId; - String status(); + String status; - String message(); + String message; } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/MultiMap.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/MultiMap.java new file mode 100644 index 00000000..ff09ba3a --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/MultiMap.java @@ -0,0 +1,65 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2019-2020 Nordix Foundation. 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.ccsdk.oran.a1policymanagementservice.repository; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +/** + * A map, where each key can be bound to may values (where each value has an own + * ID) + */ +public class MultiMap { + + private final Map> map = new HashMap<>(); + + public void put(String key, String id, T value) { + this.map.computeIfAbsent(key, k -> new HashMap<>()).put(id, value); + } + + public T remove(String key, String id) { + Map innerMap = this.map.get(key); + if (innerMap != null) { + T removedElement = innerMap.remove(id); + if (innerMap.isEmpty()) { + this.map.remove(key); + } + return removedElement; + } + return null; + } + + public Collection get(String key) { + Map innerMap = this.map.get(key); + if (innerMap == null) { + return Collections.emptyList(); + } + return new Vector<>(innerMap.values()); + } + + public void clear() { + this.map.clear(); + } + +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java index 882d3368..a24c5bd0 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java @@ -20,48 +20,72 @@ package org.onap.ccsdk.oran.a1policymanagementservice.repository; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.invoke.MethodHandles; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Instant; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Vector; -import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; +import lombok.Builder; +import lombok.Getter; +import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig; +import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; +import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.FileSystemUtils; + +@Configuration public class Policies { - private Map policiesId = new HashMap<>(); - private Map> policiesRic = new HashMap<>(); - private Map> policiesService = new HashMap<>(); - private Map> policiesType = new HashMap<>(); - public synchronized void put(Policy policy) { - policiesId.put(policy.id(), policy); - multiMapPut(policiesRic, policy.ric().id(), policy); - multiMapPut(policiesService, policy.ownerServiceId(), policy); - multiMapPut(policiesType, policy.type().id(), policy); + @Getter + @Builder + private static class PersistentPolicyInfo { + private String id; + private String json; + private String ownerServiceId; + private String ricId; + private String typeId; + private String statusNotificationUri; + private boolean isTransient; + private String lastModified; } - private void multiMapPut(Map> multiMap, String key, Policy value) { - multiMap.computeIfAbsent(key, k -> new HashMap<>()).put(value.id(), value); - } + private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private Map policiesId = new HashMap<>(); + private MultiMap policiesRic = new MultiMap<>(); + private MultiMap policiesService = new MultiMap<>(); + private MultiMap policiesType = new MultiMap<>(); - private void multiMapRemove(Map> multiMap, String key, Policy value) { - Map map = multiMap.get(key); - if (map != null) { - map.remove(value.id()); - if (map.isEmpty()) { - multiMap.remove(key); - } - } + private final ApplicationConfig appConfig; + private static Gson gson = new GsonBuilder().create(); + + public Policies(@Autowired ApplicationConfig appConfig) { + this.appConfig = appConfig; } - private Collection multiMapGet(Map> multiMap, String key) { - Map map = multiMap.get(key); - if (map == null) { - return Collections.emptyList(); + public synchronized void put(Policy policy) { + policiesId.put(policy.getId(), policy); + policiesRic.put(policy.getRic().id(), policy.getId(), policy); + policiesService.put(policy.getOwnerServiceId(), policy.getId(), policy); + policiesType.put(policy.getType().getId(), policy.getId(), policy); + if (this.appConfig.getVardataDirectory() != null && !policy.isTransient()) { + store(policy); } - return new Vector<>(map.values()); } public synchronized boolean containsPolicy(String id) { @@ -85,15 +109,15 @@ public class Policies { } public synchronized Collection getForService(String service) { - return multiMapGet(policiesService, service); + return policiesService.get(service); } public synchronized Collection getForRic(String ric) { - return multiMapGet(policiesRic, ric); + return policiesRic.get(ric); } public synchronized Collection getForType(String type) { - return multiMapGet(policiesType, type); + return policiesType.get(type); } public synchronized Policy removeId(String id) { @@ -105,10 +129,17 @@ public class Policies { } public synchronized void remove(Policy policy) { - policiesId.remove(policy.id()); - multiMapRemove(policiesRic, policy.ric().id(), policy); - multiMapRemove(policiesService, policy.ownerServiceId(), policy); - multiMapRemove(policiesType, policy.type().id(), policy); + if (!policy.isTransient()) { + try { + Files.delete(getPath(policy)); + } catch (IOException | ServiceException e) { + logger.debug("Could not delete policy from database: {}", e.getMessage()); + } + } + policiesId.remove(policy.getId()); + policiesRic.remove(policy.getRic().id(), policy.getId()); + policiesService.remove(policy.getOwnerServiceId(), policy.getId()); + policiesType.remove(policy.getType().getId(), policy.getId()); } public synchronized void removePoliciesForRic(String ricId) { @@ -127,5 +158,90 @@ public class Policies { Set keys = policiesId.keySet(); removeId(keys.iterator().next()); } + try { + if (this.appConfig.getVardataDirectory() != null) { + FileSystemUtils.deleteRecursively(getDatabasePath()); + } + } catch (IOException | ServiceException e) { + logger.warn("Could not delete policy database : {}", e.getMessage()); + } + } + + public void store(Policy policy) { + try { + Files.createDirectories(getDatabasePath(policy.getRic())); + try (PrintStream out = new PrintStream(new FileOutputStream(getFile(policy)))) { + out.print(gson.toJson(toStorageObject(policy))); + } + } catch (Exception e) { + logger.warn("Could not store policy: {} {}", policy.getId(), e.getMessage()); + } + } + + private File getFile(Policy policy) throws ServiceException { + return getPath(policy).toFile(); + } + + private Path getPath(Policy policy) throws ServiceException { + return Path.of(getDatabaseDirectory(policy.getRic()), policy.getId() + ".json"); + } + + public void restoreFromDatabase(Ric ric, PolicyTypes types) { + + try { + Files.createDirectories(getDatabasePath(ric)); + for (File file : getDatabasePath(ric).toFile().listFiles()) { + String json = Files.readString(file.toPath()); + PersistentPolicyInfo policyStorage = gson.fromJson(json, PersistentPolicyInfo.class); + this.put(toPolicy(policyStorage, ric, types)); + } + } catch (ServiceException | IOException e) { + logger.warn("Could not restore policy database for RIC: {}, reason : {}", ric.id(), e.getMessage()); + } + } + + private PersistentPolicyInfo toStorageObject(Policy p) { + return PersistentPolicyInfo.builder() // + .id(p.getId()) // + .json(p.getJson()) // + .ownerServiceId(p.getOwnerServiceId()) // + .ricId(p.getRic().id()) // + .statusNotificationUri(p.getStatusNotificationUri()) // + .typeId(p.getType().getId()) // + .isTransient(p.isTransient()) // + .lastModified(p.getLastModified().toString()) // + .build(); + } + + Policy toPolicy(PersistentPolicyInfo p, Ric ric, PolicyTypes types) throws EntityNotFoundException { + return Policy.builder() // + .id(p.getId()) // + .isTransient(p.isTransient()) // + .json(p.getJson()) // + .lastModified(Instant.parse(p.lastModified)) // + .ownerServiceId(p.getOwnerServiceId()) // + .ric(ric) // + .statusNotificationUri(p.getStatusNotificationUri()) // + .type(types.getType(p.getTypeId())) // + .build(); + } + + private Path getDatabasePath(Ric ric) throws ServiceException { + return Path.of(getDatabaseDirectory(ric)); + } + + private String getDatabaseDirectory(Ric ric) throws ServiceException { + return getDatabaseDirectory() + "/" + ric.id(); + } + + private String getDatabaseDirectory() throws ServiceException { + if (appConfig.getVardataDirectory() == null) { + throw new ServiceException("No database storage provided"); + } + return appConfig.getVardataDirectory() + "/database/policyInstances"; + } + + private Path getDatabasePath() throws ServiceException { + return Path.of(getDatabaseDirectory()); } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policy.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policy.java index efafa684..bdf16320 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policy.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policy.java @@ -22,25 +22,25 @@ package org.onap.ccsdk.oran.a1policymanagementservice.repository; import java.time.Instant; -import org.immutables.gson.Gson; -import org.immutables.value.Value; +import lombok.Builder; +import lombok.Getter; -@Value.Immutable -@Gson.TypeAdapters -public interface Policy { - public String id(); +@Getter +@Builder +public class Policy { + private String id; - public String json(); + private String json; - public String ownerServiceId(); + private String ownerServiceId; - public Ric ric(); + private Ric ric; - public PolicyType type(); + private PolicyType type; - public Instant lastModified(); + private Instant lastModified; - public boolean isTransient(); + private boolean isTransient; - public String statusNotificationUri(); + private String statusNotificationUri; } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyType.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyType.java index f2c6254e..9fbae6dd 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyType.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyType.java @@ -20,13 +20,13 @@ package org.onap.ccsdk.oran.a1policymanagementservice.repository; -import org.immutables.gson.Gson; -import org.immutables.value.Value; +import lombok.Builder; +import lombok.Getter; -@Value.Immutable -@Gson.TypeAdapters -public interface PolicyType { - public String id(); +@Getter +@Builder +public class PolicyType { + private String id; - public String schema(); + private String schema; } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyTypes.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyTypes.java index 7bf03782..76f0e216 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyTypes.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyTypes.java @@ -20,15 +20,41 @@ package org.onap.ccsdk.oran.a1policymanagementservice.repository; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.invoke.MethodHandles; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Vector; +import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; +import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.FileSystemUtils; +@Configuration public class PolicyTypes { + private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private Map types = new HashMap<>(); + private final ApplicationConfig appConfig; + private static Gson gson = new GsonBuilder().create(); + + public PolicyTypes(@Autowired ApplicationConfig appConfig) { + this.appConfig = appConfig; + restoreFromDatabase(); + } public synchronized PolicyType getType(String name) throws EntityNotFoundException { PolicyType t = types.get(name); @@ -43,7 +69,8 @@ public class PolicyTypes { } public synchronized void put(PolicyType type) { - types.put(type.id(), type); + types.put(type.getId(), type); + store(type); } public synchronized boolean contains(String policyType) { @@ -60,5 +87,54 @@ public class PolicyTypes { public synchronized void clear() { this.types.clear(); + try { + FileSystemUtils.deleteRecursively(getDatabasePath()); + } catch (IOException | ServiceException e) { + logger.warn("Could not delete policy type database : {}", e.getMessage()); + } + } + + public void store(PolicyType type) { + try { + Files.createDirectories(getDatabasePath()); + try (PrintStream out = new PrintStream(new FileOutputStream(getFile(type)))) { + out.print(gson.toJson(type)); + } + } catch (ServiceException e) { + logger.debug("Could not store policy type: {} {}", type.getId(), e.getMessage()); + } catch (IOException e) { + logger.warn("Could not store policy type: {} {}", type.getId(), e.getMessage()); + } + } + + private File getFile(PolicyType type) throws ServiceException { + return Path.of(getDatabaseDirectory(), type.getId() + ".json").toFile(); + } + + void restoreFromDatabase() { + try { + Files.createDirectories(getDatabasePath()); + for (File file : getDatabasePath().toFile().listFiles()) { + String json = Files.readString(file.toPath()); + PolicyType type = gson.fromJson(json, PolicyType.class); + this.types.put(type.getId(), type); + } + + } catch (IOException e) { + logger.warn("Could not restore policy type database : {}", e.getMessage()); + } catch (ServiceException e) { + logger.debug("Could not restore policy type database : {}", e.getMessage()); + } + } + + private String getDatabaseDirectory() throws ServiceException { + if (appConfig.getVardataDirectory() == null) { + throw new ServiceException("No policy type storage provided"); + } + return appConfig.getVardataDirectory() + "/database/policyTypes"; + } + + private Path getDatabasePath() throws ServiceException { + return Path.of(getDatabaseDirectory()); } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Ric.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Ric.java index c7f471eb..9c4b2750 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Ric.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Ric.java @@ -110,7 +110,7 @@ public class Ric { * @param type the policy type to support. */ public synchronized void addSupportedPolicyType(PolicyType type) { - supportedPolicyTypes.put(type.id(), type); + supportedPolicyTypes.put(type.getId(), type); } /** diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java index 29d2e4eb..771dea52 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java @@ -226,6 +226,9 @@ public class RefreshConfigTask { private void addRic(RicConfig config) { Ric ric = new Ric(config); this.rics.put(ric); + if (this.appConfig.getVardataDirectory() != null) { + this.policies.restoreFromDatabase(ric, this.policyTypes); + } runRicSynchronization(ric); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSynchronizationTask.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSynchronizationTask.java index b38a36b2..19222377 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSynchronizationTask.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSynchronizationTask.java @@ -26,7 +26,6 @@ import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1Client; import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.ServiceCallbacks; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.ImmutablePolicyType; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock.LockType; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; @@ -177,7 +176,7 @@ public class RicSynchronizationTask { } private Mono createPolicyType(String policyTypeId, String schema) { - PolicyType pt = ImmutablePolicyType.builder().id(policyTypeId).schema(schema).build(); + PolicyType pt = PolicyType.builder().id(policyTypeId).schema(schema).build(); policyTypes.put(pt); return Mono.just(pt); } @@ -189,7 +188,7 @@ public class RicSynchronizationTask { } private Flux putPolicy(Policy policy, Ric ric, A1Client a1Client) { - logger.debug("Recreating policy: {}, for ric: {}", policy.id(), ric.getConfig().ricId()); + logger.debug("Recreating policy: {}, for ric: {}", policy.getId(), ric.getConfig().ricId()); return a1Client.putPolicy(policy) // .flatMapMany(notUsed -> Flux.just(policy)); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/ServiceSupervision.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/ServiceSupervision.java index 4c063e2d..d605b69e 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/ServiceSupervision.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/ServiceSupervision.java @@ -91,15 +91,15 @@ public class ServiceSupervision { @SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally private Flux deletePolicy(Policy policy) { - Lock lock = policy.ric().getLock(); + Lock lock = policy.getRic().getLock(); return lock.lock(LockType.SHARED) // .doOnNext(notUsed -> policies.remove(policy)) // .flatMap(notUsed -> deletePolicyInRic(policy)) .doOnNext(notUsed -> logger.debug("Policy deleted due to service inactivity: {}, service: {}", - policy.id(), policy.ownerServiceId())) // + policy.getId(), policy.getOwnerServiceId())) // .doOnNext(notUsed -> lock.unlockBlocking()) // .doOnError(throwable -> lock.unlockBlocking()) // - .doOnError(throwable -> logger.debug("Failed to delete inactive policy: {}, reason: {}", policy.id(), + .doOnError(throwable -> logger.debug("Failed to delete inactive policy: {}, reason: {}", policy.getId(), throwable.getMessage())) // .flatMapMany(notUsed -> Flux.just(policy)) // .onErrorResume(throwable -> Flux.empty()); @@ -110,14 +110,14 @@ public class ServiceSupervision { } private Mono deletePolicyInRic(Policy policy) { - return a1ClientFactory.createA1Client(policy.ric()) // + return a1ClientFactory.createA1Client(policy.getRic()) // .flatMap(client -> client.deletePolicy(policy) // .onErrorResume(exception -> handleDeleteFromRicFailure(policy, exception)) // .map(nothing -> policy)); } private Mono handleDeleteFromRicFailure(Policy policy, Throwable e) { - logger.warn("Could not delete policy: {} from ric: {}. Cause: {}", policy.id(), policy.ric().id(), + logger.warn("Could not delete policy: {} from ric: {}. Cause: {}", policy.getId(), policy.getRic().id(), e.getMessage()); return Mono.empty(); } -- cgit 1.2.3-korg