From 696b3aab041353afd74e26c0b9a569d0b1b9e254 Mon Sep 17 00:00:00 2001 From: Geora Barsky Date: Fri, 12 Oct 2018 11:46:52 -0400 Subject: Adding API Mapping infrastructure Issue-ID: LOG-391 Change-Id: I30d954bcdf1cf0748bb5249cbf10defb8dbc8ff6 Signed-off-by: Geora Barsky --- config/application.properties | 20 +- config/dynamic/conf/api-handlers.xml | 13 ++ config/dynamic/routes/sdnc-api.route | 17 ++ config/rules/api-mapping-rules.drl | 39 ++++ pom.xml | 34 +++- .../pomba/contextbuilder/sdnc/Application.java | 29 ++- .../contextbuilder/sdnc/SdncConfiguration.java | 69 ++++++- .../pomba/contextbuilder/sdnc/SpringXMLConfig.java | 28 +++ .../sdnc/handlers/GenericResourceApiHandler.java | 68 +++++++ .../sdnc/handlers/VnfApiHandler.java | 52 +++++ .../contextbuilder/sdnc/model/ServiceEntity.java | 73 +++++++ .../sdnc/service/SpringServiceImpl.java | 65 +++++-- .../pomba/contextbuilder/sdnc/util/RestUtil.java | 211 +++++++++++++++++++++ .../unittest/service/SdncContextBuilderTest.java | 101 +++++++++- src/test/resources/junit/aaiResourcesData-1.json | 8 + src/test/resources/junit/customerData-1.json | 6 + .../junit/customerData-CustomerIdNotFound.json | 6 + src/test/resources/junit/queryNodeData-1.json | 8 + .../junit/queryNodeData-nullResourceLink.json | 8 + src/test/resources/sdncResponse.json | 2 +- 20 files changed, 821 insertions(+), 36 deletions(-) create mode 100644 config/dynamic/conf/api-handlers.xml create mode 100644 config/dynamic/routes/sdnc-api.route create mode 100644 config/rules/api-mapping-rules.drl create mode 100644 src/main/java/org/onap/pomba/contextbuilder/sdnc/SpringXMLConfig.java create mode 100644 src/main/java/org/onap/pomba/contextbuilder/sdnc/handlers/GenericResourceApiHandler.java create mode 100644 src/main/java/org/onap/pomba/contextbuilder/sdnc/handlers/VnfApiHandler.java create mode 100644 src/main/java/org/onap/pomba/contextbuilder/sdnc/model/ServiceEntity.java create mode 100644 src/test/resources/junit/aaiResourcesData-1.json create mode 100644 src/test/resources/junit/customerData-1.json create mode 100644 src/test/resources/junit/customerData-CustomerIdNotFound.json create mode 100644 src/test/resources/junit/queryNodeData-1.json create mode 100644 src/test/resources/junit/queryNodeData-nullResourceLink.json diff --git a/config/application.properties b/config/application.properties index 6ad4731..8fc2503 100644 --- a/config/application.properties +++ b/config/application.properties @@ -18,7 +18,8 @@ spring.jersey.type=filter spring.mvc.urls=swagger,docs,prometheus,auditevents,info,heapdump,autoconfig,beans,loggers,dump,env,trace,health,configprops,mappings,metrics,webjars - +camel.springboot.xmlRoutes = file:config/dynamic/routes/*.route +service.xml.beans = config/dynamic/conf/*.xml server.contextPath=/sdnccontextbuilder/v1 spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration @@ -46,3 +47,20 @@ sdnc.genericResourcePath=/restconf/config/GENERIC-RESOURCE-API:services/service/ #Servlet context parameters server.context_parameters.p-name=value #context parameter with p-name as key and value as value. + +# AAI REST Client Configuration +aai.serviceName=10.12.6.120 +aai.servicePort=30233 +aai.username=AAI +aai.password=OBF:1gfr1ev31gg7 +aai.httpProtocol=https +aai.connectionTimeout=5000 +aai.readTimeout=1000 + +# HTTP Basic Authorization credentials for AAI Rest Service API +aai.http.userId=admin +aai.http.password=OBF:1u2a1toa1w8v1tok1u30 + +aai.searchNodeQuery=/aai/v11/search/nodes-query?search-node-type=service-instance&filter=service-instance-id:EQUALS: +aai.customerQuery=/aai/v11/business/customers/customer/ + diff --git a/config/dynamic/conf/api-handlers.xml b/config/dynamic/conf/api-handlers.xml new file mode 100644 index 0000000..8ad08c5 --- /dev/null +++ b/config/dynamic/conf/api-handlers.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/config/dynamic/routes/sdnc-api.route b/config/dynamic/routes/sdnc-api.route new file mode 100644 index 0000000..19bc5ec --- /dev/null +++ b/config/dynamic/routes/sdnc-api.route @@ -0,0 +1,17 @@ + + + + + ${in.body.apiName} == 'VNF-API' + + + + + ${in.body.apiName} == 'GENERIC-RESOURCE-API' + + + + + + + diff --git a/config/rules/api-mapping-rules.drl b/config/rules/api-mapping-rules.drl new file mode 100644 index 0000000..6278d48 --- /dev/null +++ b/config/rules/api-mapping-rules.drl @@ -0,0 +1,39 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ +package org.onap.pomba.contextbuilder.sdnc.rules; + +import org.onap.pomba.contextbuilder.sdnc.model.ServiceEntity; + +rule "ApiMapping-1" + no-loop true + lock-on-active true + when + $s : ServiceEntity( serviceType not contains "vFW" ) + then + $s.setApiName("GENERIC-RESOURCE-API"); +end + + +rule "ApiMapping-2" + no-loop true + lock-on-active true + when + $s : ServiceEntity( serviceType contains "vFW" ) + then + $s.setApiName("VNF-API"); +end diff --git a/pom.xml b/pom.xml index 6c4a843..d1bea76 100644 --- a/pom.xml +++ b/pom.xml @@ -31,11 +31,13 @@ limitations under the License. + 2.21.1 UTF-8 ${project.build.directory}/generated-resources/swagger ${project.version}-${timestamp} ${project.version}-latest + 7.1.0.Final @@ -48,6 +50,13 @@ limitations under the License. pom import + + org.apache.camel + camel-spring-boot-dependencies + ${camel-spring-boot.version} + pom + import + @@ -95,7 +104,21 @@ limitations under the License. - + + + org.apache.camel + camel-spring-boot-starter + ${camel-spring-boot.version} + + + org.apache.camel + camel-core + ${camel-spring-boot.version} + + + org.apache.camel + camel-servlet-starter + org.slf4j @@ -146,12 +169,17 @@ limitations under the License. json-utils 0.1.0 - + org.onap.aai rest-client 1.2.1 - + + + org.kie + kie-ci + ${kie.version} + diff --git a/src/main/java/org/onap/pomba/contextbuilder/sdnc/Application.java b/src/main/java/org/onap/pomba/contextbuilder/sdnc/Application.java index e0ebfc8..93dd886 100644 --- a/src/main/java/org/onap/pomba/contextbuilder/sdnc/Application.java +++ b/src/main/java/org/onap/pomba/contextbuilder/sdnc/Application.java @@ -18,7 +18,13 @@ package org.onap.pomba.contextbuilder.sdnc; -import org.apache.velocity.app.VelocityEngine; +import org.kie.api.KieServices; +import org.kie.api.builder.KieBuilder; +import org.kie.api.builder.KieFileSystem; +import org.kie.api.builder.KieRepository; +import org.kie.api.io.Resource; +import org.kie.api.io.ResourceType; +import org.kie.api.runtime.KieContainer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -30,8 +36,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableAsync; +import java.io.File; + @SpringBootApplication -@ComponentScan(basePackages = "org.onap.pomba.contextbuilder.sdnc") +@ComponentScan(basePackages = {"org.onap.pomba.contextbuilder.sdnc","org.kie.api"}) @EnableAsync @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) public class Application extends SpringBootServletInitializer { @@ -45,9 +53,18 @@ public class Application extends SpringBootServletInitializer { } @Bean - public VelocityEngine velocityEngine() { - VelocityEngine velocityEngine = new VelocityEngine(); - velocityEngine.init(); - return velocityEngine; + public KieContainer kieContainer() { + + KieServices kServices = KieServices.Factory.get(); + KieFileSystem kfs = kServices.newKieFileSystem(); + KieRepository kr = kServices.getRepository(); + File file = new File("config/rules/api-mapping-rules.drl"); + Resource resource = kServices.getResources().newFileSystemResource(file).setResourceType(ResourceType.DRL); + kfs.write(resource); + + KieBuilder kb = kServices.newKieBuilder(kfs); + kb.buildAll(); + KieContainer kContainer = kServices.newKieContainer(kr.getDefaultReleaseId()); + return kContainer; } } \ No newline at end of file diff --git a/src/main/java/org/onap/pomba/contextbuilder/sdnc/SdncConfiguration.java b/src/main/java/org/onap/pomba/contextbuilder/sdnc/SdncConfiguration.java index ec5c8b3..71c3502 100644 --- a/src/main/java/org/onap/pomba/contextbuilder/sdnc/SdncConfiguration.java +++ b/src/main/java/org/onap/pomba/contextbuilder/sdnc/SdncConfiguration.java @@ -24,7 +24,7 @@ import org.eclipse.jetty.util.security.Password; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; - +import org.onap.aai.restclient.client.RestClient; @Component @ApplicationPath("/") @@ -70,5 +70,72 @@ public class SdncConfiguration { return ("Basic " + Base64.getEncoder().encodeToString(auth.getBytes())); } + /* AAI related interfaces */ + @Value("${aai.serviceName}") + private String aaiHost; + @Value("${aai.servicePort}") + private String aaiPort; + @Value("${aai.username}") + private String aaiUsername; + @Value("${aai.password}") + private String aaiPassword; + @Value("${aai.httpProtocol}") + private String aaiHttpProtocol; + @Value("${aai.connectionTimeout}") + private Integer aaiConnectionTimeout; + @Value("${aai.readTimeout}") + private Integer aaiReadTimeout; + + @Value("${aai.http.userId}") + private String aaiHttpUserId; + + @Value("${aai.http.password}") + private String aaiHttpPassword; + + @Value("${aai.searchNodeQuery}") + private String aaiSearchNodeQuery; + + @Value("${aai.customerQuery}") + private String aaiCustomerQuery; + + @Bean(name="aaiHttpBasicAuthorization") + public String getHttpBasicAuth() { + String auth = new String(this.aaiHttpUserId + ":" + Password.deobfuscate(this.aaiHttpPassword)); + + String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes()); + return ("Basic " + encodedAuth); + } + + @Bean(name="aaiBasicAuthorization") + public String getAAIBasicAuth() { + String auth = new String(this.aaiUsername + ":" + Password.deobfuscate(this.aaiPassword)); + String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes()); + return ("Basic " + encodedAuth); + } + + @Bean(name="aaiClient") + public RestClient restClient() { + RestClient restClient = new RestClient(); + restClient.validateServerHostname(false).validateServerCertChain(false).connectTimeoutMs(aaiConnectionTimeout).readTimeoutMs(aaiReadTimeout); + restClient.basicAuthUsername(aaiUsername); + restClient.basicAuthPassword(Password.deobfuscate(aaiPassword)); + return restClient; + } + + @Bean(name="aaiBaseUrl") + public String getAaiURL() { + return httpProtocol + "://" + aaiHost + ":" + aaiPort; + + } + + @Bean(name="aaiPathToSearchNodeQuery") + public String getAaiPathToSearchNodeQuery() { + return aaiSearchNodeQuery.trim(); + } + + @Bean(name="aaiPathToCustomerQuery") + public String getAaiPathToCustomerQuery() { + return aaiCustomerQuery.trim(); + } } diff --git a/src/main/java/org/onap/pomba/contextbuilder/sdnc/SpringXMLConfig.java b/src/main/java/org/onap/pomba/contextbuilder/sdnc/SpringXMLConfig.java new file mode 100644 index 0000000..db38754 --- /dev/null +++ b/src/main/java/org/onap/pomba/contextbuilder/sdnc/SpringXMLConfig.java @@ -0,0 +1,28 @@ +/** + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ +package org.onap.pomba.contextbuilder.sdnc; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; + +@Configuration +@ImportResource({"file:${service.xml.beans}"}) +public class SpringXMLConfig { + + +} \ No newline at end of file diff --git a/src/main/java/org/onap/pomba/contextbuilder/sdnc/handlers/GenericResourceApiHandler.java b/src/main/java/org/onap/pomba/contextbuilder/sdnc/handlers/GenericResourceApiHandler.java new file mode 100644 index 0000000..885c923 --- /dev/null +++ b/src/main/java/org/onap/pomba/contextbuilder/sdnc/handlers/GenericResourceApiHandler.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +package org.onap.pomba.contextbuilder.sdnc.handlers; + +import org.apache.camel.Exchange; +import org.onap.pomba.common.datatypes.ModelContext; +import org.onap.pomba.contextbuilder.sdnc.exception.AuditException; +import org.onap.pomba.contextbuilder.sdnc.model.ServiceEntity; +import org.onap.pomba.contextbuilder.sdnc.util.RestUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.ws.rs.client.Client; + +@Component +public class GenericResourceApiHandler { + + private static Logger log = LoggerFactory.getLogger(GenericResourceApiHandler.class); + @Autowired + private Client jerseyClient; + @Autowired + private String sdncBaseUrl; + @Autowired + private String sdncBasicAuthorization; + @Autowired + private String sdncGenericResourcePath; + + + + public ModelContext process(Exchange exchange) throws Exception { + + ModelContext context; + log.info("in GENERIC-RESOURCE-API HANDLER: "); + + ServiceEntity serviceEntity = (ServiceEntity)exchange.getIn().getBody(); + String serviceInstanceId = serviceEntity.getServiceInstanceId(); + + try { + String sdncResponse = RestUtil.getSdncGenericResource(jerseyClient, sdncBaseUrl, sdncBasicAuthorization, sdncGenericResourcePath, serviceInstanceId); + context = RestUtil.transform(sdncResponse); + } catch (AuditException ae) { + throw ae; + } catch (Exception e) { + throw new AuditException(e.getLocalizedMessage()); + } + + return context; + } + +} diff --git a/src/main/java/org/onap/pomba/contextbuilder/sdnc/handlers/VnfApiHandler.java b/src/main/java/org/onap/pomba/contextbuilder/sdnc/handlers/VnfApiHandler.java new file mode 100644 index 0000000..bfedf69 --- /dev/null +++ b/src/main/java/org/onap/pomba/contextbuilder/sdnc/handlers/VnfApiHandler.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +package org.onap.pomba.contextbuilder.sdnc.handlers; + +import org.apache.camel.Exchange; +import org.onap.pomba.common.datatypes.ModelContext; +import org.onap.pomba.common.datatypes.Service; +import org.onap.pomba.contextbuilder.sdnc.model.ServiceEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class VnfApiHandler { + + private static Logger log = LoggerFactory.getLogger(VnfApiHandler.class); + + public ModelContext process(Exchange exchange) throws Exception { + + log.info("in VNF-API HANDLER: "); + +// dummy population of the model context +// The following lines should be replaced with the logic of calling to SDN-C VNF-API +// and transforming the response into common model + ModelContext context = new ModelContext(); + Service service = new Service(); + ServiceEntity serviceEntity = (ServiceEntity)exchange.getIn().getBody(); + service.setName( serviceEntity.getServiceType() + " service instance"); + context.setService(service); +// end dummy code + + return context; + } + + +} diff --git a/src/main/java/org/onap/pomba/contextbuilder/sdnc/model/ServiceEntity.java b/src/main/java/org/onap/pomba/contextbuilder/sdnc/model/ServiceEntity.java new file mode 100644 index 0000000..2f08533 --- /dev/null +++ b/src/main/java/org/onap/pomba/contextbuilder/sdnc/model/ServiceEntity.java @@ -0,0 +1,73 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ +package org.onap.pomba.contextbuilder.sdnc.model; + +public class ServiceEntity { + + private String customerType; + private String customerName; + private String serviceType; + private String apiName; + private String serviceInstanceId; + private String customerId; + + public String getCustomerId() { + return customerId; + } + + public void setCustomerId(String customerId) { + this.customerId = customerId; + } + + public String getServiceInstanceId() { return serviceInstanceId; } + + public void setServiceInstanceId(String serviceInstanceId) { this.serviceInstanceId = serviceInstanceId; } + + public String getCustomerType() { + return customerType; + } + + public void setCustomerType(String customerType) { + this.customerType = customerType; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public String getServiceType() { + return serviceType; + } + + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + + public String getApiName() { + return apiName; + } + + public void setApiName(String apiName) { + this.apiName = apiName; + } + +} diff --git a/src/main/java/org/onap/pomba/contextbuilder/sdnc/service/SpringServiceImpl.java b/src/main/java/org/onap/pomba/contextbuilder/sdnc/service/SpringServiceImpl.java index daf6bf8..b19c24c 100644 --- a/src/main/java/org/onap/pomba/contextbuilder/sdnc/service/SpringServiceImpl.java +++ b/src/main/java/org/onap/pomba/contextbuilder/sdnc/service/SpringServiceImpl.java @@ -18,57 +18,82 @@ package org.onap.pomba.contextbuilder.sdnc.service; -import javax.ws.rs.client.Client; +import org.apache.camel.ProducerTemplate; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; import org.onap.pomba.common.datatypes.ModelContext; import org.onap.pomba.contextbuilder.sdnc.exception.AuditException; import org.onap.pomba.contextbuilder.sdnc.service.rs.RestService; -import org.onap.pomba.contextbuilder.sdnc.util.RestUtil; +import org.onap.pomba.contextbuilder.sdnc.model.ServiceEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.onap.pomba.contextbuilder.sdnc.util.RestUtil; +import org.onap.aai.restclient.client.RestClient; @Service public class SpringServiceImpl implements SpringService { private static Logger log = LoggerFactory.getLogger(RestService.class); @Autowired - private Client jerseyClient; + private String sdncCtxBuilderBasicAuthorization; + private KieContainer kieContainer; @Autowired - private String sdncBaseUrl; + private ProducerTemplate producerTemplate; + + //AAI related @Autowired - private String sdncBasicAuthorization; + private String aaiBasicAuthorization; @Autowired - private String sdncGenericResourcePath; + private RestClient aaiClient; @Autowired - private String sdncCtxBuilderBasicAuthorization; + private String aaiBaseUrl; + @Autowired + private String aaiPathToSearchNodeQuery; + @Autowired + private String aaiPathToCustomerQuery; public SpringServiceImpl() { // needed for instantiation } + @Autowired + public SpringServiceImpl(KieContainer kieContainer) { + this.kieContainer = kieContainer; + + } @Override public ModelContext getContext(String serviceInstanceId, String transactionId) throws AuditException { ModelContext context = null; - String url = "serviceInstanceId=" + serviceInstanceId + " transactionId=" + transactionId; - log.info("URL Query the SDN-C model data with URL: " , url); - - // Retrieve the service instance information from SDNC and AAI - try { - String sdncResponse = RestUtil.getSdncGenericResource(jerseyClient, sdncBaseUrl, sdncBasicAuthorization, sdncGenericResourcePath, serviceInstanceId); - log.info("sdncResponse: ", sdncResponse); - context = RestUtil.transform(sdncResponse); - } catch (AuditException ae) { - throw ae; - } catch (Exception e) { - throw new AuditException(e.getLocalizedMessage()); - } + + // Call AAI system to populate ServiceData + ServiceEntity serviceEntity = RestUtil.getServiceEntity(aaiClient, aaiBaseUrl, aaiBasicAuthorization, aaiPathToSearchNodeQuery, aaiPathToCustomerQuery, serviceInstanceId, transactionId); + + processApiMappingRules(serviceEntity); + log.info("SDN-C determined API: " + serviceEntity.getApiName()); + + context = producerTemplate.requestBody("direct:startRoutingProcess", serviceEntity, ModelContext.class); + return context; } + private void processApiMappingRules(ServiceEntity serviceData){ + + KieSession kieSession = kieContainer.newKieSession(); + log.info ("KIE Session is created"); + kieSession.insert(serviceData); + kieSession.fireAllRules(); + log.info("Rules are fired"); + kieSession.getFactHandles().forEach(fh -> kieSession.delete(fh)); + kieSession.dispose(); + } + public String getSdncAuthoriztion() { return sdncCtxBuilderBasicAuthorization; } + + } diff --git a/src/main/java/org/onap/pomba/contextbuilder/sdnc/util/RestUtil.java b/src/main/java/org/onap/pomba/contextbuilder/sdnc/util/RestUtil.java index 806514c..8701c89 100644 --- a/src/main/java/org/onap/pomba/contextbuilder/sdnc/util/RestUtil.java +++ b/src/main/java/org/onap/pomba/contextbuilder/sdnc/util/RestUtil.java @@ -34,6 +34,16 @@ import org.onap.pomba.contextbuilder.sdnc.exception.AuditException; import org.onap.pomba.contextbuilder.sdnc.service.rs.RestService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.onap.aai.restclient.client.OperationResult; +import org.onap.aai.restclient.client.RestClient; +import javax.ws.rs.core.MediaType; +import com.sun.jersey.core.util.MultivaluedMapImpl; +import java.util.Map; +import java.util.Collections; +import javax.ws.rs.core.MultivaluedMap; +import org.json.JSONArray; +import org.json.JSONException; +import org.onap.pomba.contextbuilder.sdnc.model.ServiceEntity; public class RestUtil { @@ -46,6 +56,22 @@ public class RestUtil { public static final String FROM_APP_ID = "X-FromAppId"; public static final String AUTHORIZATION = "Authorization"; + // AAI related + private static final String APP_NAME = "sdncCtxBuilder"; + private static final String EMPTY_JSON_STRING = "{}"; + private static final String JSON_ATT_RESOURCE_TYPE = "resource-type"; + private static final String JSON_ATT_RESOURCE_LINK = "resource-link"; + private static final String RESULT_DATA = "result-data"; + private static final String CATALOG_SERVICE_INSTANCE = "service-instance"; + private static final String CUSTOMER_ID_STRING = "/customers/customer/"; + private static final String SERVICE_TYPE_STRING = "/service-subscriptions/service-subscription/"; + private static final String CUSTOMER = "customer"; + private static final String JSON_ATT_GLOBAL_CUSTOMER_ID = "global-customer-id"; + private static final String JSON_ATT_SUBSCRIBER_TYPE = "subscriber-type"; + private static final String JSON_ATT_SUBSCRIBER_NAME = "subscriber-name"; + + private static final String FORWARD_SLASH = "/"; + // Parameters for Query SDNC Model Data REST API URL private static final String SERVICE_INSTANCE_ID = "serviceInstanceId"; @@ -147,4 +173,189 @@ public class RestUtil { return MessageFormat.format(siPath, vfModuleLink); } + /** + * Get customer info from multiple AAI api + * @param aaiClient + * @param aaiBaseUrl + * @param aaiBasicAuthorization + * @param aaiPathToSearchNodeQuery + * @param aaiPathToCustomerQuery + * @param serviceInstaceId + * @param transactionId + * @return + * @throws AuditException + */ + public static ServiceEntity getServiceEntity(RestClient aaiClient, + String aaiBaseUrl, + String aaiBasicAuthorization, + String aaiPathToSearchNodeQuery, + String aaiPathToCustomerQuery, + String serviceInstanceId, + String transactionId)throws AuditException { + + String obtainResourceLink_url = generateUrl_ForResourceLink(aaiBaseUrl, aaiPathToSearchNodeQuery, serviceInstanceId); + String aaiResourceData = getAaiResource(aaiClient, obtainResourceLink_url, aaiBasicAuthorization, transactionId, MediaType.valueOf(MediaType.APPLICATION_JSON)); + + // Handle the case if the service instance is not found in AAI + if (isEmptyJson(aaiResourceData)) { + log.info(" Service Instance {} is not found from AAI", serviceInstanceId); + // Only return the empty Json on the root level. i.e service instance + return null; + } + + String resourceLink = extractResourceLinkBasedOnServiceInstance(aaiResourceData, CATALOG_SERVICE_INSTANCE); + + ServiceEntity serviceEntityObj = createServiceEntityObj (resourceLink); //customerId and serviceType are updated here. + if (serviceEntityObj != null) { + serviceEntityObj.setServiceInstanceId(serviceInstanceId); + String customerId = serviceEntityObj.getCustomerId(); + // Obtain customerType and customerName + String obtainCustomer_url = generateUrl_ForCustomer (aaiBaseUrl, aaiPathToCustomerQuery, customerId); + String aaiCustomerData = getAaiResource(aaiClient, obtainCustomer_url, aaiBasicAuthorization, transactionId, MediaType.valueOf(MediaType.APPLICATION_JSON)); + if (isEmptyJson(aaiCustomerData)) { + log.info(" Customer name {} is not found from AAI", customerId); + // Only return the empty Json on the root level. i.e service instance + throw new AuditException(INTERNAL_SERVER_ERROR + ": Customer ID cannot be found from AAI :" + customerId); + } + // Update customerType and customerName to the existing serviceEntityObj + updateServiceEntityObj ( aaiCustomerData , serviceEntityObj); + } + + return serviceEntityObj; + } + + private static boolean isEmptyJson(String serviceInstancePayload) { + return (serviceInstancePayload.equals(EMPTY_JSON_STRING)); + } + + private static String generateUrl_ForResourceLink (String aaiBaseURL, String aaiPathToSearchNodeQuery ,String serviceInstanceId) { + return aaiBaseURL + aaiPathToSearchNodeQuery + serviceInstanceId; + } + + private static String generateUrl_ForCustomer (String aaiBaseURL, String aaiPathToCustomerQuery ,String customerId) { + return aaiBaseURL + aaiPathToCustomerQuery + customerId; + } + + @SuppressWarnings("unchecked") + private static Map> buildHeaders(String aaiBasicAuthorization, String transactionId) { + MultivaluedMap headers = new MultivaluedMapImpl(); + headers.put(TRANSACTION_ID, Collections.singletonList(transactionId)); + headers.put(FROM_APP_ID, Collections.singletonList(APP_NAME)); + headers.put(AUTHORIZATION, Collections.singletonList(aaiBasicAuthorization)); + return headers; + } + + private static String getAaiResource(RestClient client, String url, String aaiBasicAuthorization, String transId, MediaType mediaType) + throws AuditException { + OperationResult result = client.get(url, buildHeaders(aaiBasicAuthorization, transId), MediaType.valueOf(MediaType.APPLICATION_JSON)); + + if (result.getResultCode() == 200) { + return result.getResult(); + } else if (result.getResultCode() == 404) { + // Resource not found, generate empty JSON format + log.info("Resource for {} is not found: {}", url, "return empty Json format"); + return new JSONObject().toString(); + + } else { + throw new AuditException(INTERNAL_SERVER_ERROR + " with " + result.getFailureCause()); + } + } + + /* + * Extract the resource-Link from Json payload. For example + * { + * "result-data": [ + * { + * "resource-type": "service-instance", + * "resource-link": "/aai/v11/business/customers/customer/DemoCust_651800ed-2a3c-45f5-b920-85c1ed155fc2/service-subscriptions/service-subscription/vFW/service-instances/service-instance/adc3cc2a-c73e-414f-8ddb-367de81300cb" + * } + * ] + * } + */ + private static String extractResourceLinkBasedOnServiceInstance(String payload, String catalog) throws AuditException { + String resourceLink = null; + log.info("Fetching the resource-link based on resource-type=" + catalog); + + try { + JSONArray result_data_list = new JSONObject(payload).getJSONArray(RESULT_DATA); + if (result_data_list != null) { + for (int i = 0; i < result_data_list.length(); i++) { + JSONObject obj = result_data_list.optJSONObject(i); + if (obj.has(JSON_ATT_RESOURCE_TYPE) && (obj.getString(JSON_ATT_RESOURCE_TYPE).equals(catalog) )) { + resourceLink = obj.getString(JSON_ATT_RESOURCE_LINK); + log.info(resourceLink); + return resourceLink; + } + } + } + } catch (JSONException e) { + log.error(e.getMessage()); + throw new AuditException("Json Reader Parse Error " + e.getMessage()); + } + + log.warn("resource-link CANNOT be found: ", payload ); + + return resourceLink; + } + + /* + * Extract the "subscriber-name" and "subscriber-type" from Json payload. For example + * { + * "global-customer-id": "OttoonMorph36", + * "subscriber-name": "OttoonMorph36", + * "subscriber-type": "CUST", + * "resource-version": "1526324315029" + * } + */ + private static void updateServiceEntityObj(String payload, ServiceEntity serviceEntityObj) throws AuditException { + if (serviceEntityObj == null ) { + throw new AuditException("null pointer serviceEntityObj"); + } + String customerId = serviceEntityObj.getCustomerId(); + log.info("Fetching the subscriber type based on customer-id = " + customerId); + + try { + JSONObject obj = new JSONObject (payload); + if (obj.has(JSON_ATT_GLOBAL_CUSTOMER_ID) && (obj.getString(JSON_ATT_GLOBAL_CUSTOMER_ID).equals(customerId) )) { + serviceEntityObj.setCustomerType(obj.getString(JSON_ATT_SUBSCRIBER_TYPE)); + serviceEntityObj.setCustomerName(obj.getString(JSON_ATT_SUBSCRIBER_NAME)); + return; + } + } catch (JSONException e) { + log.error(e.getMessage()); + throw new AuditException("Json Reader Parse Error " + e.getMessage()); + } + + log.warn("subscriberType (" + customerId + ") CANNOT be found: ", payload ); + + return; + } + + /* Look for "/customers/customer/" and "/service-subscriptions/service-subscription/" in resourceLink + * and find the customer id and service type. + * For example, + * "/aai/v11/business/customers/customer/DemoCust_651800ed-2a3c-45f5-b920-85c1ed155fc2/service-subscriptions/service-subscription/vFW/service-instances/service-instance/adc3cc2a-c73e-414f-8ddb-367de81300cb" + * customerId = DemoCust_651800ed-2a3c-45f5-b920-85c1ed155fc2 + * serviceType = vFW + * */ + + private static ServiceEntity createServiceEntityObj (String resourceLink) { + int customer_id_idx = resourceLink.indexOf(CUSTOMER_ID_STRING); + int service_type_idx = resourceLink.indexOf(SERVICE_TYPE_STRING); + + if (( customer_id_idx < 0 ) || ( service_type_idx < 0 )) { + return null; + } + + ServiceEntity serviceEntity = new ServiceEntity (); + serviceEntity.setCustomerId(abstractStrInfo(resourceLink, CUSTOMER_ID_STRING)); + serviceEntity.setServiceType(abstractStrInfo(resourceLink, SERVICE_TYPE_STRING)); + return serviceEntity; + } + + private static String abstractStrInfo (String origStr, String matchStr) { + String after = origStr.substring( origStr.indexOf(matchStr) + matchStr.length()); + + return after.substring(0, after.indexOf(FORWARD_SLASH)); + } } diff --git a/src/test/java/org/onap/pomba/contextbuilder/sdnc/unittest/service/SdncContextBuilderTest.java b/src/test/java/org/onap/pomba/contextbuilder/sdnc/unittest/service/SdncContextBuilderTest.java index 91ab1cf..2d21ca4 100644 --- a/src/test/java/org/onap/pomba/contextbuilder/sdnc/unittest/service/SdncContextBuilderTest.java +++ b/src/test/java/org/onap/pomba/contextbuilder/sdnc/unittest/service/SdncContextBuilderTest.java @@ -50,21 +50,44 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; +import org.onap.aai.restclient.client.RestClient; +import org.onap.pomba.contextbuilder.sdnc.Application; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.UUID; +import org.onap.pomba.contextbuilder.sdnc.model.ServiceEntity; @RunWith(SpringJUnit4ClassRunner.class) @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) @WebAppConfiguration -@SpringBootTest -@TestPropertySource(properties = {"sdnc.host=localhost", "sdnc.port=30202"}) +@SpringBootTest (classes = Application.class) +@TestPropertySource(properties = {"sdnc.host=localhost", "sdnc.port=30202", + "aai.httpProtocol=http", "aai.serviceName=localhost", "aai.servicePort=9808"}) public class SdncContextBuilderTest { - private String serviceInstanceId = "c6456519-6acf-4adb-997c-3c363dd4caaf"; + private String serviceInstanceId = "7d518257-49bd-40ac-8d17-017a726ec12a"; //match to the test data in junit/queryNodeData-1.json private String testRestHeaders = "testRestHeaders"; - @Autowired + private String customerId = "DemoCust_651800ed-2a3c-45f5-b920-85c1ed155fc2"; // match to queryNodeData-1.json and customerData-1.json + @Autowired RestService service; @Autowired private String sdncCtxBuilderBasicAuthorization; + //AAI related + @Autowired + private String aaiBasicAuthorization; + @Autowired + private RestClient aaiClient; + @Autowired + private String aaiBaseUrl; + @Autowired + private String aaiPathToSearchNodeQuery; + @Autowired + private String aaiPathToCustomerQuery; + @Rule + public WireMockRule aaiEnricherRule = new WireMockRule(wireMockConfig().port(9808)); + @Rule public WireMockRule sdncRule = new WireMockRule(wireMockConfig().port(30202)); @@ -129,6 +152,12 @@ public class SdncContextBuilderTest { "testVerifyServiceDecomposition", "test1", sdncCtxBuilderBasicAuthorization); when(mockHttpHeaders.getRequestHeaders()).thenReturn(multivaluedMapImpl); + + String queryNodeUrl = aaiPathToSearchNodeQuery + serviceInstanceId; + addResponse(queryNodeUrl, "junit/queryNodeData-1.json", aaiEnricherRule); + String customerUrl = aaiPathToCustomerQuery + customerId; + addResponse(customerUrl, "junit/customerData-1.json", aaiEnricherRule); + Response response = this.service.getContext(mockHttpHeaders, serviceInstanceId); assertEquals(Status.OK.getStatusCode(), response.getStatus()); @@ -152,4 +181,68 @@ public class SdncContextBuilderTest { } return headers; } + + //AAI related + + @Test + public void testObtainResouceLinkBasedOnServiceInstanceFromAAI() throws Exception { + String transactionId = UUID.randomUUID().toString(); + String queryNodeUrl = aaiPathToSearchNodeQuery + serviceInstanceId; + addResponse(queryNodeUrl, "junit/queryNodeData-1.json", aaiEnricherRule); + String customerUrl = aaiPathToCustomerQuery + customerId; + addResponse(customerUrl, "junit/customerData-1.json", aaiEnricherRule); + + ServiceEntity serviceEntity = RestUtil.getServiceEntity(aaiClient,aaiBaseUrl,aaiBasicAuthorization, aaiPathToSearchNodeQuery, aaiPathToCustomerQuery, serviceInstanceId, transactionId); + + assertEquals(serviceInstanceId, serviceEntity.getServiceInstanceId()); + assertEquals("vFW", serviceEntity.getServiceType()); // serviceType is hard-coded in queryNodeData-1.json + assertEquals(customerId, serviceEntity.getCustomerId()); // customerId is hard-coded in queryNodeData-1.json + assertEquals("DemoCust_651800ed-2a3c-45f5-b920-85c1ed155fc2", serviceEntity.getCustomerName()); // customerName is hard-coded in queryNodeData-1.json + assertEquals("CUST", serviceEntity.getCustomerType()); //customerType is hard-coded in customerData-1.json + } + + @Test + public void testObtainResouceLinkBasedOnServiceInstanceFromAAI_nullResourceLink() throws Exception { + String transactionId = UUID.randomUUID().toString(); + String queryNodeUrl = aaiPathToSearchNodeQuery + serviceInstanceId; + addResponse(queryNodeUrl, "junit/queryNodeData-nullResourceLink.json", aaiEnricherRule); + + try { + RestUtil.getServiceEntity(aaiClient,aaiBaseUrl,aaiBasicAuthorization, aaiPathToSearchNodeQuery, aaiPathToCustomerQuery, serviceInstanceId, transactionId); + } catch (Exception e) { + assertTrue(e.getMessage().contains("JSONObject[\"resource-link\"] not found")); + } + } + + @Test + public void testObtainResouceLinkBasedOnServiceInstanceFromAAI_nullCustomerType() throws Exception { + String transactionId = UUID.randomUUID().toString(); + String queryNodeUrl = aaiPathToSearchNodeQuery + serviceInstanceId; + addResponse(queryNodeUrl, "junit/queryNodeData-1.json", aaiEnricherRule); + String customerUrl = aaiPathToCustomerQuery + customerId; + addResponse(customerUrl, "junit/customerData-CustomerIdNotFound.json", aaiEnricherRule); + + try { + RestUtil.getServiceEntity(aaiClient,aaiBaseUrl,aaiBasicAuthorization, aaiPathToSearchNodeQuery, aaiPathToCustomerQuery, serviceInstanceId, transactionId); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Customer ID cannot be found from AAI")); + } + } + + private void addResponse(String path, String classpathResource, WireMockRule thisMock) throws IOException { + String payload = readFully(ClassLoader.getSystemResourceAsStream(classpathResource)); + thisMock.stubFor(get(path).willReturn(okJson(payload))); + } + + private String readFully(InputStream in) throws IOException { + char[] cbuf = new char[1024]; + StringBuilder content = new StringBuilder(); + try (InputStreamReader reader = new InputStreamReader(in, "UTF-8")) { + int count; + while ((count = reader.read(cbuf)) >= 0) { + content.append(cbuf, 0, count); + } + } + return content.toString(); + } } diff --git a/src/test/resources/junit/aaiResourcesData-1.json b/src/test/resources/junit/aaiResourcesData-1.json new file mode 100644 index 0000000..66563d5 --- /dev/null +++ b/src/test/resources/junit/aaiResourcesData-1.json @@ -0,0 +1,8 @@ +{ + "related-to": "vnfc", + "related-link": "/aai/v11/network/vnfcs/vnfc/zrdm5aepdg01vmg003", + "relationship-data": [ + { "relationship-key": "vnfc.vnfc-name", + "relationship-value": "zrdm5aepdg01vmg003" } + ] +} \ No newline at end of file diff --git a/src/test/resources/junit/customerData-1.json b/src/test/resources/junit/customerData-1.json new file mode 100644 index 0000000..31e6baa --- /dev/null +++ b/src/test/resources/junit/customerData-1.json @@ -0,0 +1,6 @@ +{ + "global-customer-id": "DemoCust_651800ed-2a3c-45f5-b920-85c1ed155fc2", + "subscriber-name": "DemoCust_651800ed-2a3c-45f5-b920-85c1ed155fc2", + "subscriber-type": "CUST", + "resource-version": "1526324315029" +} \ No newline at end of file diff --git a/src/test/resources/junit/customerData-CustomerIdNotFound.json b/src/test/resources/junit/customerData-CustomerIdNotFound.json new file mode 100644 index 0000000..e2f71c6 --- /dev/null +++ b/src/test/resources/junit/customerData-CustomerIdNotFound.json @@ -0,0 +1,6 @@ +{ + "global-customer-id": "dummy", + "subscriber-name": "dummy", + "subscriber-type": "CUST", + "resource-version": "1526324315029" +} \ No newline at end of file diff --git a/src/test/resources/junit/queryNodeData-1.json b/src/test/resources/junit/queryNodeData-1.json new file mode 100644 index 0000000..e827391 --- /dev/null +++ b/src/test/resources/junit/queryNodeData-1.json @@ -0,0 +1,8 @@ +{ + "result-data": [ + { + "resource-type": "service-instance", + "resource-link": "/aai/v11/business/customers/customer/DemoCust_651800ed-2a3c-45f5-b920-85c1ed155fc2/service-subscriptions/service-subscription/vFW/service-instances/service-instance/7d518257-49bd-40ac-8d17-017a726ec12a" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/junit/queryNodeData-nullResourceLink.json b/src/test/resources/junit/queryNodeData-nullResourceLink.json new file mode 100644 index 0000000..36eb667 --- /dev/null +++ b/src/test/resources/junit/queryNodeData-nullResourceLink.json @@ -0,0 +1,8 @@ +{ + "result-data": [ + { + "resource-type": "service-instance", + "related-link": "/aai/v11/network/vnfcs/vnfc/zrdm5aepdg01vmg003" + } + ] +} diff --git a/src/test/resources/sdncResponse.json b/src/test/resources/sdncResponse.json index 25499c9..27b791a 100644 --- a/src/test/resources/sdncResponse.json +++ b/src/test/resources/sdncResponse.json @@ -1 +1 @@ -{"service":[{"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","service-status":{"final-indicator":"Y","rpc-action":"assign","rpc-name":"vf-module-topology-operation","response-code":"200","response-timestamp":"2018-08-27T01:58:25.652Z","action":"CreateVfModuleInstance","response-message":"","request-status":"synccomplete"},"service-data":{"service-request-input":{"service-instance-name":"vcpe_svc_vcpesvc_rescust_0822a_201808262153","service-input-parameters":{"param":[{"name":"BRG_WAN_MAC_Address","value":"fa:16:3e:79:24:0e"},{"name":"customerLongitude","value":"-97.040443"},{"name":"customerLatitude","value":"32.897480"},{"name":"Homing_Solution","value":"sniro"},{"name":"customerName","value":"some_company"}]}},"service-information":{"service-id":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb","onap-model-information":{"model-invariant-uuid":"3a4e6986-5c5e-434e-b0be-8d718107fa83","model-name":"vcpesvc_rescust_0822a","model-version":"1.0","model-uuid":"209efacc-54d4-4f12-9064-099d47c36a29"},"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","global-customer-id":"SDN-ETHERNET-INTERNET","subscription-service-type":"vCPE"},"service-topology":{"service-topology-identifier":{"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","service-instance-name":"vcpe_svc_vcpesvc_rescust_0822a_201808262153","global-customer-id":"SDN-ETHERNET-INTERNET","service-type":"vCPE"},"onap-model-information":{"model-invariant-uuid":"3a4e6986-5c5e-434e-b0be-8d718107fa83","model-name":"vcpesvc_rescust_0822a","model-version":"1.0","model-uuid":"209efacc-54d4-4f12-9064-099d47c36a29"}},"sdnc-request-header":{"svc-action":"assign","svc-request-id":"dd3dffc8-6a15-4f7f-9787-d835ee247283","svc-notification-url":"http://c1.vm1.mso.simpledemo.openecomp.org:8080/adapters/rest/SDNCNotify"},"request-information":{"request-id":"2a950a5c-21bf-4496-a592-b51f45719603","request-action":"CreateServiceInstance","source":"MSO"},"vnfs":{"vnf":[{"vnf-id":"bf2a200d-744f-4900-afc4-d5ef44638467","vnf-data":{"vf-modules":{"vf-module":[{"vf-module-id":"815e8636-5c2a-41ad-b24d-17c824106bd2","vf-module-data":{"service-information":{"service-id":"null","onap-model-information":{"model-invariant-uuid":"3a4e6986-5c5e-434e-b0be-8d718107fa83","model-name":"vcpesvc_rescust_0822a","model-version":"1.0","model-uuid":"209efacc-54d4-4f12-9064-099d47c36a29"},"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","global-customer-id":"SDN-ETHERNET-INTERNET","subscription-service-type":"null"},"vf-module-topology":{"onap-model-information":{"model-invariant-uuid":"7e91451d-e320-4755-a1a8-fcf140b86779","model-name":"VcpevspVgw0822a..base_vcpe_vgw..module-0","model-version":"1","model-customization-uuid":"7fbb59b7-a7ac-4fa6-b0bc-42f47339010a","model-uuid":"1908874e-cfae-4ee1-93b9-f4ba46b460ff"},"vf-module-parameters":{"param":[{"name":"mux_ip_addr","value":"10.5.0.21"},{"name":"mux_gw_private_net_id","value":"vcpe_net_mux_gw_201808231522"},{"name":"vg_vgmux_tunnel_vni","value":"107"},{"name":"repo_url_artifacts","value":"https://nexus.onap.org/content/groups/staging"},{"name":"cpe_public_net_id","value":"vcpe_net_cpe_public_201808231522"},{"name":"key_name","value":"vgw_key"},{"name":"onap_private_subnet_id","value":"oam_onap_1MdY"},{"name":"cpe_public_net_cidr","value":"10.2.0.0/24"},{"name":"mux_gw_private_net_cidr","value":"10.5.0.0/24"},{"name":"cloud_env","value":"openstack"},{"name":"cpe_public_subnet_id","value":"vcpe_net_cpe_public_subnet_201808231522"},{"name":"mux_gw_private_subnet_id","value":"vcpe_net_mux_gw_subnet_201808231522"},{"name":"onap_private_net_id","value":"oam_onap_1MdY"},{"name":"repo_url_blob","value":"https://nexus.onap.org/content/sites/raw"},{"name":"install_script_version","value":"1.1.1"},{"name":"demo_artifacts_version","value":"1.1.1"},{"name":"vgw_name_0","value":"zdcpe1cpe01gw01_201808261550"},{"name":"vgw_private_ip_1","value":"10.0.101.99"},{"name":"vgw_private_ip_0","value":"10.5.0.107"},{"name":"public_net_id","value":"971040b2-7059-49dc-b220-4fab50cb2ad4"},{"name":"vgw_private_ip_2","value":"10.2.0.6"},{"name":"onap_private_net_cidr","value":"10.0.0.0/16"},{"name":"pub_key","value":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKXDgoo3+WOqcUG8/5uUbk81+yczgwC4Y8ywTmuQqbNxlY1oQ0YxdMUqUnhitSXs5S/yRuAVOYHwGg2mCs20oAINrP+mxBI544AMIb9itPjCtgqtE2EWo6MmnFGbHB4Sx3XioE7F4VPsh7japsIwzOjbrQe+Mua1TGQ5d4nfEOQaaglXLLPFfuc7WbhbJbK6Q7rHqZfRcOwAMXgDoBqlyqKeiKwnumddo2RyNT8ljYmvB6buz7KnMinzo7qB0uktVT05FH9Rg0CTWH5norlG5qXgP2aukL0gk1ph8iAt7uYLf1ktp+LJI2gaF6L0/qli9EmVCSLr1uJ38Q8CBflhkh"}]},"tenant":"7fad299815104c0a8f90a8df80343f03","aic-clli":"clli1","aic-cloud-region":"RegionOne","vf-module-topology-identifier":{"vf-module-id":"815e8636-5c2a-41ad-b24d-17c824106bd2","vf-module-name":"zRegionOne06_base_vcpe_vgw_0","vf-module-type":"VcpevspVgw0822a..base_vcpe_vgw..module-0"},"vf-module-assignments":{"vms":{"vm":[{"vm-type":"vgw","vm-count":1,"vm-type-tag":"vgw","vm-names":{"vm-name":["zRegionOne06001"]}}]}}},"vf-module-request-input":{"vf-module-name":"zRegionOne06_base_vcpe_vgw_0","tenant":"7fad299815104c0a8f90a8df80343f03","aic-cloud-region":"RegionOne"},"vf-module-information":{"onap-model-information":{"model-invariant-uuid":"7e91451d-e320-4755-a1a8-fcf140b86779","model-name":"VcpevspVgw0822a..base_vcpe_vgw..module-0","model-version":"1","model-customization-uuid":"7fbb59b7-a7ac-4fa6-b0bc-42f47339010a","model-uuid":"1908874e-cfae-4ee1-93b9-f4ba46b460ff"},"vf-module-id":"815e8636-5c2a-41ad-b24d-17c824106bd2","vf-module-type":"VcpevspVgw0822a..base_vcpe_vgw..module-0"},"sdnc-request-header":{"svc-action":"assign","svc-request-id":"2a950a5c-21bf-4496-a592-b51f45719603-1535335110722","svc-notification-url":"http://c1.vm1.mso.simpledemo.openecomp.org:8080/adapters/rest/SDNCNotify"},"vnf-information":{"vnf-id":"bf2a200d-744f-4900-afc4-d5ef44638467","vnf-type":"vcpesvc_rescust_0822a/vcpevsp_vgw_0822a 0","onap-model-information":{"model-invariant-uuid":"71370375-e1b4-4ad2-9832-1b7877428c81","model-name":"vcpevsp_vgw_0822a","model-version":"1.0","model-customization-uuid":"d4484d8e-09c8-4e1e-89f7-b556bf7c57ba","model-uuid":"7dd31559-9fc6-4b0d-bbe3-7ba641bf8a9b"}},"request-information":{"request-id":"2a950a5c-21bf-4496-a592-b51f45719603","request-action":"CreateVfModuleInstance","source":"VID"},"vf-module-level-oper-status":{"order-status":"PendingCreate","last-rpc-action":"assign"}}}]},"vnf-level-oper-status":{"last-rpc-action":"activate","order-status":"Created","last-action":"CreateVnfInstance"},"service-information":{"service-id":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb","onap-model-information":{"model-invariant-uuid":"3a4e6986-5c5e-434e-b0be-8d718107fa83","model-name":"vcpesvc_rescust_0822a","model-version":"1.0","model-uuid":"209efacc-54d4-4f12-9064-099d47c36a29"},"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","global-customer-id":"SDN-ETHERNET-INTERNET","subscription-service-type":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"},"sdnc-request-header":{"svc-action":"activate","svc-request-id":"2a950a5c-21bf-4496-a592-b51f45719603-1535335104196","svc-notification-url":"http://c1.vm1.mso.simpledemo.openecomp.org:8080/adapters/rest/SDNCNotify"},"vnf-information":{"vnf-id":"bf2a200d-744f-4900-afc4-d5ef44638467","vnf-type":"vcpesvc_rescust_0822a/vcpevsp_vgw_0822a 0","onap-model-information":{"model-invariant-uuid":"71370375-e1b4-4ad2-9832-1b7877428c81","model-name":"vcpevsp_vgw_0822a","model-version":"1.0","model-customization-uuid":"d4484d8e-09c8-4e1e-89f7-b556bf7c57ba","model-uuid":"7dd31559-9fc6-4b0d-bbe3-7ba641bf8a9b"}},"request-information":{"request-id":"2a950a5c-21bf-4496-a592-b51f45719603","request-action":"CreateVnfInstance","source":"VID"},"vnf-request-input":{"vnf-name":"zRegionOne06","tenant":"7fad299815104c0a8f90a8df80343f03","aic-cloud-region":"RegionOne"},"vnf-topology":{"onap-model-information":{"model-invariant-uuid":"71370375-e1b4-4ad2-9832-1b7877428c81","model-name":"vcpevsp_vgw_0822a","model-version":"1.0","model-customization-uuid":"d4484d8e-09c8-4e1e-89f7-b556bf7c57ba","model-uuid":"7dd31559-9fc6-4b0d-bbe3-7ba641bf8a9b"},"tenant":"7fad299815104c0a8f90a8df80343f03","aic-clli":"clli1","aic-cloud-region":"RegionOne","vnf-topology-identifier-structure":{"vnf-id":"bf2a200d-744f-4900-afc4-d5ef44638467","vnf-type":"vcpesvc_rescust_0822a/vcpevsp_vgw_0822a 0","vnf-name":"zRegionOne06"},"vnf-resource-assignments":{"availability-zones":{"availability-zone":["nova"],"max-count":1}}}}}]},"service-level-oper-status":{"last-rpc-action":"assign","order-status":"Created","last-action":"CreateServiceInstance"}}}]} +{"service":[{"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","service-status":{"final-indicator":"Y","rpc-action":"assign","rpc-name":"vf-module-topology-operation","response-code":"200","response-timestamp":"2018-08-27T01:58:25.652Z","action":"CreateVfModuleInstance","response-message":"","request-status":"synccomplete"},"service-data":{"service-request-input":{"service-instance-name":"vfw_svc_vfwsvc_rescust_0822a_201808262153","service-input-parameters":{"param":[{"name":"BRG_WAN_MAC_Address","value":"fa:16:3e:79:24:0e"},{"name":"customerLongitude","value":"-97.040443"},{"name":"customerLatitude","value":"32.897480"},{"name":"Homing_Solution","value":"sniro"},{"name":"customerName","value":"some_company"}]}},"service-information":{"service-id":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb","onap-model-information":{"model-invariant-uuid":"3a4e6986-5c5e-434e-b0be-8d718107fa83","model-name":"vfwsvc_rescust_0822a","model-version":"1.0","model-uuid":"209efacc-54d4-4f12-9064-099d47c36a29"},"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","global-customer-id":"SDN-ETHERNET-INTERNET","subscription-service-type":"vFW"},"service-topology":{"service-topology-identifier":{"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","service-instance-name":"vfw_svc_vfwsvc_rescust_0822a_201808262153","global-customer-id":"SDN-ETHERNET-INTERNET","service-type":"vFW"},"onap-model-information":{"model-invariant-uuid":"3a4e6986-5c5e-434e-b0be-8d718107fa83","model-name":"vfwsvc_rescust_0822a","model-version":"1.0","model-uuid":"209efacc-54d4-4f12-9064-099d47c36a29"}},"sdnc-request-header":{"svc-action":"assign","svc-request-id":"dd3dffc8-6a15-4f7f-9787-d835ee247283","svc-notification-url":"http://c1.vm1.mso.simpledemo.openecomp.org:8080/adapters/rest/SDNCNotify"},"request-information":{"request-id":"2a950a5c-21bf-4496-a592-b51f45719603","request-action":"CreateServiceInstance","source":"MSO"},"vnfs":{"vnf":[{"vnf-id":"bf2a200d-744f-4900-afc4-d5ef44638467","vnf-data":{"vf-modules":{"vf-module":[{"vf-module-id":"815e8636-5c2a-41ad-b24d-17c824106bd2","vf-module-data":{"service-information":{"service-id":"null","onap-model-information":{"model-invariant-uuid":"3a4e6986-5c5e-434e-b0be-8d718107fa83","model-name":"vfwsvc_rescust_0822a","model-version":"1.0","model-uuid":"209efacc-54d4-4f12-9064-099d47c36a29"},"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","global-customer-id":"SDN-ETHERNET-INTERNET","subscription-service-type":"null"},"vf-module-topology":{"onap-model-information":{"model-invariant-uuid":"7e91451d-e320-4755-a1a8-fcf140b86779","model-name":"VfwvspVgw0822a..base_vfw_vgw..module-0","model-version":"1","model-customization-uuid":"7fbb59b7-a7ac-4fa6-b0bc-42f47339010a","model-uuid":"1908874e-cfae-4ee1-93b9-f4ba46b460ff"},"vf-module-parameters":{"param":[{"name":"mux_ip_addr","value":"10.5.0.21"},{"name":"mux_gw_private_net_id","value":"vfw_net_mux_gw_201808231522"},{"name":"vg_vgmux_tunnel_vni","value":"107"},{"name":"repo_url_artifacts","value":"https://nexus.onap.org/content/groups/staging"},{"name":"cpe_public_net_id","value":"vfw_net_cpe_public_201808231522"},{"name":"key_name","value":"vgw_key"},{"name":"onap_private_subnet_id","value":"oam_onap_1MdY"},{"name":"cpe_public_net_cidr","value":"10.2.0.0/24"},{"name":"mux_gw_private_net_cidr","value":"10.5.0.0/24"},{"name":"cloud_env","value":"openstack"},{"name":"cpe_public_subnet_id","value":"vfw_net_cpe_public_subnet_201808231522"},{"name":"mux_gw_private_subnet_id","value":"vfw_net_mux_gw_subnet_201808231522"},{"name":"onap_private_net_id","value":"oam_onap_1MdY"},{"name":"repo_url_blob","value":"https://nexus.onap.org/content/sites/raw"},{"name":"install_script_version","value":"1.1.1"},{"name":"demo_artifacts_version","value":"1.1.1"},{"name":"vgw_name_0","value":"zdcpe1cpe01gw01_201808261550"},{"name":"vgw_private_ip_1","value":"10.0.101.99"},{"name":"vgw_private_ip_0","value":"10.5.0.107"},{"name":"public_net_id","value":"971040b2-7059-49dc-b220-4fab50cb2ad4"},{"name":"vgw_private_ip_2","value":"10.2.0.6"},{"name":"onap_private_net_cidr","value":"10.0.0.0/16"},{"name":"pub_key","value":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKXDgoo3+WOqcUG8/5uUbk81+yczgwC4Y8ywTmuQqbNxlY1oQ0YxdMUqUnhitSXs5S/yRuAVOYHwGg2mCs20oAINrP+mxBI544AMIb9itPjCtgqtE2EWo6MmnFGbHB4Sx3XioE7F4VPsh7japsIwzOjbrQe+Mua1TGQ5d4nfEOQaaglXLLPFfuc7WbhbJbK6Q7rHqZfRcOwAMXgDoBqlyqKeiKwnumddo2RyNT8ljYmvB6buz7KnMinzo7qB0uktVT05FH9Rg0CTWH5norlG5qXgP2aukL0gk1ph8iAt7uYLf1ktp+LJI2gaF6L0/qli9EmVCSLr1uJ38Q8CBflhkh"}]},"tenant":"7fad299815104c0a8f90a8df80343f03","aic-clli":"clli1","aic-cloud-region":"RegionOne","vf-module-topology-identifier":{"vf-module-id":"815e8636-5c2a-41ad-b24d-17c824106bd2","vf-module-name":"zRegionOne06_base_vfw_vgw_0","vf-module-type":"VfwvspVgw0822a..base_vfw_vgw..module-0"},"vf-module-assignments":{"vms":{"vm":[{"vm-type":"vgw","vm-count":1,"vm-type-tag":"vgw","vm-names":{"vm-name":["zRegionOne06001"]}}]}}},"vf-module-request-input":{"vf-module-name":"zRegionOne06_base_vfw_vgw_0","tenant":"7fad299815104c0a8f90a8df80343f03","aic-cloud-region":"RegionOne"},"vf-module-information":{"onap-model-information":{"model-invariant-uuid":"7e91451d-e320-4755-a1a8-fcf140b86779","model-name":"VfwvspVgw0822a..base_vfw_vgw..module-0","model-version":"1","model-customization-uuid":"7fbb59b7-a7ac-4fa6-b0bc-42f47339010a","model-uuid":"1908874e-cfae-4ee1-93b9-f4ba46b460ff"},"vf-module-id":"815e8636-5c2a-41ad-b24d-17c824106bd2","vf-module-type":"VfwvspVgw0822a..base_vfw_vgw..module-0"},"sdnc-request-header":{"svc-action":"assign","svc-request-id":"2a950a5c-21bf-4496-a592-b51f45719603-1535335110722","svc-notification-url":"http://c1.vm1.mso.simpledemo.openecomp.org:8080/adapters/rest/SDNCNotify"},"vnf-information":{"vnf-id":"bf2a200d-744f-4900-afc4-d5ef44638467","vnf-type":"vfwsvc_rescust_0822a/vfwvsp_vgw_0822a 0","onap-model-information":{"model-invariant-uuid":"71370375-e1b4-4ad2-9832-1b7877428c81","model-name":"vfwvsp_vgw_0822a","model-version":"1.0","model-customization-uuid":"d4484d8e-09c8-4e1e-89f7-b556bf7c57ba","model-uuid":"7dd31559-9fc6-4b0d-bbe3-7ba641bf8a9b"}},"request-information":{"request-id":"2a950a5c-21bf-4496-a592-b51f45719603","request-action":"CreateVfModuleInstance","source":"VID"},"vf-module-level-oper-status":{"order-status":"PendingCreate","last-rpc-action":"assign"}}}]},"vnf-level-oper-status":{"last-rpc-action":"activate","order-status":"Created","last-action":"CreateVnfInstance"},"service-information":{"service-id":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb","onap-model-information":{"model-invariant-uuid":"3a4e6986-5c5e-434e-b0be-8d718107fa83","model-name":"vfwsvc_rescust_0822a","model-version":"1.0","model-uuid":"209efacc-54d4-4f12-9064-099d47c36a29"},"service-instance-id":"7d518257-49bd-40ac-8d17-017a726ec12a","global-customer-id":"SDN-ETHERNET-INTERNET","subscription-service-type":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"},"sdnc-request-header":{"svc-action":"activate","svc-request-id":"2a950a5c-21bf-4496-a592-b51f45719603-1535335104196","svc-notification-url":"http://c1.vm1.mso.simpledemo.openecomp.org:8080/adapters/rest/SDNCNotify"},"vnf-information":{"vnf-id":"bf2a200d-744f-4900-afc4-d5ef44638467","vnf-type":"vfwsvc_rescust_0822a/vfwvsp_vgw_0822a 0","onap-model-information":{"model-invariant-uuid":"71370375-e1b4-4ad2-9832-1b7877428c81","model-name":"vfwvsp_vgw_0822a","model-version":"1.0","model-customization-uuid":"d4484d8e-09c8-4e1e-89f7-b556bf7c57ba","model-uuid":"7dd31559-9fc6-4b0d-bbe3-7ba641bf8a9b"}},"request-information":{"request-id":"2a950a5c-21bf-4496-a592-b51f45719603","request-action":"CreateVnfInstance","source":"VID"},"vnf-request-input":{"vnf-name":"zRegionOne06","tenant":"7fad299815104c0a8f90a8df80343f03","aic-cloud-region":"RegionOne"},"vnf-topology":{"onap-model-information":{"model-invariant-uuid":"71370375-e1b4-4ad2-9832-1b7877428c81","model-name":"vfwvsp_vgw_0822a","model-version":"1.0","model-customization-uuid":"d4484d8e-09c8-4e1e-89f7-b556bf7c57ba","model-uuid":"7dd31559-9fc6-4b0d-bbe3-7ba641bf8a9b"},"tenant":"7fad299815104c0a8f90a8df80343f03","aic-clli":"clli1","aic-cloud-region":"RegionOne","vnf-topology-identifier-structure":{"vnf-id":"bf2a200d-744f-4900-afc4-d5ef44638467","vnf-type":"vfwsvc_rescust_0822a/vfwvsp_vgw_0822a 0","vnf-name":"zRegionOne06"},"vnf-resource-assignments":{"availability-zones":{"availability-zone":["nova"],"max-count":1}}}}}]},"service-level-oper-status":{"last-rpc-action":"assign","order-status":"Created","last-action":"CreateServiceInstance"}}}]} -- cgit 1.2.3-korg