Disabling archive functionality for normatives
[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             ActionStatus status = result.right().value();
81             if (ActionStatus.CANNOT_ARCHIVE_SYSTEM_DEPLOYED_RESOURCES.equals(status)) {
82                 throw new ByActionStatusComponentException(status, containerComponentType, componentId);
83             }
84             throw new ByActionStatusComponentException(status, componentId);
85         }
86         this.auditAction(ArchiveOperation.Action.ARCHIVE, result.left().value(), user, containerComponentType);
87         // Send Archive Notification To Facade
88         wrapWithTryCatch(() -> sendNotificationToFacade(componentId, ChangeTypeEnum.ARCHIVE));
89     }
90
91     public void restoreComponent(String containerComponentType, String userId, String componentId) {
92         User user = accessValidations.userIsAdminOrDesigner(userId, containerComponentType + "_RESTORE");
93         Either<List<String>, ActionStatus> result = this.archiveOperation.restoreComponent(componentId);
94         if (result.isRight()) {
95             throw new ByActionStatusComponentException(result.right().value(), componentId);
96         }
97         this.auditAction(ArchiveOperation.Action.RESTORE, result.left().value(), user, containerComponentType);
98         // Send Archive Notification To Facade
99         wrapWithTryCatch(() -> sendNotificationToFacade(componentId, ChangeTypeEnum.RESTORE));
100     }
101
102     public List<String> onVspArchive(String userId, List<String> csarUuids) {
103         return this.onVspArchiveOrRestore(userId, csarUuids, ArchiveOperation.Action.ARCHIVE);
104     }
105
106     public List<String> onVspRestore(String userId, List<String> csarUuids) {
107         return this.onVspArchiveOrRestore(userId, csarUuids, ArchiveOperation.Action.RESTORE);
108     }
109
110     private List<String> onVspArchiveOrRestore(String userId, List<String> csarUuids, ArchiveOperation.Action action) {
111         accessValidations.userIsAdminOrDesigner(userId, action.name() + "_VSP");
112         ActionStatus actionStatus;
113         List<String> failedCsarIDs = new LinkedList<>();
114         for (String csarUuid : csarUuids) {
115             try {
116                 if (action == ArchiveOperation.Action.ARCHIVE) {
117                     actionStatus = this.archiveOperation.onVspArchived(csarUuid);
118                 } else {
119                     actionStatus = this.archiveOperation.onVspRestored(csarUuid);
120                 }
121                 //If not found VFs with this CSAR ID we still want a success (nothing is actually done)
122                 if (actionStatus == ActionStatus.RESOURCE_NOT_FOUND) {
123                     actionStatus = ActionStatus.OK;
124                 }
125                 if (actionStatus != ActionStatus.OK) {
126                     failedCsarIDs.add(csarUuid);
127                 }
128             } catch (Exception e) {
129                 log.error("Failed to handle notification: {} on VSP for csarUuid: {}", action.name(), csarUuid);
130                 log.error("Exception Thrown:", e);
131                 failedCsarIDs.add(csarUuid);
132             }
133         }
134         return failedCsarIDs;
135     }
136
137     public Map<String, List<CatalogComponent>> getArchiveComponents(String userId, List<OriginTypeEnum> excludeTypes) {
138         try {
139             Either<List<CatalogComponent>, StorageOperationStatus> components = toscaOperationFacade
140                 .getCatalogOrArchiveComponents(false, excludeTypes);
141             if (components.isLeft()) {
142                 List<CatalogComponent> comps = components.left().value();
143                 return comps.stream().collect(Collectors.groupingBy(cmpt -> ComponentTypeEnum.findParamByType(cmpt.getComponentType())));
144             } else {
145                 log.info("No components found");
146                 return new HashMap<>();
147             }
148         } catch (Exception e) {
149             log.error("Error fetching archived elements", e);
150             throw e;
151         } finally {
152             janusGraphDao.commit();
153         }
154     }
155
156     @VisibleForTesting
157     void auditAction(ArchiveOperation.Action action, List<String> affectedCompIds, User user, String containerComponentType) {
158         String comment = String.format("All versions of this component were %s", action == ArchiveOperation.Action.ARCHIVE ? "archived" : "restored");
159         HashSet<String> auditDoneUUIDs = new HashSet<>();
160         for (String componentId : affectedCompIds) {
161             Either<Component, StorageOperationStatus> result = toscaOperationFacade.getToscaElement(componentId, new ComponentParametersView());
162             if (result.isRight()) {
163                 log.error(EcompLoggerErrorCode.DATA_ERROR, null, "GetToscaElement", result.right().value().name() + "for component with id {}",
164                     componentId);
165                 continue;
166             }
167             if (auditDoneUUIDs.add(result.left().value().getUUID())) {
168                 //a component with this UUID is not added to audit DB/log for current archive/restore operation yet - add to audit DB now
169
170                 AuditingActionEnum auditAction = action == ArchiveOperation.Action.ARCHIVE ? AuditingActionEnum.ARCHIVE_COMPONENT
171                     : AuditingActionEnum.RESTORE_COMPONENT; //The audit Action
172                 result.left().foreachDoEffect(c -> {
173                     // The archive/restore records have been retrieved from Cassandra using the separate queries.
174
175                     // Setting current version as null allows to avoid appearing same records in ActivityLog twice:
176
177                     // - first time as per current version query
178
179                     //- second type as per archive/restore query
180                     c.setVersion(null);
181                     componentUtils.auditComponentAdmin(componentUtils.getResponseFormat(ActionStatus.OK), user, c, auditAction,
182                         ComponentTypeEnum.findByParamName(containerComponentType), comment);
183                 });
184             }
185         }
186     }
187
188     protected Either<Component, ResponseFormat> sendNotificationToFacade(String componentId, ChangeTypeEnum changeStatus) {
189         if (log.isDebugEnabled()) {
190             log.debug("build {} notification for facade start", changeStatus.name());
191         }
192         Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade.getToscaElement(componentId);
193         Component component = toscaElement.left().value();
194         ActionStatus status = catalogOperations.updateCatalog(changeStatus, component);
195         if (status != ActionStatus.OK) {
196             return Either.right(componentUtils.getResponseFormat(status));
197         }
198         return Either.left(component);
199     }
200 }