For more information about license please see the [LICENSE](LICENSE.txt) file for details.
-## O-RAN-SC ControlPanel Gateway:
-To view the policy or enrichment information in control panel gui along with Policy Management Service & Enrichment Coordinator Service you should also have nonrtric gateway because all the request from the gui is passed through this API gateway.
-To start all the necessary components,
-docker-compose -f docker-compose.yaml -f control-panel/docker-compose.yaml -f nonrtric-gateway/docker-compose.yaml -f policy-service/docker-compose.yaml -f ecs/docker-compose.yaml -f a1-sim/docker-compose.yaml up
## O-RAN-SC docker-compose files:
The docker compose file helps the user to deploy all or partial components of nonrtric with one command.
This is to generate some data into the ECS microservice
prepareDmaapMsg.sh
-This is to generate some data into the Dmaap MR, so that PMS reads message from MR
\ No newline at end of file
+This is to generate some data into the Dmaap MR, so that PMS reads message from MR
+
+## O-RAN-SC Control Panel
+
+The Non-RT RIC Control Panel is a graphical user interface that enables the user to view and manage the A1 policies in the RAN and also view producers and jobs for the Enrichement coordinator service.
+
+### O-RAN-SC Control Panel Gateway:
+
+To view the policy or enrichment information in control panel gui along with Policy Management Service & Enrichment Coordinator Service you should also have nonrtric gateway because all the request from the gui is passed through this API gateway.
+
+#### Prerequisite:
+
+Make sure to follow the section regarding sample data so there is data available to see in the interface.
+
+To start all the necessary components, run the following command:
+
+docker-compose -f docker-compose.yaml -f control-panel/docker-compose.yaml -f nonrtric-gateway/docker-compose.yaml -f policy-service/docker-compose.yaml -f ecs/docker-compose.yaml -f a1-sim/docker-compose.yaml up
\ No newline at end of file
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Job"}}},
"required": true
},
+ "description": "The job will be enabled when a producer is available",
"operationId": "putIndividualInfoJob",
"responses": {
"200": {
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
}
},
- "parameters": [{
- "schema": {"type": "string"},
- "in": "path",
- "name": "infoJobId",
- "required": true
- }],
+ "parameters": [
+ {
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoJobId",
+ "required": true
+ },
+ {
+ "schema": {
+ "default": false,
+ "type": "boolean"
+ },
+ "in": "query",
+ "name": "typeCheck",
+ "description": "when true, a validation of that the type exists and that the job matches the type schema.",
+ "required": false
+ }
+ ],
"tags": ["Data consumer"]
}
},
tags:
- Data consumer
summary: Individual data subscription job
+ description: The job will be enabled when a producer is available
operationId: putIndividualInfoJob
parameters:
- name: infoJobId
explode: false
schema:
type: string
+ - name: typeCheck
+ in: query
+ description: when true, a validation of that the type exists and that the
+ job matches the type schema.
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: boolean
+ default: false
requestBody:
content:
application/json:
public static final String INDIVIDUAL_JOB = "Individual data subscription job";
+ public static final String PUT_INDIVIDUAL_JOB_DESCRIPTION = "The job will be enabled when a producer is available";
+
public static final String INFO_TYPE_ID_PARAM = "infoTypeId";
public static final String INFO_TYPE_ID_PARAM_DESCRIPTION =
"selects subscription jobs of matching information type";
+ public static final String PERFORM_TYPE_CHECK_PARAM = "typeCheck";
+ public static final String PERFORM_TYPE_CHECK_PARAM_DESCRIPTION =
+ "when true, a validation of that the type exists and that the job matches the type schema.";
+
private ConsumerConsts() {
}
}
path = "/info-jobs/{infoJobId}", //
produces = MediaType.APPLICATION_JSON_VALUE, //
consumes = MediaType.APPLICATION_JSON_VALUE)
- @Operation(summary = ConsumerConsts.INDIVIDUAL_JOB)
+ @Operation(summary = ConsumerConsts.INDIVIDUAL_JOB, description = ConsumerConsts.PUT_INDIVIDUAL_JOB_DESCRIPTION)
@ApiResponses(
value = { //
@ApiResponse(
})
public Mono<ResponseEntity<Object>> putIndividualInfoJob( //
@PathVariable("infoJobId") String jobId, //
+ @Parameter(
+ name = ConsumerConsts.PERFORM_TYPE_CHECK_PARAM,
+ required = false, //
+ description = ConsumerConsts.PERFORM_TYPE_CHECK_PARAM_DESCRIPTION) //
+ @RequestParam(
+ name = ConsumerConsts.PERFORM_TYPE_CHECK_PARAM,
+ required = false,
+ defaultValue = "false") boolean performTypeCheck,
@RequestBody ConsumerJobInfo informationJobObject) {
final boolean isNewJob = this.jobs.get(jobId) == null;
- return validatePutInfoJob(jobId, informationJobObject) //
+ return validatePutInfoJob(jobId, informationJobObject, performTypeCheck) //
.flatMap(this::startInfoSubscriptionJob) //
.doOnNext(newEiJob -> this.jobs.put(newEiJob)) //
.flatMap(newEiJob -> Mono.just(new ResponseEntity<>(isNewJob ? HttpStatus.CREATED : HttpStatus.OK)))
.flatMap(noOfAcceptingProducers -> Mono.just(newInfoJob));
}
- private Mono<EiJob> validatePutInfoJob(String jobId, ConsumerJobInfo jobInfo) {
+ private Mono<EiJob> validatePutInfoJob(String jobId, ConsumerJobInfo jobInfo, boolean performTypeCheck) {
try {
- EiType infoType = this.infoTypes.getType(jobInfo.infoTypeId);
- validateJsonObjectAgainstSchema(infoType.getJobDataSchema(), jobInfo.jobDefinition);
+ if (performTypeCheck) {
+ EiType infoType = this.infoTypes.getType(jobInfo.infoTypeId);
+ validateJsonObjectAgainstSchema(infoType.getJobDataSchema(), jobInfo.jobDefinition);
+ }
EiJob existingEiJob = this.jobs.get(jobId);
if (existingEiJob != null && !existingEiJob.getTypeId().equals(jobInfo.infoTypeId)) {
throw new ServiceException("Not allowed to change type for existing job", HttpStatus.CONFLICT);
}
- return Mono.just(toEiJob(jobInfo, jobId, infoType));
+ return Mono.just(toEiJob(jobInfo, jobId, jobInfo.infoTypeId));
} catch (Exception e) {
return Mono.error(e);
}
}
}
- private EiJob toEiJob(ConsumerJobInfo info, String id, EiType type) {
+ private EiJob toEiJob(ConsumerJobInfo info, String id, String typeId) {
return EiJob.builder() //
.id(id) //
- .typeId(type.getId()) //
+ .typeId(typeId) //
.owner(info.owner) //
.jobData(info.jobDefinition) //
.targetUrl(info.jobResultUri) //
.build();
}
+ private EiJob toEiJob(ConsumerJobInfo info, String id, EiType type) {
+ return toEiJob(info, id, type.getId());
+ }
+
private ConsumerInfoTypeInfo toInfoTypeInfo(EiType type) {
return new ConsumerInfoTypeInfo(type.getJobDataSchema());
}
verifyJobStatus(EI_JOB_ID, "ENABLED");
}
+ @Test
+ void consumerPutInformationJob_noType() throws JsonMappingException, JsonProcessingException, ServiceException {
+ String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId?typeCheck=false";
+ String body = gson.toJson(consumerJobInfo());
+ ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
+ assertThat(this.eiJobs.size()).isEqualTo(1);
+ assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
+ verifyJobStatus(EI_JOB_ID, "DISABLED");
+
+ putEiProducerWithOneType(PRODUCER_ID, TYPE_ID);
+
+ verifyJobStatus(EI_JOB_ID, "ENABLED");
+
+ }
+
@Test
void a1ePutEiJob_jsonSchemavalidationError() throws Exception {
putEiProducerWithOneType(PRODUCER_ID, TYPE_ID);
void consumerPutJob_jsonSchemavalidationError() throws Exception {
putEiProducerWithOneType(PRODUCER_ID, TYPE_ID);
- String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId";
+ String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId?typeCheck=true";
// The element with name "property1" is mandatory in the schema
ConsumerJobInfo jobInfo = new ConsumerJobInfo("typeId", jsonObject("{ \"XXstring\" : \"value\" }"), "owner",
"targetUri", "jobStatusUrl");
-Subproject commit ab7baa0563069bc403c840b39f22a9e7e900fb72
+Subproject commit b28e811178bf9d828615f62c67f30a78c0414eb1
__create_topic $MR_WRITE_TOPIC "Topic for writing policy messages"
- __dmaap_pipeclean $MR_READ_TOPIC "/events/A1-POLICY-AGENT-READ" "/events/A1-POLICY-AGENT-READ/users/policy-agent?timeout=1000&limit=100"
+ __dmaap_pipeclean $MR_READ_TOPIC "/events/$MR_READ_TOPIC" "/events/$MR_READ_TOPIC/users/policy-agent?timeout=1000&limit=100"
- __dmaap_pipeclean $MR_WRITE_TOPIC "/events/A1-POLICY-AGENT-WRITE" "/events/A1-POLICY-AGENT-WRITE/users/mr-stub?timeout=1000&limit=100"
+ __dmaap_pipeclean $MR_WRITE_TOPIC "/events/$MR_WRITE_TOPIC" "/events/$MR_WRITE_TOPIC/users/mr-stub?timeout=1000&limit=100"
echo " Current topics:"
curlString="$MR_DMAAP_PATH/topics"
MR_STUB_LOCALHOST_PORT=3908 # MR stub container external port (host -> container)
MR_DMAAP_LOCALHOST_SECURE_PORT=3905 # MR stub container internal port (container -> container)
MR_STUB_LOCALHOST_SECURE_PORT=3909 # MR stub container external secure port (host -> container)
-MR_READ_URL="/events/A1-POLICY-AGENT-READ/users/policy-agent?timeout=15000&limit=100" # Path to read messages from MR
-MR_WRITE_URL="/events/A1-POLICY-AGENT-WRITE" # Path write messages to MR
MR_READ_TOPIC="A1-POLICY-AGENT-READ" # Read topic
MR_WRITE_TOPIC="A1-POLICY-AGENT-WRITE" # Write topic
+MR_READ_URL="/events/$MR_READ_TOPIC/users/policy-agent?timeout=15000&limit=100" # Path to read messages from MR
+MR_WRITE_URL="/events/$MR_WRITE_TOPIC" # Path to write messages to MR
MR_STUB_ALIVE_URL="/" # Base path for mr stub alive check
MR_DMAAP_ALIVE_URL="/topics" # Base path for dmaap-mr alive check
MR_DMAAP_COMPOSE_DIR="dmaapmr" # Dir in simulator_group for dmaap mr for - docker-compose
MR_STUB_LOCALHOST_PORT=3908 # MR stub container external port (host -> container)
MR_DMAAP_LOCALHOST_SECURE_PORT=3905 # MR stub container internal port (container -> container)
MR_STUB_LOCALHOST_SECURE_PORT=3909 # MR stub container external secure port (host -> container)
-MR_READ_URL="/events/A1-POLICY-AGENT-READ/users/policy-agent?timeout=15000&limit=100" # Path to read messages from MR
-MR_WRITE_URL="/events/A1-POLICY-AGENT-WRITE" # Path write messages to MR
MR_READ_TOPIC="A1-POLICY-AGENT-READ" # Read topic
MR_WRITE_TOPIC="A1-POLICY-AGENT-WRITE" # Write topic
+MR_READ_URL="/events/$MR_READ_TOPIC/users/policy-agent?timeout=15000&limit=100" # Path to read messages from MR
+MR_WRITE_URL="/events/$MR_WRITE_TOPIC" # Path to write messages to MR
MR_STUB_ALIVE_URL="/" # Base path for mr stub alive check
MR_DMAAP_ALIVE_URL="/topics" # Base path for dmaap-mr alive check
MR_DMAAP_COMPOSE_DIR="dmaapmr" # Dir in simulator_group for dmaap mr for - docker-compose
MR_STUB_LOCALHOST_PORT=3908 # MR stub container external port (host -> container)
MR_DMAAP_LOCALHOST_SECURE_PORT=3905 # MR stub container internal port (container -> container)
MR_STUB_LOCALHOST_SECURE_PORT=3909 # MR stub container external secure port (host -> container)
-MR_READ_URL="/events/A1-POLICY-AGENT-READ/users/policy-agent?timeout=15000&limit=100" # Path to read messages from MR
-MR_WRITE_URL="/events/A1-POLICY-AGENT-WRITE" # Path write messages to MR
MR_READ_TOPIC="A1-POLICY-AGENT-READ" # Read topic
MR_WRITE_TOPIC="A1-POLICY-AGENT-WRITE" # Write topic
+MR_READ_URL="/events/$MR_READ_TOPIC/users/policy-agent?timeout=15000&limit=100" # Path to read messages from MR
+MR_WRITE_URL="/events/$MR_WRITE_TOPIC" # Path to write messages to MR
MR_STUB_ALIVE_URL="/" # Base path for mr stub alive check
MR_DMAAP_ALIVE_URL="/topics" # Base path for dmaap-mr alive check
MR_DMAAP_COMPOSE_DIR="dmaapmr" # Dir in simulator_group for dmaap mr for - docker-compose
MR_STUB_LOCALHOST_PORT=3908 # MR stub container external port (host -> container)
MR_DMAAP_LOCALHOST_SECURE_PORT=3905 # MR stub container internal port (container -> container)
MR_STUB_LOCALHOST_SECURE_PORT=3909 # MR stub container external secure port (host -> container)
-MR_READ_URL="/events/A1-POLICY-AGENT-READ/users/policy-agent?timeout=15000&limit=100" # Path to read messages from MR
-MR_WRITE_URL="/events/A1-POLICY-AGENT-WRITE" # Path write messages to MR
MR_READ_TOPIC="A1-POLICY-AGENT-READ" # Read topic
MR_WRITE_TOPIC="A1-POLICY-AGENT-WRITE" # Write topic
+MR_READ_URL="/events/$MR_READ_TOPIC/users/policy-agent?timeout=15000&limit=100" # Path to read messages from MR
+MR_WRITE_URL="/events/$MR_WRITE_TOPIC" # Path to write messages to MR
MR_STUB_ALIVE_URL="/" # Base path for mr stub alive check
MR_DMAAP_ALIVE_URL="/topics" # Base path for dmaap-mr alive check
MR_DMAAP_COMPOSE_DIR="dmaapmr" # Dir in simulator_group for dmaap mr for - docker-compose
### MR-stub interface, for MR control
# Send a message to MR
-# URI and parameters (GET): /send-request?operation=<GET|PUT|POST|DELETE>&url=<url>
+# URI and parameters (PUT or POST): /send-request?operation=<GET|PUT|POST|DELETE>&url=<url>
# response: <correlation-id> (http 200) o4 400 for parameter error or 500 for other errors
@app.route(APP_WRITE_URL,
methods=['PUT','POST'])
print("No env variables - OK")
if __name__ == "__main__":
- app.run(port=HOST_PORT, host=HOST_IP)
\ No newline at end of file
+ app.run(port=HOST_PORT, host=HOST_IP)