2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.components.upgrade;
23 import fj.data.Either;
24 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
25 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
26 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
27 import org.openecomp.sdc.be.components.validation.UserValidations;
28 import org.openecomp.sdc.be.dao.api.ActionStatus;
29 import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
30 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
31 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
32 import org.openecomp.sdc.be.impl.ComponentsUtils;
33 import org.openecomp.sdc.be.model.*;
34 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
35 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.UpgradeOperation;
36 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
37 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
38 import org.openecomp.sdc.be.user.Role;
39 import org.openecomp.sdc.common.log.wrappers.Logger;
40 import org.openecomp.sdc.exception.ResponseFormat;
43 import java.util.stream.Collectors;
45 @org.springframework.stereotype.Component("upgradeBusinessLogic")
46 public class UpgradeBusinessLogic {
48 private final LifecycleBusinessLogic lifecycleBusinessLogic;
49 private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
50 private final UserValidations userValidations;
51 private final ToscaOperationFacade toscaOperationFacade;
52 private final ComponentsUtils componentsUtils;
53 private final UpgradeOperation upgradeOperation;
54 private final JanusGraphDao janusGraphDao;
55 private LifecycleChangeInfoWithAction changeInfo = new LifecycleChangeInfoWithAction("automated upgrade");
57 private static final List<String> UUID_PROPS_NAMES = Arrays.asList("depending_service_uuid", "providing_service_uuid");
58 private static final List<String> INV_UUID_PROPS_NAMES = Arrays.asList("depending_service_invariant_uuid", "providing_service_invariant_uuid");
59 private static final List<String> NAME_PROPS_NAMES = Arrays.asList("depending_service_name", "providing_service_name");
61 private static final Logger LOGGER = Logger.getLogger(UpgradeBusinessLogic.class);
63 public UpgradeBusinessLogic(LifecycleBusinessLogic lifecycleBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBusinessLogic, UserValidations userValidations, ToscaOperationFacade toscaOperationFacade, ComponentsUtils componentsUtils,
64 UpgradeOperation upgradeOperation, JanusGraphDao janusGraphDao) {
65 this.lifecycleBusinessLogic = lifecycleBusinessLogic;
66 this.componentInstanceBusinessLogic = componentInstanceBusinessLogic;
67 this.userValidations = userValidations;
68 this.toscaOperationFacade = toscaOperationFacade;
69 this.componentsUtils = componentsUtils;
70 this.upgradeOperation = upgradeOperation;
71 this.janusGraphDao = janusGraphDao;
81 public UpgradeStatus automatedUpgrade(String componentId, List<UpgradeRequest> upgradeRequest, String userId) {
82 UpgradeStatus status = new UpgradeStatus();
83 User user = userValidations.validateUserExists(userId, "automated upgrade", false);
85 Either<Component, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaFullElement(componentId);
86 if (storageStatus.isRight()) {
87 status.setError(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(storageStatus.right().value()), componentId));
90 Component component = storageStatus.left().value();
91 if (!component.isHighestVersion() || component.getLifecycleState() != LifecycleStateEnum.CERTIFIED) {
92 LOGGER.debug("automated Upgrade failed - target is not higest certified component {} state {} version {} ", component.getName(), component.getLifecycleState(), component.getVersion());
93 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_NOT_HIHGEST_CERTIFIED, component.getName());
94 status.setError(responseFormat);
95 componentsUtils.auditComponentAdmin(responseFormat, user, component, getAuditTypeByComponent(component), component.getComponentType());
99 if ( component.isArchived() ){
100 LOGGER.debug("automated Upgrade failed - target is archived component {} version {} ", component.getName(), component.getVersion());
101 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, component.getName());
102 status.setError(responseFormat);
103 componentsUtils.auditComponentAdmin(responseFormat, user, component, getAuditTypeByComponent(component), component.getComponentType());
107 switch (component.getComponentType()) {
109 hadnleUpgradeVFInService(component, upgradeRequest, user, status);
112 hadnleUpgradeService(component, upgradeRequest, user, status);
115 LOGGER.debug("automated Upgrade failed - Not supported type {} for component {} ", component.getComponentType(), component.getName());
116 status.setError(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR));
127 public Either<List<ComponentDependency>, ResponseFormat> getComponentDependencies(String componentId, String userId) {
129 User user = userValidations.validateUserExists(userId, "get Component Dependencies for automated upgrade", false);
131 return upgradeOperation.getComponentDependencies(componentId)
133 .map(rf -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(rf)));
135 // all operation were read only. no commit needed
136 janusGraphDao.rollback();
141 private UpgradeStatus hadnleUpgradeVFInService(Component component, List<UpgradeRequest> componentUids, User user, UpgradeStatus upgradeStatus) {
142 Resource vfResource = (Resource) component;
143 if (vfResource.getResourceType() != ResourceTypeEnum.VF) {
144 LOGGER.debug("automated Upgrade failed - target is not VF resource {} {} ", vfResource.getName(), vfResource.getResourceType());
145 upgradeStatus.setStatus(ActionStatus.GENERAL_ERROR);
146 componentsUtils.auditComponentAdmin(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR), user, component, getAuditTypeByComponent(component), component.getComponentType());
147 return upgradeStatus;
149 componentUids.forEach(request -> upgradeInSingleService(request, vfResource, user, upgradeStatus));
150 upgradeStatus.setStatus(ActionStatus.OK);
151 componentsUtils.auditComponentAdmin(componentsUtils.getResponseFormat(ActionStatus.OK), user, component, AuditingActionEnum.VF_UPGRADE_SERVICES, component.getComponentType());
153 return upgradeStatus;
156 private UpgradeStatus hadnleUpgradeService(Component component, List<UpgradeRequest> upgradeRequest, User user, UpgradeStatus upgradeStatus) {
157 if ( Role.TESTER.name().equals(user.getRole()) ){
158 user.setRole(Role.DESIGNER.name());
159 LOGGER.debug("Change temporary for update service reference user role from TESTER to DESINGER");
161 Service service = (Service) component;
162 upgradeRequest.forEach(request -> upgradeSingleService(request, service, user, upgradeStatus));
163 upgradeStatus.setStatus(ActionStatus.OK);
164 componentsUtils.auditComponentAdmin(componentsUtils.getResponseFormat(ActionStatus.OK), user, component, AuditingActionEnum.UPDATE_SERVICE_REFERENCE, component.getComponentType());
165 return upgradeStatus;
168 private ActionStatus upgradeSingleService(UpgradeRequest request, Service service, User user, UpgradeStatus upgradeStatus) {
169 if (request.getResourceId() == null) {
170 // upgrade proxy version
171 return upgradeInSingleService(request, service, user, upgradeStatus);
173 // upgrade allotted resource -> service
174 return upgradeChainResourceService(request, service, user, upgradeStatus);
178 private ActionStatus upgradeInSingleService(UpgradeRequest request, Component newVersionComponent, User user, UpgradeStatus upgradeStatus) {
179 String serviceId = request.getServiceId();
180 return toscaOperationFacade.getToscaFullElement(serviceId)
181 .either(l -> handleService(l, newVersionComponent, user, upgradeStatus), err -> {
182 LOGGER.debug("Failed to fetch service by id {} error {}", serviceId, err);
183 ActionStatus errS = componentsUtils.convertFromStorageResponse(err);
184 upgradeStatus.addServiceStatus(serviceId, errS);
189 private ActionStatus upgradeChainResourceService(UpgradeRequest request, Service service, User user, UpgradeStatus upgradeStatus) {
191 Either<? extends Component, ActionStatus> upgradeAllottedResource = upgradeAllottedResource(request, user, upgradeStatus, service);
192 if (upgradeAllottedResource.isRight()) {
193 return upgradeAllottedResource.right().value();
196 resource = upgradeAllottedResource.left().value();
197 // update VF instance in service
199 Either<Component, StorageOperationStatus> serviceContainer = toscaOperationFacade.getToscaFullElement(request.getServiceId());
200 if (serviceContainer.isRight()) {
201 LOGGER.debug("Failed to fetch resource by id {} error {}", request.getServiceId(), serviceContainer.right().value());
202 ActionStatus errS = componentsUtils.convertFromStorageResponse(serviceContainer.right().value());
203 upgradeStatus.addServiceStatus(request.getServiceId(), errS);
206 return handleService(serviceContainer.left().value(), resource, user, upgradeStatus);
210 private Either<? extends Component, ActionStatus> upgradeAllottedResource(UpgradeRequest request, User user, UpgradeStatus upgradeStatus, Service service) {
211 return getElement(request.getResourceId(), upgradeStatus, request)
213 .bind(l -> upgradeStateAlloted(request, user, upgradeStatus, service, l));
216 private Either<Component, ActionStatus> getElement(String id, UpgradeStatus upgradeStatus, UpgradeRequest request) {
217 return toscaOperationFacade.getToscaElement(id)
220 ActionStatus errS = componentsUtils.convertFromStorageResponse(err);
221 upgradeStatus.addServiceStatus(request.getServiceId(), errS);
226 private Either<? extends Component, ActionStatus> upgradeStateAlloted(UpgradeRequest request, User user, UpgradeStatus upgradeStatus, Service service, Component resource) {
227 if (resource.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT) {
228 LOGGER.debug("Automated upgrade failedd. Alloted vf {} is in state NOT_CERTIFIED_CHECKOUT", request.getResourceId());
229 upgradeStatus.addServiceStatus(request.getServiceId(), ActionStatus.RESOURCE_LIFECYCLE_STATE_NOT_VALID);
230 return Either.right(ActionStatus.RESOURCE_LIFECYCLE_STATE_NOT_VALID);
233 // update properties-reference to service in VF on VFCI
234 return changeComponentState(resource, LifeCycleTransitionEnum.CHECKOUT, user, upgradeStatus, request.getServiceId())
236 .bind(l -> updateAllottedPropsAndCertify(request, user, upgradeStatus, service, l));
239 private Either<? extends Component, ActionStatus> updateAllottedPropsAndCertify(UpgradeRequest request, User user, UpgradeStatus upgradeStatus, Service service, Component resource) {
240 Either<? extends Component, ActionStatus> result = null;
242 List<String> instanceIds = upgradeOperation.getInstanceIdFromAllottedEdge(resource.getUniqueId(), service.getInvariantUUID());
243 if (instanceIds != null) {
244 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = resource.getComponentInstancesProperties();
245 Map<String, List<ComponentInstanceProperty>> propertiesToUpdate = new HashMap<>();
247 instanceIds.forEach(id -> findPropertiesToUpdate(id, componentInstancesProperties, propertiesToUpdate, service));
249 Either<Map<String, List<ComponentInstanceProperty>>, StorageOperationStatus> updatePropsResult = toscaOperationFacade.updateComponentInstancePropsToComponent(propertiesToUpdate, resource.getUniqueId());
250 if (updatePropsResult.isRight()) {
251 LOGGER.debug("Failed to update properties in Allotted resource {} {}, Error {}. ", resource.getName(), resource.getUniqueId(), updatePropsResult.right().value());
253 result = Either.right(ActionStatus.GENERAL_ERROR);
258 result = changeComponentState(resource, LifeCycleTransitionEnum.CERTIFY, user, upgradeStatus, request.getServiceId());
261 LOGGER.debug("No Instances to update in allotted resource {} ", resource.getName());
262 result = Either.right(ActionStatus.NO_INSTANCES_TO_UPGRADE);
266 if ( result.isRight() ){
267 // undo checkout resource in case of failure
268 LOGGER.debug("Failed to update Allotted resource {} {}, Error {}. UNDOCHEKOUT our resource", resource.getName(), resource.getUniqueId(), result.right().value());
270 upgradeStatus.addServiceStatus(request.getServiceId(), ActionStatus.GENERAL_ERROR);
275 private void undocheckoutComponent(User user, Component resource) {
276 Either<? extends Component, ResponseFormat> changeComponentState = lifecycleBusinessLogic.changeComponentState(resource.getComponentType(), resource.getUniqueId(), user, LifeCycleTransitionEnum.UNDO_CHECKOUT, changeInfo, false, true);
277 if (changeComponentState.isRight()) {
278 LOGGER.debug("Failed to UNDOCHECKOUT Service {} {}, Error {}", resource.getName(), resource.getUniqueId(), changeComponentState.right().value());
282 private void findPropertiesToUpdate(String id, Map<String, List<ComponentInstanceProperty>> componentInstancesProperties, Map<String, List<ComponentInstanceProperty>> propertiesToUpdate, Service service) {
283 List<ComponentInstanceProperty> list = componentInstancesProperties.get(id);
284 List<ComponentInstanceProperty> propsPerInstance = new ArrayList<>();
286 if (UUID_PROPS_NAMES.contains(p.getName())) {
287 p.setValue(service.getUUID());
288 propsPerInstance.add(p);
290 if (INV_UUID_PROPS_NAMES.contains(p.getName())) {
291 p.setValue(service.getInvariantUUID());
292 propsPerInstance.add(p);
294 if (NAME_PROPS_NAMES.contains(p.getName())) {
295 p.setValue(service.getName());
296 propsPerInstance.add(p);
299 propertiesToUpdate.put(id, propsPerInstance);
302 private ActionStatus handleService(Component component, Component newVersionComponent, User user, UpgradeStatus upgradeStatus) {
303 if (component.getComponentType() != ComponentTypeEnum.SERVICE) {
304 LOGGER.debug("component with id {} and name {} isn't SERVICE. type{} ", component.getName(), component.getUniqueId(), component.getComponentType());
305 upgradeStatus.addServiceStatus(component, ActionStatus.GENERAL_ERROR);
306 return ActionStatus.GENERAL_ERROR;
309 Service service = (Service) component;
310 if (component.getLifecycleState() != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT) {
311 LOGGER.debug("Service {} {} is not in CHECKOUT state . Try to checkout it", component.getName(), component.getUniqueId());
312 Either<? extends Component, ActionStatus> changeComponentState = changeComponentState(component, LifeCycleTransitionEnum.CHECKOUT, user, upgradeStatus, null);
313 if ( changeComponentState.isRight() ){
314 return changeComponentState.right().value();
316 service = (Service) changeComponentState.left().value();
317 //need to fetch service again with capability properties
318 Either<Component, StorageOperationStatus> toscaFullElement = toscaOperationFacade.getToscaFullElement(service.getUniqueId());
319 if ( toscaFullElement.isRight() ){
320 return componentsUtils.convertFromStorageResponse(toscaFullElement.right().value());
322 service = (Service) toscaFullElement.left().value();
324 LOGGER.debug("Service {} {} is in CHECKOUT state . Restricted update operation", component.getName(), component.getUniqueId());
325 upgradeStatus.addServiceStatus(component, ActionStatus.COMPONENT_IN_CHECKOUT_STATE);
326 return ActionStatus.COMPONENT_IN_CHECKOUT_STATE;
328 ActionStatus status = ActionStatus.GENERAL_ERROR;
330 status = handleInstances(newVersionComponent, user, upgradeStatus, service);
332 if (status != ActionStatus.OK) {
333 LOGGER.debug("Failed to upgrade instance for service {} status {}. Undocheckout service", service.getName(), status);
334 undocheckoutComponent(user, service);
336 upgradeStatus.addServiceStatus(component, status);
342 private Either<? extends Component,ActionStatus> changeComponentState(Component component, LifeCycleTransitionEnum nextState, User user, UpgradeStatus upgradeStatus, String idForStatus){
343 if ( component.isArchived() ){
344 LOGGER.debug("Component {} from type {} id {} is archived, Error {}", nextState, component.getName(), component.getComponentType(), component.getUniqueId());
345 setUpgradeStatus(component, upgradeStatus, idForStatus);
346 return Either.right(ActionStatus.COMPONENT_IS_ARCHIVED);
348 return lifecycleBusinessLogic.changeComponentState(component.getComponentType(), component.getUniqueId(), user, nextState, changeInfo, false, true)
351 LOGGER.debug("Failed to {} Component {} from type {} id {}, Error {}", nextState, component.getName(), component.getComponentType(), component.getUniqueId(), err);
352 setUpgradeStatus(component, upgradeStatus, idForStatus);
353 return ActionStatus.GENERAL_ERROR;
359 private void setUpgradeStatus(Component component, UpgradeStatus upgradeStatus, String idForStatus) {
360 if ( idForStatus == null ){
361 upgradeStatus.addServiceStatus(component, ActionStatus.GENERAL_ERROR);
363 upgradeStatus.addServiceStatus(idForStatus, ActionStatus.GENERAL_ERROR);
367 private ActionStatus handleInstances(Component newVersionComponent, User user, UpgradeStatus upgradeStatus, Service service) {
368 List<ComponentInstance> componentInstances = service.getComponentInstances();
369 if (componentInstances != null) {
370 List<ComponentInstance> instanceToChange = componentInstances
372 .filter(ci -> matchInstance(ci, newVersionComponent))
373 .collect(Collectors.toList());
374 if (instanceToChange != null && !instanceToChange.isEmpty()) {
375 return changeInstances(newVersionComponent, user, upgradeStatus, service, instanceToChange);
377 LOGGER.debug("No instances for change version");
378 return ActionStatus.NO_INSTANCES_TO_UPGRADE;
381 return ActionStatus.OK;
384 private ActionStatus changeInstances(Component newVersionComponent, User user, UpgradeStatus upgradeStatus, Service service, List<ComponentInstance> instanceToChange) {
385 Component serviceToUpgrade = service;
386 for (ComponentInstance ci : instanceToChange) {
387 Either<Component, ActionStatus> fetchService = fetchService(service.getUniqueId(),service.getName());
388 if ( fetchService.isRight()){
389 upgradeStatus.addServiceStatus(service, fetchService.right().value());
390 return fetchService.right().value();
392 serviceToUpgrade = fetchService.left().value();
393 ActionStatus status = changeVersionOfInstance(serviceToUpgrade, ci, newVersionComponent, user);
394 if (status != ActionStatus.OK) {
395 LOGGER.debug("Failed to change for instance {} version in service {}", ci.getName(), service.getName());
396 upgradeStatus.addServiceStatus(service, status);
400 Either<Component, ActionStatus> fetchService = fetchService(service.getUniqueId(),service.getName());
401 if ( fetchService.isRight()){
402 upgradeStatus.addServiceStatus(service, fetchService.right().value());
403 return fetchService.right().value();
405 serviceToUpgrade = fetchService.left().value();
407 Either<? extends Component, ActionStatus> changeComponentState = changeComponentState(serviceToUpgrade, LifeCycleTransitionEnum.CHECKIN, user, upgradeStatus, null);
408 if ( changeComponentState.isRight() ){
409 return changeComponentState.right().value();
411 upgradeStatus.addServiceStatus(serviceToUpgrade, ActionStatus.OK);
412 return ActionStatus.OK;
416 private Either<Component, ActionStatus> fetchService(String uniqueId, String name) {
417 return toscaOperationFacade.getToscaFullElement(uniqueId)
420 LOGGER.debug("Failed to fetch service {} id {} error {}", name, uniqueId, r);
421 return ActionStatus.GENERAL_ERROR;
425 private ActionStatus changeVersionOfInstance(Component service, ComponentInstance ci, Component newVersionComponent, User user) {
426 LOGGER.debug("In Service {} change instance version {} to version {}", service.getName(), ci.getName(), newVersionComponent.getVersion());
427 ComponentInstance newComponentInstance = new ComponentInstance();
428 newComponentInstance.setComponentUid(newVersionComponent.getUniqueId());
429 Either<ComponentInstance, ResponseFormat> changeInstanceVersion = componentInstanceBusinessLogic.changeInstanceVersion(service, ci, newComponentInstance, user, service.getComponentType());
430 if (changeInstanceVersion.isLeft()) {
431 return ActionStatus.OK;
433 return ActionStatus.GENERAL_ERROR;
437 private boolean matchInstance(ComponentInstance ci, Component newVersionComponent) {
438 Either<Component, StorageOperationStatus> toscaElement;
439 ComponentParametersView filters = new ComponentParametersView(true);
440 if (newVersionComponent.getComponentType() == ComponentTypeEnum.SERVICE) {
441 if (ci.getIsProxy()) {
442 toscaElement = toscaOperationFacade.getToscaElement(ci.getSourceModelUid(), filters);
447 toscaElement = toscaOperationFacade.getToscaElement(ci.getComponentUid(), filters);
449 if (toscaElement.isLeft()) {
450 Component origin = toscaElement.left().value();
451 if (newVersionComponent.getInvariantUUID().equals(origin.getInvariantUUID()) && !newVersionComponent.getVersion().equals(origin.getVersion())) {
452 // only for same invariant UUID (same component) but different versions
458 private AuditingActionEnum getAuditTypeByComponent(Component component){
459 if ( ComponentTypeEnum.RESOURCE == component.getComponentType()){
460 return AuditingActionEnum.VF_UPGRADE_SERVICES;
462 return AuditingActionEnum.UPDATE_SERVICE_REFERENCE;