Added callback to R-APPS invoked after RIC recovery 12/2212/2
authorPatrikBuhr <patrik.buhr@est.tech>
Tue, 14 Jan 2020 08:00:57 +0000 (09:00 +0100)
committerPatrikBuhr <patrik.buhr@est.tech>
Tue, 14 Jan 2020 09:48:54 +0000 (10:48 +0100)
Improved error handling in dashboard
Improved error handling in agent NBI
Added ?policyTypeId= in the A1 API
Added a callback to R-APPS invoked when RIC instances has been deleted
or when RIC policy types has changed.

Issue-ID: NONRTRIC-84
Change-Id: I04a4b514fce45e249364bd03813a7afb93320a07
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
23 files changed:
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/PolicyController.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/policyagentapi/PolicyAgentApi.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/policyagentapi/PolicyAgentApiImpl.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/PolicyControllerMockConfiguration.java
policy-agent/src/main/java/org/oransc/policyagent/clients/A1Client.java
policy-agent/src/main/java/org/oransc/policyagent/clients/A1ClientImpl.java
policy-agent/src/main/java/org/oransc/policyagent/controllers/PolicyController.java
policy-agent/src/main/java/org/oransc/policyagent/controllers/ServiceController.java
policy-agent/src/main/java/org/oransc/policyagent/controllers/ServiceRegistrationInfo.java
policy-agent/src/main/java/org/oransc/policyagent/repository/Service.java
policy-agent/src/main/java/org/oransc/policyagent/repository/Services.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/RepositorySupervision.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/RicRecoveryTask.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/StartupService.java
policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java
policy-agent/src/test/java/org/oransc/policyagent/MockPolicyAgent.java
policy-agent/src/test/java/org/oransc/policyagent/clients/A1ClientImplTest.java
policy-agent/src/test/java/org/oransc/policyagent/tasks/RepositorySupervisionTest.java
policy-agent/src/test/java/org/oransc/policyagent/tasks/StartupServiceTest.java
policy-agent/src/test/java/org/oransc/policyagent/utils/MockA1Client.java [new file with mode: 0644]
policy-agent/src/test/resources/policy_types/demo-policy-schema-1.json
policy-agent/src/test/resources/policy_types/demo-policy-schema-3.json
policy-agent/src/test/resources/test_application_configuration.json

