2 * Copyright © 2016-2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.asdctool.migration.tasks.mig1806;
19 import com.google.common.collect.ImmutableSet;
20 import fj.data.Either;
21 import org.apache.tinkerpop.gremlin.structure.Direction;
22 import org.apache.tinkerpop.gremlin.structure.Edge;
23 import org.apache.tinkerpop.gremlin.structure.Vertex;
24 import org.janusgraph.core.JanusGraphVertex;
25 import org.openecomp.sdc.asdctool.migration.core.DBVersion;
26 import org.openecomp.sdc.asdctool.migration.core.task.Migration;
27 import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult;
28 import org.openecomp.sdc.be.config.ConfigurationManager;
29 import org.openecomp.sdc.be.dao.api.ActionStatus;
30 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
31 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
32 import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
33 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
34 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
35 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
36 import org.openecomp.sdc.be.dao.jsongraph.utils.IdBuilderUtils;
37 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
38 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
39 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
40 import org.openecomp.sdc.be.model.Component;
41 import org.openecomp.sdc.be.model.ComponentParametersView;
42 import org.openecomp.sdc.be.model.Service;
43 import org.openecomp.sdc.be.model.User;
44 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
45 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
46 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
47 import org.openecomp.sdc.be.model.operations.impl.UserAdminOperation;
49 import java.math.BigInteger;
50 import java.util.ArrayList;
51 import java.util.EnumMap;
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.Iterator;
55 import java.util.List;
58 import java.util.stream.Collectors;
60 //@org.springframework.stereotype.Component
61 public class ForwardPathMigration implements Migration {
63 private JanusGraphDao janusGraphDao;
64 private UserAdminOperation userAdminOperation;
65 private ToscaOperationFacade toscaOperationFacade;
66 private User user = null;
68 public ForwardPathMigration(JanusGraphDao janusGraphDao,
69 UserAdminOperation userAdminOperation, ToscaOperationFacade toscaOperationFacade) {
70 this.janusGraphDao = janusGraphDao;
71 this.userAdminOperation = userAdminOperation;
72 this.toscaOperationFacade = toscaOperationFacade;
76 public String description() {
77 return "remove corrupted forwarding paths ";
81 public DBVersion getVersion() {
82 return DBVersion.from(BigInteger.valueOf(1806), BigInteger.valueOf(0));
86 public MigrationResult migrate() {
87 final String userId = ConfigurationManager.getConfigurationManager().getConfiguration().getAutoHealingOwner();
89 Either<User, ActionStatus> userData = (Either<User, ActionStatus>) userAdminOperation
90 .getUserData(userId, false);
91 if (userData.isRight()) {
92 return MigrationResult.error(
93 "failed to delete unused forwarding paths. Failed to resolve user : " + userId + " error " + userData
96 user = userData.left().value();
98 StorageOperationStatus status = cleanAllServices();
100 return status == StorageOperationStatus.OK ? MigrationResult.success()
101 : MigrationResult.error("failed to remove corrupted forwarding paths . Error : " + status);
105 private StorageOperationStatus cleanAllServices() {
106 StorageOperationStatus status;
108 Map<GraphPropertyEnum, Object> hasProps = new EnumMap<>(GraphPropertyEnum.class);
109 hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
110 Map<GraphPropertyEnum, Object> hasNotProps = new HashMap<>();
111 hasNotProps.put(GraphPropertyEnum.IS_DELETED, true);
112 status = janusGraphDao
113 .getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps, hasNotProps, JsonParseFlagEnum.ParseAll)
114 .either(this::cleanServices, this::handleError);
118 private StorageOperationStatus cleanServices(List<GraphVertex> containersV) {
119 StorageOperationStatus status = StorageOperationStatus.OK;
120 for (GraphVertex container : containersV) {
121 ComponentParametersView componentParametersView = new ComponentParametersView();
122 componentParametersView.setIgnoreComponentInstances(false);
123 componentParametersView.setIgnoreCapabilities(false);
124 componentParametersView.setIgnoreRequirements(false);
125 componentParametersView.setIgnoreForwardingPath(false);
126 Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade
127 .getToscaElement(container.getUniqueId(), componentParametersView);
128 if (toscaElement.isRight()) {
129 return toscaElement.right().value();
131 status = fixDataOnGraph(toscaElement.left().value());
132 if (status != StorageOperationStatus.OK) {
140 private StorageOperationStatus handleError(JanusGraphOperationStatus err) {
141 janusGraphDao.rollback();
142 return DaoStatusConverter
143 .convertJanusGraphStatusToStorageStatus(
144 JanusGraphOperationStatus.NOT_FOUND == err ? JanusGraphOperationStatus.OK : err);
147 private StorageOperationStatus fixDataOnGraph(Component component) {
148 if (!(component instanceof Service)){
149 return StorageOperationStatus.OK;
151 Service service = (Service) component;
152 Either<GraphVertex, JanusGraphOperationStatus> getResponse = janusGraphDao.getVertexById(service.getUniqueId(),
153 JsonParseFlagEnum.NoParse);
154 if (getResponse.isRight()) {
155 return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getResponse.right().value());
158 Set<String> ciNames = new HashSet<>();
159 if (service.getComponentInstances() != null && !service.getComponentInstances().isEmpty()) {
160 ciNames = service.getComponentInstances().stream().map(ci -> ci.getName())
161 .collect(Collectors.toSet());
163 GraphVertex componentVertex = getResponse.left().value();
165 GraphVertex toscaDataVertex;
166 Either<GraphVertex, JanusGraphOperationStatus> groupVertexEither = janusGraphDao.getChildVertex(componentVertex,
167 EdgeLabelEnum.FORWARDING_PATH, JsonParseFlagEnum.ParseJson);
168 if (groupVertexEither.isRight() && groupVertexEither.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
169 return StorageOperationStatus.OK;
171 if (groupVertexEither.isRight()) {
172 return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(groupVertexEither.right().value());
174 toscaDataVertex = groupVertexEither.left().value();
175 Map<String, ForwardingPathDataDefinition> forwardingPaths = new HashMap<>(
176 (Map<String, ForwardingPathDataDefinition>) toscaDataVertex.getJson());
177 List<String> toBeDeletedFP = new ArrayList<>();
178 for (Map.Entry<String, ForwardingPathDataDefinition> forwardingPathDataDefinition : forwardingPaths
180 Set<String> nodeNames = forwardingPathDataDefinition.getValue().getPathElements()
181 .getListToscaDataDefinition()
182 .stream().map(element -> ImmutableSet.of(element.getFromNode(), element.getToNode()))
183 .flatMap(set -> set.stream()).collect(Collectors.toSet());
184 if (!ciNames.containsAll(nodeNames)) {
185 toBeDeletedFP.add(forwardingPathDataDefinition.getKey());
188 if (toBeDeletedFP.isEmpty()) {
189 janusGraphDao.rollback();
190 return StorageOperationStatus.OK;
192 toBeDeletedFP.stream().forEach(fpKey -> forwardingPaths.remove(fpKey));
193 toscaDataVertex.setJson(forwardingPaths);
194 Either<GraphVertex, JanusGraphOperationStatus> updatevertexEither = updateOrCopyOnUpdate(
195 toscaDataVertex, componentVertex);
196 if (updatevertexEither.isRight()) {
197 janusGraphDao.rollback();
198 return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatevertexEither.right().value());
200 janusGraphDao.commit();
201 return StorageOperationStatus.OK;
204 private Either<GraphVertex, JanusGraphOperationStatus> cloneDataVertex(GraphVertex dataVertex, GraphVertex toscaElementVertex, Edge edgeToRemove) {
205 EdgeLabelEnum label = EdgeLabelEnum.FORWARDING_PATH;
206 GraphVertex newDataVertex = new GraphVertex(dataVertex.getLabel());
207 String id = IdBuilderUtils.generateChildId(toscaElementVertex.getUniqueId(), dataVertex.getLabel());
208 newDataVertex.cloneData(dataVertex);
209 newDataVertex.setUniqueId(id);
211 Either<GraphVertex, JanusGraphOperationStatus> createVertex = janusGraphDao.createVertex(newDataVertex);
212 if (createVertex.isRight()) {
215 newDataVertex = createVertex.left().value();
216 JanusGraphOperationStatus
217 createEdge = janusGraphDao
218 .createEdge(toscaElementVertex, newDataVertex, label, janusGraphDao.getEdgeProperties(edgeToRemove));
219 if (createEdge != JanusGraphOperationStatus.OK) {
220 return Either.right(createEdge);
222 edgeToRemove.remove();
223 return Either.left(newDataVertex);
226 private Either<GraphVertex, JanusGraphOperationStatus> updateOrCopyOnUpdate(GraphVertex dataVertex, GraphVertex toscaElementVertex ) {
227 EdgeLabelEnum label = EdgeLabelEnum.FORWARDING_PATH;
228 Iterator<Edge> edges = dataVertex.getVertex().edges(Direction.IN, label.name());
230 Edge edgeToRemove = null;
231 while (edges.hasNext()) {
232 Edge edge = edges.next();
234 Vertex outVertex = edge.outVertex();
235 String outId = (String) janusGraphDao
236 .getProperty((JanusGraphVertex) outVertex, GraphPropertyEnum.UNIQUE_ID.getProperty());
237 if (toscaElementVertex.getUniqueId().equals(outId)) {
241 if (edgeToRemove == null) {
242 return Either.right(JanusGraphOperationStatus.GENERAL_ERROR);
247 return Either.right(JanusGraphOperationStatus.GENERAL_ERROR);
250 return janusGraphDao.updateVertex(dataVertex);
253 return cloneDataVertex(dataVertex, toscaElementVertex, edgeToRemove);