19afff0668e4f936984c972e429e7d4e8edc8ff0
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ArchiveBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22 package org.openecomp.sdc.be.components.impl;
23
24 import static org.openecomp.sdc.common.datastructure.FunctionalInterfaces.wrapWithTryCatch;
25
26 import com.google.common.annotations.VisibleForTesting;
27 import fj.data.Either;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.stream.Collectors;
34 import org.openecomp.sdc.be.catalog.enums.ChangeTypeEnum;
35 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
36 import org.openecomp.sdc.be.components.validation.AccessValidations;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
39 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
40 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
41 import org.openecomp.sdc.be.facade.operations.CatalogOperation;
42 import org.openecomp.sdc.be.impl.ComponentsUtils;
43 import org.openecomp.sdc.be.model.Component;
44 import org.openecomp.sdc.be.model.ComponentParametersView;
45 import org.openecomp.sdc.be.model.User;
46 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
47 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation;
48 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
49 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
50 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
51 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
52 import org.openecomp.sdc.common.log.wrappers.Logger;
53 import org.openecomp.sdc.exception.ResponseFormat;
54
55 @org.springframework.stereotype.Component
56 public class ArchiveBusinessLogic {
57
58     private static final Logger log = Logger.getLogger(ArchiveBusinessLogic.class.getName());
59     private final JanusGraphDao janusGraphDao;
60     private final AccessValidations accessValidations;
61     private final ArchiveOperation archiveOperation;
62     private final ToscaOperationFacade toscaOperationFacade;
63     private final ComponentsUtils componentUtils;
64     private final CatalogOperation catalogOperations;
65
66     public ArchiveBusinessLogic(JanusGraphDao janusGraphDao, AccessValidations accessValidations, ArchiveOperation archiveOperation,
67                                 ToscaOperationFacade tof, ComponentsUtils componentsUtils, CatalogOperation catalogOperations) {
68         this.janusGraphDao = janusGraphDao;
69         this.accessValidations = accessValidations;
70         this.archiveOperation = archiveOperation;
71         this.toscaOperationFacade = tof;
72         this.componentUtils = componentsUtils;
73         this.catalogOperations = catalogOperations;
74     }
75
76     public void archiveComponent(String containerComponentType, String userId, String componentId) {
77         User user = accessValidations.userIsAdminOrDesigner(userId, containerComponentType + "_ARCHIVE");
78         Either<List<String>, ActionStatus> result = this.archiveOperation.archiveComponent(componentId);
79         if (result.isRight()) {
80             throw new ByActionStatusComponentException(result.right().value(), componentId);
81         }
82         this.auditAction(ArchiveOperation.Action.ARCHIVE, result.left().value(), user, containerComponentType);
83         // Send Archive Notification To Facade
84         wrapWithTryCatch(() -> sendNotificationToFacade(componentId, ChangeTypeEnum.ARCHIVE));
85     }
86
87     public void restoreComponent(String containerComponentType, String userId, String componentId) {
88         User user = accessValidations.userIsAdminOrDesigner(userId, containerComponentType + "_RESTORE");
89         Either<List<String>, ActionStatus> result = this.archiveOperation.restoreComponent(componentId);
90         if (result.isRight()) {
91             throw new ByActionStatusComponentException(result.right().value(), componentId);
92         }
93         this.auditAction(ArchiveOperation.Action.RESTORE, result.left().value(), user, containerComponentType);
94         // Send Archive Notification To Facade
95         wrapWithTryCatch(() -> sendNotificationToFacade(componentId, ChangeTypeEnum.RESTORE));
96     }
97
98     public List<String> onVspArchive(String userId, List<String> csarUuids) {
99         return this.onVspArchiveOrRestore(userId, csarUuids, ArchiveOperation.Action.ARCHIVE);
100     }
101
102     public List<String> onVspRestore(String userId, List<String> csarUuids) {
103         return this.onVspArchiveOrRestore(userId, csarUuids, ArchiveOperation.Action.RESTORE);
104     }
105
106     private List<String> onVspArchiveOrRestore(String userId, List<String> csarUuids, ArchiveOperation.Action action) {
107         accessValidations.userIsAdminOrDesigner(userId, action.name() + "_VSP");
108         ActionStatus actionStatus;
109         List<String> failedCsarIDs = new LinkedList<>();
110         for (String csarUuid : csarUuids) {
111             try {
112                 if (action == ArchiveOperation.Action.ARCHIVE) {
113                     actionStatus = this.archiveOperation.onVspArchived(csarUuid);
114                 } else {
115                     actionStatus = this.archiveOperation.onVspRestored(csarUuid);
116                 }
117                 //If not found VFs with this CSAR ID we still want a success (nothing is actually done)
118                 if (actionStatus == ActionStatus.RESOURCE_NOT_FOUND) {
119                     actionStatus = ActionStatus.OK;
120                 }
121                 if (actionStatus != ActionStatus.OK) {
122                     failedCsarIDs.add(csarUuid);
123                 }
124             } catch (Exception e) {
125                 log.error("Failed to handle notification: {} on VSP for csarUuid: {}", action.name(), csarUuid);
126                 log.error("Exception Thrown:", e);
127                 failedCsarIDs.add(csarUuid);
128             }
129         }
130         return failedCsarIDs;
131     }
132
133     public Map<String, List<CatalogComponent>> getArchiveComponents(String userId, List<OriginTypeEnum> excludeTypes) {
134         try {
135             Either<List<CatalogComponent>, StorageOperationStatus> components = toscaOperationFacade
136                 .getCatalogOrArchiveComponents(false, excludeTypes);
137             if (components.isLeft()) {
138                 List<CatalogComponent> comps = components.left().value();
139                 return comps.stream().collect(Collectors.groupingBy(cmpt -> ComponentTypeEnum.findParamByType(cmpt.getComponentType())));
140             } else {
141                 log.info("No components found");
142                 return new HashMap<>();
143             }
144         } catch (Exception e) {
145             log.error("Error fetching archived elements", e);
146             throw e;
147         } finally {
148             janusGraphDao.commit();
149         }
150     }
151
152     @VisibleForTesting
153     void auditAction(ArchiveOperation.Action action, List<String> affectedCompIds, User user, String containerComponentType) {
154         String comment = String.format("All versions of this component were %s", action == ArchiveOperation.Action.ARCHIVE ? "archived" : "restored");
155         HashSet<String> auditDoneUUIDs = new HashSet<>();
156         for (String componentId : affectedCompIds) {
157             Either<Component, StorageOperationStatus> result = toscaOperationFacade.getToscaElement(componentId, new ComponentParametersView());
158             if (result.isRight()) {
159                 log.error(EcompLoggerErrorCode.DATA_ERROR, null, "GetToscaElement", result.right().value().name() + "for component with id {}",
160                     componentId);
161                 continue;
162             }
163             if (auditDoneUUIDs.add(result.left().value().getUUID())) {
164                 //a component with this UUID is not added to audit DB/log for current archive/restore operation yet - add to audit DB now
165
166                 AuditingActionEnum auditAction = action == ArchiveOperation.Action.ARCHIVE ? AuditingActionEnum.ARCHIVE_COMPONENT
167                     : AuditingActionEnum.RESTORE_COMPONENT; //The audit Action
168                 result.left().foreachDoEffect(c -> {
169                     // The archive/restore records have been retrieved from Cassandra using the separate queries.
170
171                     // Setting current version as null allows to avoid appearing same records in ActivityLog twice:
172
173                     // - first time as per current version query
174
175                     //- second type as per archive/restore query
176                     c.setVersion(null);
177                     componentUtils.auditComponentAdmin(componentUtils.getResponseFormat(ActionStatus.OK), user, c, auditAction,
178                         ComponentTypeEnum.findByParamName(containerComponentType), comment);
179                 });
180             }
181         }
182     }
183
184     protected Either<Component, ResponseFormat> sendNotificationToFacade(String componentId, ChangeTypeEnum changeStatus) {
185         if (log.isDebugEnabled()) {
186             log.debug("build {} notification for facade start", changeStatus.name());
187         }
188         Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade.getToscaElement(componentId);
189         Component component = toscaElement.left().value();
190         ActionStatus status = catalogOperations.updateCatalog(changeStatus, component);
191         if (status != ActionStatus.OK) {
192             return Either.right(componentUtils.getResponseFormat(status));
193         }
194         return Either.left(component);
195     }
196 }