Fix compile issue. 57/23357/1
authorLuji7 <lu.ji3@zte.com.cn>
Mon, 13 Nov 2017 14:49:51 +0000 (22:49 +0800)
committerLuji7 <lu.ji3@zte.com.cn>
Mon, 13 Nov 2017 14:49:55 +0000 (22:49 +0800)
Change-Id: If03d57ee29eaa661b8a9ed64130ffc62c9f308f2
Issue-id: USECASEUI-55
Signed-off-by: Luji7 <lu.ji3@zte.com.cn>
server/src/main/java/org/onap/usecaseui/server/controller/lcm/PackageDistributionController.java
server/src/main/java/org/onap/usecaseui/server/service/lcm/PackageDistributionService.java
server/src/main/java/org/onap/usecaseui/server/service/lcm/domain/aai/bean/SDNCControllerRsp.java
server/src/main/java/org/onap/usecaseui/server/service/lcm/domain/sdc/bean/Vnf.java
server/src/main/java/org/onap/usecaseui/server/service/lcm/domain/so/bean/OperationProgressInformation.java
server/src/main/java/org/onap/usecaseui/server/service/lcm/domain/vfc/VfcService.java
server/src/main/java/org/onap/usecaseui/server/service/lcm/impl/DefaultPackageDistributionService.java
server/src/main/java/org/onap/usecaseui/server/service/lcm/impl/DefaultServiceTemplateService.java
server/src/test/java/org/onap/usecaseui/server/controller/lcm/PackageDistributionControllerTest.java
server/src/test/java/org/onap/usecaseui/server/service/lcm/impl/DefaultPackageDistributionServiceTest.java
server/src/test/java/org/onap/usecaseui/server/service/lcm/impl/DefaultServiceTemplateServiceTest.java

index 0de43e1..588108d 100644 (file)
@@ -28,6 +28,7 @@ import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
 
 @Controller
 @org.springframework.context.annotation.Configuration
@@ -62,8 +63,21 @@ public class PackageDistributionController {
     }
 
     @ResponseBody
-    @RequestMapping(value = {"/uui-lcm/jobs/{jobId}"}, method = RequestMethod.POST , produces = "application/json")
-    public JobStatus getJobStatus(@PathVariable(value="jobId") String jobId){
-        return packageDistributionService.getJobStatus(jobId);
+    @RequestMapping(value = {"/uui-lcm/jobs/{jobId}"}, method = RequestMethod.GET , produces = "application/json")
+    public JobStatus getJobStatus(@PathVariable(value="jobId") String jobId, HttpServletRequest request){
+        String responseId = request.getParameter("responseId");
+        return packageDistributionService.getJobStatus(jobId, responseId);
+    }
+
+    @ResponseBody
+    @RequestMapping(value = {"/uui-lcm/ns-packages/{casrId}"}, method = RequestMethod.DELETE , produces = "application/json")
+    public DistributionResult deleteNsPackage(@PathVariable("casrId") String casrId){
+        return packageDistributionService.deleteNsPackage(casrId);
+    }
+
+    @ResponseBody
+    @RequestMapping(value = {"/uui-lcm/vf-packages/{casrId}"}, method = RequestMethod.DELETE , produces = "application/json")
+    public DistributionResult deleteVfPackage(@PathVariable("casrId") String casrId){
+        return packageDistributionService.deleteVfPackage(casrId);
     }
 }
index 2778613..0aa7226 100644 (file)
@@ -29,5 +29,9 @@ public interface PackageDistributionService {
 
     Job postVfPackage(Csar csar);
 
-    JobStatus getJobStatus(String jobId);
+    JobStatus getJobStatus(String jobId, String responseId);
+
+    DistributionResult deleteNsPackage(String csarId);
+
+    DistributionResult deleteVfPackage(String csarId);
 }
