You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

Page for general findings around the investigation of the optimal path for CLAMP and Tosca Control Loop Integration.

CLAMP Code Walkthrough videos can be found here

Tosca handling in CLAMP vs Tosca Control Loop - Findings

CSAR from SDC Flow

  1. CSAR contains the DCAE blueprint to be used to deploy to DCAE but also contains a reference to a microservice policy type. CLAMP, on startup, pulls all the policy types and pulls them periodically after that. Clamp creates LOOP TEMPLATES from in its database from the blueprints. CLAMP uses the reference from the CSAR to associate the relevant microservice policy type with a loop template. Thus, CLAMP knows which monitoring policy type to use for creation of a Loop instance.
  2. As shown in "src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java", multiple microservices per blueprint may not be supported by CLAMP. How much work would be required to support multiple BPs?
  3. The Blueprint Artifact in the CSAR is used to populate the "loop_template" db. These "loop_templates" are used to create instances. All interaction with the database is done using the SpringBoot "@Repository" pattern. Standard boilerplate db interaction is done in most cases with "JpaRepository" (find, save etc).
  4. CLAMP also gets the policy type (based on the policy type id in the CSAR) from the database. The types are then added to the "loop_element_models" table. The relationship between "loop_element_models" and "policy_models" is recorded in the "loopelementmodels_to_policymodels" table.
  5. The relationship between the loop element models and the loop templates is also recorded in the "looptemplates_to_loopelementmodels" table. In this way, the blueprint templates is associated with a microservice policy.

Loop Creation Flow

When a loop is created in UI or directly in backend:

  1. The loop is saved in the "loops" table.
  2. The microservice policy is created (with a generated name) in the "micro_service_policies" table along with the policy type associated with it and the json representation of the policy type.
  3. The relationship between the microservice policies and the loops is recorded in the "loops_to_microservicepolicies" table. This contains the loop names and the microservice policy names.


REST in CLAMP vs REST in Control Loop PoC - Findings

  1. LoopService and MicroservicePolicyService classes resemble our PoC Provider classes, such as Commissioning and Instantiation Provider where java code in regards to CRUD resides
    1.  Examples:

      LoopService.getLoop()
      public Loop getLoop(String loopName) {
              return loopsRepository.findById(loopName).orElse(null);
      }
      ControlLoopInstantiationProvider.GetControlLoops()
      public ControlLoops getControlLoops(String name, String version) throws PfModelException {
          ControlLoops controlLoops = new ControlLoops();
          controlLoops.setControlLoopList(controlLoopProvider.getControlLoops(name, version));
      
          return controlLoops;
      }
    2.  The differences start here, as CLAMP uses the Spring Framework Repository Interfaces to handle database calls, where as PoC is using the code defined in policy-models in regards to Tosca and our own models and JPA classes for ControlLoop related objects. 
      i.e LoopsRepository extends JpaRepository (Spring Framework). Our providers are either created by us or use policy ones i.e. PolicyModelsProvider.
    3.  There seems to be a lot of specific methods for updating the loop templates, such as updateDcaeDeploymentFields() and addOperationalPolicy(). In our case that is handled within the TOSCA service template itself, by mending the template where these objects can be added as nodeTemplates(ControlLoopElements), without having to be specific to a DCAE control loop. Further info in TOSCA handling.

  2.  Actual REST code is handled rather differently. In CLAMP LoopController class serves as a class to introduce Springboot Framework with the "@Controller" annotation, and methods defined in this class are just calling the LoopService Methods. This is to allow these methods to be more easily called by the CAMEL flows using :
    e.g. "<to uri="bean:org.onap.policy.clamp.loop.LoopController?method=getLoop(${header.loopName})"/". In CAMEL the response, logging and error handling occurs, with the code just throwing the exception.
    In our case, our REST code along with annotations, definitions and responses is in our Controllers, which call the provider methods to do the actual interaction. e.g. CommissioningController, which defines the path along with other java.wx.rs inputs.
    1. Examples:

      LoopController.getLoop()
      public Loop getLoop(String loopName) {
          return loopService.getLoop(loopName);
      }
      CAMEL for getLoop
      <get uri="/v2/loop/{loopName}" outType="org.onap.policy.clamp.loop.Loop"
           produces="application/json">
          <route>
              <removeHeaders pattern="*" excludePattern="loopName"/>
              <doTry>
                  <to
                          uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Loop')"/>
                  <to
                          uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')"/>
                  <to
                          uri="bean:org.onap.policy.clamp.loop.LoopController?method=getLoop(${header.loopName})"/>
                  <to
                          uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
                  <doCatch>
                      <exception>java.lang.Exception</exception>
                      <handled>
                          <constant>true</constant>
                      </handled>
                      <to
                              uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
                      <log loggingLevel="ERROR"
                           message="GET Loop request failed for loop: ${header.loopName}, ${exception.stacktrace}"/>
      
                      <setHeader name="CamelHttpResponseCode">
                          <constant>500</constant>
                      </setHeader>
                      <setBody>
                          <simple>GET Loop FAILED</simple>
                      </setBody>
                  </doCatch>
              </doTry>
          </route>
      </get>
      Java Code for PoC way of handling REST
      @GET
      @Path("/instantiation")
      @ApiOperation(value = "Query details of the requested control loops",
              notes = "Queries details of the requested control loops, returning all control loop details",
              response = ControlLoops.class,
              tags = {
                  "Clamp control loop Instantiation API"
              },
              authorizations = @Authorization(value = AUTHORIZATION_TYPE),
              responseHeaders = {
                      @ResponseHeader(
                              name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
                                      response = String.class),
                      @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
                                      response = String.class),
                      @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
                                      response = String.class),
                      @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
                                      response = UUID.class)},
              extensions = {
                      @Extension(
                              name = EXTENSION_NAME,
                              properties = {
                                      @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
                                      @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
                          }
                      )
                  }
          )
      @ApiResponses(
              value = {
                  @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
                  @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
                  @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
              }
          )
      // @formatter:on
      public Response query(
              @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
              @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name,
              @ApiParam(value = "Control Loop definition version",
                      required = true) @QueryParam("version") String version) {
      
          try {
              ControlLoops response = provider.getControlLoops(name, version);
              return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
                      .build();
      
          } catch (PfModelRuntimeException | PfModelException e) {
              LOGGER.warn("commisssioning of control loop failed", e);
              return createInstantiationErrorResponse(e, requestId);
          }
      
      }
    2. My knowledge on Spring is limited. Overall it seems more of a preference. Switching PoC way to handle REST to Spring/CAMEL as is in CLAMP should not be a massive hurdle, unless if Spring can only handle database queries which are defined by Spring Interfaces, and we cannot create "@Controller" for our provider(Service) code which uses our own JPA code for interacting with the DB
  • No labels