Dublin yang model update 67/81967/3
authorCheung, Pat (kc1472) <kc1472@att.com>
Mon, 11 Mar 2019 17:23:05 +0000 (17:23 +0000)
committerCheung, Pat (kc1472) <kc1472@att.com>
Mon, 11 Mar 2019 18:09:40 +0000 (18:09 +0000)
PNF support in Dublin

Change-Id: Icb2a00b37be11e1d0ac1b13940c0c8053a2a5b64
Issue-ID: SDNC-633
Signed-off-by: Cheung, Pat (kc1472) <kc1472@att.com>
generic-resource-api/model/src/main/yang/GENERIC-RESOURCE-API.yang
generic-resource-api/provider/src/main/java/org/onap/sdnc/northbound/GenericResourceApiProvider.java
generic-resource-api/provider/src/main/java/org/onap/sdnc/northbound/GenericResourceApiUtil.java
generic-resource-api/provider/src/test/java/org/onap/sdnc/northbound/PnfTopologyOperationRPCTest.java [new file with mode: 0644]
generic-resource-api/provider/src/test/java/org/onap/sdnc/northbound/util/GenericResourceApiSvcLogicServiceClientMockUtil.java
generic-resource-api/provider/src/test/java/org/onap/sdnc/northbound/util/MDSALUtil.java

index 62d8c7b..ac89e02 100644 (file)
@@ -51,6 +51,20 @@ module GENERIC-RESOURCE-API {
                }\r
             }\r
          }\r
