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=========================================================
20 package org.openecomp.sdc.be.model.jsonjanusgraph.operations;
22 import static org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation.Action.ARCHIVE;
23 import static org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation.Action.RESTORE;
25 import fj.data.Either;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.LinkedList;
29 import java.util.List;
31 import java.util.stream.Collectors;
32 import org.openecomp.sdc.be.dao.api.ActionStatus;
33 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
34 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
35 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
36 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
37 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
38 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
39 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
40 import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition;
41 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
42 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
43 import org.openecomp.sdc.be.model.LifecycleStateEnum;
44 import org.openecomp.sdc.be.model.jsonjanusgraph.enums.JsonConstantKeysEnum;
45 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
46 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
47 import org.openecomp.sdc.common.log.wrappers.Logger;
48 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.stereotype.Component;
52 * Created by yavivi on 25/03/2018.
55 public class ArchiveOperation extends BaseOperation {
57 private static final Logger log = Logger.getLogger(ArchiveOperation.class.getName());
59 private IGraphLockOperation graphLockOperation;
61 public ArchiveOperation(JanusGraphDao janusGraphDao, IGraphLockOperation graphLockOperation) {
62 this.janusGraphDao = janusGraphDao;
63 this.graphLockOperation = graphLockOperation;
66 public Either<List<String>, ActionStatus> archiveComponent(String componentId) {
67 final Either<GraphVertex, JanusGraphOperationStatus> vertexResult = this.janusGraphDao.getVertexById(componentId);
68 if (vertexResult.isLeft()) {
69 return doAction(ARCHIVE, vertexResult.left().value());
71 return Either.right(onError(ARCHIVE.name(), componentId, vertexResult.right().value()));
75 public Either<List<String>, ActionStatus> restoreComponent(String componentId) {
76 final Either<GraphVertex, JanusGraphOperationStatus> vertexResult = this.janusGraphDao.getVertexById(componentId);
77 if (vertexResult.isLeft()) {
78 return doAction(RESTORE, vertexResult.left().value());
80 return Either.right(onError(RESTORE.name(), componentId, vertexResult.right().value()));
84 public ActionStatus onVspRestored(String csarId) {
85 return onVspStateChanged(RESTORE, csarId);
88 public ActionStatus onVspArchived(String csarId) {
89 return onVspStateChanged(ARCHIVE, csarId);
92 private ActionStatus onVspStateChanged(Action action, String csarId) {
93 Map<GraphPropertyEnum, Object> props = new HashMap<>();
94 props.put(GraphPropertyEnum.CSAR_UUID, csarId);
95 Either<List<GraphVertex>, JanusGraphOperationStatus> vfsE = janusGraphDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, props);
96 return vfsE.either(vList -> setVspArchived(action, vList), s -> onError("VSP_" + action.name(), csarId, s));
99 private ActionStatus setVspArchived(Action action, List<GraphVertex> vList) {
100 if (!vList.isEmpty()) {
101 //Find & Lock the highest version component
102 GraphVertex highestVersion = this.getHighestVersionFrom(vList.get(0));
103 StorageOperationStatus lockStatus = this.graphLockOperation
104 .lockComponent(highestVersion.getUniqueId(), highestVersion.getType().getNodeType());
105 if (lockStatus != StorageOperationStatus.OK) {
106 return onError(action.name(), highestVersion.getUniqueId(), JanusGraphOperationStatus.ALREADY_LOCKED);
109 //Set isVspArchived flag
110 for (GraphVertex v : vList) {
111 boolean val = action == ARCHIVE ? true : false;
112 v.setJsonMetadataField(JsonPresentationFields.IS_VSP_ARCHIVED, val);
113 v.addMetadataProperty(GraphPropertyEnum.IS_VSP_ARCHIVED, val);
114 janusGraphDao.updateVertex(v);
116 return commitAndCheck("VSP_" + action.name(), vList.toString());
118 this.graphLockOperation.unlockComponent(highestVersion.getUniqueId(), highestVersion.getType().getNodeType());
121 return ActionStatus.OK;
124 public List<String> setArchivedOriginsFlagInComponentInstances(GraphVertex compositionService) {
125 List<String> ciUidsWithArchivedOrigins = new LinkedList();
126 Either<List<GraphVertex>, JanusGraphOperationStatus> instanceOfVerticesE = janusGraphDao
127 .getChildrenVertices(compositionService, EdgeLabelEnum.INSTANCE_OF, JsonParseFlagEnum.NoParse);
128 Either<List<GraphVertex>, JanusGraphOperationStatus> proxyOfVerticesE = janusGraphDao
129 .getChildrenVertices(compositionService, EdgeLabelEnum.PROXY_OF, JsonParseFlagEnum.NoParse);
130 List<GraphVertex> all = new LinkedList<>();
131 if (instanceOfVerticesE.isLeft()) {
132 all.addAll(instanceOfVerticesE.left().value());
134 if (proxyOfVerticesE.isLeft()) {
135 all.addAll(proxyOfVerticesE.left().value());
137 List<GraphVertex> archivedOrigins = all.stream().filter(v -> Boolean.TRUE.equals(v.getMetadataProperty(GraphPropertyEnum.IS_ARCHIVED)))
138 .collect(Collectors.toList());
139 List<String> archivedOriginsUids = archivedOrigins.stream().map(GraphVertex::getUniqueId).collect(Collectors.toList());
140 Map<String, CompositionDataDefinition> compositionsJson = (Map<String, CompositionDataDefinition>) compositionService.getJson();
141 if (compositionsJson != null) {
142 CompositionDataDefinition composition = compositionsJson.get(JsonConstantKeysEnum.COMPOSITION.getValue());
143 if (composition != null) {
144 //Get all component instances from composition
145 Map<String, ComponentInstanceDataDefinition> componentInstances = composition.getComponentInstances();
146 //Extract component instances uids that has archived origins
147 ciUidsWithArchivedOrigins = componentInstances.values().stream().
148 //filter CIs whose origins are marked as archived (componentUid is in archivedOriginsUids) the second condition handles the PROXY_OF case)
149 filter(ci -> archivedOriginsUids.contains(ci.getComponentUid()) || archivedOriginsUids
150 .contains(ci.getToscaPresentationValue(JsonPresentationFields.CI_SOURCE_MODEL_UID)))
151 .map(ComponentInstanceDataDefinition::getUniqueId).collect(Collectors.toList());
152 //set archived origins flag
153 componentInstances.values().stream().filter(ci -> archivedOriginsUids.contains(ci.getComponentUid()) || archivedOriginsUids
154 .contains(ci.getToscaPresentationValue(JsonPresentationFields.CI_SOURCE_MODEL_UID))).forEach(ci -> ci.setOriginArchived(true));
157 return ciUidsWithArchivedOrigins;
160 private Either<List<String>, ActionStatus> doAction(Action action, GraphVertex componentVertex) {
161 GraphVertex highestVersion = this.getHighestVersionFrom(componentVertex);
162 if (action.equals(ARCHIVE) && isInCheckoutState(highestVersion)) {
163 return Either.right(ActionStatus.INVALID_SERVICE_STATE);
165 //Lock the Highest Version
166 StorageOperationStatus lockStatus = this.graphLockOperation
167 .lockComponent(highestVersion.getUniqueId(), highestVersion.getType().getNodeType());
168 if (lockStatus != StorageOperationStatus.OK) {
169 return Either.right(onError(action.name(), componentVertex.getUniqueId(), JanusGraphOperationStatus.ALREADY_LOCKED));
171 //Refetch latest version with full parsing
172 highestVersion = this.janusGraphDao.getVertexById(highestVersion.getUniqueId(), JsonParseFlagEnum.ParseAll).left().value();
174 //Get Catalog and Archive Roots
175 GraphVertex catalogRoot = janusGraphDao.getVertexByLabel(VertexTypeEnum.CATALOG_ROOT).left().value();
176 GraphVertex archiveRoot = janusGraphDao.getVertexByLabel(VertexTypeEnum.ARCHIVE_ROOT).left().value();
177 if (action == ARCHIVE) {
178 archiveEdges(catalogRoot, archiveRoot, highestVersion);
179 } else if (action == RESTORE) {
180 restoreEdges(catalogRoot, archiveRoot, highestVersion);
182 setPropertiesByAction(highestVersion, action);
183 janusGraphDao.updateVertex(highestVersion);
184 List<String> affectedComponentIds = handleParents(highestVersion, catalogRoot, archiveRoot, action);
185 ActionStatus sc = commitAndCheck(action.name(), highestVersion.getUniqueId());
186 return sc == ActionStatus.OK ? Either.left(affectedComponentIds) : Either.right(sc);
188 this.graphLockOperation.unlockComponent(highestVersion.getUniqueId(), highestVersion.getType().getNodeType());
192 private ActionStatus commitAndCheck(String action, String componentId) {
193 JanusGraphOperationStatus status = janusGraphDao.commit();
194 if (!status.equals(JanusGraphOperationStatus.OK)) {
195 return onError(action, componentId, status);
197 return ActionStatus.OK;
200 private boolean isInCheckoutState(GraphVertex v) {
201 if (LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name().equals(v.getMetadataProperty(GraphPropertyEnum.STATE))) {
208 * Walks on children until highest version is reached
213 private GraphVertex getHighestVersionFrom(GraphVertex v) {
214 Either<GraphVertex, JanusGraphOperationStatus> childVertexE = janusGraphDao
215 .getChildVertex(v, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
216 GraphVertex highestVersionVertex = v;
217 while (childVertexE.isLeft()) {
218 highestVersionVertex = childVertexE.left().value();
219 childVertexE = janusGraphDao.getChildVertex(highestVersionVertex, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
221 return highestVersionVertex;
224 private boolean isHighestVersion(GraphVertex v) {
225 Boolean highest = (Boolean) v.getMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION);
226 return highest != null && highest;
229 private List<String> handleParents(GraphVertex v, GraphVertex catalogRoot, GraphVertex archiveRoot, Action action) {
230 Either<GraphVertex, JanusGraphOperationStatus> parentVertexE = janusGraphDao
231 .getParentVertex(v, EdgeLabelEnum.VERSION, JsonParseFlagEnum.ParseAll);
232 List<String> affectedCompIds = new ArrayList();
233 affectedCompIds.add(v.getUniqueId());
234 while (parentVertexE.isLeft()) {
235 GraphVertex cv = parentVertexE.left().value();
236 affectedCompIds.add(cv.getUniqueId());
237 boolean isHighestVersion = isHighestVersion(cv);
238 if (isHighestVersion) {
239 if (action == ARCHIVE) {
240 archiveEdges(catalogRoot, archiveRoot, cv);
242 restoreEdges(catalogRoot, archiveRoot, cv);
245 setPropertiesByAction(cv, action);
246 janusGraphDao.updateVertex(cv);
247 parentVertexE = janusGraphDao.getParentVertex(cv, EdgeLabelEnum.VERSION, JsonParseFlagEnum.ParseAll);
249 return affectedCompIds;
252 private void archiveEdges(GraphVertex catalogRoot, GraphVertex archiveRoot, GraphVertex v) {
253 janusGraphDao.deleteAllEdges(catalogRoot, v, EdgeLabelEnum.CATALOG_ELEMENT);
254 janusGraphDao.createEdge(archiveRoot, v, EdgeLabelEnum.ARCHIVE_ELEMENT, null);
255 setPropertiesByAction(v, ARCHIVE);
258 private void restoreEdges(GraphVertex catalogRoot, GraphVertex archiveRoot, GraphVertex v) {
259 janusGraphDao.deleteAllEdges(archiveRoot, v, EdgeLabelEnum.ARCHIVE_ELEMENT);
260 janusGraphDao.createEdge(catalogRoot, v, EdgeLabelEnum.CATALOG_ELEMENT, null);
261 setPropertiesByAction(v, RESTORE);
264 private void setPropertiesByAction(GraphVertex v, Action action) {
265 long now = System.currentTimeMillis();
266 boolean isArchived = action == ARCHIVE ? true : false;
267 v.addMetadataProperty(GraphPropertyEnum.IS_ARCHIVED, isArchived);
268 v.addMetadataProperty(GraphPropertyEnum.ARCHIVE_TIME, now);
269 v.setJsonMetadataField(JsonPresentationFields.IS_ARCHIVED, isArchived);
270 v.setJsonMetadataField(JsonPresentationFields.ARCHIVE_TIME, now);
273 private ActionStatus onError(String action, String componentId, JanusGraphOperationStatus s) {
274 ActionStatus ret = ActionStatus.GENERAL_ERROR;
275 if (s == JanusGraphOperationStatus.NOT_FOUND) {
276 ret = ActionStatus.RESOURCE_NOT_FOUND;
277 } else if (s == JanusGraphOperationStatus.ALREADY_LOCKED) {
278 ret = ActionStatus.COMPONENT_IN_USE;
280 String retCodeVal = ret.name();
281 log.error("error occurred when trying to {} {}. Return code is: {}", action, componentId, retCodeVal);
285 public enum Action {ARCHIVE, RESTORE;}