diff options
Diffstat (limited to 'nokiav2/driver/src/main/java/org')
12 files changed, 1029 insertions, 595 deletions
diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/SelfRegistrationManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/SelfRegistrationManager.java index 123f263d..1319405e 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/SelfRegistrationManager.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/SelfRegistrationManager.java @@ -59,6 +59,10 @@ public class SelfRegistrationManager { private String driverVnfmExternalIp; @Value("${server.port}") private String driverPort; + @Value("${skipLcnSubscription}") + private boolean skipLcnSubscription; + @Value("${skipSelfRegistration}") + private boolean skipSelfRegistration; private volatile boolean ready = false; SelfRegistrationManager(VnfmInfoProvider vnfmInfoProvider, MsbApiProvider msbApiProvider, CbamRestApiProvider cbamRestApiProvider) { @@ -72,11 +76,17 @@ public class SelfRegistrationManager { */ public void register() { //the order is important (only publish it's existence after the subscription has been created) - subscribeToLcns(); + if(!skipLcnSubscription) { + subscribeToLcns(); + } try { - registerMicroService(); + if(!skipSelfRegistration) { + registerMicroService(); + } } catch (RuntimeException e) { - deleteSubscriptions(); + if(!skipLcnSubscription) { + deleteSubscriptions(); + } throw e; } ready = true; @@ -86,24 +96,28 @@ public class SelfRegistrationManager { * De-register the VNFM driver from the micro-service bus */ public void deRegister() { - try { - logger.info("Cancelling micro service registration"); - msbApiProvider.getMsbApi().deleteMicroService(SERVICE_NAME, DRIVER_VERSION, null, null).blockingFirst(); - } catch (Exception e) { - //ONAP throws 500 internal server error, but deletes the micro service - boolean serviceFoundAfterDelete = false; + if(!skipSelfRegistration) { try { - msbApiProvider.getMsbApi().getMicroService_0(SERVICE_NAME, DRIVER_VERSION, null, null, null, null, null); - serviceFoundAfterDelete = true; - } catch (Exception e1) { - logger.info("Unable to query " + SERVICE_NAME + " from MSB (so the service was successfully deleted)", e1); - // the micro service was deleted (even though 500 HTTP code was reported) - } - if (serviceFoundAfterDelete) { - throw buildFatalFailure(logger, "Unable to deRegister Nokia VNFM driver", e); + logger.info("Cancelling micro service registration"); + msbApiProvider.getMsbApi().deleteMicroService(SERVICE_NAME, DRIVER_VERSION, null, null).blockingFirst(); + } catch (Exception e) { + //ONAP throws 500 internal server error, but deletes the micro service + boolean serviceFoundAfterDelete = false; + try { + msbApiProvider.getMsbApi().getMicroService_0(SERVICE_NAME, DRIVER_VERSION, null, null, null, null, null); + serviceFoundAfterDelete = true; + } catch (Exception e1) { + logger.info("Unable to query " + SERVICE_NAME + " from MSB (so the service was successfully deleted)", e1); + // the micro service was deleted (even though 500 HTTP code was reported) + } + if (serviceFoundAfterDelete) { + throw buildFatalFailure(logger, "Unable to deRegister Nokia VNFM driver", e); + } } } - deleteSubscriptions(); + if(!skipLcnSubscription) { + deleteSubscriptions(); + } } /** @@ -113,7 +127,7 @@ public class SelfRegistrationManager { */ @VisibleForTesting public void assureSubscription(String vnfmId) { - if (!vnfmIdToSubscriptionId.containsKey(vnfmId)) { + if (!vnfmIdToSubscriptionId.containsKey(vnfmId) && !skipLcnSubscription) { subscribeToLcn(vnfmId); } } diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/ISoV2LifecycleManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/ISoV2LifecycleManager.java new file mode 100644 index 00000000..32cc779e --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/ISoV2LifecycleManager.java @@ -0,0 +1,102 @@ +/* + * Copyright 2016-2017, Nokia Corporation + * + * 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. + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so; + +import javax.servlet.http.HttpServletResponse; +import org.onap.vnfmadapter.so.v2.model.*; + +public interface ISoV2LifecycleManager { + + /** + * Create the VNF in VNFM + * + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param request the SO VNF creation request + * @param httpResponse the HTTP response + */ + void createVnf(String vnfIdInAai, SoV2VnfCreateRequest request, HttpServletResponse httpResponse); + + /** + * Query VNF + * + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param request the VF module update request + * @param httpResponse the HTTP response + * @return the VNF query + */ + SoV2VnfQueryResponse queryVnf(String vnfIdInAai, SoV2VnfQueryRequest request, HttpServletResponse httpResponse); + + /** + * Delete the VNF in VNFM + * + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param request the VNF deletion request + * @param httpServletResponse the HTTP response + */ + void delete(String vnfIdInAai, SoV2VnfDeleteRequest request, HttpServletResponse httpServletResponse); + + /** + * Update the VNF in VNFM + * + * - only the VNF modifiable attributes are updated + * + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param request the SO VNF update request + * @param httpResponse the HTTP response + * @return the response the HTTP response + */ + SoV2VnfUpdateResponse updateVnf(String vnfIdInAai, SoV2VnfUpdateRequest request, HttpServletResponse httpResponse); + + + /** + * Rollback the operation on the VNFM + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param rollback the rollback parameters + */ + void rollback(String vnfIdInAai, SoV2RollbackVnfUpdate rollback, HttpServletResponse httpServletResponse); + + /** + * Create VF module in VNFM + * + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param vfModuleId the identifier of the VF module in A&AI + * @param request the creation request + * @param httpResponse the HTTP response + */ + void createVfModule(String vnfIdInAai, String vfModuleId, SoV2VfModuleCreateRequest request, HttpServletResponse httpResponse); + + /** + * Delete VF module in VNFM + * + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param vfModuleId the identifier of the VF module in A&AI + * @param request the deletion request + * @param httpResponse the HTTP response + */ + void deleteVfModule(String vnfIdInAai, String vfModuleId, SoV2VnfDeleteRequest request, HttpServletResponse httpResponse); + + /** + * Update VF module + * + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param vfModuleId the identifier of the VF module in A&AI + * @param request the VF module update request + * @param httpResponse the HTTP response + * @return the response + */ + SoV2VnfUpdateResponse updateVfModule(String vnfIdInAai, String vfModuleId, SoV2VnfUpdateRequest request, HttpServletResponse httpResponse); + +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoLifecycleManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoLifecycleManager.java deleted file mode 100644 index b368fa1f..00000000 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoLifecycleManager.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright 2016-2017, Nokia Corporation - * - * 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. - */ -package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so; - - -import com.nokia.cbam.lcm.v32.model.*; -import com.nokia.cbam.lcm.v32.model.VimInfo; -import java.util.ArrayList; -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VimInfoProvider; -import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.direct.AAIExternalSystemInfoProvider; -import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.direct.notification.GenericVnfManager; -import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils; -import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.*; -import org.onap.vnfmadapter.so.model.*; -import org.onap.vnfmdriver.model.ExtVirtualLinkInfo; -import org.onap.vnfmdriver.model.*; -import org.onap.vnfmdriver.model.VnfInfo; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import static java.util.Optional.of; -import static java.util.Optional.ofNullable; - -import static com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum.*; -import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.direct.notification.VnfcManager.buildCbamId; -import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION; -import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager.getVnfdIdFromModifyableAttributes; -import static org.onap.vnfmadapter.so.model.SoJobStatus.*; - -/** - * Responsible for providing access to AAI APIs. - * Handles authentication and mandatory parameters. - */ - -@Component -public class SoLifecycleManager { - private final LifecycleManager lifecycleManager; - private final VimInfoProvider vimInfoProvider; - private final CbamRestApiProvider cbamRestApiProvider; - private final JobManager jobManager; - private final GenericVnfManager genericVnfManager; - - - @Autowired - SoLifecycleManager(LifecycleManagerForSo lifecycleManager, AAIExternalSystemInfoProvider vimInfoProvider, CbamRestApiProviderForSo cbamRestApiProvider, JobManagerForSo jobManager, GenericVnfManager genericVnfManager) { - this.lifecycleManager = lifecycleManager; - this.vimInfoProvider = vimInfoProvider; - this.cbamRestApiProvider = cbamRestApiProvider; - this.jobManager = jobManager; - this.genericVnfManager = genericVnfManager; - } - - /** - * Creates the VNF in SO terminology - * - * @param vnfmId the identifier of the VNFM - * @param request the VNF creation request - * @return the VNF creation response - */ - public SoVnfCreationResponse create(String vnfmId, SoVnfCreationRequest request) { - SoVnfCreationResponse response = new SoVnfCreationResponse(); - LifecycleManager.VnfCreationResult result = lifecycleManager.create(vnfmId, request.getCsarId(), request.getName(), request.getDescription()); - response.setVnfId(result.getVnfInfo().getId()); - genericVnfManager.createOrUpdate(response.getVnfId(), false, vnfmId, ofNullable(request.getNsId())); - return response; - } - - /** - * Activate the VNF in SO terminology - * - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @param soRequest the VNF activation request - * @param httpResponse the HTTP response - * @return the job handler of the VNF activation - */ - public SoJobHandler activate(String vnfmId, String vnfId, SoVnfActivationRequest soRequest, HttpServletResponse httpResponse) { - AdditionalParameters additionalParameters = new AdditionalParameters(); - additionalParameters.setAdditionalParams(buildAdditionalParameters(soRequest.getAdditionalParams())); - String vimId = soRequest.getVimId(); - org.onap.vnfmdriver.model.VimInfo vimInfo = vimInfoProvider.getVimInfo(vimId); - additionalParameters.setVimType(vimTypeHeuristic(vimInfo.getUrl())); - processVdus(soRequest, additionalParameters, vimId); - additionalParameters.setInstantiationLevel("default"); - processNetworks(soRequest, additionalParameters, vimId); - processZones(soRequest, additionalParameters, vimId); - com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst(); - String onapVnfdId = getVnfdIdFromModifyableAttributes(cbamVnfInfo); - VnfInfo vnfInfo = lifecycleManager.queryVnf(vnfmId, vnfId); - List<ExtVirtualLinkInfo> externalVirtualLinks = new ArrayList<>(); - VnfInstantiateResponse instantiate = lifecycleManager.instantiate(vnfmId, externalVirtualLinks, httpResponse, soRequest.getAdditionalParams(), additionalParameters, vnfId, onapVnfdId, vnfInfo.getVnfdId()); - return buildJobHandler(instantiate.getJobId()); - } - - /** - * Scale the VNF - * - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @param soRequest the VNF scale request - * @param httpResponse the HTTP response - * @return the job handler of the VNF activation - */ - public SoJobHandler scale(String vnfmId, String vnfId, SoVnfScaleRequest soRequest, HttpServletResponse httpResponse) { - org.onap.vnfmdriver.model.VnfScaleRequest driverRequest = new org.onap.vnfmdriver.model.VnfScaleRequest(); - driverRequest.setAdditionalParam(buildAdditionalParameters(soRequest.getAdditionalParams())); - driverRequest.setAspectId(soRequest.getAspectId()); - driverRequest.setNumberOfSteps(soRequest.getSteps().toString()); - driverRequest.setType(soRequest.getDirection() == SoScaleDirection.IN ? org.onap.vnfmdriver.model.ScaleDirection.IN : org.onap.vnfmdriver.model.ScaleDirection.OUT); - return buildJobHandler(lifecycleManager.scaleVnf(vnfmId, vnfId, driverRequest, httpResponse).getJobId()); - } - - /** - * Heal the VNF - * - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @param request the VNF heal request - * @param httpResponse the HTTP response - * @return the job handler of the VNF activation - */ - public SoJobHandler heal(String vnfmId, String vnfId, SoVnfHealRequest request, HttpServletResponse httpResponse) { - org.onap.vnfmdriver.model.VnfHealRequest vnfHealRequest = new org.onap.vnfmdriver.model.VnfHealRequest(); - VnfHealRequestAffectedvm affectedVm = new VnfHealRequestAffectedvm(); - affectedVm.setVimid("notUsedByDriver"); - affectedVm.setVduid("notUsedByDriver"); - affectedVm.setVmname("unknown"); - vnfHealRequest.setAffectedvm(affectedVm); - vnfHealRequest.setAction("heal"); - return buildJobHandler(lifecycleManager.healVnf(vnfmId, vnfId, vnfHealRequest, of(buildCbamId(request.getVnfcId())), httpResponse).getJobId()); - } - - /** - * Deactivate the VNF - * - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @param soRequest the VNF deactivation request - * @param httpResponse the HTTP response - * @return the job handler of the VNF activation - */ - public SoJobHandler deactivate(String vnfmId, String vnfId, SoVnfTerminationRequest soRequest, HttpServletResponse httpResponse) { - VnfTerminateRequest driverRequest = new VnfTerminateRequest(); - if (soRequest.getMode() == SoTerminationMode.FORCEFUL) { - driverRequest.setTerminationType(VnfTerminationType.FORCEFUL); - } else { - driverRequest.setTerminationType(VnfTerminationType.GRACEFUL); - driverRequest.setGracefulTerminationTimeout(soRequest.getGracefulTerminationTimeoutInMs().toString()); - - } - return buildJobHandler(lifecycleManager.terminateAndDelete(vnfmId, vnfId, driverRequest, httpResponse).getJobId()); - } - - /** - * Delete the VNF - * - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @return the job handler of the VNF activation - */ - public void delete(String vnfmId, String vnfId) { - lifecycleManager.deleteVnf(vnfmId, vnfId); - } - - /** - * Execute a custom operation on a VNF - * - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @param request the VNF custom - * @param httpResponse the HTTP response - * @return the job handler of the VNF activation - */ - public SoJobHandler customOperation(String vnfmId, String vnfId, SoVnfCustomOperation request, HttpServletResponse httpResponse) { - String operationId = request.getOperationId(); - CustomOperationRequest cbamRequest = new CustomOperationRequest(); - cbamRequest.setAdditionalParams(buildAdditionalParameters(request.getAdditionalParams())); - return buildJobHandler(lifecycleManager.customOperation(vnfmId, vnfId, operationId, request.getAdditionalParams(), httpResponse).getJobId()); - } - - /** - * @param jobId the identifier of the job - * @param vnfmId the identifier of the VNFM - * @return the details of the job - */ - public SoJobDetail getJobDetails(String vnfmId, String jobId) { - SoJobDetail jobDetail = new SoJobDetail(); - jobDetail.setJobId(jobId); - JobStatus currentStatus = jobManager.getJob(vnfmId, jobId).getResponseDescriptor().getStatus(); - if (JobStatus.STARTED.equals(currentStatus)) { - jobDetail.setStatus(STARTED); - } else if (JobStatus.PROCESSING.equals(currentStatus)) { - jobDetail.setStatus(STARTED); - } else if (JobStatus.FINISHED.equals(currentStatus)) { - jobDetail.setStatus(FINISHED); - } else if (JobStatus.TIMEOUT.equals(currentStatus)) { - jobDetail.setStatus(FAILED); - } else {//ERROR - jobDetail.setStatus(FAILED); - } - return jobDetail; - } - - private VimInfo.VimInfoTypeEnum vimTypeHeuristic(String url) { - if (url.contains("/v3")) { - return OPENSTACK_V3_INFO; - } else if (url.contains("/v2")) { - return OPENSTACK_V2_INFO; - } else { - return VMWARE_VCLOUD_INFO; - } - } - - private Object buildAdditionalParameters(Object additionalParams) { - return additionalParams; - } - - private SoJobHandler buildJobHandler(String jobId) { - SoJobHandler jobHandler = new SoJobHandler(); - jobHandler.setJobId(jobId); - return jobHandler; - } - - private void processVdus(SoVnfActivationRequest request, AdditionalParameters additionalParameters, String vimId) { - if (request.getVduMappings() != null) { - for (SoVduMapping vduMapping : request.getVduMappings()) { - VimComputeResourceFlavour flavour = new VimComputeResourceFlavour(); - flavour.setVimId(vimId); - flavour.setVnfdVirtualComputeDescId(vduMapping.getVduId()); - flavour.setResourceId(vduMapping.getFlavourId()); - additionalParameters.getComputeResourceFlavours().add(flavour); - VimSoftwareImage image = new VimSoftwareImage(); - image.setVimId(vimId); - image.setResourceId(vduMapping.getImageId()); - image.setVnfdSoftwareImageId(vduMapping.getVduId() + CbamUtils.SEPARATOR + "image"); - additionalParameters.getSoftwareImages().add(image); - } - } - } - - private void processNetworks(SoVnfActivationRequest request, AdditionalParameters additionalParameters, String vimId) { - if (request.getNetworkMappings() != null) { - for (SoNetworkMapping networkMapping : request.getNetworkMappings()) { - ExtVirtualLinkData extVirtualLinkData = createExtVirtualLinkData(additionalParameters, networkMapping.getVldId()); - extVirtualLinkData.setVimId(vimId); - extVirtualLinkData.setResourceId(networkMapping.getNetworkProviderId()); - processAssingedAddress(networkMapping, extVirtualLinkData); - } - } - } - - private void processAssingedAddress(SoNetworkMapping networkMapping, ExtVirtualLinkData extVirtualLinkData) { - if (networkMapping.getAssignedAddresses() != null) { - for (SoAssignedAddresses assignedAddresses : networkMapping.getAssignedAddresses()) { - VnfExtCpData extCpData = createExtVirtualLinkData(extVirtualLinkData.getExtCps(), assignedAddresses.getCpdId()); - addMissing(extCpData, assignedAddresses.getIpAddress()); - } - } - } - - private void processZones(SoVnfActivationRequest request, AdditionalParameters additionalParameters, String vimId) { - if (request.getServerMappings() != null) { - for (SoServerMapping serverMapping : request.getServerMappings()) { - ZoneInfo zone = locateOrCreateZone(additionalParameters.getZones(), serverMapping.getVduId()); - zone.setResourceId(serverMapping.getAvailabilityZoneId()); - zone.setVimId(vimId); - } - } - } - - private ZoneInfo locateOrCreateZone(List<ZoneInfo> zones, String vduId) { - for (ZoneInfo zone : zones) { - if (zone.getId().equals(vduId)) { - return zone; - } - } - ZoneInfo zoneInfo = new ZoneInfo(); - zoneInfo.setId(vduId); - zones.add(zoneInfo); - return zoneInfo; - } - - private void addMissing(VnfExtCpData extCpData, String ipAddress) { - if (extCpData.getAddresses() == null) { - extCpData.setAddresses(new ArrayList<>()); - } - for (NetworkAddress networkAddress : extCpData.getAddresses()) { - if (ipAddress.equals(networkAddress.getIp())) { - return; - } - } - NetworkAddress address = new NetworkAddress(); - address.setIp(ipAddress); - extCpData.getAddresses().add(address); - } - - private VnfExtCpData createExtVirtualLinkData(List<VnfExtCpData> extCps, String cpdId) { - for (VnfExtCpData extCp : extCps) { - if (extCp.getCpdId().equals(cpdId)) { - return extCp; - } - } - VnfExtCpData extCp = new VnfExtCpData(); - extCp.setCpdId(cpdId); - extCps.add(extCp); - return extCp; - } - - private ExtVirtualLinkData createExtVirtualLinkData(AdditionalParameters additionalParameters, String virtualLinkId) { - ExtVirtualLinkData nonExistingVl = new ExtVirtualLinkData(); - nonExistingVl.setExtVirtualLinkId(virtualLinkId); - additionalParameters.getExtVirtualLinks().add(nonExistingVl); - return nonExistingVl; - } -}
\ No newline at end of file diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoV2LifecycleManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoV2LifecycleManager.java new file mode 100644 index 00000000..708f9477 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoV2LifecycleManager.java @@ -0,0 +1,421 @@ +/* + * Copyright 2016-2017, Nokia Corporation + * + * 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. + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so; + + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.nokia.cbam.lcm.v32.model.*; +import com.nokia.cbam.lcm.v32.model.VnfInfo; +import java.util.*; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; +import org.onap.aai.model.GenericVnf; +import org.onap.aai.model.VfModule; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IPackageProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.direct.AAIExternalSystemInfoProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.direct.AAIRestApiProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.direct.SdcPackageProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.OnapR2HeatPackageBuilder; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.*; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.LifecycleChangeNotificationManager; +import org.onap.vnfmadapter.so.v2.model.*; +import org.onap.vnfmdriver.model.ExtVirtualLinkInfo; +import org.onap.vnfmdriver.model.*; +import org.onap.vnfmdriver.model.ScaleDirection; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.yaml.snakeyaml.Yaml; + +import static java.util.Optional.empty; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.OnapR2HeatPackageBuilder.*; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.*; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Responsible for providing access to AAI APIs. + * Handles authentication and mandatory parameters. + */ +@Component +public class SoV2LifecycleManager implements ISoV2LifecycleManager{ + private static Logger logger = getLogger(SoV2LifecycleManager.class); + private final LifecycleManager lifecycleManager; + private final CbamRestApiProvider cbamRestApiProvider; + private final JobManager jobManager; + private final AAIRestApiProvider aaiRestApiProvider; + private final AAIExternalSystemInfoProvider aaiExternalSystemInfoProvider; + private final IPackageProvider packageProvider; + + @Autowired + SoV2LifecycleManager(LifecycleManagerForSo lifecycleManager, CbamRestApiProviderForSo cbamRestApiProvider, JobManagerForSo jobManager, AAIRestApiProvider aaiRestApiProvider, AAIExternalSystemInfoProvider aaiExternalSystemInfoProvider, SdcPackageProvider packageProvider) { + this.lifecycleManager = lifecycleManager; + this.cbamRestApiProvider = cbamRestApiProvider; + this.jobManager = jobManager; + this.aaiRestApiProvider = aaiRestApiProvider; + this.aaiExternalSystemInfoProvider = aaiExternalSystemInfoProvider; + this.packageProvider = packageProvider; + } + + @Override + public void createVnf(String vnfIdInAai, SoV2VnfCreateRequest request, HttpServletResponse httpResponse) { + GenericVnf genericVnf = aaiRestApiProvider.getNetworkApi().getNetworkGenericVnfsGenericVnf(vnfIdInAai, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).blockingFirst(); + VnfmInfo vnfmInfo = locateVnfm(genericVnf); + Optional<com.nokia.cbam.lcm.v32.model.VnfInfo> matchingVnf = locateVnfBasedOnAaiVnfId(vnfIdInAai, vnfmInfo); + if (request.isFailIfExists() != null && request.isFailIfExists()) { + if (matchingVnf.isPresent()) { + throw buildFatalFailure(logger, "The VNF with " + vnfIdInAai + " identifier in A&AI can not be found in the VNFM"); + } + } + String vnfIdInVnfm = null; + if (!matchingVnf.isPresent()) { + try { + LifecycleManager.VnfCreationResult creationResult = lifecycleManager.create(vnfmInfo.getVnfmId(), genericVnf.getModelVersionId(), request.getName(), vnfIdInAai); + vnfIdInVnfm = creationResult.getVnfInfo().getId(); + } catch (Exception e) { + logger.warn("Unable to create VNF with " + vnfIdInAai + " identifier in AAI", e); + cleanUpVnf(vnfIdInAai, vnfmInfo, request, httpResponse); + } + } else { + vnfIdInVnfm = matchingVnf.get().getId(); + } + try { + com.nokia.cbam.lcm.v32.model.VnfInfo vnfAfterCreation = cbamRestApiProvider.getCbamLcmApi(vnfmInfo.getVnfmId()).vnfsVnfInstanceIdGet(vnfIdInVnfm, CbamRestApiProvider.NOKIA_LCM_API_VERSION).blockingFirst(); + updateModifiableAttributes(vnfmInfo.getVnfmId(), vnfAfterCreation, request.getInputs()); + String vimId = request.getCloudOwner() + SEPARATOR + request.getRegionName(); + List<ExtVirtualLinkInfo> externalVirtualLinks = addExtVirtualLinks(vimId, request.getInputs()); + JsonObject operationAdditionalParameters = new JsonObject(); + operationAdditionalParameters.addProperty("vimId", vimId); + AdditionalParameters additionalParameters = buildAdditionalParameters(request, genericVnf, vimId); + String etsiVnfdId = packageProvider.getCbamVnfdId(genericVnf.getModelVersionId()); + if (!vnfAfterCreation.getInstantiationState().equals(InstantiationState.INSTANTIATED)) { + lifecycleManager.instantiate(vnfmInfo.getVnfmId(), externalVirtualLinks, httpResponse, operationAdditionalParameters, additionalParameters, vnfIdInVnfm, genericVnf.getModelVersionId(), etsiVnfdId); + logger.info("The VNF in VNFM with " + vnfIdInAai + " identifier in A&AI and " + vnfIdInVnfm + " identifier in VNFM has been instantiated"); + } else { + logger.info("The VNF in VNFM with " + vnfIdInAai + " identifier in A&AI and " + vnfIdInVnfm + " identifier in VNFM is already instantiated"); + } + } catch (Exception e) { + logger.warn("The VNF in VNFM with " + vnfIdInAai + " identifier in A&AI and " + vnfIdInVnfm + " identifier in VNFM can not be instantiated", e); + cleanUpVnf(vnfIdInAai, vnfmInfo, request, httpResponse); + } + } + + @Override + public SoV2VnfQueryResponse queryVnf(String vnfIdInAai, SoV2VnfQueryRequest request, HttpServletResponse httpResponse) { + GenericVnf genericVnf = aaiRestApiProvider.getNetworkApi().getNetworkGenericVnfsGenericVnf(vnfIdInAai, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).blockingFirst(); + VnfmInfo vnfmInfo = locateVnfm(genericVnf); + Optional<com.nokia.cbam.lcm.v32.model.VnfInfo> matchingVnf = locateVnfBasedOnAaiVnfId(vnfIdInAai, vnfmInfo); + SoV2VnfQueryResponse response = new SoV2VnfQueryResponse(); + response.setStatus(getStatus(vnfmInfo, matchingVnf)); + return response; + } + + private SoVnfStatus getStatus(VnfmInfo vnfmInfo, Optional<VnfInfo> matchingVnf) { + if(matchingVnf.isPresent()){ + OperationExecution lastOperation = findLastOperation(vnfmInfo.getVnfmId(), matchingVnf.get().getId()); + if(lastOperation.getStatus().equals(OperationStatus.FINISHED)){ + return SoVnfStatus.ACTIVE; + } + else if(lastOperation.getStatus().equals(OperationStatus.FAILED)){ + return SoVnfStatus.FAILED; + } + else { + return SoVnfStatus.UNKNOWN; + } + } + else{ + return SoVnfStatus.NOTFOUND; + } + } + + private void cleanUpVnf(String vnfIdInAai, VnfmInfo vnfmInfo, SoV2VnfCreateRequest request, HttpServletResponse httpServletResponse) { + if(request.isDeleteUponFailure() != null && request.isDeleteUponFailure()) { + logger.info("Cleaning up the VNF in VNFM with " + vnfIdInAai + " identifier in A&AI"); + SoV2VnfDeleteRequest deleteRequest = new SoV2VnfDeleteRequest(); + deleteRequest.setMsoRequest(request.getMsoRequest()); + delete(vnfIdInAai, deleteRequest, httpServletResponse); + } + } + + private AdditionalParameters buildAdditionalParameters(SoV2VnfCreateRequest request, GenericVnf genericVnf, String vimId) { + AdditionalParameters additionalParameters = new AdditionalParameters(); + buildZones(additionalParameters, vimId, request.getInputs()); + JsonObject cbamVnfd = new Gson().toJsonTree(new Yaml().load(packageProvider.getCbamVnfdId(genericVnf.getModelVersionId()))).getAsJsonObject(); + VduMappings vduMappings = getVduToVirtualComputeDescriptoId(cbamVnfd); + buildFlavours(vimId, additionalParameters, request.getInputs(), vduMappings.vduIdToVirtualComputeId); + buildExtenstions(request, additionalParameters); + buildImages(vimId, vduMappings, additionalParameters, request.getInputs()); + setInstantiationLevel(cbamVnfd, additionalParameters); + return additionalParameters; + } + + private List<ExtVirtualLinkInfo> addExtVirtualLinks(String vimId, SoInput inputs) { + List<ExtVirtualLinkInfo> externalVirtualLinks = new ArrayList<>(); + for (Map.Entry<String, String> netInput : filterInput(inputs, ".*" + NET_ID)) { + ExtVirtualLinkInfo vl = new ExtVirtualLinkInfo(); + String ecpId = netInput.getKey().replaceAll(NET_ID + "$", ""); + vl.setVim(new ExtVirtualLinkInfoVim()); + vl.getVim().setVimid(vimId); + vl.setResourceId(netInput.getValue()); + vl.setCpdId(ecpId); + externalVirtualLinks.add(vl); + } + return externalVirtualLinks; + } + + private void setInstantiationLevel(JsonObject cbamVnfd, AdditionalParameters additionalParameters) { + JsonObject topologyTemplate = child(cbamVnfd, "topology_template"); + JsonObject substitutionMappings = child(topologyTemplate, "substitution_mappings"); + JsonObject deploymentFlavor = child(child(substitutionMappings, "capabilities"), "deployment_flavour"); + String defaultInstantiationLevel = childElement(child(deploymentFlavor, "properties"), "default_instantiation_level_id").getAsString(); + additionalParameters.setInstantiationLevel(defaultInstantiationLevel); + } + + private void buildImages(String vimId, VduMappings vduMappings, AdditionalParameters additionalParameters, SoInput inputs) { + for (Map.Entry<String, String> imageInput : filterInput(inputs, ".*" + IMAGE_NAME)) { + String vduName = imageInput.getKey().replace(IMAGE_NAME, ""); + if (vduMappings.vduIdToVirtualSoftwareId.containsKey(vduName)) { + VimSoftwareImage image = new VimSoftwareImage(); + image.setVimId(vimId); + image.setResourceId(imageInput.getKey()); + image.setVnfdSoftwareImageId(vduMappings.vduIdToVirtualSoftwareId.get(vduName)); + additionalParameters.getSoftwareImages().add(image); + } + } + } + + private void buildExtenstions(SoV2VnfCreateRequest request, AdditionalParameters additionalParameters) { + for (Map.Entry<String, String> extenstion : filterInput(request.getInputs(), ".*" + ETSI_MODIFIABLE_ATTRIBUTES_EXTENSTION)) { + VnfProperty property = new VnfProperty(); + property.setName(extenstion.getKey().replace(ETSI_MODIFIABLE_ATTRIBUTES_EXTENSTION, "")); + property.setValue(extenstion.getValue()); + additionalParameters.getExtensions().add(property); + } + } + + private static class VduMappings { + HashMap<String, String> vduIdToVirtualComputeId = new HashMap<>(); + HashMap<String, String> vduIdToVirtualSoftwareId = new HashMap<>(); + } + + private VduMappings getVduToVirtualComputeDescriptoId(JsonObject root) { + VduMappings vduMappings = new VduMappings(); + JsonObject topologyTemplate = child(root, "topology_template"); + JsonObject nodeTemplates = child(topologyTemplate, "node_templates"); + for (Map.Entry<String, JsonElement> vdu : OnapR2HeatPackageBuilder.filterType(nodeTemplates, "tosca.nodes.nfv.VDU")) { + boolean found = false; + for (JsonElement requirement : childElement(vdu.getValue().getAsJsonObject(), "requirements").getAsJsonArray()) { + if (requirement.getAsJsonObject().has("virtual_compute")) { + vduMappings.vduIdToVirtualComputeId.put(vdu.getKey(), requirement.getAsJsonObject().get("virtual_compute").getAsString()); + found = true; + } + if (requirement.getAsJsonObject().has("sw_image")) { + vduMappings.vduIdToVirtualSoftwareId.put(vdu.getKey(), requirement.getAsJsonObject().get("sw_image").getAsString()); + } + } + if (!found) { + throw buildFatalFailure(logger, "Unable to find virtualComputeDescriptor for " + vdu.getKey() + " identifier"); + } + } + return vduMappings; + } + + private void buildFlavours(String vimId, AdditionalParameters additionalParameters, SoInput inputs, Map<String, String> vduToVirtualComputeDescriptoId) { + for (Map.Entry<String, String> input : filterInput(inputs, ".*_flavor_name")) { + String vduName = input.getKey().replaceAll("_flavor_name$", ""); + VimComputeResourceFlavour flavor = new VimComputeResourceFlavour(); + flavor.setVimId(vimId); + flavor.setVnfdVirtualComputeDescId(vduToVirtualComputeDescriptoId.get(vduName)); + flavor.setResourceId(input.getValue()); + additionalParameters.getComputeResourceFlavours().add(flavor); + } + } + + private Set<Map.Entry<String, String>> filterInput(SoInput input, String pattern) { + return input.entrySet().stream().filter(i -> i.getKey().matches(pattern)).collect(Collectors.toSet()); + } + + private void buildZones(AdditionalParameters additionalParameters, String vimId, SoInput inputs) { + for (Map.Entry<String, String> input : filterInput(inputs, "availability_zone_[0-9]*")) { + ZoneInfo zone = new ZoneInfo(); + zone.setId(input.getKey()); + zone.setResourceId(input.getValue()); + zone.setVimId(vimId); + additionalParameters.getZones().add(zone); + } + } + + private OperationExecution findLastOperation(String vnfmId, String vnfIdInVnfm) { + List<OperationExecution> operationExecutions = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdOperationExecutionsGet(vnfIdInVnfm, CbamRestApiProvider.NOKIA_LCM_API_VERSION).blockingFirst(); + return LifecycleChangeNotificationManager.NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions).get(0); + } + + @Override + public void delete(String vnfIdInAai, SoV2VnfDeleteRequest request, HttpServletResponse httpServletResponse) { + GenericVnf genericVnf = aaiRestApiProvider.getNetworkApi().getNetworkGenericVnfsGenericVnf(vnfIdInAai, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).blockingFirst(); + VnfmInfo vnfmInfo = locateVnfm(genericVnf); + Optional<com.nokia.cbam.lcm.v32.model.VnfInfo> matchingVnf = locateVnfBasedOnAaiVnfId(vnfIdInAai, vnfmInfo); + if (matchingVnf.isPresent()) { + VnfTerminateRequest terminateRequest = new VnfTerminateRequest(); + terminateRequest.setTerminationType(VnfTerminationType.GRACEFUL); + terminateRequest.setGracefulTerminationTimeout(Long.valueOf(60 * 60 * 1000L).toString()); + jobManager.waitForJobToFinish(lifecycleManager.terminateAndDelete(vnfmInfo.getVnfmId(), matchingVnf.get().getId(), terminateRequest, httpServletResponse)); + } + } + + @Override + public void rollback(String vnfIdInAai, SoV2RollbackVnfUpdate rollback, HttpServletResponse httpServletResponse) { + GenericVnf genericVnf = aaiRestApiProvider.getNetworkApi().getNetworkGenericVnfsGenericVnf(vnfIdInAai, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).blockingFirst(); + VnfmInfo vnfmInfo = locateVnfm(genericVnf); + VnfInfo vnfInfo = expectVnfBasedOnAaiVnfId(vnfIdInAai, vnfmInfo); + ModifyVnfInfoRequest request= new ModifyVnfInfoRequest(); + request.setExtensions(buildExtension(rollback.getOriginalVnfProperties())); + lifecycleManager.executeModifyVnfInfo(vnfmInfo.getVnfmId(), vnfInfo.getId(), request); + } + + @Override + public void createVfModule(String vnfIdInAai, String vfModuleId, SoV2VfModuleCreateRequest request, HttpServletResponse httpResponse) { + GenericVnf genericVnf = aaiRestApiProvider.getNetworkApi().getNetworkGenericVnfsGenericVnf(vnfIdInAai, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).blockingFirst(); + VnfmInfo vnfmInfo = locateVnfm(genericVnf); + VnfInfo vnfInfo = expectVnfBasedOnAaiVnfId(vnfIdInAai, vnfmInfo); + healVnfIfRequired(vnfIdInAai, httpResponse, vnfmInfo, vnfInfo); + executeScale(request.getScalingAspectId(), httpResponse, genericVnf, vnfmInfo, vnfInfo); + } + + @Override + public void deleteVfModule(String vnfIdInAai, String vfModuleId, SoV2VnfDeleteRequest request, HttpServletResponse httpResponse) { + GenericVnf genericVnf = aaiRestApiProvider.getNetworkApi().getNetworkGenericVnfsGenericVnf(vnfIdInAai, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).blockingFirst(); + VnfmInfo vnfmInfo = locateVnfm(genericVnf); + VnfInfo vnfInfo = expectVnfBasedOnAaiVnfId(vnfIdInAai, vnfmInfo); + VfModule vfModule = aaiRestApiProvider.getNetworkApi().getNetworkGenericVnfsGenericVnfVfModulesVfModule(genericVnf.getVnfId(), vfModuleId, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).blockingFirst(); + String aspectId = vfModule.getHeatStackId(); + executeScale(aspectId, httpResponse, genericVnf, vnfmInfo, vnfInfo); + healVnfIfRequired(vnfIdInAai, httpResponse, vnfmInfo, vnfInfo); + } + + @Override + public SoV2VnfUpdateResponse updateVfModule(String vnfIdInAai, String vfModuleId, SoV2VnfUpdateRequest request, HttpServletResponse httpResponse) { + return updateVnf(vnfIdInAai, request, httpResponse); + } + + private void executeScale(String aspectId, HttpServletResponse httpResponse, GenericVnf genericVnf, VnfmInfo vnfmInfo, VnfInfo vnfInfo) { + ScaleInfo scaleInfo = vnfInfo.getInstantiatedVnfInfo().getScaleStatus().stream().filter(s -> s.getAspect().equals(aspectId)).findFirst().get(); + long expectedStepCount = genericVnf.getVfModules().stream().filter(m -> m.getHeatStackId().equals(aspectId)).count(); + if(expectedStepCount != scaleInfo.getScaleLevel().longValue()){ + VnfScaleRequest scaleRequest = new VnfScaleRequest(); + scaleRequest.setAspectId(aspectId); + scaleRequest.setType(expectedStepCount > scaleInfo.getScaleLevel().longValue() ? ScaleDirection.OUT : ScaleDirection.IN); + scaleRequest.setNumberOfSteps(Long.valueOf(Math.abs(expectedStepCount - scaleInfo.getScaleLevel().longValue())).toString()); + JobInfo jobInfo = lifecycleManager.scaleVnf(vnfmInfo.getVnfmId(), vnfInfo.getId(), scaleRequest, httpResponse); + jobManager.waitForJobToFinish(jobInfo); + } + } + + private void healVnfIfRequired(String vnfIdInAai, HttpServletResponse httpResponse, VnfmInfo vnfmInfo, VnfInfo vnfInfo) { + OperationExecution lastOperation = findLastOperation(vnfmInfo.getVnfmId(), vnfIdInAai); + if(lastOperation.getStatus().equals(OperationStatus.FAILED)){ + VnfHealRequest healRequest = new VnfHealRequest(); + healRequest.setAffectedvm(new VnfHealRequestAffectedvm()); + healRequest.setAction("reboot"); + JobInfo jobInfo = lifecycleManager.healVnf(vnfmInfo.getVnfmId(), vnfInfo.getId(), healRequest, empty(), httpResponse); + jobManager.waitForJobToFinish(jobInfo); + } + } + + @Override + public SoV2VnfUpdateResponse updateVnf(String vnfIdInAai, SoV2VnfUpdateRequest request, HttpServletResponse httpResponse) { + GenericVnf genericVnf = aaiRestApiProvider.getNetworkApi().getNetworkGenericVnfsGenericVnf(vnfIdInAai, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).blockingFirst(); + VnfmInfo vnfmInfo = locateVnfm(genericVnf); + Optional<com.nokia.cbam.lcm.v32.model.VnfInfo> matchingVnf = locateVnfBasedOnAaiVnfId(vnfIdInAai, vnfmInfo); + Map<String, String> specifiedExtensions = collecSpecifiedExtensions(request.getInputs()); + SoV2VnfUpdateResponse response = new SoV2VnfUpdateResponse(); + Map<String, String> existingProperties = matchingVnf.get().getExtensions().stream().filter(p -> specifiedExtensions.containsKey(p.getName())).collect(Collectors.toMap(vnfProperty -> vnfProperty.getName(), vnfProperty -> vnfProperty.getValue().toString())); + response.setOriginalVnfProperties(new OriginalVnfProperties()); + response.getOriginalVnfProperties().putAll(existingProperties); + if(matchingVnf.isPresent()){ + try{ + ModifyVnfInfoRequest modifyRequest = new ModifyVnfInfoRequest(); + modifyRequest.setExtensions(buildExtension(specifiedExtensions)); + lifecycleManager.executeModifyVnfInfo(vnfmInfo.getVnfmId(), matchingVnf.get().getId(), modifyRequest); + response.setSuccessful(true); + } + catch (Exception e){ + response.setSuccessful(false); + } + return response; + } + else{ + throw buildFatalFailure(logger, "No VNF with " + vnfIdInAai + " identifier in A&AI exists in the VNFM"); + } + } + + private List<VnfProperty> buildExtension(Map<String, String> specifiedExtensions) { + return specifiedExtensions.entrySet().stream().map(e -> { + VnfProperty p = new VnfProperty(); + p.setName(e.getKey()); + p.setValue(e.getValue()); + return p; + }).collect(toList()); + } + + private void updateModifiableAttributes(String vnfmId, com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo, SoInput inputs) { + ModifyVnfInfoRequest request = new ModifyVnfInfoRequest(); + request.setExtensions(new ArrayList<>()); + Map<String, String> specifedExtensions = collecSpecifiedExtensions(inputs); + for (Map.Entry<String, String> specifiedExtension : specifedExtensions.entrySet()) { + Optional<VnfProperty> exactProperty = vnfInfo.getExtensions().stream().filter(p -> p.getName().equals(specifiedExtension.getKey()) && p.getValue().equals(specifiedExtension.getValue())).findFirst(); + if (!exactProperty.isPresent()) { + VnfProperty onapCsarIdProperty = new VnfProperty(); + onapCsarIdProperty.setName(specifiedExtension.getKey()); + onapCsarIdProperty.setValue(specifiedExtension.getValue()); + request.getExtensions().add(onapCsarIdProperty); + } + } + if (!request.getExtensions().isEmpty()) { + lifecycleManager.executeModifyVnfInfo(vnfmId, vnfInfo.getId(), request); + } + } + + private Map<String, String> collecSpecifiedExtensions(SoInput inputs) { + return inputs.entrySet().stream().filter(i -> i.getKey().startsWith("etsi.modifiableAttribute.")).collect(toMap(i -> i.getKey().replace("etsi.modifiableAttribute.", ""), i -> i.getValue())); + } + + private Optional<com.nokia.cbam.lcm.v32.model.VnfInfo> locateVnfBasedOnAaiVnfId(String vnfIdInAai, VnfmInfo vnfmInfo) { + return cbamRestApiProvider.getCbamLcmApi(vnfmInfo.getVnfmId()).vnfsGet(CbamRestApiProvider.NOKIA_LCM_API_VERSION).blockingFirst().stream().filter(vnf -> vnf.getDescription().equals(vnfIdInAai)).findFirst(); + } + + private com.nokia.cbam.lcm.v32.model.VnfInfo expectVnfBasedOnAaiVnfId(String vnfIdInAai, VnfmInfo vnfmInfo) { + Optional<VnfInfo> vnfInfo = locateVnfBasedOnAaiVnfId(vnfIdInAai, vnfmInfo); + if(!vnfInfo.isPresent()){ + throw buildFatalFailure(logger, "Unable to locate VNF with " + vnfIdInAai + " A&AI identifier in VNFM"); + } + return vnfInfo.get(); + } + + private VnfmInfo locateVnfm(GenericVnf vnf) { + for (String vnfmId : aaiExternalSystemInfoProvider.getVnfms()) { + VnfmInfo vnfmInfo = aaiExternalSystemInfoProvider.queryVnfmInfoFromSource(vnfmId); + if (vnfmInfo.getType().equals(vnf.getNfType())) { + return vnfmInfo; + } + } + throw buildFatalFailure(logger, "Unable to locate a VNFM for VNF with " + vnf.getVnfId() + " identifier with " + vnf.getNfType() + " type"); + } +}
\ No newline at end of file diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java new file mode 100644 index 00000000..f437a902 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java @@ -0,0 +1,216 @@ +/* + * Copyright 2016-2017, Nokia Corporation + * + * 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. + */ + +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer; + +import com.google.common.collect.Sets; +import com.google.gson.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager; +import org.slf4j.Logger; +import org.yaml.snakeyaml.Yaml; + +import static java.util.stream.Collectors.toSet; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.*; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Transforms a CBAM package into an ONAP package + */ +public class OnapR2HeatPackageBuilder { + public static final String ETSI_MODIFIABLE_ATTRIBUTES_EXTENSTION = "etsi_modifiable_attributes_extenstion_"; + public static final String IMAGE_NAME = "_image_name"; + public static final String FLAVOR_NAME = "_flavor_name"; + public static final String NET_ID = "_net_id"; + private static Logger logger = getLogger(OnapR2HeatPackageBuilder.class); + public static final String BASE_ENV_FILE_NAME = "base.env"; + public static final String BASE_YAML_FILE_NAME = "base.yaml"; + + private Set<String> autoManagedExtensions = Sets.newHashSet(LifecycleManager.ONAP_CSAR_ID, LifecycleManager.EXTERNAL_VNFM_ID); + + Map<String, String> processVnfd(String cbamVnfd) { + Map<String, String> files = new HashMap<>(); + JsonObject root = new Gson().toJsonTree(new Yaml().load(cbamVnfd)).getAsJsonObject(); + JsonObject topologyTemplate = child(root, "topology_template"); + JsonObject substitutionMappings = child(topologyTemplate, "substitution_mappings"); + JsonObject capabilities = child(substitutionMappings, "capabilities"); + JsonObject deploymentFlavour = child(capabilities, "deployment_flavour"); + JsonArray policies = childElement(topologyTemplate, "policies").getAsJsonArray(); + JsonObject manifest = new JsonObject(); + manifest.addProperty("name", "ONAP VNF package"); + manifest.addProperty("description", ""); + JsonArray data = new JsonArray(); + manifest.add("data", data); + JsonObject deploymentFlavorProperties = child(deploymentFlavour, "properties"); + if (deploymentFlavorProperties.has("scaling_aspects")) { + JsonObject scalingAspects = child(deploymentFlavorProperties, "scaling_aspects"); + for (Map.Entry<String, JsonElement> scalingAspect : scalingAspects.entrySet()) { + processAspect(files, data, policies, scalingAspect.getKey(), childElement(scalingAspect.getValue().getAsJsonObject(), "max_scale_level").getAsLong()); + } + } + processBaseIncrement(topologyTemplate, files, policies, data); + files.put("MANIFEST.json", new GsonBuilder().setPrettyPrinting().create().toJson(manifest)); + return files; + } + + private void processBaseIncrement(JsonObject topologyTemplate, Map<String, String> files, JsonArray policies, JsonArray data) { + StringBuilder envContent = prepareEvnContent(); + StringBuilder yamlContent = prepareYamlContent(); + if (topologyTemplate.has("node_templates")) { + JsonObject nodeTemplates = child(topologyTemplate, "node_templates"); + processEcps(nodeTemplates, envContent, yamlContent); + for (Map.Entry<String, JsonElement> vdu : filterType(nodeTemplates, "tosca.nodes.nfv.VDU")) { + addImageAndFlavor(envContent, yamlContent, vdu); + } + } + processModifiableAttributes(topologyTemplate, envContent, yamlContent); + data.add(buildManifestEntry(BASE_ENV_FILE_NAME, BASE_YAML_FILE_NAME, true)); + files.put(BASE_ENV_FILE_NAME, envContent.toString()); + files.put(BASE_YAML_FILE_NAME, yamlContent.toString()); + } + + private void processModifiableAttributes(JsonObject topologyTemplate, StringBuilder envContent, StringBuilder yamlContent) { + JsonObject capabilities = child(child(topologyTemplate, "substitution_mappings"), "capabilities"); + if (capabilities.has("vnf")) { + JsonObject vnf = child(capabilities, "vnf"); + if (vnf.has("properties")) { + JsonObject properties = child(vnf, "properties"); + if (properties.has("modifiable_attributes")) { + JsonObject modifiableAttributes = child(properties, "modifiable_attributes"); + if (modifiableAttributes.has("extensions")) { + JsonObject extensions = child(modifiableAttributes, "extensions"); + for (Map.Entry<String, JsonElement> extension : extensions.entrySet()) { + if (!autoManagedExtensions.contains(extension.getKey())) { + addParameter(yamlContent, envContent, ETSI_MODIFIABLE_ATTRIBUTES_EXTENSTION + extension.getKey(), "Modifiable attribute", "Modifiable attribute for " + extension.getKey()); + } + } + } + } + } + } + } + + public static Set<Map.Entry<String, JsonElement>> filterType(JsonObject nodeTemplates, String type) { + return nodeTemplates.entrySet().stream().filter(e -> e.getValue().getAsJsonObject().get("type").equals(type)).collect(toSet()); + } + + private void processEcps(JsonObject nodeTemplates, StringBuilder envContent, StringBuilder yamlContent) { + for (Map.Entry<String, JsonElement> node : filterType(nodeTemplates, "tosca.nodes.nfv.ECP")) { + envContent.append(" " + node.getKey() + NET_ID + ": PUT YOUR NETWORK ID HERE\n"); + addYamlParameter(yamlContent, node.getKey() + NET_ID, "Network id", "Network identifier for " + node.getKey() + " ECP"); + } + } + + private StringBuilder prepareYamlContent() { + StringBuilder yamlContent = new StringBuilder(); + yamlContent.append("heat_template_version: 2013-05-23\n"); + yamlContent.append("parameters:\n"); + return yamlContent; + } + + private void processAspect(Map<String, String> files, JsonArray data, JsonArray policies, String aspectName, long maxScaleLevel) { + JsonObject aspect = locateAspect(locateHeatPolicy(policies), aspectName); + StringBuilder envContent = prepareEvnContent(); + StringBuilder yamlContent = prepareYamlContent(); + if (aspect.has("vdus")) { + processMapping(aspect, envContent, yamlContent); + } + if (maxScaleLevel > 1001) { + throw buildFatalFailure(logger, "Refusing to create more than 1001 scaling levels"); + } + envContent.append(" etsi.scalingAspectId: "+ aspectName + "\n"); + for (int scaleIndex = 0; scaleIndex < maxScaleLevel; scaleIndex++) { + String envFileName = "module_" + aspectName + "_" + scaleIndex + ".env"; + files.put(envFileName, envContent.toString()); + String yamlFileName = "module_" + aspectName + "_" + scaleIndex + ".yaml"; + files.put(yamlFileName, yamlContent.toString()); + data.add(buildManifestEntry(envFileName, yamlFileName, false)); + } + } + + private StringBuilder prepareEvnContent() { + StringBuilder envContent = new StringBuilder(); + envContent.append("parameters:\n"); + return envContent; + } + + private JsonObject buildManifestEntry(String envFileName, String yamlFileName, boolean base) { + JsonObject manifestEntry = new JsonObject(); + manifestEntry.addProperty("file", yamlFileName); + manifestEntry.addProperty("type", "HEAT"); + manifestEntry.addProperty("isBase", Boolean.toString(base)); + JsonArray envEntries = new JsonArray(); + manifestEntry.add("data", envEntries); + JsonObject envEntry = new JsonObject(); + envEntries.add(envEntry); + envEntry.addProperty("file", envFileName); + envEntry.addProperty("type", "HEAT_ENV"); + return manifestEntry; + } + + private void processMapping(JsonObject mapping, StringBuilder envContent, StringBuilder yamlContent) { + for (Map.Entry<String, JsonElement> vdusElement : child(mapping, "vdus").entrySet()) { + addImageAndFlavor(envContent, yamlContent, vdusElement); + } + if (mapping.has("externalConnectionPoints")) { + for (Map.Entry<String, JsonElement> externalConnectionPoints : child(mapping, "externalConnectionPoints").entrySet()) { + addParameter(yamlContent, envContent, externalConnectionPoints.getKey() + "_net_id", "Network id", "Network to be used for " + externalConnectionPoints.getKey() + " ECP"); + addParameter(yamlContent, envContent, externalConnectionPoints.getKey() + "_subnet_id", "Subnet id", "Subnet to be used for " + externalConnectionPoints.getKey() + " ECP"); + } + } + } + + private void addImageAndFlavor(StringBuilder envContent, StringBuilder yamlContent, Map.Entry<String, JsonElement> vdusElement) { + String vdu = vdusElement.getKey(); + addParameter(yamlContent, envContent, vdu + IMAGE_NAME, "Image name or identifier", "Image to be used for " + vdu + " VDU"); + addParameter(yamlContent, envContent, vdu + FLAVOR_NAME, "Flavor name or identifier", "Flavor to be used for " + vdu + " VDU"); + } + + private void addParameter(StringBuilder yamlContent, StringBuilder envContent, String key, String label, String description) { + addYamlParameter(yamlContent, key, label, description); + envContent.append(" " + key + ": PUT YOUR " + label.toUpperCase() + " HERE\n"); + } + + private void addYamlParameter(StringBuilder yamlContent, String key, String label, String description) { + yamlContent.append(" " + key + ":\n"); + yamlContent.append(" type: string\n"); + yamlContent.append(" label: " + label + "\n"); + yamlContent.append(" description: " + description + "\n"); + } + + private JsonObject locateHeatPolicy(JsonArray policies) { + for (int index = 0; index < policies.size(); index++) { + JsonObject c = policies.get(index).getAsJsonObject(); + JsonObject policy = c.getAsJsonObject().entrySet().iterator().next().getValue().getAsJsonObject(); + if ("tosca.policies.nfv.HeatMapping".equals(childElement(policy, "type").getAsString())) { + return policy; + } + } + throw buildFatalFailure(logger, "The heat_mapping section is missing from VNFD"); + } + + private JsonObject locateAspect(JsonObject policy, String aspectName) { + for (Map.Entry<String, JsonElement> aspect : child(child(policy, "properties"), "aspects").entrySet()) { + if (aspect.getKey().equals(aspectName)) { + return aspect.getValue().getAsJsonObject(); + } + } + throw buildFatalFailure(logger, "Unable to locate " + aspectName + " in heat policy"); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfPackageBuilder.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfPackageBuilder.java index 8de82347..70b18c55 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfPackageBuilder.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfPackageBuilder.java @@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -41,7 +42,7 @@ public class OnapVnfPackageBuilder { * @param args not used (required due to signature) */ public static void main(String[] args) throws Exception { - byte[] covert = new OnapVnfPackageBuilder().covert(systemFunctions().in(), SupportedOnapPackageVersions.V1); + byte[] covert = new OnapVnfPackageBuilder().covert(systemFunctions().in(), SupportedOnapPackageVersions.V1TOSCA); systemFunctions().out().write(covert); } @@ -55,11 +56,35 @@ public class OnapVnfPackageBuilder { String vnfdLocation = getVnfdLocation(new ByteArrayInputStream(cbamVnfPackage)); ByteArrayOutputStream vnfdContent = getFileInZip(new ByteArrayInputStream(cbamVnfPackage), vnfdLocation); byte[] cbamVnfdContent = vnfdContent.toByteArray(); - String onapVnfd = SupportedOnapPackageVersions.V2 == version ? - new OnapR2VnfdBuilder().toOnapVnfd(new String(cbamVnfdContent, StandardCharsets.UTF_8)) : - new OnapR1VnfdBuilder().toOnapVnfd(new String(cbamVnfdContent, StandardCharsets.UTF_8)); byte[] modifiedCbamPackage = new CbamVnfPackageBuilder().toModifiedCbamVnfPackage(cbamVnfPackage, vnfdLocation, new CbamVnfdBuilder().build(new String(cbamVnfdContent))); - return buildNewOnapPackage(modifiedCbamPackage, onapVnfd); + switch (version){ + case V1TOSCA: + case V2TOSCA: + String onapVnfd = SupportedOnapPackageVersions.V2TOSCA == version ? + new OnapR2VnfdBuilder().toOnapVnfd(new String(cbamVnfdContent, StandardCharsets.UTF_8)) : + new OnapR1VnfdBuilder().toOnapVnfd(new String(cbamVnfdContent, StandardCharsets.UTF_8)); + return buildNewOnapPackage(modifiedCbamPackage, onapVnfd); + case V2HEAT: + default: + Map<String, String> files = new OnapR2HeatPackageBuilder().processVnfd(new String(cbamVnfdContent)); + return buildHeatOnapPackage(modifiedCbamPackage, files); + } + + } + + private byte [] buildHeatOnapPackage(byte [] modifiedCbamPackage, Map<String, String> heatFiles) throws IOException { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + ZipOutputStream out = new ZipOutputStream(result); + out.putNextEntry(new ZipEntry("Artifacts/Deployment/OTHER/cbam.package.zip")); + out.write(modifiedCbamPackage); + out.closeEntry(); + for (Map.Entry<String, String> file : heatFiles.entrySet()) { + out.putNextEntry(new ZipEntry(file.getKey())); + out.write(file.getValue().getBytes()); + out.closeEntry(); + } + out.close(); + return result.toByteArray(); } private byte[] buildNewOnapPackage(byte[] modifiedCbamPackage, String onapVnfd) throws IOException { diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/SupportedOnapPackageVersions.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/SupportedOnapPackageVersions.java index 545b2d9e..b5f5a06d 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/SupportedOnapPackageVersions.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/SupportedOnapPackageVersions.java @@ -20,6 +20,7 @@ package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer; * The supported ONAP package versions */ public enum SupportedOnapPackageVersions { - V1, - V2 + V1TOSCA, + V2TOSCA, + V2HEAT }
\ No newline at end of file diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoApi.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoApi.java deleted file mode 100644 index eb6c289f..00000000 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoApi.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2016-2017, Nokia Corporation - * - * 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. - */ -package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.restapi; - -import javax.servlet.http.HttpServletResponse; -import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so.SoLifecycleManager; -import org.onap.vnfmadapter.so.model.*; -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -import static javax.servlet.http.HttpServletResponse.SC_CREATED; - -import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.Constants.BASE_URL; -import static org.slf4j.LoggerFactory.getLogger; -import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; -import static org.springframework.web.bind.annotation.RequestMethod.*; - -/** - * Responsible for providing the Nokia sVNFM REST APIs - */ -@Controller -@RequestMapping(value = BASE_URL + "/so") -public class SoApi { - private static Logger logger = getLogger(SoApi.class); - - private final SoLifecycleManager soLifecycleManager; - - @Autowired - SoApi(SoLifecycleManager lifecycleManager) { - this.soLifecycleManager = lifecycleManager; - } - - /** - * Create the VNF - * - * @param request the creation request - * @param vnfmId the identifier of the VNFM - * @param httpResponse the HTTP response - * @return the descriptor of the created VNF - */ - @RequestMapping(value = "/{vnfmId}/vnfs", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) - @ResponseBody - public SoVnfCreationResponse createVnf(@RequestBody SoVnfCreationRequest request, @PathVariable("vnfmId") String vnfmId, HttpServletResponse httpResponse) { - logger.info("REST: Create the VNF"); - SoVnfCreationResponse response = soLifecycleManager.create(vnfmId, request); - httpResponse.setStatus(SC_CREATED); - return response; - } - - /** - * Activate the VNF - * - * @param request the activation request - * @param vnfmId the identifier of the VNFM - * @param httpResponse the HTTP response - * @return the descriptor of the created VNF - */ - @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) - @ResponseBody - public SoJobHandler activateVnf(@RequestBody SoVnfActivationRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) { - logger.info("REST: Activate the VNF"); - return soLifecycleManager.activate(vnfmId, vnfId, request, httpResponse); - } - - /** - * Execute custom operation on the VNF - * - * @param request the custom operation request - * @param vnfmId the identifier of the VNFM - * @param httpResponse the HTTP response - * @return the descriptor of the created VNF - */ - @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}/customOperation", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) - @ResponseBody - public SoJobHandler executeCustomOperation(@RequestBody SoVnfCustomOperation request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) { - logger.info("REST: Execute custom operation on the VNF"); - return soLifecycleManager.customOperation(vnfmId, vnfId, request, httpResponse); - } - - /** - * Terminate the VNF - * - * @param request the termination request - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @param httpResponse the HTTP response - * @return the job representing the VNF termination operation - */ - @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}/terminate", method = POST, produces = APPLICATION_JSON_VALUE) - @ResponseBody - public SoJobHandler deactivateVnf(@RequestBody SoVnfTerminationRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) { - logger.info("REST: Deactivate the VNF"); - return soLifecycleManager.deactivate(vnfmId, vnfId, request, httpResponse); - } - - /** - * Delete the VNF - * - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @param httpResponse the HTTP response - */ - @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}", method = DELETE) - public void deleteVnf(@PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) { - logger.info("REST: Delete the VNF"); - soLifecycleManager.delete(vnfmId, vnfId); - httpResponse.setStatus(HttpServletResponse.SC_NO_CONTENT); - } - - /** - * Query the job - * - * @param jobId the identifier of the job - * @param vnfmId the identifier of the VNFM - * @param httpResponse the HTTP response - * @return the instantiated VNF info - */ - @RequestMapping(value = "/{vnfmId}/jobs/{jobId}", method = GET, produces = APPLICATION_JSON_VALUE) - @ResponseBody - public SoJobDetail getJob(@PathVariable("vnfmId") String vnfmId, @PathVariable("jobId") String jobId, HttpServletResponse httpResponse) { - logger.trace("REST: Query the job"); - return soLifecycleManager.getJobDetails(vnfmId, jobId); - } - - /** - * Scale the VNF (defined further in the VF-C driver integration documentation) - * - * @param request the scaling request - * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF - * @param httpResponse the HTTP response - * @return the job representing the scaling operation - */ - @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}/scale", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) - @ResponseBody - public SoJobHandler scaleVnf(@RequestBody SoVnfScaleRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) { - logger.info("REST: Scale the VNF"); - return soLifecycleManager.scale(vnfmId, vnfId, request, httpResponse); - } - - /** - * Heal the VNF (defined further in the VF-C driver integration documentation) - * - * @param request the healing request - * @param vnfmId the identifier of the VNFM - * @param vnfInstanceId the identifier of the VNF - * @param httpResponse the HTTP response - * @return the job representing the healing operation - */ - @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}/heal", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) - @ResponseBody - public SoJobHandler healVnf(@RequestBody SoVnfHealRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfInstanceId, HttpServletResponse httpResponse) { - logger.info("REST: Heal the VNF"); - return soLifecycleManager.heal(vnfmId, vnfInstanceId, request, httpResponse); - } -} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoV2Api.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoV2Api.java new file mode 100644 index 00000000..13d4ef8e --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoV2Api.java @@ -0,0 +1,194 @@ +/* + * Copyright 2016-2017, Nokia Corporation + * + * 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. + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.restapi; + +import javax.servlet.http.HttpServletResponse; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so.SoV2LifecycleManager; +import org.onap.vnfmadapter.so.v2.model.*; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import static javax.servlet.http.HttpServletResponse.SC_CREATED; +import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.Constants.BASE_URL; +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; +import static org.springframework.web.bind.annotation.RequestMethod.*; + +/** + * Responsible for providing the Nokia sVNFM REST APIs + */ +@Controller +@RequestMapping(value = BASE_URL + "/so/v2") +public class SoV2Api { + private static Logger logger = getLogger(SoV2Api.class); + + private final SoV2LifecycleManager soLifecycleManager; + + @Autowired + SoV2Api(SoV2LifecycleManager lifecycleManager) { + this.soLifecycleManager = lifecycleManager; + } + + /** + * Create the VNF + * + * @param request the creation request + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param httpResponse the HTTP response + * @return the descriptor of the created VNF + */ + @RequestMapping(value = "/vnfs/{vnfIdInAai}", method = POST, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public void createVnf(@RequestBody SoV2VnfCreateRequest request, @PathVariable("vnfIdInAai") String vnfIdInAai, HttpServletResponse httpResponse) { + logger.info("REST: Create the VNF"); + soLifecycleManager.createVnf(vnfIdInAai, request, httpResponse); + httpResponse.setStatus(SC_NO_CONTENT); + } + + /** + * Query the VNF + * + * @param request the creation request + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param httpResponse the HTTP response + * @return the descriptor of the created VNF + */ + @RequestMapping(value = "/vnfs/{vnfIdInAai}", method = POST, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public SoV2VnfQueryResponse queryVnf(@RequestBody SoV2VnfQueryRequest request, @PathVariable("vnfIdInAai") String vnfIdInAai, HttpServletResponse httpResponse) { + logger.info("REST: Create the VNF"); + return soLifecycleManager.queryVnf(vnfIdInAai, request, httpResponse); + } + + /** + * Terminate the VNF + * + * @param request the termination request + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param httpResponse the HTTP response + * @return the job representing the VNF termination operation + */ + @RequestMapping(value = "/vnfs/{vnfIdInAai}", method = DELETE, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public void delete(@RequestBody SoV2VnfDeleteRequest request, @PathVariable("vnfIdInAai") String vnfIdInAai, HttpServletResponse httpResponse) { + logger.info("REST: Deactivate the VNF"); + soLifecycleManager.delete(vnfIdInAai, request, httpResponse); + httpResponse.setStatus(SC_NO_CONTENT); + } + + /** + * Update the VNF + * + * @param request the creation request + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param httpResponse the HTTP response + * @return the descriptor of the created VNF + */ + @RequestMapping(value = "/vnfs/{vnfIdInAai}", method = PUT, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public SoV2VnfUpdateResponse updateVnf(@RequestBody SoV2VnfUpdateRequest request, @PathVariable("vnfIdInAai") String vnfIdInAai, HttpServletResponse httpResponse) { + logger.info("REST: Update the VNF"); + return soLifecycleManager.updateVnf(vnfIdInAai, request, httpResponse); + } + + /** + * Rollback update VNF + * + * @param request the rollback request + * @param httpResponse the HTTP response + */ + @RequestMapping(value = "/vnfs/{vnfIdInAai}/rollback", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public void rollback(@RequestBody SoV2RollbackVnfUpdate request, @PathVariable("vnfIdInAai") String vnfIdInAai, HttpServletResponse httpResponse) { + logger.info("REST: Create the VF"); + soLifecycleManager.rollback(vnfIdInAai, request, httpResponse); + } + + /** + * Create the VF module + * + * @param request the creation request + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param httpResponse the HTTP response + */ + @RequestMapping(value = "/vfmodule/{vnfIdInAai}/{vfModuleId}", method = POST, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public void createVfModule(@RequestBody SoV2VfModuleCreateRequest request, @PathVariable("vnfIdInAai") String vnfIdInAai, @PathVariable("vfModuleId") String vfModuleId, HttpServletResponse httpResponse) { + logger.info("REST: Create the VF"); + soLifecycleManager.createVfModule(vnfIdInAai, vfModuleId, request, httpResponse); + httpResponse.setStatus(SC_CREATED); + } + + /** + * Terminate the VF module + * + * @param request the termination request + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param httpResponse the HTTP response + */ + @RequestMapping(value = "/vfmodule/{vnfIdInAai}/{vfModuleId}", method = DELETE, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public void deleteVfModule(@RequestBody SoV2VnfDeleteRequest request, @PathVariable("vnfIdInAai") String vnfIdInAai, @PathVariable("vfModuleId") String vfModuleId, HttpServletResponse httpResponse) { + logger.info("REST: Deactivate the VNF"); + soLifecycleManager.deleteVfModule(vnfIdInAai, vfModuleId, request, httpResponse); + httpResponse.setStatus(SC_NO_CONTENT); + } + + /** + * Update the VF module + * + * @param request the creation request + * @param vnfIdInAai the identifier of the VNF in A&AI + * @param httpResponse the HTTP response + * @return the descriptor of the created VNF + */ + @RequestMapping(value = "/vfmodule/{vnfIdInAai}/{vfModuleId}", method = PUT, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public SoV2VnfUpdateResponse updateVfModule(@RequestBody SoV2VnfUpdateRequest request, @PathVariable("vnfIdInAai") String vnfIdInAai, @PathVariable("vfModuleId") String vfModuleId, HttpServletResponse httpResponse) { + logger.info("REST: Update the VNF"); + return soLifecycleManager.updateVfModule(vnfIdInAai, vfModuleId, request, httpResponse); + } + + /** + * Rollback update VNF + * + * @param request the rollback request + * @param httpResponse the HTTP response + */ + @RequestMapping(value = "/vfmodule/{vnfIdInAai}/{vfModuleId}/rollback", method = PUT, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public void rollbackVfModuleUpdate(@RequestBody SoV2RollbackVnfUpdate request, @PathVariable("vnfIdInAai") String vnfIdInAai, HttpServletResponse httpResponse) { + logger.info("REST: Roll back VF module update"); + soLifecycleManager.rollback(vnfIdInAai, request, httpResponse); + } + + /** + * Provides a probe for SO to test health of VNFM adapter + * + * @param httpResponse the HTTP response + */ + @RequestMapping(value = "/ping", method = GET) + public void testLcnConnectivity(HttpServletResponse httpResponse) { + httpResponse.setStatus(HttpServletResponse.SC_OK); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java index 5895108f..d1ec9e0a 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java @@ -23,7 +23,6 @@ import java.util.*; * Represents the additional parameters to be sent during instantiation from VF-C to the driver */ public class AdditionalParameters { - private VimInfoTypeEnum vimType; private String instantiationLevel; private List<VimComputeResourceFlavour> computeResourceFlavours = new ArrayList<>(); private List<ZoneInfo> zones = new ArrayList<>(); @@ -33,7 +32,6 @@ public class AdditionalParameters { private List<ExtVirtualLinkData> extVirtualLinks = new ArrayList<>(); private List<VnfProperty> extensions = new ArrayList<>(); private Object additionalParams; - private String domain; public AdditionalParameters() { //only used through reflection (gson) @@ -54,20 +52,6 @@ public class AdditionalParameters { } /** - * @return the type of the VIM - */ - public VimInfoTypeEnum getVimType() { - return vimType; - } - - /** - * @param vimType the type of the VIM - */ - public void setVimType(VimInfoTypeEnum vimType) { - this.vimType = vimType; - } - - /** * @return the flavours to be used for the VNF */ public List<VimComputeResourceFlavour> getComputeResourceFlavours() { @@ -159,14 +143,6 @@ public class AdditionalParameters { this.extVirtualLinks = extVirtualLinks; } - public String getDomain() { - return domain; - } - - public void setDomain(String domain) { - this.domain = domain; - } - /** * @return the extensions of the VNF modifiable attributes */ @@ -188,8 +164,7 @@ public class AdditionalParameters { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AdditionalParameters that = (AdditionalParameters) o; - return vimType == that.vimType && - Objects.equals(domain, that.domain) && + return Objects.equals(instantiationLevel, that.instantiationLevel) && Objects.equals(computeResourceFlavours, that.computeResourceFlavours) && Objects.equals(zones, that.zones) && @@ -203,13 +178,12 @@ public class AdditionalParameters { @Override public int hashCode() { - return Objects.hash(vimType, domain, instantiationLevel, computeResourceFlavours, zones, softwareImages, extManagedVirtualLinks, externalConnectionPointAddresses, extVirtualLinks, extensions, additionalParams); + return Objects.hash(instantiationLevel, computeResourceFlavours, zones, softwareImages, extManagedVirtualLinks, externalConnectionPointAddresses, extVirtualLinks, extensions, additionalParams); } @Override public String toString() { return "AdditionalParameters{" + - "vimType=" + vimType + ", instantiationLevel='" + instantiationLevel + '\'' + ", computeResourceFlavours=" + computeResourceFlavours + ", zones=" + zones + @@ -219,7 +193,6 @@ public class AdditionalParameters { ", extVirtualLinks=" + extVirtualLinks + ", extensions=" + extensions + ", additionalParams=" + additionalParams + - ", domain='" + domain + '\'' + '}'; } }
\ No newline at end of file diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/JobManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/JobManager.java index 34dce147..c7d19779 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/JobManager.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/JobManager.java @@ -27,10 +27,7 @@ import com.nokia.cbam.lcm.v32.model.VnfInfo; import java.util.*; import javax.servlet.http.HttpServletResponse; import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager; -import org.onap.vnfmdriver.model.JobDetailInfo; -import org.onap.vnfmdriver.model.JobDetailInfoResponseDescriptor; -import org.onap.vnfmdriver.model.JobResponseInfo; -import org.onap.vnfmdriver.model.JobStatus; +import org.onap.vnfmdriver.model.*; import org.slf4j.Logger; import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; @@ -183,6 +180,15 @@ public class JobManager { } } + public void waitForJobToFinish(JobInfo jobInfo) { + while(true){ + if(ongoingJobs.contains(jobInfo.getJobId())){ + return; + } + systemFunctions().sleep(500L); + } + } + private JobDetailInfo getJobDetailInfoForMissingVnf(String jobId) { if (ongoingJobs.contains(jobId)) { return reportOngoing(jobId); diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java index 7c8e2318..8e72d688 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java @@ -37,6 +37,7 @@ import org.onap.vnfmdriver.model.*; import org.onap.vnfmdriver.model.VimInfo; import org.onap.vnfmdriver.model.VnfInfo; import org.slf4j.Logger; +import org.springframework.util.StringUtils; import org.yaml.snakeyaml.Yaml; import static java.lang.Integer.parseInt; @@ -176,7 +177,6 @@ public class LifecycleManager { @SuppressWarnings("squid:S00107") //wrapping them into an object makes the code less readable public VnfInstantiateResponse instantiate(String vnfmId, List<ExtVirtualLinkInfo> externalVirtualLinks, HttpServletResponse httpResponse, Object operationAdditionalParameters, AdditionalParameters additionalParameters, String vnfId, String onapVnfdId, String vnfmVnfdId) { logOperationInput(vnfId, "instantiation", additionalParameters); - validateVimType(additionalParameters.getVimType()); VnfInstantiateResponse response = new VnfInstantiateResponse(); response.setVnfInstanceId(vnfId); String vimId = getVimId(operationAdditionalParameters); @@ -212,7 +212,6 @@ public class LifecycleManager { */ public VnfInstantiateResponse createAndInstantiate(String vnfmId, VnfInstantiateRequest request, HttpServletResponse httpResponse) { AdditionalParameters additionalParameters = convertInstantiationAdditionalParams(request.getVnfPackageId(), request.getAdditionalParam()); - validateVimType(additionalParameters.getVimType()); VnfCreationResult creationResult = create(vnfmId, request.getVnfDescriptorId(), request.getVnfInstanceName(), request.getVnfInstanceDescription()); return instantiate(vnfmId, request.getExtVirtualLink(), httpResponse, request.getAdditionalParam(), additionalParameters, creationResult.vnfInfo.getId(), request.getVnfPackageId(), creationResult.vnfdId); } @@ -268,31 +267,18 @@ public class LifecycleManager { } private com.nokia.cbam.lcm.v32.model.VimInfo addVim(AdditionalParameters additionalParameters, String vimId, GrantVNFResponseVim vim, VimInfo vimInfo) { - if (additionalParameters.getVimType() == OPENSTACK_V2_INFO) { - return buildOpenStackV2INFO(vimId, vim, vimInfo); - - } else if (additionalParameters.getVimType() == OPENSTACK_V3_INFO) { - if (isEmpty(vimInfo.getDomain())) { - if (isEmpty(additionalParameters.getDomain())) { - throw buildFatalFailure(logger, "The cloud did not supply the cloud domain (Amsterdam release) and was not supplied as additional data"); - } else { - logger.warn("Setting domain from additional parameters"); - vimInfo.setDomain(additionalParameters.getDomain()); - } + if (vimInfo.getType().equals("openstack")) { + if (StringUtils.isEmpty(vimInfo.getDomain())) { + return buildOpenStackV2INFO(vimId, vim, vimInfo); + } else { + return buildOpenStackV3INFO(vimId, vim, vimInfo); } - return buildOpenStackV3INFO(vimId, vim, vimInfo); } else { //OTHER VIM TYPE is not possible return buildVcloudInfo(vimId, vimInfo); } } - private void validateVimType(com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum vimType) { - if (com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum.OTHER_VIM_INFO.equals(vimType)) { - throw buildFatalFailure(logger, "Only " + OPENSTACK_V2_INFO + ", " + OPENSTACK_V3_INFO + " and " + VMWARE_VCLOUD_INFO + " is the supported VIM types"); - } - } - private String getVimId(Object additionalParams) { return childElement(new Gson().toJsonTree(additionalParams).getAsJsonObject(), "vimId").getAsString(); } @@ -367,7 +353,7 @@ public class LifecycleManager { executeModifyVnfInfo(vnfmId, vnfId, request); } - private void executeModifyVnfInfo(String vnfmId, String vnfId, ModifyVnfInfoRequest request) { + public void executeModifyVnfInfo(String vnfmId, String vnfId, ModifyVnfInfoRequest request) { try { OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdPatch(vnfId, request, NOKIA_LCM_API_VERSION).blockingFirst(); waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId()); @@ -459,16 +445,16 @@ public class LifecycleManager { * </ul> * * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier of the VNF + * @param vnfIdInVnfm the identifier of the VNF in VNFM * @param request the termination request * @param httpResponse the HTTP response * @return the job for polling the progress of the termination */ - public JobInfo terminateAndDelete(String vnfmId, String vnfId, VnfTerminateRequest request, HttpServletResponse httpResponse) { - logOperationInput(vnfId, "termination", request); - return scheduleExecution(vnfId, httpResponse, "terminateVnf", jobInfo -> { - terminateVnf(vnfmId, vnfId, request, jobInfo); - deleteVnf(vnfmId, vnfId); + public JobInfo terminateAndDelete(String vnfmId, String vnfIdInVnfm, VnfTerminateRequest request, HttpServletResponse httpResponse) { + logOperationInput(vnfIdInVnfm, "termination", request); + return scheduleExecution(vnfIdInVnfm, httpResponse, "terminateVnf", jobInfo -> { + terminateVnf(vnfmId, vnfIdInVnfm, request, jobInfo); + deleteVnf(vnfmId, vnfIdInVnfm); }); } @@ -528,12 +514,12 @@ public class LifecycleManager { * Delete the VNF * * @param vnfmId the identifier of the VNFM - * @param vnfId the identifier fo the VNF + * @param vnfIdInVnfm the identifier fo the VNF */ - public void deleteVnf(String vnfmId, String vnfId) { - logger.info("Deleting VNF with {} identifier", vnfId); - cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION).blockingFirst(null); - logger.info("The VNF with {} identifier has been deleted", vnfId); + public void deleteVnf(String vnfmId, String vnfIdInVnfm) { + logger.info("Deleting VNF with {} identifier", vnfIdInVnfm); + cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfIdInVnfm, NOKIA_LCM_API_VERSION).blockingFirst(null); + logger.info("The VNF with {} identifier has been deleted", vnfIdInVnfm); } private String getVimIdFromInstantiationRequest(String vnfmId, com.nokia.cbam.lcm.v32.model.VnfInfo vnf) { |