+         container pnfs {\r
+            list pnf {\r
+               key "pnf-id";\r
+               leaf pnf-id {\r
+                  type string;\r
+                  mandatory true;\r
+               }\r
+               container pnf-data {\r
+                  uses pnf-operation-information;\r
+                  uses pnf-topology;\r
+                  uses pnf-level-oper-status;\r
+               }\r
+            }\r
+         }\r
          container vnfs {\r
             list vnf {\r
                key "vnf-id";\r
@@ -429,6 +443,79 @@ module GENERIC-RESOURCE-API {
          uses oper-status-data;\r
       }\r
    }\r
+   grouping pnf-operation-information {\r
+      uses sdnc-request-header;\r
+      uses request-information;\r
+      uses service-information;\r
+      uses pnf-details;\r
+      uses pnf-request-input;\r
+   }\r
+   grouping pnf-details {\r
+      container pnf-details {\r
+         leaf pnf-id {\r
+            description "pnfId*Identifier of this Pnf information element. CORRELATIONID = PNF-NAME (A&AI)";\r
+            type string;\r
+            mandatory true;\r
+         }\r
+         leaf pnf-type {\r
+            description "pnfType (template)*Type of Resource. NEW type: PNF (pre-defined in SDC)";\r
+            type string;\r
+         }\r
+         leaf pnf-name {\r
+            type string;\r
+         }\r
+         uses onap-model-information;\r
+      }\r
+   }\r
+   grouping pnf-request-input {\r
+      container pnf-request-input {\r
+         leaf request-version {\r
+            description "keep this? e.g. 1702";\r
+            type string;\r
+         }\r
+         leaf pnf-name {\r
+            type string;\r
+         }\r
+         uses region-identifier;\r
+         container pnf-input-parameters {\r
+            uses param;\r
+         }\r
+      }\r
+   }\r
+   grouping pnf-topology {\r
+      container pnf-topology {\r
+         uses pnf-topology-identifier-structure;\r
+         uses region-identifier;\r
+         uses onap-model-information;\r
+         container pnf-parameters-data {\r
+            uses param;\r
+         }\r
+         leaf sdnc-generated-cloud-resources {\r
+            description "Indicate if source is sdnc generated cloud param.When true, the parameters are literal HEAT template parameter names;When false, the parameters need to be converted to HEAT format";\r
+            type boolean;\r
+         }\r
+      }\r
+   }\r
+   grouping pnf-topology-identifier-structure {\r
+      container pnf-topology-identifier-structure {\r
+         leaf pnf-id {\r
+            type string;\r
+         }\r
+         leaf pnf-type {\r
+            description "In preload tree, this label is used for the vf-module-type";\r
+            type string;\r
+         }\r
+         leaf pnf-name {\r
+            description "optionally comes from pnf-request-input container or is assigned by sdn-c";\r
+            type string;\r
+         }\r
+      }\r
+   }\r
+   grouping pnf-level-oper-status {\r
+      container pnf-level-oper-status {\r
+         uses oper-status-data;\r
+      }\r
+   }\r
    grouping vnf-operation-information {\r
       uses sdnc-request-header;\r
       uses request-information;\r
@@ -2353,6 +2440,9 @@ module GENERIC-RESOURCE-API {
                enum "CreateVnfInstance";\r
                enum "ActivateVnfInstance";\r
                enum "DeleteVnfInstance";\r
+               enum "CreatePnfInstance";\r
+               enum "ActivatePnfInstance";\r
+               enum "DeletePnfInstance";\r
                enum "CreateVfModuleInstance";\r
                enum "ActivateVfModuleInstance";\r
                enum "DeleteVfModuleInstance";\r
@@ -2580,12 +2670,15 @@ module GENERIC-RESOURCE-API {
             enum "CreateNetworkInstance";\r
             enum "ActivateNetworkInstance";\r
             enum "DeActivateNetworkInstance";\r
+            enum "DeleteNetworkInstance";\r
             enum "CreateServiceInstance";\r
             enum "DeleteServiceInstance";\r
-            enum "DeleteNetworkInstance";\r
             enum "CreateVnfInstance";\r
             enum "ActivateVnfInstance";\r
             enum "DeleteVnfInstance";\r
+            enum "CreatePnfInstance";\r
+            enum "ActivatePnfInstance";\r
+            enum "DeletePnfInstance";\r
             enum "CreateVfModuleInstance";\r
             enum "ActivateVfModuleInstance";\r
             enum "DeleteVfModuleInstance";\r
@@ -2690,6 +2783,11 @@ module GENERIC-RESOURCE-API {
          uses instance-reference;\r
       }\r
    }\r
+   grouping pnf-response-information {\r
+      container pnf-response-information {\r
+         uses instance-reference;\r
+      }\r
+   }\r
    grouping contrail-route-response-information {\r
       container contrail-route-response-information {\r
          uses instance-reference;\r
@@ -3135,6 +3233,16 @@ module GENERIC-RESOURCE-API {
          uses service-response-information;\r
       }\r
    }\r
+   rpc pnf-topology-operation {\r
+      input {\r
+         uses pnf-operation-information;\r
+      }\r
+      output {\r
+         uses topology-response-common;\r
+         uses pnf-response-information;\r
+         uses service-response-information;\r
+      }\r
+   }\r
    rpc contrail-route-topology-operation {\r
       input {\r
          uses contrail-route-operation-information;\r
index 8c7e1a3..2a71e6d 100644 (file)
@@ -96,6 +96,10 @@ import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.re
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationInputBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationOutput;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationInput;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationOutput;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationOutputBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.brg.response.information.BrgResponseInformationBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.connection.attachment.response.information.ConnectionAttachmentResponseInformationBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.contrail.route.response.information.ContrailRouteResponseInformationBuilder;
@@ -123,6 +127,7 @@ import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.re
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.tunnelxconn.response.information.TunnelxconnResponseInformationBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vf.module.response.information.VfModuleResponseInformationBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.response.information.VnfResponseInformationBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.response.information.PnfResponseInformationBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -184,6 +189,7 @@ public class GenericResourceApiProvider implements AutoCloseable, GENERICRESOURC
     private static final String SERVICE_OBJECT_PATH_PARAM = "service-object-path";
     private static final String NETWORK_OBJECT_PATH_PARAM = "network-object-path";
     private static final String VNF_OBJECT_PATH_PARAM = "vnf-object-path";
+    private static final String PNF_OBJECT_PATH_PARAM = "pnf-object-path";
     private static final String VF_MODULE_OBJECT_PATH_PARAM = "vf-module-object-path";
     private static final String UPDATING_MDSAL_ERROR_MESSAGE = "Caught Exception updating MD-SAL for {} [{}] \n";
     private static final String UPDATING_MDSAL_ERROR_MESSAGE_2 = "Caught Exception updating MD-SAL for {} [{},{}] \n";
@@ -782,6 +788,224 @@ public class GenericResourceApiProvider implements AutoCloseable, GENERICRESOURC
         return input.getSdncRequestHeader() != null && input.getSdncRequestHeader().getSvcAction() != null;
     }
 
+
+    @Override
+    public ListenableFuture<RpcResult<PnfTopologyOperationOutput>> pnfTopologyOperation(PnfTopologyOperationInput input) {
+
+        final String svcOperation = "pnf-topology-operation";
+        ServiceData serviceData;
+        ServiceStatusBuilder serviceStatusBuilder = new ServiceStatusBuilder();
+        Properties properties = new Properties();
+
+        log.info(CALLED_STR, svcOperation);
+        // create a new response object
+        PnfTopologyOperationOutputBuilder responseBuilder = new PnfTopologyOperationOutputBuilder();
+
+        if (hasInvalidServiceId(input)) {
+            log.debug(NULL_OR_EMPTY_ERROR_MESSAGE, svcOperation);
+            responseBuilder.setResponseCode("404");
+            responseBuilder.setResponseMessage(NULL_OR_EMPTY_ERROR_PARAM);
+            responseBuilder.setAckFinalIndicator("Y");
+            RpcResult<PnfTopologyOperationOutput> rpcResult = RpcResultBuilder.<PnfTopologyOperationOutput>status(true)
+                    .withResult(responseBuilder.build()).build();
+            // return error
+            return Futures.immediateFuture(rpcResult);
+        }
+
+        // Grab the service instance ID from the input buffer
+        String siid = input.getServiceInformation().getServiceInstanceId();
+
+        trySetSvcRequestId(input, responseBuilder);
+
+        /* Comment out mandatory check for pnf id for scenario wherein for assign/create request pnf-id is generated by
+        SDNC itself.
+        if (hasInvalidPnfId(input)) {
+            log.debug("exiting {} because of null or empty pnf-id", svcOperation);
+            responseBuilder.setResponseCode("404");
+            responseBuilder.setResponseMessage("invalid input, null or empty pnf-id");
+            responseBuilder.setAckFinalIndicator("Y");
+
+            RpcResult<PnfTopologyOperationOutput> rpcResult = RpcResultBuilder.<PnfTopologyOperationOutput>status(true)
+                    .withResult(responseBuilder.build()).build();
+
+            return Futures.immediateFuture(rpcResult);
+        }
+        */
+
+        String pnfId = input.getPnfDetails().getPnfId();
+        ServiceDataBuilder serviceDataBuilder = new ServiceDataBuilder();
+        getServiceData(siid, serviceDataBuilder);
+
+        ServiceDataBuilder operDataBuilder = new ServiceDataBuilder();
+        getServiceData(siid, operDataBuilder, LogicalDatastoreType.OPERATIONAL);
+
+        // Set the serviceStatus based on input
+        setServiceStatus(serviceStatusBuilder, input.getSdncRequestHeader());
+        setServiceStatus(serviceStatusBuilder, input.getRequestInformation());
+
+        //
+        // setup a service-data object builder
+        // ACTION pnf-topology-operation
+        // INPUT:
+        // USES sdnc-request-header;
+        // USES request-information;
+        // USES service-information;
+        // USES pnf-details
+        // OUTPUT:
+        // USES pnf-topology-response-body;
+        // USES pnf-details
+        // USES service-information
+        //
+        // uses oper-status;
+
+        log.info(ADDING_INPUT_DATA_LOG, svcOperation, siid, input);
+        PnfTopologyOperationInputBuilder inputBuilder = new PnfTopologyOperationInputBuilder(input);
+        GenericResourceApiUtil.toProperties(properties, inputBuilder.build());
+
+        log.info(ADDING_OPERATIONAL_DATA_LOG, svcOperation, siid, operDataBuilder.build());
+        GenericResourceApiUtil.toProperties(properties, OPERATIONAL_DATA_PARAM, operDataBuilder);
+
+        // Call SLI sync method
+
+        ResponseObject responseObject = new ResponseObject("200", "");
+        String ackFinal = "Y";
+        String serviceObjectPath = null;
+        String pnfObjectPath = null;
+        Properties respProps = tryGetProperties(svcOperation, properties, serviceDataBuilder, responseObject);
+
+        if (respProps != null) {
+            responseObject.setMessage(respProps.getProperty(ERROR_MESSAGE_PARAM));
+            responseObject.setStatusCode(respProps.getProperty(ERROR_CODE_PARAM));
+            ackFinal = respProps.getProperty(ACK_FINAL_PARAM, "Y");
+            if (pnfId == null) {
+                pnfId = respProps.getProperty("pnfId");
+            }
+            serviceObjectPath = respProps.getProperty(SERVICE_OBJECT_PATH_PARAM);
+            pnfObjectPath = respProps.getProperty(PNF_OBJECT_PATH_PARAM);
+        }
+
+        setServiceStatus(serviceStatusBuilder, responseObject.getStatusCode(), responseObject.getMessage(), ackFinal);
+        serviceStatusBuilder.setRequestStatus(RequestStatus.Synccomplete);
+        serviceStatusBuilder.setRpcName(svcOperation);
+
+        if (failed(responseObject)) {
+            responseBuilder.setResponseCode(responseObject.getStatusCode());
+            responseBuilder.setResponseMessage(responseObject.getMessage());
+            responseBuilder.setAckFinalIndicator(ackFinal);
+
+            ServiceBuilder serviceBuilder = new ServiceBuilder();
+            serviceBuilder.setServiceInstanceId(siid);
+            serviceBuilder.setServiceStatus(serviceStatusBuilder.build());
+            try {
+                saveService(serviceBuilder.build(), true, LogicalDatastoreType.CONFIGURATION);
+                trySaveService(input, serviceBuilder);
+            } catch (Exception e) {
+                log.error(UPDATING_MDSAL_ERROR_MESSAGE, svcOperation, siid, e);
+            }
+            log.error(RETURNED_FAILED_MESSAGE, svcOperation, siid, responseBuilder.build());
+
+            RpcResult<PnfTopologyOperationOutput> rpcResult = RpcResultBuilder.<PnfTopologyOperationOutput>status(true)
+                    .withResult(responseBuilder.build()).build();
+
+            // return error
+            return Futures.immediateFuture(rpcResult);
+        }
+
+        // Got success from SLI
+        try {
+            serviceData = serviceDataBuilder.build();
+            log.info(UPDATING_MDSAL_INFO_MESSAGE, svcOperation, siid, serviceData);
+
+            // service object
+            ServiceBuilder serviceBuilder = new ServiceBuilder();
+            serviceBuilder.setServiceData(serviceData);
+            serviceBuilder.setServiceInstanceId(siid);
+            serviceBuilder.setServiceStatus(serviceStatusBuilder.build());
+            saveService(serviceBuilder.build(), false, LogicalDatastoreType.CONFIGURATION);
+
+            if (isValidRequest(input) && input.getSdncRequestHeader().getSvcAction().equals(SvcAction.Activate)) {
+                // Only update operational tree on Assign
+                log.info(UPDATING_TREE_INFO_MESSAGE);
+                saveService(serviceBuilder.build(), false, LogicalDatastoreType.OPERATIONAL);
+            }
+
+            ServiceResponseInformationBuilder serviceResponseInformationBuilder = new ServiceResponseInformationBuilder();
+            serviceResponseInformationBuilder.setInstanceId(siid);
+            serviceResponseInformationBuilder.setObjectPath(serviceObjectPath);
+            responseBuilder.setServiceResponseInformation(serviceResponseInformationBuilder.build());
+
+            PnfResponseInformationBuilder pnfResponseInformationBuilder = new PnfResponseInformationBuilder();
+            pnfResponseInformationBuilder.setInstanceId(pnfId);
+            pnfResponseInformationBuilder.setObjectPath(pnfObjectPath);
+            responseBuilder.setPnfResponseInformation(pnfResponseInformationBuilder.build());
+
+        } catch (Exception e) {
+            log.error(UPDATING_MDSAL_ERROR_MESSAGE, svcOperation, siid, e);
+            responseBuilder.setResponseCode("500");
+            responseBuilder.setResponseMessage(e.getMessage());
+            responseBuilder.setAckFinalIndicator("Y");
+            log.error(RETURNED_FAILED_MESSAGE, svcOperation, siid, responseBuilder.build());
+
+            RpcResult<PnfTopologyOperationOutput> rpcResult = RpcResultBuilder.<PnfTopologyOperationOutput>status(true)
+                    .withResult(responseBuilder.build()).build();
+
+            return Futures.immediateFuture(rpcResult);
+        }
+
+        // Update succeeded
+        responseBuilder.setResponseCode(responseObject.getStatusCode());
+        responseBuilder.setAckFinalIndicator(ackFinal);
+        trySetResponseMessage(responseBuilder, responseObject);
+        log.info(UPDATED_MDSAL_INFO_MESSAGE, svcOperation, siid);
+        log.info(RETURNED_SUCCESS_MESSAGE, svcOperation, siid, responseBuilder.build());
+
+        RpcResult<PnfTopologyOperationOutput> rpcResult = RpcResultBuilder.<PnfTopologyOperationOutput>status(true)
+                .withResult(responseBuilder.build()).build();
+
+        // return success
+        return Futures.immediateFuture(rpcResult);
+    }
+
+    private void trySetResponseMessage(PnfTopologyOperationOutputBuilder responseBuilder,
+            ResponseObject responseObject) {
+        if (responseObject.getMessage() != null) {
+            responseBuilder.setResponseMessage(responseObject.getMessage());
+        }
+    }
+
+    private void trySaveService(PnfTopologyOperationInput input, ServiceBuilder serviceBuilder) {
+        if (isValidRequest(input) && (input.getSdncRequestHeader().getSvcAction().equals(SvcAction.Delete)
+                || input.getSdncRequestHeader().getSvcAction().equals(SvcAction.Activate))) {
+
+            // Only update operational tree on activate or delete
+            log.info(UPDATING_TREE_INFO_MESSAGE);
+            saveService(serviceBuilder.build(), false, LogicalDatastoreType.OPERATIONAL);
+        }
+    }
+
+    private boolean hasInvalidPnfId(PnfTopologyOperationInput input) {
+        return input.getPnfDetails() == null || input.getPnfDetails().getPnfId() == null
+                || input.getPnfDetails().getPnfId().length() == 0;
+    }
+
+    private boolean hasInvalidServiceId(PnfTopologyOperationInput input) {
+        return input == null || input.getServiceInformation() == null
+                || input.getServiceInformation().getServiceInstanceId() == null
+                || input.getServiceInformation().getServiceInstanceId().length() == 0;
+    }
+
+    private void trySetSvcRequestId(PnfTopologyOperationInput input,
+            PnfTopologyOperationOutputBuilder responseBuilder) {
+        if (input.getSdncRequestHeader() != null) {
+            responseBuilder.setSvcRequestId(input.getSdncRequestHeader().getSvcRequestId());
+        }
+    }
+
+    private boolean isValidRequest(PnfTopologyOperationInput input) {
+        return input.getSdncRequestHeader() != null && input.getSdncRequestHeader().getSvcAction() != null;
+    }
+
+
     @Override
     public ListenableFuture<RpcResult<VnfTopologyOperationOutput>> vnfTopologyOperation(VnfTopologyOperationInput input) {
 
index 0ad9ac1..6397983 100644 (file)
@@ -112,7 +112,16 @@ public class GenericResourceApiUtil extends MdsalHelper {
         org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.resource.assignments.vnf.resource.assignments.vnf.networks.VnfNetworkBuilder u105 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.resource.assignments.vnf.resource.assignments.vnf.networks.VnfNetworkBuilder();
         org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.response.information.VnfResponseInformationBuilder u106 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.response.information.VnfResponseInformationBuilder();
         org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.topology.identifier.structure.VnfTopologyIdentifierStructureBuilder u107 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.topology.identifier.structure.VnfTopologyIdentifierStructureBuilder();
-        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationInputBuilder u110 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationInputBuilder();
-        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationOutputBuilder u111 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationOutputBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationInputBuilder u108 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationInputBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationOutputBuilder u109 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationOutputBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.service.data.service.data.PnfsBuilder u110 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.service.data.service.data.PnfsBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.service.data.service.data.pnfs.PnfBuilder u111 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.service.data.service.data.pnfs.PnfBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.service.data.service.data.pnfs.pnf.PnfDataBuilder u112 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.service.data.service.data.pnfs.pnf.PnfDataBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.request.input.PnfRequestInputBuilder u113 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.request.input.PnfRequestInputBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.request.input.pnf.request.input.PnfInputParametersBuilder u114 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.request.input.pnf.request.input.PnfInputParametersBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.response.information.PnfResponseInformationBuilder u115 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.response.information.PnfResponseInformationBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.topology.identifier.structure.PnfTopologyIdentifierStructureBuilder u116 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.topology.identifier.structure.PnfTopologyIdentifierStructureBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationInputBuilder u117 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationInputBuilder();
+        org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationOutputBuilder u118 = new org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationOutputBuilder();
     }
 }
diff --git a/generic-resource-api/provider/src/test/java/org/onap/sdnc/northbound/PnfTopologyOperationRPCTest.java b/generic-resource-api/provider/src/test/java/org/onap/sdnc/northbound/PnfTopologyOperationRPCTest.java
new file mode 100644 (file)
index 0000000..60a0e1f
--- /dev/null
@@ -0,0 +1,208 @@
+package org.onap.sdnc.northbound;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.onap.sdnc.northbound.GenericResourceApiProvider.APP_NAME;
+import static org.onap.sdnc.northbound.GenericResourceApiProvider.NO_SERVICE_LOGIC_ACTIVE;
+import static org.onap.sdnc.northbound.GenericResourceApiProvider.NULL_OR_EMPTY_ERROR_PARAM;
+import static org.onap.sdnc.northbound.util.MDSALUtil.build;
+import static org.onap.sdnc.northbound.util.MDSALUtil.exec;
+import static org.onap.sdnc.northbound.util.MDSALUtil.requestInformation;
+import static org.onap.sdnc.northbound.util.MDSALUtil.sdncRequestHeader;
+import static org.onap.sdnc.northbound.util.MDSALUtil.serviceInformationBuilder;
+import static org.onap.sdnc.northbound.util.MDSALUtil.serviceResponseInformation;
+import static org.onap.sdnc.northbound.util.MDSALUtil.pnfDetailsBuilder;
+import static org.onap.sdnc.northbound.util.MDSALUtil.pnfResponseInformation;
+import static org.onap.sdnc.northbound.util.MDSALUtil.pnfTopologyOperationInput;
+import static org.onap.sdnc.northbound.util.MDSALUtil.pnfTopologyOperationOutput;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.sdnc.northbound.util.PropBuilder;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainClosedException;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationInput;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationOutput;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.request.information.RequestInformation;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.sdnc.request.header.SdncRequestHeader.SvcAction;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+@RunWith(MockitoJUnitRunner.class)
+public class PnfTopologyOperationRPCTest extends GenericResourceApiProviderTest {
+
+    private static final String SVC_OPERATION = "pnf-topology-operation";
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        svcClient.setScvOperation(SVC_OPERATION);
+    }
+
+    @Test
+    public void should_fail_when_service_info_not_present() throws Exception {
+
+        PnfTopologyOperationInput input = build(pnfTopologyOperationInput());
+
+        PnfTopologyOperationOutput output =
+            exec(genericResourceApiProvider::pnfTopologyOperation, input, RpcResult::getResult);
+
+        assertEquals("404", output.getResponseCode());
+        assertEquals(NULL_OR_EMPTY_ERROR_PARAM, output.getResponseMessage());
+        assertEquals("Y", output.getAckFinalIndicator());
+    }
+
+
+    /*
+    @Test
+    public void should_fail_when_invalid_pnf_id() throws Exception {
+
+        PnfTopologyOperationInput input = build(pnfTopologyOperationInput()
+            .setServiceInformation(build(serviceInformationBuilder().
+                setServiceInstanceId("test-service-instance-id")
+            ))
+        );
+
+        PnfTopologyOperationOutput output =
+            exec(genericResourceApiProvider::pnfTopologyOperation, input, RpcResult::getResult);
+
+        assertEquals("404", output.getResponseCode());
+        assertEquals("invalid input, null or empty pnf-id", output.getResponseMessage());
+        assertEquals("Y", output.getAckFinalIndicator());
+    }*/
+
+
+    @Test
+    public void should_fail_when_client_execution_failed() throws Exception {
+
+        svcClient.mockHasGraph(true);
+        svcClient.mockExecute(new RuntimeException("test exception"));
+
+        PnfTopologyOperationInput input = build(pnfTopologyOperationInput()
+            .setServiceInformation(build(serviceInformationBuilder()
+                .setServiceInstanceId("test-service-instance-id")
+            ))
+            .setPnfDetails(build(pnfDetailsBuilder()
+                .setPnfId("test-pnf-id")
+            ))
+        );
+
+        PnfTopologyOperationOutput output =
+            exec(genericResourceApiProvider::pnfTopologyOperation, input, RpcResult::getResult);
+
+        assertEquals("500", output.getResponseCode());
+        assertEquals("test exception", output.getResponseMessage());
+        assertEquals("Y", output.getAckFinalIndicator());
+    }
+
+    @Test
+    public void should_fail_when_client_has_no_graph() throws Exception {
+
+        svcClient.mockHasGraph(false);
+
+        PnfTopologyOperationInput input = build(pnfTopologyOperationInput()
+            .setServiceInformation(build(serviceInformationBuilder()
+                .setServiceInstanceId("test-service-instance-id")
+            ))
+            .setPnfDetails(build(pnfDetailsBuilder()
+                .setPnfId("test-pnf-id")
+            ))
+        );
+
+        PnfTopologyOperationOutput output =
+            exec(genericResourceApiProvider::pnfTopologyOperation, input, RpcResult::getResult);
+
+        assertEquals("503", output.getResponseCode());
+        assertEquals(NO_SERVICE_LOGIC_ACTIVE + APP_NAME + ": '" + SVC_OPERATION + "'", output.getResponseMessage());
+        assertEquals("Y", output.getAckFinalIndicator());
+    }
+
+    @Test
+    public void should_fail_when_failed_to_update_mdsal() throws Exception {
+
+        PropBuilder svcResultProp = svcClient.createExecuteOKResult();
+        svcClient.mockExecute(svcResultProp);
+        svcClient.mockHasGraph(true);
+        WriteTransaction mockWriteTransaction = mock(WriteTransaction.class);
+        when(mockWriteTransaction.submit()).thenThrow(new TransactionChainClosedException("test exception"));
+
+        DataBroker spyDataBroker = Mockito.spy(dataBroker);
+        when(spyDataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTransaction);
+        genericResourceApiProvider.setDataBroker(spyDataBroker);
+
+        PnfTopologyOperationInput input = build(pnfTopologyOperationInput()
+            .setServiceInformation(build(serviceInformationBuilder()
+                .setServiceInstanceId("test-service-instance-id")
+            ))
+            .setPnfDetails(build(pnfDetailsBuilder()
+                .setPnfId("test-pnf-id")
+            ))
+        );
+
+        PnfTopologyOperationOutput output =
+            exec(genericResourceApiProvider::pnfTopologyOperation, input, RpcResult::getResult);
+
+        assertEquals("500", output.getResponseCode());
+        assertEquals("test exception", output.getResponseMessage());
+        assertEquals("Y", output.getAckFinalIndicator());
+    }
+
+    @Test
+    public void should_complete_with_success_when_no_errors() throws Exception {
+
+        svcClient.mockHasGraph(true);
+        PropBuilder svcResultProp = svcClient.createExecuteOKResult();
+        svcClient.mockExecute(svcResultProp);
+
+        PnfTopologyOperationInput input = build(pnfTopologyOperationInput()
+            .setSdncRequestHeader(build(sdncRequestHeader()
+                .setSvcRequestId("test-svc-request-id")
+                .setSvcAction(SvcAction.Assign)
+            ))
+            .setRequestInformation(build(requestInformation()
+                .setRequestId("test-request-id")
+                .setRequestAction(RequestInformation.RequestAction.CreateServiceInstance)
+            ))
+            .setServiceInformation(build(serviceInformationBuilder()
+                .setServiceInstanceId("test-service-instance-id")
+            ))
+            .setPnfDetails(build(pnfDetailsBuilder()
+                .setPnfId("test-pnf-id")
+            ))
+        );
+
+        PnfTopologyOperationOutput output =
+            exec(genericResourceApiProvider::pnfTopologyOperation, input, RpcResult::getResult);
+
+        assertEquals("200", output.getResponseCode());
+        assertEquals("OK", output.getResponseMessage());
+        assertEquals("Y", output.getAckFinalIndicator());
+
+        PnfTopologyOperationOutput expectedPnfTopologyOperationOutput = createExpectedOutput(svcResultProp,
+            input);
+        assertEquals(expectedPnfTopologyOperationOutput, output);
+    }
+
+    private PnfTopologyOperationOutput createExpectedOutput(PropBuilder svcResultProp,
+        PnfTopologyOperationInput pnfTopologyOperationInput) {
+        return build(
+            pnfTopologyOperationOutput()
+                .setSvcRequestId(pnfTopologyOperationInput.getSdncRequestHeader().getSvcRequestId())
+                .setResponseCode(svcResultProp.get(svcClient.errorCode))
+                .setAckFinalIndicator(svcResultProp.get(svcClient.ackFinal))
+                .setResponseMessage(svcResultProp.get(svcClient.errorMessage))
+                .setServiceResponseInformation(build(serviceResponseInformation()
+                    .setInstanceId(pnfTopologyOperationInput.getServiceInformation().getServiceInstanceId())
+                    .setObjectPath(svcResultProp.get(svcClient.serviceObjectPath))
+                ))
+                .setPnfResponseInformation(build(pnfResponseInformation()
+                    .setInstanceId(pnfTopologyOperationInput.getPnfDetails().getPnfId())
+                    .setObjectPath(svcResultProp.get(svcClient.pnfObjectPath))
+                ))
+        );
+    }
+}
index 36c6c7f..b0cd627 100644 (file)
@@ -50,6 +50,7 @@ public class GenericResourceApiSvcLogicServiceClientMockUtil {
     public final String ackFinal = "ack-final";
     public final String serviceObjectPath = "service-object-path";
     public final String networkObjectPath = "network-object-path";
+    public final String pnfObjectPath = "pnf-object-path";
     public final String vnfObjectPath = "vnf-object-path";
     public final String vfModuleObjectPath = "vf-module-object-path";
     public final String networkId = "networkId";
@@ -98,6 +99,7 @@ public class GenericResourceApiSvcLogicServiceClientMockUtil {
             .set(ackFinal, "Y")
             .set(serviceObjectPath, "serviceObjectPath: XYZ")
             .set(networkObjectPath, "networkObjectPath: XYZ")
+            .set(pnfObjectPath,  "pnfObjectPath: XYZ")
             .set(vnfObjectPath,  "vnfObjectPath: XYZ")
             .set(vfModuleObjectPath,  "vfModuleObjectPath: XYZ")
             .set(networkId, "networkId: XYZ");
index 9ed690c..d959b9f 100644 (file)
@@ -46,6 +46,8 @@ import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.re
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VfModuleTopologyOperationOutputBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationInputBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.VnfTopologyOperationOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.PnfTopologyOperationOutputBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.brg.response.information.BrgResponseInformationBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.connection.attachment.response.information.ConnectionAttachmentResponseInformationBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.contrail.route.response.information.ContrailRouteResponseInformationBuilder;
@@ -71,6 +73,9 @@ import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.re
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.information.VnfInformationBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.response.information.VnfResponseInformationBuilder;
 import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vnf.topology.identifier.structure.VnfTopologyIdentifierStructureBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.details.PnfDetailsBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.response.information.PnfResponseInformationBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.pnf.topology.identifier.structure.PnfTopologyIdentifierStructureBuilder;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
@@ -158,6 +163,14 @@ public class MDSALUtil {
         return new VfModuleTopologyOperationOutputBuilder();
     }
 
+    public static PnfTopologyOperationInputBuilder pnfTopologyOperationInput() {
+        return new PnfTopologyOperationInputBuilder();
+    }
+
+    public static PnfTopologyOperationOutputBuilder pnfTopologyOperationOutput() {
+        return new PnfTopologyOperationOutputBuilder();
+    }
+
     public static VnfTopologyOperationInputBuilder vnfTopologyOperationInput() {
         return new VnfTopologyOperationInputBuilder();
     }
@@ -204,6 +217,10 @@ public class MDSALUtil {
         return new ContrailRouteResponseInformationBuilder();
     }
 
+    public static PnfResponseInformationBuilder pnfResponseInformation() {
+        return new PnfResponseInformationBuilder();
+    }
+
     public static VnfResponseInformationBuilder vnfResponseInformation() {
         return new VnfResponseInformationBuilder();
     }
@@ -224,6 +241,10 @@ public class MDSALUtil {
         return new NetworkTopologyIdentifierStructureBuilder();
     }
 
+    public static PnfDetailsBuilder pnfDetailsBuilder() {
+        return new PnfDetailsBuilder();
+    }
+
     public static VnfInformationBuilder vnfInformationBuilder() {
         return new VnfInformationBuilder();
     }
@@ -256,6 +277,10 @@ public class MDSALUtil {
         return new NetworkTopologyOperationOutputBuilder();
     }
 
+    public static PnfTopologyIdentifierStructureBuilder pnfTopologyIdentifierStructureBuilder() {
+        return new PnfTopologyIdentifierStructureBuilder();
+    }
+
     public static VnfTopologyIdentifierStructureBuilder vnfTopologyIdentifierStructureBuilder() {
         return new VnfTopologyIdentifierStructureBuilder();
     }