diff options
author | talig <talig@amdocs.com> | 2018-02-28 10:53:11 +0200 |
---|---|---|
committer | Avi Gaffa <avi.gaffa@amdocs.com> | 2018-02-28 11:28:17 +0000 |
commit | 1b03220adb20c86530e983a6cda78e1732cc05d7 (patch) | |
tree | 9eb1192f6baf4f12196a43c2364eb7db09cb7727 | |
parent | 23cc7f5c7d811d7ed1038b354db4c07687e17cc3 (diff) |
Healing manager logic enhancements
Check whether healers need to run before running them.
Heal private: if there's at least one structure healer - force sync (instead of running data healers).
Change-Id: I5cc5ce43d61a59d5cfd6a1db717d6e3e4be1119a
Issue-ID: SDC-1066
Signed-off-by: talig <talig@amdocs.com>
5 files changed, 180 insertions, 149 deletions
diff --git a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-api/src/main/java/org/openecomp/sdc/healing/interfaces/Healer.java b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-api/src/main/java/org/openecomp/sdc/healing/interfaces/Healer.java index 13599ea5d4..46ed591f8c 100644 --- a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-api/src/main/java/org/openecomp/sdc/healing/interfaces/Healer.java +++ b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-api/src/main/java/org/openecomp/sdc/healing/interfaces/Healer.java @@ -18,7 +18,9 @@ package org.openecomp.sdc.healing.interfaces; import org.openecomp.sdc.versioning.dao.types.Version; -@FunctionalInterface public interface Healer { - Object heal(String itemId, Version version) throws Exception; + + boolean isHealingNeeded(String itemId, Version version); + + void heal(String itemId, Version version) throws Exception; } diff --git a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/java/org/openecomp/sdc/healing/impl/HealingManagerImpl.java b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/java/org/openecomp/sdc/healing/impl/HealingManagerImpl.java index 4a0bf13f41..eef8c3cd44 100644 --- a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/java/org/openecomp/sdc/healing/impl/HealingManagerImpl.java +++ b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/java/org/openecomp/sdc/healing/impl/HealingManagerImpl.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,33 +24,29 @@ import org.openecomp.core.utilities.CommonMethods; import org.openecomp.core.utilities.file.FileUtils; import org.openecomp.core.utilities.json.JsonUtil; import org.openecomp.sdc.common.errors.CoreException; +import org.openecomp.sdc.common.errors.ErrorCategory; import org.openecomp.sdc.common.errors.ErrorCode; import org.openecomp.sdc.common.errors.Messages; -import org.openecomp.sdc.common.session.SessionContext; import org.openecomp.sdc.common.session.SessionContextProviderFactory; import org.openecomp.sdc.datatypes.model.ItemType; import org.openecomp.sdc.healing.api.HealingManager; import org.openecomp.sdc.healing.dao.HealingDao; import org.openecomp.sdc.healing.interfaces.Healer; -import org.openecomp.sdc.healing.types.HealCode; import org.openecomp.sdc.healing.types.HealerType; import org.openecomp.sdc.versioning.VersioningManager; import org.openecomp.sdc.versioning.dao.types.Version; import org.openecomp.sdc.versioning.dao.types.VersionStatus; import org.openecomp.sdc.versioning.types.VersionCreationMethod; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; -/** - * Created by Talio on 11/29/2016. - */ public class HealingManagerImpl implements HealingManager { private static final String HEALERS_BY_ENTITY_TYPE_FILE = "entityHealingConfiguration.json"; @@ -66,134 +62,142 @@ public class HealingManagerImpl implements HealingManager { } @Override - public Optional<Version> healItemVersion(String itemId, Version version, ItemType itemType, - boolean force) { + public Optional<Version> healItemVersion(final String itemId, final Version version, + final ItemType itemType, final boolean force) { String user = getUser(); if (force || isPrivateHealingNeededByFlag(itemId, version.getId(), user)) { - version = versioningManager.get(itemId, version); - Version origVersion = version; - if (version.getStatus() == VersionStatus.Certified) { - Optional<Version> newVersion = createNewVersion(itemId, version); - if (!newVersion.isPresent()) { - // do NOT turn off flag here (in thought of saving version calculate performance next - // time) because maybe next time the next version will be available (due to deletion of - // the taken one) - return Optional.empty(); - } - version = newVersion.get(); + + Map<String, Collection<String>> healersByType = getItemHealers(itemType); + List<String> failureMessages = new LinkedList<>(); + List<Healer> structureHealersToRun = + getHealersToRun(healersByType.get(HealerType.structure.name()), itemId, version, + failureMessages); + List<Healer> dataHealersToRun = + getHealersToRun(healersByType.get(HealerType.data.name()), itemId, version, + failureMessages); + + if (structureHealersToRun.isEmpty() && dataHealersToRun.isEmpty()) { + markAsHealed(itemId, version.getId(), user); + markAsHealed(itemId, version.getId(), PUBLIC_USER); + return Optional.empty(); + } + + Optional<Version> healVersion = getHealVersion(itemId, version); + if (!healVersion.isPresent()) { + // do NOT turn off flag here (in thought of saving version calculate performance next + // time) because maybe next time the next version will be available (due to deletion of + // the taken one) + return Optional.empty(); } - doHeal(itemId, version, origVersion, itemType, user, force); - return Optional.of(version); + failureMessages.addAll( + doHeal(itemId, healVersion.get(), version, structureHealersToRun, dataHealersToRun, user, + force)); + + handleFailures(failureMessages); + return healVersion; } return Optional.empty(); } - private void doHeal(String itemId, Version version, Version origVersion, - ItemType itemType, String user, boolean force) { - Optional<String> privateFailureMessages = - healPrivate(itemId, version, origVersion, getItemHealers(itemType), user); + private Optional<Version> getHealVersion(String itemId, Version version) { + version.setStatus(versioningManager.get(itemId, version).getStatus()); + return version.getStatus() == VersionStatus.Certified + ? createNewVersion(itemId, version.getId()) + : Optional.of(version); + } + + private Optional<Version> createNewVersion(String itemId, String versionId) { + Version newVersion = new Version(); + newVersion.setBaseId(versionId); + try { + return Optional.of(versioningManager.create(itemId, newVersion, VersionCreationMethod.major)); + } catch (Exception e) { + return Optional.empty(); + } + } - Optional<String> publicFailureMessages = + private List<String> doHeal(String itemId, Version version, Version origVersion, + List<Healer> structureHealersToRun, + List<Healer> dataHealersToRun, String user, + boolean force) { + List<String> failureMessages = force || origVersion.getStatus() == VersionStatus.Certified || isPublicHealingNeededByFlag(itemId, origVersion.getId()) - ? healPublic(itemId, version, origVersion, getItemHealers(itemType), user) - : Optional.empty(); + ? healPublic(itemId, version, origVersion, structureHealersToRun, dataHealersToRun, + user) + : new LinkedList<>(); - if (privateFailureMessages.isPresent() || publicFailureMessages.isPresent()) { - throw new CoreException(new ErrorCode.ErrorCodeBuilder().withMessage( - publicFailureMessages.orElse("") + " " + privateFailureMessages.orElse("")) - .build()); - } + failureMessages.addAll( + healPrivate(itemId, version, origVersion, structureHealersToRun, dataHealersToRun, user)); + + return failureMessages; } - private Optional<String> healPrivate(String itemId, Version version, Version origVersion, - Map<String, Map<String, String>> itemHealers, String user) { - if (origVersion.getStatus() != VersionStatus.Certified) { - itemHealers.remove(HealerType.structure.name()); + private List<String> healPrivate(String itemId, Version version, Version origVersion, + List<Healer> structureHealersToRun, + List<Healer> dataHealersToRun, String user) { + List<String> failureMessages; + if (origVersion.getStatus() == VersionStatus.Certified) { + failureMessages = executeHealers(itemId, version, + Stream.concat(structureHealersToRun.stream(), dataHealersToRun.stream()) + .collect(Collectors.toList())); + } else { + if (structureHealersToRun.isEmpty()) { + failureMessages = executeHealers(itemId, version, dataHealersToRun); + } else { + versioningManager.forceSync(itemId, version); + failureMessages = new LinkedList<>(); + } } - - Optional<String> privateHealingFailureMessages = executeHealers(itemId, version, itemHealers); markAsHealed(itemId, origVersion.getId(), user); - return privateHealingFailureMessages; + return failureMessages; } - private Optional<String> healPublic(String itemId, Version version, Version origVersion, - Map<String, Map<String, String>> itemHealers, String user) { - Optional<String> healingFailureMessages = origVersion.getStatus() == VersionStatus.Certified - ? Optional.empty() - : healPublic(itemId, version, itemHealers, user); + private List<String> healPublic(String itemId, Version version, Version origVersion, + List<Healer> structureHealersToRun, + List<Healer> dataHealersToRun, String user) { + List<String> failureMessages = origVersion.getStatus() == VersionStatus.Certified + ? new LinkedList<>() + : healPublic(itemId, version, + Stream.concat(structureHealersToRun.stream(), dataHealersToRun.stream()) + .collect(Collectors.toList()), user); markAsHealed(itemId, origVersion.getId(), PUBLIC_USER); - return healingFailureMessages; + return failureMessages; } - private Optional<String> healPublic(String itemId, Version version, - Map<String, Map<String, String>> itemHealers, String user) { - SessionContext context = - SessionContextProviderFactory.getInstance().createInterface().get(); - SessionContextProviderFactory.getInstance().createInterface().create(user - + HEALING_USER_SUFFIX,context.getTenant()); + private List<String> healPublic(String itemId, Version version, List<Healer> healers, + String user) { + String tenant = SessionContextProviderFactory.getInstance().createInterface().get().getTenant(); + SessionContextProviderFactory.getInstance().createInterface() + .create(user + HEALING_USER_SUFFIX, tenant); - versioningManager.sync(itemId, version); + versioningManager.forceSync(itemId, version); - Optional<String> healingFailureMessages = executeHealers(itemId, version, itemHealers); + List<String> failureMessages = executeHealers(itemId, version, healers); Version publicVersion = versioningManager.get(itemId, version); if (Objects.nonNull(publicVersion.getState()) && publicVersion.getState().isDirty()) { versioningManager.publish(itemId, version, "Healing vsp"); } - SessionContextProviderFactory.getInstance().createInterface().create(user, context.getTenant()); - return healingFailureMessages; + SessionContextProviderFactory.getInstance().createInterface().create(user, tenant); + return failureMessages; } - private Optional<Version> createNewVersion(String itemId, Version version) { - Version newVersion = new Version(); - newVersion.setBaseId(version.getId()); - try { - return Optional.of(versioningManager.create(itemId, newVersion, VersionCreationMethod.major)); - } catch (Exception e) { - return Optional.empty(); - } - } - - private Optional<String> executeHealers(String itemId, Version version, - Map<String, Map<String, String>> itemHealers) { - List<String> healers = itemHealers.values().stream() - .map(Map::values) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - - List<String> healingFailureMessages = new ArrayList<>(); - for (String implClassName : healers) { - executeHealer(itemId, version, implClassName, healingFailureMessages); - } - - return healingFailureMessages.isEmpty() - ? Optional.empty() - : Optional.of(CommonMethods.listToSeparatedString(healingFailureMessages, '\n')); - } - - - private Object executeHealer(String itemId, Version version, String healerClassName, - List<String> healingFailureMessages) { - Healer healer; - try { - healer = getHealerImplInstance(healerClassName); - } catch (Exception e) { - healingFailureMessages - .add(String.format(Messages.CANT_LOAD_HEALING_CLASS.getErrorMessage(), - healerClassName)); - return null; + private List<String> executeHealers(String itemId, Version version, List<Healer> healers) { + List<String> failureMessages = new LinkedList<>(); + for (Healer healer : healers) { + try { + healer.heal(itemId, version); + } catch (Exception e) { + failureMessages.add( + String.format("Failure in healer %s: %s", healer.getClass().getName(), e.getMessage())); + } } - try { - return healer.heal(itemId, version); - } catch (Exception e) { - healingFailureMessages.add(e.getMessage() + " ,healer name :" + healerClassName); - } - return null; + return failureMessages; } private boolean isPrivateHealingNeededByFlag(String itemId, String version, String user) { @@ -214,17 +218,39 @@ public class HealingManagerImpl implements HealingManager { healingDao.setItemHealingFlag(false, user, itemId, versionId); } - private Map<String, Map<String, String>> getItemHealers(ItemType itemType) { + private void handleFailures(List<String> failureMessages) { + if (!failureMessages.isEmpty()) { + throw new CoreException(new ErrorCode.ErrorCodeBuilder() + .withCategory(ErrorCategory.APPLICATION) + .withMessage(CommonMethods.listToSeparatedString(failureMessages, '\n')).build()); + } + } + + private List<Healer> getHealersToRun(Collection<String> healersClassNames, String itemId, + Version version, List<String> failureMessages) { + return healersClassNames.stream() + .map(healerClassName -> getHealerInstance(healerClassName, failureMessages)) + .filter(Optional::isPresent) + .map(Optional::get) + .filter(healer -> healer.isHealingNeeded(itemId, version)) + .collect(Collectors.toList()); + } + + private Optional<Healer> getHealerInstance(String healerClassName, List<String> failureMessages) { + try { + return Optional.of((Healer) Class.forName(healerClassName).getConstructor().newInstance()); + } catch (Exception e) { + failureMessages + .add(String.format(Messages.CANT_LOAD_HEALING_CLASS.getErrorMessage(), healerClassName)); + return Optional.empty(); + } + } + + private Map<String, Collection<String>> getItemHealers(ItemType itemType) { Map healingConfig = FileUtils .readViaInputStream(HEALERS_BY_ENTITY_TYPE_FILE, stream -> JsonUtil.json2Object(stream, Map.class)); - return (Map<String, Map<String, String>>) healingConfig.get(itemType.name()); - } - - private Healer getHealerImplInstance(String implClassName) - throws InstantiationException, IllegalAccessException, InvocationTargetException, - NoSuchMethodException, ClassNotFoundException { - return (Healer) Class.forName(implClassName).getConstructor().newInstance(); + return (Map<String, Collection<String>>) healingConfig.get(itemType.name()); } private String getUser() { diff --git a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/resources/entityHealingConfiguration.json b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/resources/entityHealingConfiguration.json index 64f43a6625..2fc23372de 100644 --- a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/resources/entityHealingConfiguration.json +++ b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/resources/entityHealingConfiguration.json @@ -1,15 +1,15 @@ { "vsp": { - "structure": { - "ownerHealer": "org.openecomp.sdc.healing.healers.OwnerHealer" - }, - "data": { - "toscaServiceModelHealer": "org.openecomp.sdc.healing.healers.ToscaServiceModelHealer" - } + "structure": [ + "org.openecomp.sdc.healing.healers.OwnerHealer" + ], + "data": [ + "org.openecomp.sdc.healing.healers.ToscaServiceModelHealer" + ] }, "vlm": { - "structure": { - "ownerHealer": "org.openecomp.sdc.healing.healers.OwnerHealer" - } + "structure": [ + "org.openecomp.sdc.healing.healers.OwnerHealer" + ] } }
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/OwnerHealer.java b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/OwnerHealer.java index 711848c4e1..7a9b6c219f 100644 --- a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/OwnerHealer.java +++ b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/OwnerHealer.java @@ -19,7 +19,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Optional; -import java.util.stream.Stream; /** * Created by ayalaben on 8/28/2017 @@ -33,12 +32,16 @@ public class OwnerHealer implements Healer { private static final SubscribersDao subscribersDao = SubscribersDaoFactory.getInstance() .createInterface(); - public Object heal(String itemId, Version version) { - Stream<ItemPermissionsEntity> itemPermissions = permissionsDao.listItemPermissions(itemId) - .stream(); + @Override + public boolean isHealingNeeded(String itemId, Version version) { + return permissionsDao.listItemPermissions(itemId).stream().noneMatch(this::isOwnerPermission) || + isOwnerMissingOnItem(itemId); + } + public void heal(String itemId, Version version) { + Collection<ItemPermissionsEntity> itemPermissions = permissionsDao.listItemPermissions(itemId); - if (itemPermissions.noneMatch(this::isOwnerPermission)) { + if (itemPermissions.stream().noneMatch(this::isOwnerPermission)) { String currentUserId = SessionContextProviderFactory.getInstance().createInterface().get().getUser().getUserId() .replace(HEALING_USER_SUFFIX, ""); @@ -46,24 +49,22 @@ public class OwnerHealer implements Healer { permissionsDao.updateItemPermissions(itemId, PermissionTypes.Owner.name(), Collections.singleton(currentUserId), new HashSet<>()); - updateItemOwner(itemId,currentUserId); + updateItemOwner(itemId, currentUserId); - subscribersDao.subscribe(currentUserId,itemId); + subscribersDao.subscribe(currentUserId, itemId); - return currentUserId; - } else if (!itemHasOwnerProperty(itemId)){ - Optional<ItemPermissionsEntity> ownerOpt = itemPermissions.filter - (this::isOwnerPermission).findFirst(); - if(ownerOpt.isPresent()) { + } else if (isOwnerMissingOnItem(itemId)) { + Optional<ItemPermissionsEntity> ownerOpt = + itemPermissions.stream().filter(this::isOwnerPermission).findFirst(); + if (ownerOpt.isPresent()) { updateItemOwner(itemId, ownerOpt.get().getUserId()); } else { throw new SdcRuntimeException("Unexpected error in Owner Healer. Item id: " + itemId); } - } - return itemPermissions.filter(this::isOwnerPermission).findFirst().get().getUserId(); + } } - private void updateItemOwner(String itemId,String userId) { + private void updateItemOwner(String itemId, String userId) { Item item = new Item(); item.setId(itemId); Item retrievedItem = itemDao.get(item); @@ -73,11 +74,11 @@ public class OwnerHealer implements Healer { } } - private boolean itemHasOwnerProperty(String itemId){ + private boolean isOwnerMissingOnItem(String itemId) { Item item = new Item(); item.setId(itemId); Item retrievedItem = itemDao.get(item); - return Objects.nonNull(retrievedItem) && Objects.nonNull(retrievedItem.getOwner()); + return Objects.nonNull(retrievedItem) && Objects.isNull(retrievedItem.getOwner()); } private boolean isOwnerPermission(ItemPermissionsEntity permissionsEntity) { diff --git a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/ToscaServiceModelHealer.java b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/ToscaServiceModelHealer.java index e07faad4fa..4fa5328b6e 100644 --- a/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/ToscaServiceModelHealer.java +++ b/openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/ToscaServiceModelHealer.java @@ -43,25 +43,28 @@ public class ToscaServiceModelHealer implements Healer { } @Override - public Object heal(String itemId, Version version) throws Exception { + public boolean isHealingNeeded(String itemId, Version version) { + OrchestrationTemplateEntity orchestrationTemplate = + orchestrationTemplateDao.get(itemId, version); + OnboardingTypesEnum onboardingTypes = + OnboardingTypesEnum.getOnboardingTypesEnum(orchestrationTemplate.getFileSuffix()); + + return Objects.nonNull(onboardingTypes) && + Objects.nonNull(orchestrationTemplate.getContentData()); + } + + @Override + public void heal(String itemId, Version version) throws Exception { OrchestrationTemplateEntity orchestrationTemplateEntity = orchestrationTemplateDao.get(itemId, version); OnboardingTypesEnum type = OnboardingTypesEnum.getOnboardingTypesEnum(orchestrationTemplateEntity.getFileSuffix()); - if (Objects.isNull(type) - || Objects.isNull(orchestrationTemplateEntity.getContentData())) { - return null; - } - Optional<ToscaServiceModel> healedServiceModel = healServiceModel(orchestrationTemplateEntity, type); healedServiceModel.ifPresent(serviceModel -> serviceModelDao .overrideServiceModel(itemId, version, serviceModel)); - - return healedServiceModel; - } private Optional<ToscaServiceModel> healServiceModel( @@ -79,7 +82,6 @@ public class ToscaServiceModelHealer implements Healer { default: return Optional.empty(); } - } private FileContentHandler getFileContentHandlerForHealing( |