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.Component;
34 import org.openecomp.sdc.be.model.ComponentDependency;
35 import org.openecomp.sdc.be.model.ComponentInstance;
36 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
37 import org.openecomp.sdc.be.model.ComponentParametersView;
38 import org.openecomp.sdc.be.model.LifeCycleTransitionEnum;
39 import org.openecomp.sdc.be.model.LifecycleStateEnum;
40 import org.openecomp.sdc.be.model.Resource;
41 import org.openecomp.sdc.be.model.Service;
42 import org.openecomp.sdc.be.model.User;
43 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
44 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.UpgradeOperation;
45 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
46 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
47 import org.openecomp.sdc.be.user.Role;
48 import org.openecomp.sdc.common.log.wrappers.Logger;
49 import org.openecomp.sdc.exception.ResponseFormat;
51 import java.util.ArrayList;
52 import java.util.Arrays;
53 import java.util.HashMap;
54 import java.util.List;
56 import java.util.stream.Collectors;
58 @org.springframework.stereotype.Component("upgradeBusinessLogic")
59 public class UpgradeBusinessLogic {
61 private final LifecycleBusinessLogic lifecycleBusinessLogic;
62 private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
63 private final UserValidations userValidations;
64 private final ToscaOperationFacade toscaOperationFacade;
65 private final ComponentsUtils componentsUtils;
66 private final UpgradeOperation upgradeOperation;
67 private final JanusGraphDao janusGraphDao;
68 private LifecycleChangeInfoWithAction changeInfo = new LifecycleChangeInfoWithAction("automated upgrade");
70 private static final List<String> UUID_PROPS_NAMES = Arrays.asList("depending_service_uuid", "providing_service_uuid");
71 private static final List<String> INV_UUID_PROPS_NAMES = Arrays.asList("depending_service_invariant_uuid", "providing_service_invariant_uuid");
72 private static final List<String> NAME_PROPS_NAMES = Arrays.asList("depending_service_name", "providing_service_name");
74 private static final Logger LOGGER = Logger.getLogger(UpgradeBusinessLogic.class);
76 public UpgradeBusinessLogic(LifecycleBusinessLogic lifecycleBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBusinessLogic, UserValidations userValidations, ToscaOperationFacade toscaOperationFacade, ComponentsUtils componentsUtils,
77 UpgradeOperation upgradeOperation, JanusGraphDao janusGraphDao) {
78 this.lifecycleBusinessLogic = lifecycleBusinessLogic;
79 this.componentInstanceBusinessLogic = componentInstanceBusinessLogic;
80 this.userValidations = userValidations;
81 this.toscaOperationFacade = toscaOperationFacade;
82 this.componentsUtils = componentsUtils;
83 this.upgradeOperation = upgradeOperation;
84 this.janusGraphDao = janusGraphDao;
94 public UpgradeStatus automatedUpgrade(String componentId, List<UpgradeRequest> upgradeRequest, String userId) {
95 UpgradeStatus status = new UpgradeStatus();
96 User user = userValidations.validateUserExists(userId);
98 Either<Component, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaFullElement(componentId);
99 if (storageStatus.isRight()) {
100 status.setError(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(storageStatus.right().value()), componentId));
103 Component component = storageStatus.left().value();
104 if (!component.isHighestVersion() || component.getLifecycleState() != LifecycleStateEnum.CERTIFIED) {
105 LOGGER.debug("automated Upgrade failed - target is not higest certified component {} state {} version {} ", component.getName(), component.getLifecycleState(), component.getVersion());
106 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_NOT_HIHGEST_CERTIFIED, component.getName());
107 status.setError(responseFormat);
108 componentsUtils.auditComponentAdmin(responseFormat, user, component, getAuditTypeByComponent(component), component.getComponentType());
112 if ( component.isArchived() ){
113 LOGGER.debug("automated Upgrade failed - target is archived component {} version {} ", component.getName(), component.getVersion());
114 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, component.getName());
115 status.setError(responseFormat);
116 componentsUtils.auditComponentAdmin(responseFormat, user, component, getAuditTypeByComponent(component), component.getComponentType());
120 switch (component.getComponentType()) {
122 hadnleUpgradeVFInService(component, upgradeRequest, user, status);
125 hadnleUpgradeService(component, upgradeRequest, user, status);
128 LOGGER.debug("automated Upgrade failed - Not supported type {} for component {} ", component.getComponentType(), component.getName());
129 status.setError(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR));
140 public Either<List<ComponentDependency>, ResponseFormat> getComponentDependencies(String componentId, String userId) {
142 User user = userValidations.validateUserExists(userId);
144 return upgradeOperation.getComponentDependencies(componentId)
146 .map(rf -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(rf)));
148 // all operation were read only. no commit needed
149 janusGraphDao.rollback();
154 private UpgradeStatus hadnleUpgradeVFInService(Component component, List<UpgradeRequest> componentUids, User user, UpgradeStatus upgradeStatus) {
155 Resource vfResource = (Resource) component;
156 if (vfResource.getResourceType() != ResourceTypeEnum.VF) {
157 LOGGER.debug("automated Upgrade failed - target is not VF resource {} {} ", vfResource.getName(), vfResource.getResourceType());
158 upgradeStatus.setStatus(ActionStatus.GENERAL_ERROR);
159 componentsUtils.auditComponentAdmin(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR), user, component, getAuditTypeByComponent(component), component.getComponentType());
160 return upgradeStatus;
162 componentUids.forEach(request -> upgradeInSingleService(request, vfResource, user, upgradeStatus));
163 upgradeStatus.setStatus(ActionStatus.OK);
164 componentsUtils.auditComponentAdmin(componentsUtils.getResponseFormat(ActionStatus.OK), user, component, AuditingActionEnum.VF_UPGRADE_SERVICES, component.getComponentType());
166 return upgradeStatus;
169 private UpgradeStatus hadnleUpgradeService(Component component, List<UpgradeRequest> upgradeRequest, User user, UpgradeStatus upgradeStatus) {
170 if ( Role.TESTER.name().equals(user.getRole()) ){
171 user.setRole(Role.DESIGNER.name());
172 LOGGER.debug("Change temporary for update service reference user role from TESTER to DESINGER");
174 Service service = (Service) component;
175 upgradeRequest.forEach(request -> upgradeSingleService(request, service, user, upgradeStatus));
176 upgradeStatus.setStatus(ActionStatus.OK);
177 componentsUtils.auditComponentAdmin(componentsUtils.getResponseFormat(ActionStatus.OK), user, component, AuditingActionEnum.UPDATE_SERVICE_REFERENCE, component.getComponentType());
178 return upgradeStatus;
181 private ActionStatus upgradeSingleService(UpgradeRequest request, Service service, User user, UpgradeStatus upgradeStatus) {
182 if (request.getResourceId() == null) {
183 // upgrade proxy version
184 return upgradeInSingleService(request, service, user, upgradeStatus);
186 // upgrade allotted resource -> service
187 return upgradeChainResourceService(request, service, user, upgradeStatus);
191 private ActionStatus upgradeInSingleService(UpgradeRequest request, Component newVersionComponent, User user, UpgradeStatus upgradeStatus) {
192 String serviceId = request.getServiceId();
193 return toscaOperationFacade.getToscaFullElement(serviceId)
194 .either(l -> handleService(l, newVersionComponent, user, upgradeStatus), err -> {
195 LOGGER.debug("Failed to fetch service by id {} error {}", serviceId, err);
196 ActionStatus errS = componentsUtils.convertFromStorageResponse(err);
197 upgradeStatus.addServiceStatus(serviceId, errS);
202 private ActionStatus upgradeChainResourceService(UpgradeRequest request, Service service, User user, UpgradeStatus upgradeStatus) {
204 Either<? extends Component, ActionStatus> upgradeAllottedResource = upgradeAllottedResource(request, user, upgradeStatus, service);
205 if (upgradeAllottedResource.isRight()) {
206 return upgradeAllottedResource.right().value();
209 resource = upgradeAllottedResource.left().value();
210 // update VF instance in service
212 Either<Component, StorageOperationStatus> serviceContainer = toscaOperationFacade.getToscaFullElement(request.getServiceId());
213 if (serviceContainer.isRight()) {
214 LOGGER.debug("Failed to fetch resource by id {} error {}", request.getServiceId(), serviceContainer.right().value());
215 ActionStatus errS = componentsUtils.convertFromStorageResponse(serviceContainer.right().value());
216 upgradeStatus.addServiceStatus(request.getServiceId(), errS);
219 return handleService(serviceContainer.left().value(), resource, user, upgradeStatus);
223 private Either<? extends Component, ActionStatus> upgradeAllottedResource(UpgradeRequest request, User user, UpgradeStatus upgradeStatus, Service service) {
224 return getElement(request.getResourceId(), upgradeStatus, request)
226 .bind(l -> upgradeStateAlloted(request, user, upgradeStatus, service, l));
229 private Either<Component, ActionStatus> getElement(String id, UpgradeStatus upgradeStatus, UpgradeRequest request) {
230 return toscaOperationFacade.getToscaElement(id)
233 ActionStatus errS = componentsUtils.convertFromStorageResponse(err);
234 upgradeStatus.addServiceStatus(request.getServiceId(), errS);
239 private Either<? extends Component, ActionStatus> upgradeStateAlloted(UpgradeRequest request, User user, UpgradeStatus upgradeStatus, Service service, Component resource) {
240 if (resource.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT) {
241 LOGGER.debug("Automated upgrade failedd. Alloted vf {} is in state NOT_CERTIFIED_CHECKOUT", request.getResourceId());
242 upgradeStatus.addServiceStatus(request.getServiceId(), ActionStatus.RESOURCE_LIFECYCLE_STATE_NOT_VALID);
243 return Either.right(ActionStatus.RESOURCE_LIFECYCLE_STATE_NOT_VALID);
246 // update properties-reference to service in VF on VFCI
247 return changeComponentState(resource, LifeCycleTransitionEnum.CHECKOUT, user, upgradeStatus, request.getServiceId())
249 .bind(l -> updateAllottedPropsAndCertify(request, user, upgradeStatus, service, l));
252 private Either<? extends Component, ActionStatus> updateAllottedPropsAndCertify(UpgradeRequest request, User user, UpgradeStatus upgradeStatus, Service service, Component resource) {
253 Either<? extends Component, ActionStatus> result = null;
255 List<String> instanceIds = upgradeOperation.getInstanceIdFromAllottedEdge(resource.getUniqueId(), service.getInvariantUUID());
256 if (instanceIds != null) {
257 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = resource.getComponentInstancesProperties();
258 Map<String, List<ComponentInstanceProperty>> propertiesToUpdate = new HashMap<>();
260 instanceIds.forEach(id -> findPropertiesToUpdate(id, componentInstancesProperties, propertiesToUpdate, service));
262 Either<Map<String, List<ComponentInstanceProperty>>, StorageOperationStatus> updatePropsResult = toscaOperationFacade.updateComponentInstancePropsToComponent(propertiesToUpdate, resource.getUniqueId());
263 if (updatePropsResult.isRight()) {
264 LOGGER.debug("Failed to update properties in Allotted resource {} {}, Error {}. ", resource.getName(), resource.getUniqueId(), updatePropsResult.right().value());
266 result = Either.right(ActionStatus.GENERAL_ERROR);
271 result = changeComponentState(resource, LifeCycleTransitionEnum.CERTIFY, user, upgradeStatus, request.getServiceId());
274 LOGGER.debug("No Instances to update in allotted resource {} ", resource.getName());
275 result = Either.right(ActionStatus.NO_INSTANCES_TO_UPGRADE);
279 if ( result.isRight() ){
280 // undo checkout resource in case of failure
281 LOGGER.debug("Failed to update Allotted resource {} {}, Error {}. UNDOCHEKOUT our resource", resource.getName(), resource.getUniqueId(), result.right().value());
283 upgradeStatus.addServiceStatus(request.getServiceId(), ActionStatus.GENERAL_ERROR);
288 private void undocheckoutComponent(User user, Component resource) {
289 Either<? extends Component, ResponseFormat> changeComponentState = lifecycleBusinessLogic.changeComponentState(resource.getComponentType(), resource.getUniqueId(), user, LifeCycleTransitionEnum.UNDO_CHECKOUT, changeInfo, false, true);
290 if (changeComponentState.isRight()) {
291 LOGGER.debug("Failed to UNDOCHECKOUT Service {} {}, Error {}", resource.getName(), resource.getUniqueId(), changeComponentState.right().value());
295 private void findPropertiesToUpdate(String id, Map<String, List<ComponentInstanceProperty>> componentInstancesProperties, Map<String, List<ComponentInstanceProperty>> propertiesToUpdate, Service service) {
296 List<ComponentInstanceProperty> list = componentInstancesProperties.get(id);
297 List<ComponentInstanceProperty> propsPerInstance = new ArrayList<>();
299 if (UUID_PROPS_NAMES.contains(p.getName())) {
300 p.setValue(service.getUUID());
301 propsPerInstance.add(p);
303 if (INV_UUID_PROPS_NAMES.contains(p.getName())) {
304 p.setValue(service.getInvariantUUID());
305 propsPerInstance.add(p);
307 if (NAME_PROPS_NAMES.contains(p.getName())) {
308 p.setValue(service.getName());
309 propsPerInstance.add(p);
312 propertiesToUpdate.put(id, propsPerInstance);
315 private ActionStatus handleService(Component component, Component newVersionComponent, User user, UpgradeStatus upgradeStatus) {
316 if (component.getComponentType() != ComponentTypeEnum.SERVICE) {
317 LOGGER.debug("component with id {} and name {} isn't SERVICE. type{} ", component.getName(), component.getUniqueId(), component.getComponentType());
318 upgradeStatus.addServiceStatus(component, ActionStatus.GENERAL_ERROR);
319 return ActionStatus.GENERAL_ERROR;
322 Service service = (Service) component;
323 if (component.getLifecycleState() != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT) {
324 LOGGER.debug("Service {} {} is not in CHECKOUT state . Try to checkout it", component.getName(), component.getUniqueId());
325 Either<? extends Component, ActionStatus> changeComponentState = changeComponentState(component, LifeCycleTransitionEnum.CHECKOUT, user, upgradeStatus, null);
326 if ( changeComponentState.isRight() ){
327 return changeComponentState.right().value();
329 service = (Service) changeComponentState.left().value();
330 //need to fetch service again with capability properties
331 Either<Component, StorageOperationStatus> toscaFullElement = toscaOperationFacade.getToscaFullElement(service.getUniqueId());
332 if ( toscaFullElement.isRight() ){
333 return componentsUtils.convertFromStorageResponse(toscaFullElement.right().value());
335 service = (Service) toscaFullElement.left().value();
337 LOGGER.debug("Service {} {} is in CHECKOUT state . Restricted update operation", component.getName(), component.getUniqueId());
338 upgradeStatus.addServiceStatus(component, ActionStatus.COMPONENT_IN_CHECKOUT_STATE);
339 return ActionStatus.COMPONENT_IN_CHECKOUT_STATE;
341 ActionStatus status = ActionStatus.GENERAL_ERROR;
343 status = handleInstances(newVersionComponent, user, upgradeStatus, service);
345 if (status != ActionStatus.OK) {
346 LOGGER.debug("Failed to upgrade instance for service {} status {}. Undocheckout service", service.getName(), status);
347 undocheckoutComponent(user, service);
349 upgradeStatus.addServiceStatus(component, status);
355 private Either<? extends Component,ActionStatus> changeComponentState(Component component, LifeCycleTransitionEnum nextState, User user, UpgradeStatus upgradeStatus, String idForStatus){
356 if ( component.isArchived() ){
357 LOGGER.debug("Component {} from type {} id {} is archived, Error {}", nextState, component.getName(), component.getComponentType(), component.getUniqueId());
358 setUpgradeStatus(component, upgradeStatus, idForStatus);
359 return Either.right(ActionStatus.COMPONENT_IS_ARCHIVED);
361 return lifecycleBusinessLogic.changeComponentState(component.getComponentType(), component.getUniqueId(), user, nextState, changeInfo, false, true)
364 LOGGER.debug("Failed to {} Component {} from type {} id {}, Error {}", nextState, component.getName(), component.getComponentType(), component.getUniqueId(), err);
365 setUpgradeStatus(component, upgradeStatus, idForStatus);
366 return ActionStatus.GENERAL_ERROR;
372 private void setUpgradeStatus(Component component, UpgradeStatus upgradeStatus, String idForStatus) {
373 if ( idForStatus == null ){
374 upgradeStatus.addServiceStatus(component, ActionStatus.GENERAL_ERROR);
376 upgradeStatus.addServiceStatus(idForStatus, ActionStatus.GENERAL_ERROR);
380 private ActionStatus handleInstances(Component newVersionComponent, User user, UpgradeStatus upgradeStatus, Service service) {
381 List<ComponentInstance> componentInstances = service.getComponentInstances();
382 if (componentInstances != null) {
383 List<ComponentInstance> instanceToChange = componentInstances
385 .filter(ci -> matchInstance(ci, newVersionComponent))
386 .collect(Collectors.toList());
387 if (instanceToChange != null && !instanceToChange.isEmpty()) {
388 return changeInstances(newVersionComponent, user, upgradeStatus, service, instanceToChange);
390 LOGGER.debug("No instances for change version");
391 return ActionStatus.NO_INSTANCES_TO_UPGRADE;
394 return ActionStatus.OK;
397 private ActionStatus changeInstances(Component newVersionComponent, User user, UpgradeStatus upgradeStatus, Service service, List<ComponentInstance> instanceToChange) {
398 Component serviceToUpgrade = service;
399 for (ComponentInstance ci : instanceToChange) {
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();
406 ActionStatus status = changeVersionOfInstance(serviceToUpgrade, ci, newVersionComponent, user);
407 if (status != ActionStatus.OK) {
408 LOGGER.debug("Failed to change for instance {} version in service {}", ci.getName(), service.getName());
409 upgradeStatus.addServiceStatus(service, status);
413 Either<Component, ActionStatus> fetchService = fetchService(service.getUniqueId(),service.getName());
414 if ( fetchService.isRight()){
415 upgradeStatus.addServiceStatus(service, fetchService.right().value());
416 return fetchService.right().value();
418 serviceToUpgrade = fetchService.left().value();
420 Either<? extends Component, ActionStatus> changeComponentState = changeComponentState(serviceToUpgrade, LifeCycleTransitionEnum.CHECKIN, user, upgradeStatus, null);
421 if ( changeComponentState.isRight() ){
422 return changeComponentState.right().value();
424 upgradeStatus.addServiceStatus(serviceToUpgrade, ActionStatus.OK);
425 return ActionStatus.OK;
429 private Either<Component, ActionStatus> fetchService(String uniqueId, String name) {
430 return toscaOperationFacade.getToscaFullElement(uniqueId)
433 LOGGER.debug("Failed to fetch service {} id {} error {}", name, uniqueId, r);
434 return ActionStatus.GENERAL_ERROR;
438 private ActionStatus changeVersionOfInstance(Component service, ComponentInstance ci, Component newVersionComponent, User user) {
439 LOGGER.debug("In Service {} change instance version {} to version {}", service.getName(), ci.getName(), newVersionComponent.getVersion());
440 ComponentInstance newComponentInstance = new ComponentInstance();
441 newComponentInstance.setComponentUid(newVersionComponent.getUniqueId());
442 ComponentInstance changeInstanceVersion = componentInstanceBusinessLogic.changeInstanceVersion(service, ci, newComponentInstance, user, service.getComponentType());
443 return ActionStatus.OK;
446 private boolean matchInstance(ComponentInstance ci, Component newVersionComponent) {
447 Either<Component, StorageOperationStatus> toscaElement;
448 ComponentParametersView filters = new ComponentParametersView(true);
449 if (newVersionComponent.getComponentType() == ComponentTypeEnum.SERVICE) {
450 if (ci.getIsProxy()) {
451 toscaElement = toscaOperationFacade.getToscaElement(ci.getSourceModelUid(), filters);
456 toscaElement = toscaOperationFacade.getToscaElement(ci.getComponentUid(), filters);
458 if (toscaElement.isLeft()) {
459 Component origin = toscaElement.left().value();
460 if (newVersionComponent.getInvariantUUID().equals(origin.getInvariantUUID()) && !newVersionComponent.getVersion().equals(origin.getVersion())) {
461 // only for same invariant UUID (same component) but different versions
467 private AuditingActionEnum getAuditTypeByComponent(Component component){
468 if ( ComponentTypeEnum.RESOURCE == component.getComponentType()){
469 return AuditingActionEnum.VF_UPGRADE_SERVICES;
471 return AuditingActionEnum.UPDATE_SERVICE_REFERENCE;