18e1f77876d9c073bdff97328cd986a1d2ad8793
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.controlloop.runtime.commissioning.rest;
22
23 import io.swagger.annotations.ApiOperation;
24 import io.swagger.annotations.ApiParam;
25 import io.swagger.annotations.ApiResponse;
26 import io.swagger.annotations.ApiResponses;
27 import io.swagger.annotations.Authorization;
28 import io.swagger.annotations.Extension;
29 import io.swagger.annotations.ExtensionProperty;
30 import io.swagger.annotations.ResponseHeader;
31 import java.util.List;
32 import java.util.UUID;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.GET;
35 import javax.ws.rs.HeaderParam;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.Path;
38 import javax.ws.rs.QueryParam;
39 import javax.ws.rs.core.Response;
40 import javax.ws.rs.core.Response.Status;
41 import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse;
42 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler;
43 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
44 import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController;
45 import org.onap.policy.models.base.PfModelException;
46 import org.onap.policy.models.base.PfModelRuntimeException;
47 import org.onap.policy.models.errors.concepts.ErrorResponse;
48 import org.onap.policy.models.errors.concepts.ErrorResponseInfo;
49 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
50 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 /**
55  * Class to provide REST end points for creating, deleting, querying commissioned control loops.
56  */
57 public class CommissioningController extends RestController {
58
59     private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class);
60
61     private final CommissioningProvider provider;
62
63     /**
64      * create Commissioning Controller.
65      */
66     public CommissioningController() {
67         this.provider = CommissioningHandler.getInstance().getProvider();
68     }
69
70     /**
71      * Creates a control loop definition.
72      *
73      * @param requestId request ID used in ONAP logging
74      * @param body the body of control loop following TOSCA definition
75      * @return a response
76      */
77     // @formatter:off
78     @POST
79     @Path("/commission")
80     @ApiOperation(
81             value = "Commissions control loop definitions",
82             notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs",
83             response = CommissioningResponse.class,
84             tags = {
85                     "Control Loop Commissioning API"
86             },
87             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
88             responseHeaders = {
89                     @ResponseHeader(
90                             name = VERSION_MINOR_NAME,
91                             description = VERSION_MINOR_DESCRIPTION,
92                             response = String.class),
93                     @ResponseHeader(
94                             name = VERSION_PATCH_NAME,
95                             description = VERSION_PATCH_DESCRIPTION,
96                             response = String.class),
97                     @ResponseHeader(
98                             name = VERSION_LATEST_NAME,
99                             description = VERSION_LATEST_DESCRIPTION,
100                             response = String.class),
101                     @ResponseHeader(
102                             name = REQUEST_ID_NAME,
103                             description = REQUEST_ID_HDR_DESCRIPTION,
104                             response = UUID.class)
105             },
106             extensions = {
107                     @Extension(
108                             name = EXTENSION_NAME,
109                             properties = {
110                                     @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
111                                     @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
112                             }
113                     )
114             }
115     )
116     @ApiResponses(
117             value = {
118                     @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
119                     @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
120                     @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
121             }
122     )
123     // @formatter:on
124     public Response create(
125             @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
126             @ApiParam(value = "Entity Body of Control Loop", required = true) ToscaServiceTemplate body) {
127
128         try {
129             CommissioningResponse response = provider.createControlLoopDefinitions(body);
130             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId)
131                     .entity(response).build();
132
133         } catch (PfModelRuntimeException | PfModelException e) {
134             LOGGER.warn("Commissioning of the control loops failed", e);
135             CommissioningResponse resp = new CommissioningResponse();
136             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
137             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
138         }
139
140     }
141
142     /**
143      * Deletes a control loop definition.
144      *
145      * @param requestId request ID used in ONAP logging
146      * @param name the name of the control loop definition to delete
147      * @param version the version of the control loop definition to delete
148      * @return a response
149      */
150     // @formatter:off
151     @DELETE
152     @Path("/commission")
153     @ApiOperation(value = "Delete a commissioned control loop",
154             notes = "Deletes a Commissioned Control Loop, returning optional error details",
155             response = CommissioningResponse.class,
156             tags = {
157                     "Clamp Control Loop Commissioning API"
158             },
159             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
160             responseHeaders = {
161                     @ResponseHeader(
162                             name = VERSION_MINOR_NAME,
163                             description = VERSION_MINOR_DESCRIPTION,
164                             response = String.class),
165                     @ResponseHeader(
166                             name = VERSION_PATCH_NAME,
167                             description = VERSION_PATCH_DESCRIPTION,
168                             response = String.class),
169                     @ResponseHeader(
170                             name = VERSION_LATEST_NAME,
171                             description = VERSION_LATEST_DESCRIPTION,
172                             response = String.class),
173                     @ResponseHeader(
174                             name = REQUEST_ID_NAME,
175                             description = REQUEST_ID_HDR_DESCRIPTION,
176                             response = UUID.class)},
177             extensions = {
178                     @Extension(
179                             name = EXTENSION_NAME,
180                             properties = {
181                                     @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
182                                     @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
183                             }
184                     )
185             }
186     )
187     @ApiResponses(value = {
188             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
189             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
190             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
191         }
192     )
193     // @formatter:on
194     public Response delete(
195             @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
196             @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name,
197             @ApiParam(value = "Control Loop definition version", required = true)
198             @QueryParam("version") String version) {
199
200         try {
201             CommissioningResponse response = provider.deleteControlLoopDefinition(name, version);
202             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId)
203                     .entity(response).build();
204
205         } catch (PfModelRuntimeException | PfModelException e) {
206             LOGGER.warn("Decommisssioning of control loop failed", e);
207             CommissioningResponse resp = new CommissioningResponse();
208             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
209             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
210         }
211
212     }
213
214     /**
215      * Queries details of all or specific control loop definitions.
216      *
217      * @param requestId request ID used in ONAP logging
218      * @param name the name of the control loop definition to get, null for all definitions
219      * @param version the version of the control loop definition to get, null for all definitions
220      * @return the control loop definitions
221      */
222     // @formatter:off
223     @GET
224     @Path("/commission")
225     @ApiOperation(value = "Query details of the requested commissioned control loop definitions",
226             notes = "Queries details of the requested commissioned control loop definitions, "
227                     + "returning all control loop details",
228             response = ToscaNodeTemplate.class,
229             tags = {
230                     "Clamp Control Loop Commissioning API"
231             },
232             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
233             responseHeaders = {
234                     @ResponseHeader(
235                             name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
236                             response = String.class),
237                     @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
238                             response = String.class),
239                     @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
240                             response = String.class),
241                     @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
242                             response = UUID.class)},
243             extensions = {
244                     @Extension(
245                             name = EXTENSION_NAME,
246                             properties = {
247                                     @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
248                                     @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
249                             }
250                     )
251             }
252     )
253     @ApiResponses(
254             value = {
255                     @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
256                     @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
257                     @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
258             }
259     )
260     // @formatter:on
261     public Response query(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
262                           @ApiParam(value = "Control Loop definition name", required = true)
263                           @QueryParam("name") String name,
264                           @ApiParam(value = "Control Loop definition version", required = true)
265                           @QueryParam("version") String version) {
266
267         try {
268             List<ToscaNodeTemplate> response = provider.getControlLoopDefinitions(name, version);
269             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
270                     .build();
271
272         } catch (PfModelRuntimeException | PfModelException e) {
273             LOGGER.warn("Get of control loop definitions failed", e);
274             CommissioningResponse resp = new CommissioningResponse();
275             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
276             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
277         }
278
279     }
280
281     /**
282      * Queries the elements of a specific control loop.
283      *
284      * @param requestId request ID used in ONAP logging
285      * @param name the name of the control loop definition to get
286      * @param version the version of the control loop definition to get
287      * @return the control loop element definitions
288      */
289     // @formatter:off
290     @GET
291     @Path("/commission/elements")
292     @ApiOperation(value = "Query details of the requested commissioned control loop element definitions",
293             notes = "Queries details of the requested commissioned control loop element definitions, "
294                     + "returning all control loop elements' details",
295             response = ToscaNodeTemplate.class,
296             tags = {
297                     "Clamp Control Loop Commissioning API"
298             },
299             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
300             responseHeaders = {
301                     @ResponseHeader(
302                             name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
303                             response = String.class),
304                     @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
305                             response = String.class),
306                     @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
307                             response = String.class),
308                     @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
309                             response = UUID.class)},
310             extensions = {
311                     @Extension(
312                             name = EXTENSION_NAME,
313                             properties = {
314                                     @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
315                                     @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
316                             }
317                     )
318             }
319     )
320     @ApiResponses(
321             value = {
322                     @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
323                     @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
324                     @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
325             }
326     )
327     // @formatter:on
328     public Response queryElements(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
329                                   @ApiParam(value = "Control Loop definition name", required = true)
330                                   @QueryParam("name") String name,
331                                   @ApiParam(value = "Control Loop definition version", required = true)
332                                   @QueryParam("version") String version) throws Exception {
333
334         try {
335             List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
336             //Prevent ambiguous queries with multiple returns
337             if (nodeTemplate.size() > 1) {
338                 CommissioningResponse resp = new CommissioningResponse();
339                 resp.setErrorDetails("Multiple ControlLoops are not supported");
340                 return returnResponse(Response.Status.NOT_ACCEPTABLE, requestId, resp);
341             }
342
343             List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
344             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
345                     .build();
346
347         } catch (PfModelRuntimeException | PfModelException e) {
348             LOGGER.warn("Get of control loop element definitions failed", e);
349             CommissioningResponse resp = new CommissioningResponse();
350             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
351             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
352         }
353
354     }
355
356     private Response returnResponse(Response.Status status, UUID requestId, CommissioningResponse resp) {
357         return addLoggingHeaders(addVersionControlHeaders(Response.status(status)),
358                 requestId).entity(resp).build();
359     }
360 }