index 3ceb3e7..c9d5bf6 100644 (file)
@@ -23,12 +23,12 @@ public class SDNCControllerRsp {
 
     private List<SDNCController> esrThirdpartySdncList;
 
-    @JsonProperty("esr-thirdparty-sdnc-list")
+    @JsonProperty("esr-thirdparty-sdnc")
     public List<SDNCController> getEsrThirdpartySdncList() {
         return esrThirdpartySdncList;
     }
 
-    @JsonProperty("esr-thirdparty-sdnc-list")
+    @JsonProperty("esr-thirdparty-sdnc")
     public void setEsrThirdpartySdncList(List<SDNCController> esrThirdpartySdncList) {
         this.esrThirdpartySdncList = esrThirdpartySdncList;
     }
index ca3b9c1..6e401ce 100644 (file)
@@ -30,6 +30,8 @@ public class Vnf {
 
     private String name;
 
+    private String version;
+
     public String getUuid() {
         return uuid;
     }
@@ -54,6 +56,14 @@ public class Vnf {
         this.name = name;
     }
 
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -61,11 +71,12 @@ public class Vnf {
         Vnf vnf = (Vnf) o;
         return Objects.equals(uuid, vnf.uuid) &&
                 Objects.equals(invariantUUID, vnf.invariantUUID) &&
-                Objects.equals(name, vnf.name);
+                Objects.equals(name, vnf.name) &&
+                Objects.equals(version, vnf.version);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(uuid, invariantUUID, name);
+        return Objects.hash(uuid, invariantUUID, name, version);
     }
 }
index 2cf20ad..90d2835 100644 (file)
@@ -20,13 +20,13 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 @JsonIgnoreProperties(ignoreUnknown=true)
 public class OperationProgressInformation {
 
-    private OperationProgress operation;
+    private OperationProgress operationStatus;
 
-    public OperationProgress getOperation() {
-        return operation;
+    public OperationProgress getOperationStatus() {
+        return operationStatus;
     }
 
-    public void setOperation(OperationProgress operation) {
-        this.operation = operation;
+    public void setOperationStatus(OperationProgress operationStatus) {
+        this.operationStatus = operationStatus;
     }
 }
index f762074..d569970 100644 (file)
@@ -20,10 +20,7 @@ import org.onap.usecaseui.server.service.lcm.domain.vfc.beans.DistributionResult
 import org.onap.usecaseui.server.service.lcm.domain.vfc.beans.Job;
 import org.onap.usecaseui.server.service.lcm.domain.vfc.beans.JobStatus;
 import retrofit2.Call;
-import retrofit2.http.Body;
-import retrofit2.http.GET;
-import retrofit2.http.POST;
-import retrofit2.http.Path;
+import retrofit2.http.*;
 
 public interface VfcService {
 
@@ -34,5 +31,11 @@ public interface VfcService {
     Call<Job> distributeVnfPackage(@Body Csar csar);
 
     @GET("/api/nslcm/v1/jobs/{jobId}")
-    Call<JobStatus> getJobStatus(@Path("jobId") String jobId);
+    Call<JobStatus> getJobStatus(@Path("jobId") String jobId, @Query("responseId") String responseId);
+
+    @DELETE("/api/catalog/v1/nspackages/{csarId}")
+    Call<DistributionResult> deleteNsPackage(@Path("csarId") String csarId);
+
+    @DELETE("/api/catalog/v1/vnfpackages/{csarId}")
+    Call<DistributionResult> deleteVnfPackage(@Path("csarId") String csarId);
 }
index da8fd69..6514fd9 100644 (file)
@@ -122,9 +122,9 @@ public class DefaultPackageDistributionService implements PackageDistributionSer
     }
 
     @Override
-    public JobStatus getJobStatus(String jobId) {
+    public JobStatus getJobStatus(String jobId, String responseId) {
         try {
-            Response<JobStatus> response = vfcService.getJobStatus(jobId).execute();
+            Response<JobStatus> response = vfcService.getJobStatus(jobId, responseId).execute();
             if (response.isSuccessful()) {
                 return response.body();
             } else {
@@ -135,4 +135,34 @@ public class DefaultPackageDistributionService implements PackageDistributionSer
             throw new VfcException("VFC service is not available!", e);
         }
     }
+
+    @Override
+    public DistributionResult deleteNsPackage(String csarId) {
+        try {
+            Response<DistributionResult> response = vfcService.deleteNsPackage(csarId).execute();
+            if (response.isSuccessful()) {
+                return response.body();
+            } else {
+                logger.info(String.format("Can not delete NS packages[code=%s, message=%s]", response.code(), response.message()));
+                throw new VfcException("VFC service is not available!");
+            }
+        } catch (IOException e) {
+            throw new VfcException("VFC service is not available!", e);
+        }
+    }
+
+    @Override
+    public DistributionResult deleteVfPackage(String csarId) {
+        try {
+            Response<DistributionResult> response = vfcService.deleteVnfPackage(csarId).execute();
+            if (response.isSuccessful()) {
+                return response.body();
+            } else {
+                logger.info(String.format("Can not delete VF packages[code=%s, message=%s]", response.code(), response.message()));
+                throw new VfcException("VFC service is not available!");
+            }
+        } catch (IOException e) {
+            throw new VfcException("VFC service is not available!", e);
+        }
+    }
 }
index 0419ec9..1b4cd33 100644 (file)
@@ -53,29 +53,313 @@ import static org.onap.usecaseui.server.service.lcm.domain.sdc.consts.SDCConsts.
 @EnableAspectJAutoProxy
 public class DefaultServiceTemplateService implements ServiceTemplateService {
 
+    private static final Logger logger = LoggerFactory.getLogger(DefaultServiceTemplateService.class);
+
+    private SDCCatalogService sdcCatalog;
+
+    private AAIService aaiService;
+
     public DefaultServiceTemplateService() {
+        this(RestfulServices.create(SDCCatalogService.class), RestfulServices.create(AAIService.class));
     }
 
     public DefaultServiceTemplateService(SDCCatalogService sdcCatalog, AAIService aaiService) {
+        this.sdcCatalog = sdcCatalog;
+        this.aaiService = aaiService;
     }
 
     @Override
     public List<SDCServiceTemplate> listDistributedServiceTemplate() {
-        return null;
+        try {
+            Response<List<SDCServiceTemplate>> response = this.sdcCatalog.listServices(CATEGORY_E2E_SERVICE, DISTRIBUTION_STATUS_DISTRIBUTED).execute();
+            if (response.isSuccessful()) {
+                return response.body();
+            } else {
+                logger.info(String.format("Can not get distributed e2e service templates[code=%s, message=%s]", response.code(), response.message()));
+                return Collections.emptyList();
+            }
+        } catch (IOException e) {
+            logger.error("Visit SDC Catalog occur exception");
+            throw new SDCCatalogException("SDC Catalog is not available.", e);
+        }
     }
 
     @Override
     public ServiceTemplateInput fetchServiceTemplateInput(String uuid, String toscaModelPath) {
+        return fetchServiceTemplate(uuid, toscaModelPath, false);
+    }
+
+    private ServiceTemplateInput fetchServiceTemplate(String uuid, String toscaModelPath, boolean isVF) {
+        String toPath = String.format("/home/uui/%s.csar", uuid);
+//        String toPath = String.format("D:\\volte/%s.csar", uuid);
+        try {
+            downloadFile(toscaModelPath, toPath);
+            return extractTemplate(toPath, isVF);
+        }  catch (IOException e) {
+            throw new SDCCatalogException("download csar file failed!", e);
+        } catch (JToscaException e) {
+            throw new SDCCatalogException("parse csar file failed!", e);
+        }
+    }
+
+    protected void downloadFile(String toscaModelPath, String toPath) throws IOException {
+        try {
+            String msbUrl = RestfulServices.getMsbAddress();
+            String templateUrl = String.format("http://%s%s", msbUrl, toscaModelPath);
+            ResponseBody body = sdcCatalog.downloadCsar(templateUrl).execute().body();
+            Files.write(body.bytes(),new File(toPath));
+        } catch (IOException e) {
+            logger.error(String.format("Download %s failed!", toscaModelPath));
+            throw e;
+        }
+    }
+
+    public ServiceTemplateInput extractTemplate(String toPath, boolean isVF) throws JToscaException, IOException {
+        ToscaTemplate tosca = translateToToscaTemplate(toPath);
+        ServiceTemplateInput serviceTemplateInput = newServiceTemplateInput(tosca);
+        Map<String, Input> inputsMap = getInputsMap(tosca);
+        for (NodeTemplate nodeTemplate : tosca.getNodeTemplates()) {
+            String nodeType = nodeTemplate.getMetaData().getValue("type");
+            if ("VF".equals(nodeType)) {
+                ServiceTemplateInput nodeService = fetchVFNodeTemplateInput(nodeTemplate);
+                if (nodeService == null) {
+                    continue;
+                }
+                serviceTemplateInput.addNestedTemplate(nodeService);
+            } else {
+                ServiceTemplateInput nodeService = fetchVLServiceTemplateInput(nodeTemplate, inputsMap);
+                serviceTemplateInput.addNestedTemplate(nodeService);
+            }
+        }
+        List<TemplateInput> serviceInputs = getServiceInputs(inputsMap.values());
+        serviceTemplateInput.addInputs(serviceInputs);
+        if (isVF) {
+            serviceTemplateInput.setType("VF");
+            appendLocationParameters(serviceTemplateInput, tosca);
+            appendSdnControllerParameter(serviceTemplateInput);
+        }
+        return serviceTemplateInput;
+    }
+
+    private void appendLocationParameters(ServiceTemplateInput serviceTemplateInput, ToscaTemplate tosca) {
+        for (NodeTemplate nodeTemplate : tosca.getNodeTemplates()) {
+            String type = nodeTemplate.getMetaData().getValue("type");
+            String uuid = nodeTemplate.getMetaData().getValue("UUID");
+            String nodeName = nodeTemplate.getMetaData().getValue("name");
+//            String nodeName = nodeTemplate.getName();
+            if ("VF".equals(type)) {
+                serviceTemplateInput.addInput(
+                        new TemplateInput(
+                                uuid,
+                                "vf_location",
+                                nodeName,
+                                "true",
+                                ""
+                        )
+                );
+            }
+        }
+    }
+
+    private void appendSdnControllerParameter(ServiceTemplateInput serviceTemplateInput) {
+        serviceTemplateInput.addInput(
+                new TemplateInput(
+                        "sdncontroller",
+                        "sdn_controller",
+                        "location for the service",
+                        "true",
+                        ""
+                )
+        );
+    }
+
+    private ServiceTemplateInput fetchVLServiceTemplateInput(NodeTemplate nodeTemplate, Map<String, Input> inputsMap) {
+        ServiceTemplateInput nodeService = newServiceTemplateInput(nodeTemplate);
+        String prefix = getPrefix(nodeTemplate.getName());
+        List<TemplateInput> templateInputs = collectInputs(prefix, inputsMap);
+        nodeService.addInputs(templateInputs);
+        return nodeService;
+    }
+
+    private ServiceTemplateInput fetchVFNodeTemplateInput(NodeTemplate nodeTemplate) throws IOException {
+        String nodeUUID = fetchNodeUUID(nodeTemplate);
+        if (nodeUUID == null) {
+            // not found nested node
+            return null;
+        }
+        String toscaModelURL = getToscaUrl(nodeUUID);
+        if (toscaModelURL == null) {
+            return null;
+        }
+        return fetchServiceTemplate(nodeUUID, toscaModelURL, true);
+    }
+
+    private List<TemplateInput> getServiceInputs(Collection<Input> inputs) {
+        List<TemplateInput> result = new ArrayList<>();
+        for (Input input : inputs) {
+            result.add(
+                    new TemplateInput(
+                            input.getName(),
+                            input.getType(),
+                            input.getDescription(),
+                            String.valueOf(input.isRequired()),
+                            String.valueOf(input.getDefault())
+                    )
+            );
+        }
+        return result;
+    }
+
+    private String fetchNodeUUID(NodeTemplate nodeTemplate) {
+        LinkedHashMap<String, Property> properties = nodeTemplate.getProperties();
+        for (Map.Entry<String, Property> entry : properties.entrySet()) {
+            String key = entry.getKey();
+            if (key.endsWith("providing_service_uuid")) {
+                return String.valueOf(entry.getValue().getValue());
+            }
+        }
+        // not found
         return null;
     }
 
+    private List<TemplateInput> collectInputs(String prefix, Map<String, Input> inputsMap) {
+        List<TemplateInput> result = new ArrayList<>();
+        List<String> removeItems = new ArrayList<>();
+        for (Map.Entry<String, Input> entry : inputsMap.entrySet()) {
+            String name = entry.getKey();
+            if (name.startsWith(prefix)) {
+                //remove resource name prefix which sdc added.
+                name = name.substring(prefix.length() + 1);
+                Input in = entry.getValue();
+                result.add(
+                        new TemplateInput(
+                                name,
+                                in.getType(),
+                                in.getDescription(),
+                                String.valueOf(in.isRequired()),
+                                String.valueOf(in.getDefault())
+                        )
+                );
+                removeItems.add(entry.getKey());
+            }
+        }
+        for (String key : removeItems) {
+            inputsMap.remove(key);
+        }
+        return result;
+    }
+
+    private Map<String, Input> getInputsMap(ToscaTemplate tosca) {
+        Map<String, Input> result = new HashMap<>();
+        for (Input input : tosca.getInputs()) {
+            result.put(input.getName(), input);
+        }
+        return result;
+    }
+
+    private String getPrefix(String name) {
+        return name.replaceAll(" +", "").toLowerCase();
+    }
+
+    protected String getToscaUrl(String nodeUUID) throws IOException {
+        Response<SDCServiceTemplate> response = sdcCatalog.getService(nodeUUID).execute();
+        if (response.isSuccessful()) {
+            SDCServiceTemplate template = response.body();
+            return template.getToscaModelURL();
+        } else {
+            logger.info(String.format("Cannot get tosca model for node template[%s]", nodeUUID));
+            return null;
+        }
+    }
+
+    protected ToscaTemplate translateToToscaTemplate(String toPath) throws JToscaException {
+//        return new ToscaTemplate(toPath,null,true,null,true);
+        return new ToscaTemplate(toPath,null,true,null);
+    }
+
+    private static ServiceTemplateInput newServiceTemplateInput(ToscaTemplate tosca) {
+        String invariantUUID = tosca.getMetaData().getValue("invariantUUID");
+        String uuid = tosca.getMetaData().getValue("UUID");
+        String name = tosca.getMetaData().getValue("name");
+        String type = tosca.getMetaData().getValue("type");
+        String version = tosca.getMetaData().getValue("version");
+        if (version == null) {
+            version = "";
+        }
+        String description = tosca.getMetaData().getValue("description");
+        String category = tosca.getMetaData().getValue("category");
+        String subcategory = tosca.getMetaData().getValue("subcategory");
+        if(subcategory == null) {
+            subcategory = "";
+        }
+        return new ServiceTemplateInput(
+                invariantUUID,
+                uuid,
+                name,
+                type,
+                version,
+                description,
+                category,
+                subcategory,
+                new ArrayList<>());
+    }
+
+    private static ServiceTemplateInput newServiceTemplateInput(NodeTemplate nodeTemplate) {
+        String invariantUUID = nodeTemplate.getMetaData().getValue("invariantUUID");
+        String uuid = nodeTemplate.getMetaData().getValue("UUID");
+        String name = nodeTemplate.getMetaData().getValue("name");
+        String type = nodeTemplate.getMetaData().getValue("type");
+        String version = nodeTemplate.getMetaData().getValue("version");
+        if (version == null) {
+            version = "";
+        }
+        String description = nodeTemplate.getMetaData().getValue("description");
+        String category = nodeTemplate.getMetaData().getValue("category");
+        String subcategory = nodeTemplate.getMetaData().getValue("subcategory");
+        if(subcategory == null) {
+            subcategory = "";
+        }
+        return new ServiceTemplateInput(
+                invariantUUID,
+                uuid,
+                name,
+                type,
+                version,
+                description,
+                category,
+                subcategory,
+                new ArrayList<>());
+    }
+
     @Override
     public List<VimInfo> listVim() {
-        return null;
+        try {
+            Response<VimInfoRsp> response = aaiService.listVimInfo().execute();
+            if (response.isSuccessful()) {
+                return response.body().getCloudRegion();
+            } else {
+                logger.info(String.format("Can not get vim info[code=%s, message=%s]", response.code(), response.message()));
+                return Collections.emptyList();
+            }
+        } catch (IOException e) {
+            logger.error("Visit AAI occur exception");
+            throw new AAIException("AAI is not available.", e);
+        }
     }
 
     @Override
     public List<SDNCController> listSDNCControllers() {
-        return null;
+        try {
+            Response<SDNCControllerRsp> response = aaiService.listSdncControllers().execute();
+            if (response.isSuccessful()) {
+                return response.body().getEsrThirdpartySdncList();
+            } else {
+                logger.info(String.format("Can not get sdnc controllers[code=%s, message=%s]", response.code(), response.message()));
+                return Collections.emptyList();
+            }
+        } catch (IOException e) {
+            logger.error("Visit AAI occur exception");
+            throw new AAIException("AAI is not available.", e);
+        }
     }
 }
index 7634057..c2da15b 100644 (file)
@@ -20,6 +20,8 @@ import org.junit.Test;
 import org.onap.usecaseui.server.service.lcm.PackageDistributionService;
 import org.onap.usecaseui.server.service.lcm.domain.vfc.beans.Csar;
 
+import javax.servlet.http.HttpServletRequest;
+
 import static org.mockito.Mockito.*;
 
 public class PackageDistributionControllerTest {
@@ -59,8 +61,11 @@ public class PackageDistributionControllerTest {
     @Test
     public void testGetJobStatus() throws Exception {
         String jobId = "1";
-        controller.getJobStatus(jobId);
+        String responseId = "1";
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        when(request.getParameter("responseId")).thenReturn(responseId);
+        controller.getJobStatus(jobId, request);
 
-        verify(service, times(1)).getJobStatus(jobId);
+        verify(service, times(1)).getJobStatus(jobId, responseId);
     }
 }
\ No newline at end of file
index e156d33..1b138ed 100644 (file)
@@ -144,19 +144,21 @@ public class DefaultPackageDistributionServiceTest {
     public void itCanGetJobStatusFromVFC() {
         VfcService vfcService = mock(VfcService.class);
         String jobId = "1";
+        String responseId = "1";
         JobStatus jobStatus = new JobStatus();
-        when(vfcService.getJobStatus(jobId)).thenReturn(successfulCall(jobStatus));
+        when(vfcService.getJobStatus(jobId, responseId)).thenReturn(successfulCall(jobStatus));
         PackageDistributionService service = new DefaultPackageDistributionService(null, vfcService);
 
-        Assert.assertSame(jobStatus, service.getJobStatus(jobId));
+        Assert.assertSame(jobStatus, service.getJobStatus(jobId, responseId));
     }
 
     @Test(expected = VfcException.class)
     public void getJobStatusWillThrowExceptionWhenVFCIsNotAvailable() {
         VfcService vfcService = mock(VfcService.class);
         String jobId = "1";
-        when(vfcService.getJobStatus(jobId)).thenReturn(failedCall("VFC is not available!"));
+        String responseId = "1";
+        when(vfcService.getJobStatus(jobId, responseId)).thenReturn(failedCall("VFC is not available!"));
         PackageDistributionService service = new DefaultPackageDistributionService(null, vfcService);
-        service.getJobStatus(jobId);
+        service.getJobStatus(jobId, responseId);
     }
 }
\ No newline at end of file
index b9bc532..943d380 100644 (file)
@@ -46,4 +46,162 @@ import static org.onap.usecaseui.server.util.CallStub.successfulCall;
 
 public class DefaultServiceTemplateServiceTest {
 
+    @Test
+    public void itCanListDistributedServiceTemplate() {
+        List<SDCServiceTemplate> templates = Collections.singletonList(new SDCServiceTemplate("uuid", "uuid", "name", "V1","url", "category"));
+        SDCCatalogService sdcService = mock(SDCCatalogService.class);
+        when(sdcService.listServices(CATEGORY_E2E_SERVICE, DISTRIBUTION_STATUS_DISTRIBUTED)).thenReturn(successfulCall(templates));
+
+        ServiceTemplateService service = new DefaultServiceTemplateService(sdcService,null);
+
+        Assert.assertSame(templates, service.listDistributedServiceTemplate());
+    }
+
+    @Test(expected = SDCCatalogException.class)
+    public void retrieveServiceWillThrowExceptionWhenSDCIsNotAvailable() {
+        SDCCatalogService sdcService = mock(SDCCatalogService.class);
+        when(sdcService.listServices(CATEGORY_E2E_SERVICE, DISTRIBUTION_STATUS_DISTRIBUTED)).thenReturn(failedCall("SDC is not available!"));
+
+        ServiceTemplateService service = new DefaultServiceTemplateService(sdcService,null);
+        service.listDistributedServiceTemplate();
+    }
+
+    @Test
+    public void itCanRetrieveInputsFromServiceTemplate() throws IOException {
+        final String uuid = "1";
+        String modelPath = "model_path";
+        String nodeUUID = "2";
+
+        SDCCatalogService sdcService = newSdcCatalogService(nodeUUID);
+
+        List<VimInfo> vim = Collections.singletonList(new VimInfo("owner", "regionId"));
+        AAIService aaiService = newAAIService(vim);
+
+        ServiceTemplateService service = newServiceTemplateService(uuid, nodeUUID, sdcService, aaiService);
+
+        Assert.assertThat(service.fetchServiceTemplateInput(uuid, modelPath), equalTo(expectedServiceInputs(uuid, nodeUUID)));
+    }
+
+    private DefaultServiceTemplateService newServiceTemplateService(String uuid, String nodeUUID, SDCCatalogService sdcService, AAIService aaiService) {
+        return new DefaultServiceTemplateService(sdcService, aaiService) {
+
+            @Override
+            protected void downloadFile(String templateUrl, String toPath) throws IOException {
+                // download successfully...
+            }
+
+            @Override
+            protected ToscaTemplate translateToToscaTemplate(String toPath) throws JToscaException {
+                if (toPath.contains(uuid)) {
+                    return e2eToscaTemplate(nodeUUID);
+                }
+                return nodeToscaTemplate(nodeUUID);
+            }
+        };
+    }
+
+    private SDCCatalogService newSdcCatalogService(String nodeUUID) throws IOException {
+        SDCCatalogService sdcService = mock(SDCCatalogService.class);
+        when(sdcService.getService(nodeUUID)).thenReturn(successfulCall(new SDCServiceTemplate(nodeUUID, nodeUUID, "node", "V1", "nodeModelUrl", "service")));
+        return sdcService;
+    }
+
+    private ServiceTemplateInput expectedServiceInputs(String uuid, String nodeUUID) {
+        ServiceTemplateInput e2eServiceTemplateInput = new ServiceTemplateInput(
+                uuid, uuid, "VoLTE", "service","", "VoLTE", "service", "", Collections.EMPTY_LIST);
+        TemplateInput templateInput = new TemplateInput("field_name","field_type", "field_description", "true", "field_default");
+        ServiceTemplateInput nodeTemplateInput = new ServiceTemplateInput(
+                nodeUUID, nodeUUID, "", "", "","", "service", "", Collections.singletonList(templateInput));
+//        e2eServiceTemplateInput.addNestedTemplate(nodeTemplateInput);
+        return e2eServiceTemplateInput;
+    }
+
+    private ToscaTemplate e2eToscaTemplate(String nodeUUID) {
+        ToscaTemplate toscaTemplate = mock(ToscaTemplate.class);
+        Map<String, Object> e2eAttributes = new HashMap<>();
+        e2eAttributes.put("invariantUUID", "1");
+        e2eAttributes.put("UUID", "1");
+        e2eAttributes.put("name", "VoLTE");
+        e2eAttributes.put("type", "service");
+        e2eAttributes.put("description", "VoLTE");
+        e2eAttributes.put("category", "service");
+        e2eAttributes.put("subcategory", "");
+        when(toscaTemplate.getMetaData()).thenReturn(new Metadata(e2eAttributes));
+        when(toscaTemplate.getInputs()).thenReturn(new ArrayList<>());
+        NodeTemplate nodeTemplate = mock(NodeTemplate.class);
+
+        Map<String, Object> nodeUUIDAttr = new HashMap<>();
+
+        nodeUUIDAttr.put("UUID", nodeUUID);
+        when(nodeTemplate.getMetaData()).thenReturn(new Metadata(nodeUUIDAttr));
+
+        ArrayList<NodeTemplate> nodeTemplates = new ArrayList<>();
+//        nodeTemplates.add(nodeTemplate);
+        when(toscaTemplate.getNodeTemplates()).thenReturn(nodeTemplates);
+
+        return toscaTemplate;
+    }
+
+    private ToscaTemplate nodeToscaTemplate(String nodeUUID) {
+        ToscaTemplate toscaTemplate = mock(ToscaTemplate.class);
+        Map<String, Object> Attributes = new HashMap<>();
+        Attributes.put("invariantUUID", nodeUUID);
+        Attributes.put("UUID", nodeUUID);
+        Attributes.put("name", "");
+        Attributes.put("type", "");
+        Attributes.put("description", "");
+        Attributes.put("category", "service");
+        Attributes.put("subcategory", "");
+        when(toscaTemplate.getMetaData()).thenReturn(new Metadata(Attributes));
+
+        Input input = mock(Input.class);
+        when(input.getName()).thenReturn("field_name");
+        when(input.getDescription()).thenReturn("field_description");
+        when(input.getType()).thenReturn("field_type");
+        when(input.getDefault()).thenReturn("field_default");
+        when(input.isRequired()).thenReturn(true);
+
+        ArrayList<Input> inputs = new ArrayList<>();
+        inputs.add(input);
+        when(toscaTemplate.getInputs()).thenReturn(inputs);
+        when(toscaTemplate.getNodeTemplates()).thenReturn(new ArrayList<>());
+
+        return toscaTemplate;
+    }
+
+    private AAIService newAAIService(List<VimInfo> vim) {
+        AAIService aaiService = mock(AAIService.class);
+        VimInfoRsp rsp = new VimInfoRsp();
+        rsp.setCloudRegion(vim);
+        Call<VimInfoRsp> vimCall = successfulCall(rsp);
+        when(aaiService.listVimInfo()).thenReturn(vimCall);
+        return aaiService;
+    }
+
+    @Test(expected = SDCCatalogException.class)
+    public void retrieveInputsWillThrowExceptionWhenDownloadFailed() {
+        ServiceTemplateService service = new DefaultServiceTemplateService(null, null) {
+            @Override
+            protected void downloadFile(String templateUrl, String toPath) throws IOException {
+                throw new IOException("download failed!");
+            }
+        };
+        service.fetchServiceTemplateInput("1", "url");
+    }
+
+    @Test(expected = SDCCatalogException.class)
+    public void retrieveInputsWillThrowExceptionWhenParsingToscaTemplateFailed() {
+        ServiceTemplateService service = new DefaultServiceTemplateService(null, null) {
+            @Override
+            protected void downloadFile(String templateUrl, String toPath) throws IOException {
+                // download successfully...
+            }
+
+            @Override
+            protected ToscaTemplate translateToToscaTemplate(String toPath) throws JToscaException {
+                throw new JToscaException("parse tosca template failed!", "123");
+            }
+        };
+        service.fetchServiceTemplateInput("1", "url");
+    }
 }
\ No newline at end of file