index 410ad1d..529cd2a 100644 (file)
@@ -41,6 +41,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.annotation.Secured;
 import org.springframework.util.Assert;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -96,7 +97,7 @@ public class PolicyController {
        @ApiOperation(value = "Gets the policy types from Near Realtime-RIC")
        @GetMapping(POLICY_TYPES_METHOD)
        @Secured({ DashboardConstants.ROLE_ADMIN, DashboardConstants.ROLE_STANDARD })
-       public PolicyTypes getAllPolicyTypes(HttpServletResponse response) {
+       public ResponseEntity<PolicyTypes> getAllPolicyTypes(HttpServletResponse response) {
                logger.debug("getAllPolicyTypes");
                return this.policyAgentApi.getAllPolicyTypes();
        }
@@ -104,19 +105,22 @@ public class PolicyController {
        @ApiOperation(value = "Returns the policy instances for the given policy type.")
        @GetMapping(POLICY_TYPES_METHOD + "/{" + POLICY_TYPE_ID_NAME + "}/" + POLICIES_NAME)
        @Secured({ DashboardConstants.ROLE_ADMIN, DashboardConstants.ROLE_STANDARD })
-       public String getPolicyInstances(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString) {
+       public ResponseEntity<String> getPolicyInstances(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString) {
                logger.debug("getPolicyInstances {}", policyTypeIdString);
 
-               PolicyInstances i = this.policyAgentApi.getPolicyInstancesForType(policyTypeIdString);
-               String json = gson.toJson(i);
-               return json;
+               ResponseEntity<PolicyInstances> response = this.policyAgentApi.getPolicyInstancesForType(policyTypeIdString);
+               if (!response.getStatusCode().is2xxSuccessful()) {
+                       return new ResponseEntity<>(response.getStatusCode());
+               }
+               String json = gson.toJson(response.getBody());
+               return new ResponseEntity<>(json, response.getStatusCode());
        }
 
        @ApiOperation(value = "Returns a policy instance of a type")
        @GetMapping(POLICY_TYPES_METHOD + "/{" + POLICY_TYPE_ID_NAME + "}/" + POLICIES_NAME + "/{" + POLICY_INSTANCE_ID_NAME
                        + "}")
        @Secured({ DashboardConstants.ROLE_ADMIN, DashboardConstants.ROLE_STANDARD })
-       public String getPolicyInstance(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString,
+       public ResponseEntity<String> getPolicyInstance(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString,
                        @PathVariable(POLICY_INSTANCE_ID_NAME) String policyInstanceId) {
                logger.debug("getPolicyInstance {}:{}", policyTypeIdString, policyInstanceId);
                return this.policyAgentApi.getPolicyInstance(policyInstanceId);
@@ -126,12 +130,12 @@ public class PolicyController {
        @PutMapping(POLICY_TYPES_METHOD + "/{" + POLICY_TYPE_ID_NAME + "}/" + POLICIES_NAME + "/{" + POLICY_INSTANCE_ID_NAME
                        + "}")
        @Secured({ DashboardConstants.ROLE_ADMIN })
-       public void putPolicyInstance(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString,
+       public ResponseEntity<String> putPolicyInstance(@PathVariable(POLICY_TYPE_ID_NAME) String policyTypeIdString,
                        @RequestParam(name = "ric", required = true) String ric,
                        @PathVariable(POLICY_INSTANCE_ID_NAME) String policyInstanceId, @RequestBody String instance) {
                logger.debug("putPolicyInstance typeId: {}, instanceId: {}, instance: {}", policyTypeIdString, policyInstanceId,
                                instance);
-               this.policyAgentApi.putPolicy(policyTypeIdString, policyInstanceId, instance, ric);
+               return this.policyAgentApi.putPolicy(policyTypeIdString, policyInstanceId, instance, ric);
        }
 
        @ApiOperation(value = "Deletes the policy instances for the given policy type.")
@@ -164,13 +168,16 @@ public class PolicyController {
        @ApiOperation(value = "Returns the rics supporting the given policy type.")
        @GetMapping("/rics")
        @Secured({ DashboardConstants.ROLE_ADMIN, DashboardConstants.ROLE_STANDARD })
-       public String getRicsSupportingType(
+       public ResponseEntity<String> getRicsSupportingType(
                        @RequestParam(name = "policyType", required = true) String supportingPolicyType) {
                logger.debug("getRicsSupportingType {}", supportingPolicyType);
 
-               Collection<String> result = this.policyAgentApi.getRicsSupportingType(supportingPolicyType);
-               String json = gson.toJson(result);
-               return json;
+               ResponseEntity<Collection<String>> result = this.policyAgentApi.getRicsSupportingType(supportingPolicyType);
+               if (!result.getStatusCode().is2xxSuccessful()) {
+                       return new ResponseEntity<>(result.getStatusCode());
+               }
+               String json = gson.toJson(result.getBody());
+               return new ResponseEntity<>(json, result.getStatusCode());
        }
 
 };
index 144a77a..47add76 100644 (file)
@@ -23,21 +23,22 @@ import java.util.Collection;
 
 import org.oransc.ric.portal.dashboard.model.PolicyInstances;
 import org.oransc.ric.portal.dashboard.model.PolicyTypes;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.client.RestClientException;
 
 public interface PolicyAgentApi {
 
-    public PolicyTypes getAllPolicyTypes() throws RestClientException;
+    public ResponseEntity<PolicyTypes> getAllPolicyTypes() throws RestClientException;
 
-    public PolicyInstances getPolicyInstancesForType(String type);
+    public ResponseEntity<PolicyInstances> getPolicyInstancesForType(String type);
 
-    public String getPolicyInstance(String id) throws RestClientException;
+    public ResponseEntity<String> getPolicyInstance(String id) throws RestClientException;
 
-    public void putPolicy(String policyTypeIdString, String policyInstanceId, String json, String ric)
+    public ResponseEntity<String> putPolicy(String policyTypeIdString, String policyInstanceId, String json, String ric)
             throws RestClientException;
 
     public void deletePolicy(String policyInstanceId) throws RestClientException;
 
-    public Collection<String> getRicsSupportingType(String typeName);
+    public ResponseEntity<Collection<String>> getRicsSupportingType(String typeName);
 
 }
index d83023b..eb3f836 100644 (file)
@@ -26,7 +26,8 @@ import org.oransc.ric.portal.dashboard.model.PolicyInstances;
 import org.oransc.ric.portal.dashboard.model.PolicyType;
 import org.oransc.ric.portal.dashboard.model.PolicyTypes;
 import org.springframework.beans.factory.annotation.Autowired;
-
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestClientException;
 import org.springframework.web.client.RestTemplate;
@@ -84,13 +85,16 @@ public class PolicyAgentApiImpl implements PolicyAgentApi {
     }
 
     @Override
-    public PolicyTypes getAllPolicyTypes() throws RestClientException {
+    public ResponseEntity<PolicyTypes> getAllPolicyTypes() throws RestClientException {
         String url = baseUrl() + "/policy_schemas";
-        String rsp = this.restTemplate.getForObject(url, String.class);
+        ResponseEntity<String> rsp = this.restTemplate.getForEntity(url, String.class);
+        if (!rsp.getStatusCode().is2xxSuccessful()) {
+            return new ResponseEntity<>(rsp.getStatusCode());
+        }
 
         PolicyTypes result = new PolicyTypes();
         JsonParser jsonParser = new JsonParser();
-        JsonArray schemas = jsonParser.parse(rsp).getAsJsonArray();
+        JsonArray schemas = jsonParser.parse(rsp.getBody()).getAsJsonArray();
         for (JsonElement schema : schemas) {
             JsonObject schemaObj = schema.getAsJsonObject();
             String title = schemaObj.get("title").getAsString();
@@ -98,36 +102,39 @@ public class PolicyAgentApiImpl implements PolicyAgentApi {
             PolicyType pt = new PolicyType(title, schemaAsStr);
             result.add(pt);
         }
-        return result;
+        return new ResponseEntity<>(result, rsp.getStatusCode());
     }
 
     @Override
-    public PolicyInstances getPolicyInstancesForType(String type) {
+    public ResponseEntity<PolicyInstances> getPolicyInstancesForType(String type) {
         String url = baseUrl() + "/policies?type={type}";
         Map<String, ?> uriVariables = Map.of("type", type);
-        String rsp = this.restTemplate.getForObject(url, String.class, uriVariables);
+        ResponseEntity<String> rsp = this.restTemplate.getForEntity(url, String.class, uriVariables);
+        if (!rsp.getStatusCode().is2xxSuccessful()) {
+            return new ResponseEntity<>(rsp.getStatusCode());
+        }
 
         Type listType = new TypeToken<List<ImmutablePolicyInfo>>() {
         }.getType();
-        List<PolicyInfo> rspParsed = gson.fromJson(rsp, listType);
+        List<PolicyInfo> rspParsed = gson.fromJson(rsp.getBody(), listType);
 
         PolicyInstances result = new PolicyInstances();
         for (PolicyInfo p : rspParsed) {
             result.add(p);
         }
-        return result;
+        return new ResponseEntity<>(result, rsp.getStatusCode());
     }
 
     @Override
-    public String getPolicyInstance(String id) throws RestClientException {
+    public ResponseEntity<String> getPolicyInstance(String id) throws RestClientException {
         String url = baseUrl() + "/policy?instance={id}";
         Map<String, ?> uriVariables = Map.of("id", id);
 
-        return this.restTemplate.getForObject(url, String.class, uriVariables);
+        return this.restTemplate.getForEntity(url, String.class, uriVariables);
     }
 
     @Override
-    public void putPolicy(String policyTypeIdString, String policyInstanceId, String json, String ric)
+    public ResponseEntity<String> putPolicy(String policyTypeIdString, String policyInstanceId, String json, String ric)
             throws RestClientException {
         String url = baseUrl() + "/policy?type={type}&instance={instance}&ric={ric}&service={service}";
         Map<String, ?> uriVariables = Map.of( //
@@ -136,7 +143,12 @@ public class PolicyAgentApiImpl implements PolicyAgentApi {
                 "ric", ric, //
                 "service", "dashboard");
 
-        this.restTemplate.put(url, json, uriVariables);
+        try {
+            this.restTemplate.put(url, json, uriVariables);
+            return new ResponseEntity<>(HttpStatus.OK);
+        } catch (Exception e) {
+            return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
+        }
     }
 
     @Override
@@ -157,7 +169,7 @@ public class PolicyAgentApiImpl implements PolicyAgentApi {
     }
 
     @Override
-    public Collection<String> getRicsSupportingType(String typeName) {
+    public ResponseEntity<Collection<String>> getRicsSupportingType(String typeName) {
         String url = baseUrl() + "/rics?policyType={typeName}";
         Map<String, ?> uriVariables = Map.of("typeName", typeName);
         String rsp = this.restTemplate.getForObject(url, String.class, uriVariables);
@@ -170,7 +182,7 @@ public class PolicyAgentApiImpl implements PolicyAgentApi {
         for (RicInfo ric : rspParsed) {
             result.add(ric.name());
         }
-        return result;
+        return new ResponseEntity<>(result, HttpStatus.OK);
     }
 
 }
index 44d0b5c..e073ef6 100644 (file)
@@ -42,6 +42,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.test.context.TestConfiguration;
 import org.springframework.context.annotation.Bean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.client.RestClientException;
 
 /**
@@ -62,14 +64,15 @@ public class PolicyControllerMockConfiguration {
                private final Database database = new Database();
 
                @Override
-               public String getPolicyInstance(String id) throws RestClientException {
-                       return database.getInstance(id);
+               public ResponseEntity<String> getPolicyInstance(String id) throws RestClientException {
+                       return new ResponseEntity<>(database.getInstance(id), HttpStatus.OK);
                }
 
                @Override
-               public void putPolicy(String policyTypeIdString, String policyInstanceId, String json, String ric)
-                               throws RestClientException {
+               public ResponseEntity<String> putPolicy(String policyTypeIdString, String policyInstanceId, String json,
+                               String ric) throws RestClientException {
                        database.putInstance(policyTypeIdString, policyInstanceId, json, ric);
+                       return new ResponseEntity<>(HttpStatus.OK);
                }
 
                @Override
@@ -78,27 +81,27 @@ public class PolicyControllerMockConfiguration {
                }
 
                @Override
-               public PolicyTypes getAllPolicyTypes() throws RestClientException {
+               public ResponseEntity<PolicyTypes> getAllPolicyTypes() throws RestClientException {
                        PolicyTypes result = new PolicyTypes();
                        result.addAll(database.getTypes());
-                       return result;
+                       return new ResponseEntity<>(result, HttpStatus.OK);
                }
 
                @Override
-               public PolicyInstances getPolicyInstancesForType(String type) {
+               public ResponseEntity<PolicyInstances> getPolicyInstancesForType(String type) {
                        PolicyInstances result = new PolicyInstances();
                        List<PolicyInfo> inst = database.getInstances(Optional.of(type));
                        result.addAll(inst);
-                       return result;
+                       return new ResponseEntity<>(result, HttpStatus.OK);
                }
 
                @Override
-               public Collection<String> getRicsSupportingType(String typeName) {
+               public ResponseEntity<Collection<String>> getRicsSupportingType(String typeName) {
                        Vector<String> res = new Vector<>();
                        res.add("ric_1");
                        res.add("ric_2");
                        res.add("ric_3");
-                       return res;
+                       return new ResponseEntity<>(res, HttpStatus.OK);
                }
        }
 
index bc6d7cd..8d244ee 100644 (file)
@@ -22,6 +22,7 @@ package org.oransc.policyagent.clients;
 
 import java.util.Collection;
 
+import org.oransc.policyagent.repository.Policy;
 import reactor.core.publisher.Mono;
 
 public interface A1Client {
@@ -32,7 +33,7 @@ public interface A1Client {
 
     public Mono<String> getPolicyType(String nearRtRicUrl, String policyTypeId);
 
-    public Mono<String> putPolicy(String nearRtRicUrl, String policyId, String policyString);
+    public Mono<String> putPolicy(Policy policy);
 
     public Mono<String> deletePolicy(String nearRtRicUrl, String policyId);
 
index b3773b8..e576638 100644 (file)
@@ -28,6 +28,7 @@ import java.util.List;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.oransc.policyagent.repository.Policy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import reactor.core.publisher.Mono;
@@ -39,7 +40,7 @@ public class A1ClientImpl implements A1Client {
         return nearRtRicUrl + "/A1-P/v1";
     }
 
-    public AsyncRestClient createClient(final String nearRtRicUrl) {
+    protected AsyncRestClient createClient(final String nearRtRicUrl) {
         return new AsyncRestClient(getBaseUrl(nearRtRicUrl));
     }
 
@@ -68,11 +69,15 @@ public class A1ClientImpl implements A1Client {
     }
 
     @Override
-    public Mono<String> putPolicy(String nearRtRicUrl, String policyId, String policyString) {
-        logger.debug("putPolicy nearRtRicUrl = {}, policyId = {}, policyString = {}", nearRtRicUrl, policyId,
-            policyString);
-        AsyncRestClient client = createClient(nearRtRicUrl);
-        Mono<String> response = client.put("/policies/" + policyId, policyString);
+    public Mono<String> putPolicy(Policy policy) {
+        logger.debug("putPolicy nearRtRicUrl = {}, policyId = {}, policyString = {}", //
+            policy.ric().getConfig().baseUrl(), policy.id(), policy.json());
+        AsyncRestClient client = createClient(policy.ric().getConfig().baseUrl());
+        // TODO update when simulator is updated to include policy type
+        // Mono<String> response = client.put("/policies/" + policy.id() + "?policyTypeId=" + policy.type().name(),
+        // policy.json());
+        Mono<String> response = client.put("/policies/" + policy.id(), policy.json());
+
         return response.flatMap(this::createMono);
     }
 
index 6d849b1..e33fb7e 100644 (file)
@@ -172,7 +172,7 @@ public class PolicyController {
                 .ownerServiceName(service) //
                 .lastModified(getTimeStampUTC()) //
                 .build();
-            return a1Client.putPolicy(policy.ric().getConfig().baseUrl(), policy.id(), policy.json()) //
+            return a1Client.putPolicy(policy) //
                 .doOnNext(notUsed -> policies.put(policy)) //
                 .flatMap(notUsed -> {
                     return Mono.just(new ResponseEntity<>(HttpStatus.CREATED));
index 6831d4c..ad06231 100644 (file)
@@ -86,7 +86,7 @@ public class ServiceController {
     }
 
     private Service toService(ServiceRegistrationInfo s) {
-        return new Service(s.name(), Duration.ofSeconds(s.keepAliveInterval()));
+        return new Service(s.name(), Duration.ofSeconds(s.keepAliveInterval()), s.callbackUrl());
     }
 
     @GetMapping("/services")
index 81ef7ff..6458dbb 100644 (file)
@@ -27,11 +27,12 @@ public class Service {
     private final String name;
     private final Duration keepAliveInterval;
     private Instant lastPing;
-    // private final String callbackUrl1; // TBD
+    private final String callbackUrl;
 
-    public Service(String name, Duration keepAliveInterval) {
+    public Service(String name, Duration keepAliveInterval, String callbackUrl) {
         this.name = name;
         this.keepAliveInterval = keepAliveInterval;
+        this.callbackUrl = callbackUrl;
         ping();
     }
 
@@ -55,4 +56,8 @@ public class Service {
         return Duration.between(this.lastPing, Instant.now());
     }
 
+    public synchronized String getCallbackUrl() {
+        return this.callbackUrl;
+    }
+
 }
index 509b2f5..35cae71 100644 (file)
@@ -50,9 +50,12 @@ public class Services {
 
     public synchronized void put(Service service) {
         logger.debug("Put service: " + service.getName());
+        // TODO a threading problem is that this may happend at the same time as someone is iterating (getAll())
+        // This is a generic problem
         services.put(service.getName(), service);
     }
 
+    // TODO the returned value should be unmodifiable if possible
     public synchronized Collection<Service> getAll() {
         return services.values();
     }
index 9ac9d70..bfd40e5 100644 (file)
@@ -27,6 +27,7 @@ import org.oransc.policyagent.repository.Policies;
 import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Ric;
 import org.oransc.policyagent.repository.Rics;
+import org.oransc.policyagent.repository.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -49,13 +50,16 @@ public class RepositorySupervision {
     private final Policies policies;
     private final PolicyTypes policyTypes;
     private final A1Client a1Client;
+    private final Services services;
 
     @Autowired
-    public RepositorySupervision(Rics rics, Policies policies, A1Client a1Client, PolicyTypes policyTypes) {
+    public RepositorySupervision(Rics rics, Policies policies, A1Client a1Client, PolicyTypes policyTypes,
+        Services services) {
         this.rics = rics;
         this.policies = policies;
         this.a1Client = a1Client;
         this.policyTypes = policyTypes;
+        this.services = services;
     }
 
     /**
@@ -81,10 +85,6 @@ public class RepositorySupervision {
             .flatMap(ricP -> validateInstances(ricP, ric));
     }
 
-    private Flux<Ric> junk() {
-        return Flux.empty();
-    }
-
     private Mono<Ric> validateInstances(Collection<String> ricPolicies, Ric ric) {
         if (ricPolicies.size() != policies.getForRic(ric.name()).size()) {
             return startRecovery(ric);
@@ -118,7 +118,7 @@ public class RepositorySupervision {
     }
 
     private Mono<Ric> startRecovery(Ric ric) {
-        RicRecoveryTask recovery = new RicRecoveryTask(a1Client, policyTypes, policies);
+        RicRecoveryTask recovery = new RicRecoveryTask(a1Client, policyTypes, policies, services);
         recovery.run(ric);
         return Mono.empty();
     }
index 3883585..73c94e2 100644 (file)
@@ -24,6 +24,7 @@ import java.util.Collection;
 import java.util.Vector;
 
 import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.AsyncRestClient;
 import org.oransc.policyagent.exceptions.ServiceException;
 import org.oransc.policyagent.repository.ImmutablePolicyType;
 import org.oransc.policyagent.repository.Policies;
@@ -31,6 +32,8 @@ import org.oransc.policyagent.repository.Policy;
 import org.oransc.policyagent.repository.PolicyType;
 import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Ric;
+import org.oransc.policyagent.repository.Service;
+import org.oransc.policyagent.repository.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,11 +50,13 @@ public class RicRecoveryTask {
     private final A1Client a1Client;
     private final PolicyTypes policyTypes;
     private final Policies policies;
+    private final Services services;
 
-    public RicRecoveryTask(A1Client a1Client, PolicyTypes policyTypes, Policies policies) {
+    public RicRecoveryTask(A1Client a1Client, PolicyTypes policyTypes, Policies policies, Services services) {
         this.a1Client = a1Client;
         this.policyTypes = policyTypes;
         this.policies = policies;
+        this.services = services;
     }
 
     public void run(Collection<Ric> rics) {
@@ -81,14 +86,31 @@ public class RicRecoveryTask {
     private void onComplete(Ric ric) {
         logger.debug("Recovery completed for:" + ric.name());
         ric.setState(Ric.RicState.ACTIVE);
+        notifyAllServices("Recovery completed for:" + ric.name());
+    }
 
+    private void notifyAllServices(String body) {
+        for (Service service : services.getAll()) {
+            String url = service.getCallbackUrl();
+            if (service.getCallbackUrl().length() > 0) {
+                createClient(url) //
+                    .put("", body) //
+                    .subscribe(rsp -> logger.debug("Service called"),
+                        throwable -> logger.warn("Service called failed", throwable),
+                        () -> logger.debug("Service called complete"));
+            }
+        }
     }
 
     private void onError(Ric ric, Throwable t) {
-        logger.debug("Recovery failed for: {}, reason: {}", ric.name(), t.getMessage());
+        logger.warn("Recovery failed for: {}, reason: {}", ric.name(), t.getMessage());
         ric.setState(Ric.RicState.NOT_REACHABLE);
     }
 
+    private AsyncRestClient createClient(final String url) {
+        return new AsyncRestClient(url);
+    }
+
     private Flux<PolicyType> recoverPolicyTypes(Ric ric) {
         ric.clearSupportedPolicyTypes();
         return a1Client.getPolicyTypeIdentities(ric.getConfig().baseUrl()) //
index d2356ea..251f343 100644 (file)
@@ -27,6 +27,7 @@ import org.oransc.policyagent.repository.Policies;
 import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Ric;
 import org.oransc.policyagent.repository.Rics;
+import org.oransc.policyagent.repository.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -55,13 +56,18 @@ public class StartupService {
     @Autowired
     private Policies policies;
 
+    @Autowired
+    private Services services;
+
+    // Only for unittesting
     StartupService(ApplicationConfig appConfig, Rics rics, PolicyTypes policyTypes, A1Client a1Client,
-        Policies policies) {
+        Policies policies, Services services) {
         this.applicationConfig = appConfig;
         this.rics = rics;
         this.policyTypes = policyTypes;
         this.a1Client = a1Client;
         this.policies = policies;
+        this.services = services;
     }
 
     /**
@@ -73,7 +79,7 @@ public class StartupService {
         for (RicConfig ricConfig : applicationConfig.getRicConfigs()) {
             rics.put(new Ric(ricConfig));
         }
-        RicRecoveryTask recoveryTask = new RicRecoveryTask(a1Client, policyTypes, policies);
+        RicRecoveryTask recoveryTask = new RicRecoveryTask(a1Client, policyTypes, policies, services);
         recoveryTask.run(rics.getRics()); // recover all Rics
     }
 
index 365d418..e9dcaef 100644 (file)
@@ -29,7 +29,6 @@ import com.google.gson.GsonBuilder;
 import com.google.gson.reflect.TypeToken;
 
 import java.net.URL;
-import java.util.Collection;
 import java.util.List;
 import java.util.Vector;
 
@@ -52,6 +51,7 @@ import org.oransc.policyagent.repository.PolicyType;
 import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Ric;
 import org.oransc.policyagent.repository.Rics;
+import org.oransc.policyagent.utils.MockA1Client;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@@ -63,7 +63,6 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 import org.springframework.web.client.RestTemplate;
-import reactor.core.publisher.Mono;
 
 @ExtendWith(SpringExtension.class)
 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@@ -92,49 +91,6 @@ public class ApplicationTest {
         }
     }
 
-    static class A1ClientMock implements A1Client {
-        private final Policies policies;
-        private final PolicyTypes policyTypes;
-
-        A1ClientMock(Policies policies, PolicyTypes policyTypes) {
-            this.policies = policies;
-            this.policyTypes = policyTypes;
-        }
-
-        @Override
-        public Mono<Collection<String>> getPolicyTypeIdentities(String nearRtRicUrl) {
-            Vector<String> result = new Vector<>();
-            for (PolicyType p : this.policyTypes.getAll()) {
-                result.add(p.name());
-            }
-            return Mono.just(result);
-        }
-
-        @Override
-        public Mono<String> getPolicyType(String nearRtRicUrl, String policyTypeId) {
-            try {
-                return Mono.just(this.policies.get(policyTypeId).json());
-            } catch (Exception e) {
-                return Mono.error(e);
-            }
-        }
-
-        @Override
-        public Mono<String> putPolicy(String nearRtRicUrl, String policyId, String policyString) {
-            return Mono.just("OK");
-        }
-
-        @Override
-        public Mono<String> deletePolicy(String nearRtRicUrl, String policyId) {
-            return Mono.just("OK");
-        }
-
-        @Override
-        public Mono<Collection<String>> getPolicyIdentities(String nearRtRicUrl) {
-            return Mono.empty(); // problem is that a recovery will start
-        }
-    }
-
     /**
      * Overrides the BeanFactory.
      */
@@ -151,7 +107,7 @@ public class ApplicationTest {
 
         @Bean
         A1Client getA1Client() {
-            return new A1ClientMock(this.policies, this.policyTypes);
+            return new MockA1Client(this.policyTypes);
         }
 
         @Bean
@@ -397,6 +353,7 @@ public class ApplicationTest {
         ServiceRegistrationInfo service = ImmutableServiceRegistrationInfo.builder() //
             .keepAliveInterval(1) //
             .name(name) //
+            .callbackUrl("callbackUrl") //
             .build();
         String json = gson.toJson(service);
         return json;
index dd57710..420c8f7 100644 (file)
@@ -27,10 +27,6 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 import java.nio.file.Files;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Vector;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -41,28 +37,18 @@ import org.oransc.policyagent.repository.Policies;
 import org.oransc.policyagent.repository.PolicyType;
 import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Rics;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.oransc.policyagent.utils.MockA1Client;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 import org.springframework.boot.test.context.TestConfiguration;
 import org.springframework.boot.web.server.LocalServerPort;
 import org.springframework.context.annotation.Bean;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
-import reactor.core.publisher.Mono;
 
 @ExtendWith(SpringExtension.class)
 @SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
 public class MockPolicyAgent {
 
-    @Autowired
-    private Rics rics;
-
-    @Autowired
-    private Policies policies;
-
-    @Autowired
-    private PolicyTypes policyTypes;
-
     static class MockApplicationConfig extends ApplicationConfig {
 
         @Override
@@ -72,72 +58,42 @@ public class MockPolicyAgent {
         }
     }
 
-    private static class RicPolicyDatabase {
-        private Map<String, Map<String, String>> policies = new HashMap<>();
-
-        public void putPolicy(String nearRtRicUrl, String policyId, String policyString) {
-            getPolicies(nearRtRicUrl).put(policyId, policyString);
-        }
-
-        public Collection<String> getPolicyIdentities(String nearRtRicUrl) {
-            return getPolicies(nearRtRicUrl).keySet();
-        }
-
-        public void deletePolicy(String nearRtRicUrl, String policyId) {
-            getPolicies(nearRtRicUrl).remove(policyId);
-        }
-
-        private Map<String, String> getPolicies(String nearRtRicUrl) {
-            if (!policies.containsKey(nearRtRicUrl)) {
-                policies.put(nearRtRicUrl, new HashMap<>());
-            }
-            return policies.get(nearRtRicUrl);
-        }
-    }
-
-    static class A1ClientMock implements A1Client {
+    /**
+     * overrides the BeanFactory
+     */
+    @TestConfiguration
+    static class TestBeanFactory {
 
-        private final RicPolicyDatabase policies = new RicPolicyDatabase();
+        private final Rics rics = new Rics();
+        private final Policies policies = new Policies();
         private final PolicyTypes policyTypes = new PolicyTypes();
 
-        A1ClientMock() {
-            loadTypes(this.policyTypes);
-        }
-
-        @Override
-        public Mono<Collection<String>> getPolicyTypeIdentities(String nearRtRicUrl) {
-            Vector<String> result = new Vector<>();
-            for (PolicyType p : this.policyTypes.getAll()) {
-                result.add(p.name());
-            }
-            return Mono.just(result);
+        @Bean
+        public ApplicationConfig getApplicationConfig() {
+            return new MockApplicationConfig();
         }
 
-        @Override
-        public Mono<Collection<String>> getPolicyIdentities(String nearRtRicUrl) {
-            Collection<String> result = policies.getPolicyIdentities(nearRtRicUrl);
-            return Mono.just(result);
+        @Bean
+        public A1Client getA1Client() {
+            PolicyTypes ricTypes = new PolicyTypes();
+            loadTypes(ricTypes);
+            A1Client client = new MockA1Client(ricTypes);
+            return client;
         }
 
-        @Override
-        public Mono<String> getPolicyType(String nearRtRicUrl, String policyTypeId) {
-            try {
-                return Mono.just(this.policyTypes.getType(policyTypeId).schema());
-            } catch (Exception e) {
-                return Mono.error(e);
-            }
+        @Bean
+        public Policies getPolicies() {
+            return this.policies;
         }
 
-        @Override
-        public Mono<String> putPolicy(String nearRtRicUrl, String policyId, String policyString) {
-            policies.putPolicy(nearRtRicUrl, policyId, policyString);
-            return Mono.just("OK");
+        @Bean
+        public PolicyTypes getPolicyTypes() {
+            return this.policyTypes;
         }
 
-        @Override
-        public Mono<String> deletePolicy(String nearRtRicUrl, String policyId) {
-            policies.deletePolicy(nearRtRicUrl, policyId);
-            return Mono.just("OK");
+        @Bean
+        public Rics getRics() {
+            return this.rics;
         }
 
         private static File[] getResourceFolderFiles(String folder) {
@@ -164,42 +120,7 @@ public class MockPolicyAgent {
                 }
             }
         }
-    }
-
-    /**
-     * overrides the BeanFactory
-     */
-    @TestConfiguration
-    static class TestBeanFactory {
-
-        private final Rics rics = new Rics();
-        private final Policies policies = new Policies();
-        private final PolicyTypes policyTypes = new PolicyTypes();
-
-        @Bean
-        public ApplicationConfig getApplicationConfig() {
-            return new MockApplicationConfig();
-        }
-
-        @Bean
-        A1Client getA1Client() {
-            return new A1ClientMock();
-        }
-
-        @Bean
-        public Policies getPolicies() {
-            return this.policies;
-        }
 
-        @Bean
-        public PolicyTypes getPolicyTypes() {
-            return this.policyTypes;
-        }
-
-        @Bean
-        public Rics getRics() {
-            return this.rics;
-        }
     }
 
     @LocalServerPort
index f9a93c8..b3b5f48 100644 (file)
 
 package org.oransc.policyagent.clients;
 
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.util.Arrays;
+import java.util.Vector;
 
 import org.json.JSONException;
 import org.junit.jupiter.api.BeforeEach;
@@ -35,6 +37,13 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.mockito.junit.jupiter.MockitoExtension;
+import org.oransc.policyagent.configuration.ImmutableRicConfig;
+import org.oransc.policyagent.configuration.RicConfig;
+import org.oransc.policyagent.repository.ImmutablePolicy;
+import org.oransc.policyagent.repository.ImmutablePolicyType;
+import org.oransc.policyagent.repository.Policy;
+import org.oransc.policyagent.repository.PolicyType;
+import org.oransc.policyagent.repository.Ric;
 
 import reactor.core.publisher.Mono;
 import reactor.test.StepVerifier;
@@ -56,6 +65,7 @@ public class A1ClientImplTest {
     private static final String POLICY_2_ID = "policy2";
     private static final String POLICY_JSON_VALID = "{\"policyId\":\"policy1\"}";
     private static final String POLICY_JSON_INVALID = "\"policyId\":\"policy1\"}";
+    private static final String POLICY_TYPE = "typeName";
 
     @Spy
     A1ClientImpl a1Client;
@@ -111,24 +121,46 @@ public class A1ClientImplTest {
 
     @Test
     public void testPutPolicyValidResponse() {
-        when(asyncRestClientMock.put(POLICIES_URL + POLICY_1_ID, POLICY_JSON_VALID))
-            .thenReturn(Mono.just(POLICY_JSON_VALID));
+        when(asyncRestClientMock.put(anyString(), anyString())).thenReturn(Mono.just(POLICY_JSON_VALID));
 
-        Mono<String> policyMono = a1Client.putPolicy(RIC_URL, POLICY_1_ID, POLICY_JSON_VALID);
+        Mono<String> policyMono =
+            a1Client.putPolicy(createPolicy(RIC_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE));
         verify(asyncRestClientMock).put(POLICIES_URL + POLICY_1_ID, POLICY_JSON_VALID);
         StepVerifier.create(policyMono).expectNext(POLICY_JSON_VALID).expectComplete().verify();
     }
 
     @Test
     public void testPutPolicyInvalidResponse() {
-        when(asyncRestClientMock.put(POLICIES_URL + POLICY_1_ID, POLICY_JSON_VALID))
-            .thenReturn(Mono.just(POLICY_JSON_INVALID));
+        when(asyncRestClientMock.put(anyString(), anyString())).thenReturn(Mono.just(POLICY_JSON_INVALID));
 
-        Mono<String> policyMono = a1Client.putPolicy(RIC_URL, POLICY_1_ID, POLICY_JSON_VALID);
-        verify(asyncRestClientMock).put(POLICIES_URL + POLICY_1_ID, POLICY_JSON_VALID);
+        Mono<String> policyMono =
+            a1Client.putPolicy(createPolicy(RIC_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE));
         StepVerifier.create(policyMono).expectErrorMatches(throwable -> throwable instanceof JSONException).verify();
     }
 
+    private Policy createPolicy(String nearRtRicUrl, String policyId, String json, String type) {
+        return ImmutablePolicy.builder() //
+            .id(policyId) //
+            .json(json) //
+            .ownerServiceName("service") //
+            .ric(createRic(nearRtRicUrl)) //
+            .type(createPolicyType(type)) //
+            .lastModified("now") //
+            .build();
+    }
+
+    private PolicyType createPolicyType(String name) {
+        return ImmutablePolicyType.builder().name(name).schema("schema").build();
+    }
+
+    private Ric createRic(String url) {
+        RicConfig cfg = ImmutableRicConfig.builder().name("ric") //
+            .baseUrl(url) //
+            .managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
+            .build();
+        return new Ric(cfg);
+    }
+
     @Test
     public void testDeletePolicy() {
         when(asyncRestClientMock.delete(POLICIES_URL + POLICY_1_ID)).thenReturn(Mono.empty());
index 791acee..418680e 100644 (file)
@@ -47,6 +47,7 @@ import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Ric;
 import org.oransc.policyagent.repository.Ric.RicState;
 import org.oransc.policyagent.repository.Rics;
+import org.oransc.policyagent.repository.Services;
 import reactor.core.publisher.Mono;
 
 @ExtendWith(MockitoExtension.class)
@@ -94,8 +95,10 @@ public class RepositorySupervisionTest {
         Policies policies = new Policies();
         policies.put(policy1);
         PolicyTypes types = new PolicyTypes();
+        Services services = new Services();
 
-        RepositorySupervision supervisorUnderTest = new RepositorySupervision(rics, policies, a1ClientMock, types);
+        RepositorySupervision supervisorUnderTest =
+            new RepositorySupervision(rics, policies, a1ClientMock, types, services);
 
         Mono<Collection<String>> policyIds = Mono.just(Arrays.asList("policyId1", "policyId2"));
         when(a1ClientMock.getPolicyIdentities(anyString())).thenReturn(policyIds);
index 0c254d5..2ee175d 100644 (file)
@@ -50,6 +50,7 @@ import org.oransc.policyagent.repository.Policies;
 import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Ric;
 import org.oransc.policyagent.repository.Rics;
+import org.oransc.policyagent.repository.Services;
 import reactor.core.publisher.Mono;
 
 @ExtendWith(MockitoExtension.class)
@@ -92,7 +93,7 @@ public class StartupServiceTest {
         Rics rics = new Rics();
         PolicyTypes policyTypes = new PolicyTypes();
         StartupService serviceUnderTest =
-            new StartupService(appConfigMock, rics, policyTypes, a1ClientMock, new Policies());
+            new StartupService(appConfigMock, rics, policyTypes, a1ClientMock, new Policies(), new Services());
 
         serviceUnderTest.startup();
 
@@ -157,7 +158,7 @@ public class StartupServiceTest {
         Rics rics = new Rics();
         PolicyTypes policyTypes = new PolicyTypes();
         StartupService serviceUnderTest =
-            new StartupService(appConfigMock, rics, policyTypes, a1ClientMock, new Policies());
+            new StartupService(appConfigMock, rics, policyTypes, a1ClientMock, new Policies(), new Services());
 
         serviceUnderTest.startup();
 
@@ -188,7 +189,7 @@ public class StartupServiceTest {
         Rics rics = new Rics();
         PolicyTypes policyTypes = new PolicyTypes();
         StartupService serviceUnderTest =
-            new StartupService(appConfigMock, rics, policyTypes, a1ClientMock, new Policies());
+            new StartupService(appConfigMock, rics, policyTypes, a1ClientMock, new Policies(), new Services());
 
         serviceUnderTest.startup();
 
diff --git a/policy-agent/src/test/java/org/oransc/policyagent/utils/MockA1Client.java b/policy-agent/src/test/java/org/oransc/policyagent/utils/MockA1Client.java
new file mode 100644 (file)
index 0000000..1a93b4d
--- /dev/null
@@ -0,0 +1,92 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 Nordix Foundation
+ * %%
+ * 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.oransc.policyagent.utils;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.repository.Policies;
+import org.oransc.policyagent.repository.Policy;
+import org.oransc.policyagent.repository.PolicyType;
+import org.oransc.policyagent.repository.PolicyTypes;
+import reactor.core.publisher.Mono;
+
+public class MockA1Client implements A1Client {
+    private final Map<String, Policies> policies = new HashMap<>();
+    private final PolicyTypes policyTypes;
+
+    public MockA1Client(PolicyTypes policyTypes) {
+        this.policyTypes = policyTypes;
+    }
+
+    @Override
+    public Mono<Collection<String>> getPolicyTypeIdentities(String nearRtRicUrl) {
+        Vector<String> result = new Vector<>();
+        for (PolicyType p : this.policyTypes.getAll()) {
+            result.add(p.name());
+        }
+        return Mono.just(result);
+    }
+
+    @Override
+    public Mono<Collection<String>> getPolicyIdentities(String nearRtRicUrl) {
+        Vector<String> result = new Vector<>();
+        for (Policy policy : getPolicies(nearRtRicUrl).getAll()) {
+            if (policy.ric().getConfig().baseUrl().equals(nearRtRicUrl)) {
+                result.add(policy.id());
+            }
+        }
+
+        return Mono.just(result);
+    }
+
+    @Override
+    public Mono<String> getPolicyType(String nearRtRicUrl, String policyTypeId) {
+        try {
+            return Mono.just(this.policyTypes.getType(policyTypeId).schema());
+        } catch (Exception e) {
+            return Mono.error(e);
+        }
+    }
+
+    @Override
+    public Mono<String> putPolicy(Policy p) {
+        getPolicies(p.ric().getConfig().baseUrl()).put(p);
+        return Mono.just("OK");
+    }
+
+    @Override
+    public Mono<String> deletePolicy(String nearRtRicUrl, String policyId) {
+        getPolicies(nearRtRicUrl).removeId(policyId);
+        return Mono.just("OK");
+    }
+
+    private Policies getPolicies(String url) {
+        if (!policies.containsKey(url)) {
+            policies.put(url, new Policies());
+        }
+        return policies.get(url);
+    }
+
+}
index fa7410f..02bc864 100644 (file)
@@ -1,42 +1,71 @@
 {
   "$schema": "http://json-schema.org/draft-07/schema#",
-  "title": "Example_QoSTarget_1.0.0",
-  "description": "Example QoS Target policy type",
+  "title": "STD_PolicyModelUnconstrained_0.2.0",
+  "description": "Standard model of a policy with unconstrained scope id combinations",
   "type": "object",
   "properties": {
     "scope": {
       "type": "object",
       "properties": {
-        "qosId": {
-          "type": "string"
-        },
-        "cellId": {
-          "type": "string"
-        }
+        "ueId": {"type": "string"},
+        "groupId": {"type": "string"},
+        "sliceId": {"type": "string"},
+        "qosId": {"type": "string"},
+        "cellId": {"type": "string"}
       },
-      "additionalProperties": false,
-      "required": [
-        "qosId"
-      ]
+      "minProperties": 1,
+      "additionalProperties": false
     },
-    "statement": {
+    "qosObjectives": {
       "type": "object",
       "properties": {
-        "gfbr": {
-          "type": "number"
-        },
-        "mfbr": {
-          "type": "number"
-        },
-        "priorityLevel": {
-          "type": "number"
-        },
-        "pdb": {
-          "type": "number"
-        }
+        "gfbr": {"type": "number"},
+        "mfbr": {"type": "number"},
+        "priorityLevel": {"type": "number"},
+        "pdb": {"type": "number"}
       },
-      "minProperties": 1,
       "additionalProperties": false
+    },
+    "qoeObjectives": {
+      "type": "object",
+      "properties": {
+        "qoeScore": {"type": "number"},
+        "initialBuffering": {"type": "number"},
+        "reBuffFreq": {"type": "number"},
+        "stallRatio": {"type": "number"}
+      },
+      "additionalProperties": false
+    },
+    "resources": {
+      "type": "array",
+      "items": {
+        "type": "object",
+        "properties": {
+          "cellIdList": {
+            "type": "array",
+            "minItems": 1,
+            "uniqueItems": true,
+            "items": {
+              "type": "string"
+            }
+          },
+          "preference": {
+            "type": "string",
+            "enum": [
+              "SHALL",
+              "PREFER",
+              "AVOID",
+              "FORBID"
+            ]
+          },
+          "primary": {"type": "boolean"}
+        },
+        "additionalProperties": false,
+        "required": ["cellIdList", "preference"]
+      }
     }
-  }
-}
\ No newline at end of file
+  },
+  "minProperties": 2,
+  "additionalProperties": false,
+  "required": ["scope"]
+}
index 695514c..a73dd59 100644 (file)
@@ -1,59 +1,27 @@
 {
   "$schema": "http://json-schema.org/draft-07/schema#",
-  "title": "Example_TrafficSteeringPreference_1.0.0",
-  "description": "Example QoE Target policy type",
+  "title": "ERIC_QoSNudging_0.2.0",
+  "description": "QoS nudging policy type with priorityLevel and ueId and qosId as scope",
   "type": "object",
   "properties": {
     "scope": {
       "type": "object",
       "properties": {
-        "ueId": {
-          "type": "string"
-        },
-        "sliceId": {
-          "type": "string"
-        },
-        "qosId": {
-          "type": "string"
-        },
-        "cellId": {
-          "type": "string"
-        }
+        "ueId": {"type": "string"},
+        "qosId": {"type": "string"}
       },
       "additionalProperties": false,
-      "required": [
-        "ueId"
-      ]
+      "required": ["ueId", "qosId"]
     },
-    "statement": {
+    "qosObjectives": {
       "type": "object",
       "properties": {
-        "cellIdList": {
-          "type": "array",
-          "minItems": 1,
-          "uniqueItems": true,
-          "items": {
-            "type": "string"
-          }
-        },
-        "preference": {
-          "type": "string",
-          "enum": [
-            "SHALL",
-            "PREFER",
-            "AVOID",
-            "FORBID"
-          ]
-        },
-        "primary": {
-          "type": "boolean"
-        }
+        "priorityLevel": {"type": "number"}
       },
-      "required": [
-        "cellIdList",
-        "preference"
-      ],
-      "additionalProperties": false
+      "additionalProperties": false,
+      "required": ["priorityLevel"]
     }
-  }
-}
\ No newline at end of file
+  },
+  "additionalProperties": false,
+  "required": ["scope", "qosObjectives"]
+}
index 7033c4a..924b1dd 100644 (file)
@@ -9,7 +9,15 @@
                "kista_1",
                "kista_2"
             ]
+         },
+         {
+            "name": "ric2",
+            "baseUrl": "http://localhost:8081/",
+            "managedElementIds": [
+               "kista_3",
+               "kista_4"
+            ]
          }
       ]
    }
-}
\ No newline at end of file
+}