import java.util.List;
import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.configuration.ApplicationConfig;
import org.oransc.policyagent.exceptions.ServiceException;
import org.oransc.policyagent.repository.ImmutablePolicy;
+import org.oransc.policyagent.repository.Lock.LockType;
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 org.oransc.policyagent.repository.Ric;
import org.oransc.policyagent.repository.Rics;
+import org.oransc.policyagent.repository.Service;
+import org.oransc.policyagent.repository.Services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import reactor.core.publisher.Mono;
@RestController
-@Api(value = "Policy Management API")
+@Api(tags = "A1 Policy Management")
public class PolicyController {
- private final Rics rics;
- private final PolicyTypes policyTypes;
- private final Policies policies;
- private final A1ClientFactory a1ClientFactory;
+ @Autowired
+ private Rics rics;
+ @Autowired
+ private PolicyTypes policyTypes;
+ @Autowired
+ private Policies policies;
+ @Autowired
+ private A1ClientFactory a1ClientFactory;
+ @Autowired
+ private Services services;
private static Gson gson = new GsonBuilder() //
.serializeNulls() //
.create(); //
- @Autowired
- PolicyController(ApplicationConfig config, PolicyTypes types, Policies policies, Rics rics,
- A1ClientFactory a1ClientFactory) {
- this.policyTypes = types;
- this.policies = policies;
- this.rics = rics;
- this.a1ClientFactory = a1ClientFactory;
- }
-
@GetMapping("/policy_schemas")
@ApiOperation(value = "Returns policy type schema definitions")
@ApiResponses(
value = {
- @ApiResponse(code = 200, message = "Policy schemas", response = Object.class, responseContainer = "List")})
+ @ApiResponse(code = 200, message = "Policy schemas", response = Object.class, responseContainer = "List"), //
+ @ApiResponse(code = 404, message = "RIC is not found", response = String.class)})
public ResponseEntity<String> getPolicySchemas(@RequestParam(name = "ric", required = false) String ricName) {
synchronized (this.policyTypes) {
if (ricName == null) {
@GetMapping("/policy_schema")
@ApiOperation(value = "Returns one policy type schema definition")
- @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy schema", response = Object.class)})
+ @ApiResponses(
+ value = { //
+ @ApiResponse(code = 200, message = "Policy schema", response = Object.class),
+ @ApiResponse(code = 404, message = "RIC is not found", response = String.class)})
public ResponseEntity<String> getPolicySchema(@RequestParam(name = "id", required = true) String id) {
try {
PolicyType type = policyTypes.getType(id);
@GetMapping("/policy_types")
@ApiOperation(value = "Query policy type names")
@ApiResponses(
- value = {@ApiResponse(
- code = 200,
- message = "Policy type names",
- response = String.class,
- responseContainer = "List")})
+ value = {
+ @ApiResponse(
+ code = 200,
+ message = "Policy type names",
+ response = String.class,
+ responseContainer = "List"),
+ @ApiResponse(code = 404, message = "RIC is not found", response = String.class)})
public ResponseEntity<String> getPolicyTypes(@RequestParam(name = "ric", required = false) String ricName) {
synchronized (this.policyTypes) {
if (ricName == null) {
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "Policy found", response = Object.class), //
- @ApiResponse(code = 204, message = "Policy is not found")} //
+ @ApiResponse(code = 404, message = "Policy is not found")} //
)
public ResponseEntity<String> getPolicy( //
@RequestParam(name = "instance", required = true) String instance) {
Policy p = policies.getPolicy(instance);
return new ResponseEntity<>(p.json(), HttpStatus.OK);
} catch (ServiceException e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NO_CONTENT);
+ return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}
@DeleteMapping("/policy")
@ApiOperation(value = "Delete a policy", response = Object.class)
- @ApiResponses(value = {@ApiResponse(code = 204, message = "Policy deleted", response = Object.class)})
- public Mono<ResponseEntity<Void>> deletePolicy( //
+ @ApiResponses(
+ value = { //
+ @ApiResponse(code = 204, message = "Policy deleted", response = Object.class),
+ @ApiResponse(code = 404, message = "Policy is not found", response = String.class),
+ @ApiResponse(code = 423, message = "RIC is locked", response = String.class)})
+ public Mono<ResponseEntity<Object>> deletePolicy( //
@RequestParam(name = "instance", required = true) String id) {
- Policy policy = policies.get(id);
- if (policy != null && policy.ric().getState() == Ric.RicState.IDLE) {
- policies.remove(policy);
- return a1ClientFactory.createA1Client(policy.ric()) //
+ Policy policy;
+ try {
+ policy = policies.getPolicy(id);
+ keepServiceAlive(policy.ownerServiceName());
+ if (policy.ric().getState() != Ric.RicState.IDLE) {
+ return Mono.just(new ResponseEntity<>("Busy, recovering", HttpStatus.LOCKED));
+ }
+ Ric ric = policy.ric();
+ return ric.getLock().lock(LockType.SHARED) // //
+ .flatMap(lock -> a1ClientFactory.createA1Client(policy.ric())) //
+ .doOnNext(notUsed -> policies.remove(policy)) //
.flatMap(client -> client.deletePolicy(policy)) //
+ .doOnNext(notUsed -> ric.getLock().unlockBlocking()) //
+ .doOnError(notUsed -> ric.getLock().unlockBlocking()) //
.flatMap(notUsed -> Mono.just(new ResponseEntity<>(HttpStatus.NO_CONTENT)));
- } else {
+ } catch (ServiceException e) {
return Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
}
@PutMapping(path = "/policy")
@ApiOperation(value = "Put a policy", response = String.class)
- @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy created or updated")})
- public Mono<ResponseEntity<String>> putPolicy( //
+ @ApiResponses(
+ value = { //
+ @ApiResponse(code = 201, message = "Policy created", response = Object.class), //
+ @ApiResponse(code = 200, message = "Policy updated", response = Object.class), //
+ @ApiResponse(code = 423, message = "RIC is locked", response = String.class), //
+ @ApiResponse(code = 404, message = "RIC or policy type is not found", response = String.class), //
+ @ApiResponse(code = 405, message = "Change is not allowed", response = String.class)})
+ public Mono<ResponseEntity<Object>> putPolicy( //
@RequestParam(name = "type", required = true) String typeName, //
@RequestParam(name = "instance", required = true) String instanceId, //
@RequestParam(name = "ric", required = true) String ricName, //
@RequestBody Object jsonBody) {
String jsonString = gson.toJson(jsonBody);
-
Ric ric = rics.get(ricName);
PolicyType type = policyTypes.get(typeName);
+ keepServiceAlive(service);
if (ric != null && type != null && ric.getState() == Ric.RicState.IDLE) {
Policy policy = ImmutablePolicy.builder() //
.id(instanceId) //
.lastModified(getTimeStampUtc()) //
.build();
- return validateModifiedPolicy(policy) //
- .flatMap(x -> a1ClientFactory.createA1Client(ric)) //
+ final boolean isCreate = this.policies.get(policy.id()) == null;
+
+ return ric.getLock().lock(LockType.SHARED) //
+ .flatMap(p -> validateModifiedPolicy(policy)) //
+ .flatMap(notUsed -> a1ClientFactory.createA1Client(ric)) //
.flatMap(client -> client.putPolicy(policy)) //
.doOnNext(notUsed -> policies.put(policy)) //
- .flatMap(notUsed -> Mono.just(new ResponseEntity<>(HttpStatus.OK)));
+ .doOnNext(notUsed -> ric.getLock().unlockBlocking()) //
+ .doOnError(t -> ric.getLock().unlockBlocking()) //
+ .flatMap(notUsed -> Mono.just(new ResponseEntity<>(isCreate ? HttpStatus.CREATED : HttpStatus.OK))) //
+ .onErrorResume(t -> Mono.just(new ResponseEntity<>(t.getMessage(), HttpStatus.METHOD_NOT_ALLOWED)));
}
- return Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND));
+
+ return ric == null || type == null ? Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND))
+ : Mono.just(new ResponseEntity<>(HttpStatus.LOCKED)); // Recovering
}
private Mono<Object> validateModifiedPolicy(Policy policy) {
// Check that ric is not updated
Policy current = this.policies.get(policy.id());
- if (current != null) {
- if (!current.ric().name().equals(policy.ric().name())) {
- return Mono.error(new Exception("Policy cannot change RIC or service"));
- }
+ if (current != null && !current.ric().name().equals(policy.ric().name())) {
+ return Mono.error(new Exception("Policy cannot change RIC, policyId: " + current.id() + //
+ ", RIC name: " + current.ric().name() + //
+ ", new name: " + policy.ric().name()));
}
return Mono.just("OK");
}
@ApiOperation(value = "Query policies")
@ApiResponses(
value = {
- @ApiResponse(code = 200, message = "Policies", response = PolicyInfo.class, responseContainer = "List")})
+ @ApiResponse(code = 200, message = "Policies", response = PolicyInfo.class, responseContainer = "List"),
+ @ApiResponse(code = 404, message = "RIC or type not found", response = String.class)})
public ResponseEntity<String> getPolicies( //
@RequestParam(name = "type", required = false) String type, //
@RequestParam(name = "ric", required = false) String ric, //
@RequestParam(name = "service", required = false) String service) //
{
+ if ((type != null && this.policyTypes.get(type) == null)) {
+ return new ResponseEntity<>("Policy type not found", HttpStatus.NOT_FOUND);
+ }
+ if ((ric != null && this.rics.get(ric) == null)) {
+ return new ResponseEntity<>("RIC not found", HttpStatus.NOT_FOUND);
+ }
synchronized (policies) {
Collection<Policy> result = null;
try {
policiesJson = policiesToJson(result);
} catch (ServiceException e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NO_CONTENT);
+ return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(policiesJson, HttpStatus.OK);
}
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "Policy status", response = Object.class), //
- @ApiResponse(code = 204, message = "Policy is not found", response = String.class)} //
+ @ApiResponse(code = 404, message = "Policy is not found", response = String.class)} //
)
public Mono<ResponseEntity<String>> getPolicyStatus( //
@RequestParam(name = "instance", required = true) String instance) {
.flatMap(client -> client.getPolicyStatus(policy)) //
.flatMap(status -> Mono.just(new ResponseEntity<>(status, HttpStatus.OK)));
} catch (ServiceException e) {
- return Mono.just(new ResponseEntity<>(e.getMessage(), HttpStatus.NO_CONTENT));
+ return Mono.just(new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND));
+ }
+ }
+
+ private void keepServiceAlive(String name) {
+ Service s = this.services.get(name);
+ if (s != null) {
+ s.keepAlive();
}
}