This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 2738ecb64e8efadd0bd33426befbc0ae2a1e16ec Author: Alex Heneveld <a...@cloudsoft.io> AuthorDate: Thu Mar 28 14:11:04 2024 +0000 exclude mvn: and classpath: url bundles from persistence, and related tweaks - change {white,black}list to include/exclude list, for bundles - add ability to exclude bundles based on url prefix, now defaulting to mvn: and classpath: - fix bug where setPersistenceNeeded never cleared it, so it persisted more often than it should - also prevent persistence when rebinding, as there is no point --- .../CatalogOsgiVersionMoreEntityRebindTest.java | 13 ++-- .../catalog/internal/CatalogInitialization.java | 1 + .../mgmt/ha/BrooklynBomOsgiArchiveInstaller.java | 57 ++++----------- .../core/mgmt/ha/OsgiBundleInstallationResult.java | 5 ++ .../apache/brooklyn/core/mgmt/ha/OsgiManager.java | 82 ++++++++++++++++++---- .../BrooklynMementoPersisterToObjectStore.java | 20 ++++-- .../brooklyn/core/server/BrooklynServerConfig.java | 40 +++++++---- .../brooklyn/core/typereg/BasicManagedBundle.java | 4 +- .../ha/BrooklynBomOsgiArchiveInstallerTest.java | 30 ++++---- 9 files changed, 149 insertions(+), 103 deletions(-) diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java index 29b33f322b..a710d5243d 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java @@ -18,11 +18,12 @@ */ package org.apache.brooklyn.camp.brooklyn.catalog; -import org.apache.brooklyn.util.exceptions.CompoundRuntimeException; -import static org.testng.Assert.assertEquals; - import java.util.Map; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import org.apache.brooklyn.api.effector.Effector; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntitySpec; @@ -50,6 +51,7 @@ import org.apache.brooklyn.test.support.TestResourceUnavailableException; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.ResourceUtils; +import org.apache.brooklyn.util.exceptions.CompoundRuntimeException; import org.apache.brooklyn.util.exceptions.ReferenceWithError; import org.apache.brooklyn.util.javalang.Reflections; import org.apache.brooklyn.util.osgi.OsgiTestResources; @@ -61,10 +63,7 @@ import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.Test; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; +import static org.testng.Assert.assertEquals; /** Many of the same tests as per {@link OsgiVersionMoreEntityTest} but using YAML for catalog and entities, so catalog item ID is set automatically */ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTest implements OsgiTestResources { diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java index 7b24cec778..5050977767 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java @@ -555,6 +555,7 @@ public class CatalogInitialization implements ManagementContextInjectable { Set<OsgiBundleInstallationResult> bundlesToRemove = MutableSet.of(); installs.values().stream().forEach(candidate -> { if (filteredPersistedState.getBundles().containsKey(candidate.getVersionedName())) { + candidate.setRebinding(true); bundlesInOrder.add(candidate); } else { log.debug("Skipping start of persisted bundle "+candidate+" due to catalog upgrade metadata instructions"); diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java index 237249de57..cf47f230eb 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java @@ -27,26 +27,25 @@ import com.google.common.collect.Iterables; import java.io.*; import java.net.URL; import java.util.*; +import java.util.function.BiConsumer; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.jar.Attributes; import java.util.jar.Manifest; -import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.annotation.Nullable; import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.api.mgmt.rebind.ChangeListener; +import org.apache.brooklyn.api.objs.BrooklynObject; import org.apache.brooklyn.api.typereg.ManagedBundle; -import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl; import org.apache.brooklyn.api.typereg.RegisteredType; -import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.BrooklynVersion; import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog; import org.apache.brooklyn.core.catalog.internal.CatalogInitialization; import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult.ResultCode; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; -import org.apache.brooklyn.core.server.BrooklynServerConfig; import org.apache.brooklyn.core.typereg.*; import org.apache.brooklyn.core.typereg.BundleUpgradeParser.CatalogUpgrades; import org.apache.brooklyn.util.collections.MutableList; @@ -76,9 +75,6 @@ public class BrooklynBomOsgiArchiveInstaller { private static final Logger log = LoggerFactory.getLogger(BrooklynBomOsgiArchiveInstaller.class); - public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX = BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX; - public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX = BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX; - final private OsgiManager osgiManager; private ManagedBundle suppliedKnownBundleMetadata; private InputStream zipIn; @@ -117,8 +113,6 @@ public class BrooklynBomOsgiArchiveInstaller { private ManagedBundle inferredMetadata; private final boolean inputStreamSupplied; - private volatile Predicate<ManagedBundle> blacklistBundlePersistencePredicate; - public BrooklynBomOsgiArchiveInstaller(OsgiManager osgiManager, ManagedBundle knownBundleMetadata, InputStream zipIn) { this.osgiManager = osgiManager; this.suppliedKnownBundleMetadata = knownBundleMetadata; @@ -709,11 +703,12 @@ public class BrooklynBomOsgiArchiveInstaller { log.error("Error rolling back following failed install of updated "+result.getVersionedName()+"; " + "installation will likely be corrupted and correct version should be manually installed.", e); } - - if (!isBlacklistedForPersistence(result.getMetadata())) { - ((BasicManagedBundle)result.getMetadata()).setPersistenceNeeded(true); - mgmt().getRebindManager().getChangeListener().onChanged(result.getMetadata()); + + if (!isExcludedFromPersistence(oldManagedBundle)) { + ((BasicManagedBundle)oldManagedBundle).setPersistenceNeeded(true); + mgmt().getRebindManager().getChangeListener().onChanged(oldManagedBundle); } + } else { if (isBringingExistingOsgiInstalledBundleUnderBrooklynManagement) { log.debug("Uninstalling bundle "+result.getVersionedName()+" from Brooklyn management only (rollback needed but it was already installed to OSGi)"); @@ -721,7 +716,7 @@ public class BrooklynBomOsgiArchiveInstaller { log.debug("Uninstalling bundle "+result.getVersionedName()+" (roll back of failed fresh install, no previous version to revert to)"); } osgiManager.uninstallUploadedBundle(result.getMetadata(), false, isBringingExistingOsgiInstalledBundleUnderBrooklynManagement); - if (!isBlacklistedForPersistence(result.getMetadata())) { + if (!isExcludedFromPersistence(result.getMetadata())) { ((BasicManagedBundle)result.getMetadata()).setPersistenceNeeded(true); mgmt().getRebindManager().getChangeListener().onUnmanaged(result.getMetadata()); } @@ -731,7 +726,7 @@ public class BrooklynBomOsgiArchiveInstaller { if (start) { try { log.debug("Starting bundle "+result.getVersionedName()); - if (!isBlacklistedForPersistence(result.getMetadata())) { + if (!isExcludedFromPersistence(result.getMetadata()) && !Boolean.TRUE.equals(result.rebinding)) { ((BasicManagedBundle)result.getMetadata()).setPersistenceNeeded(true); if (updating) { mgmt().getRebindManager().getChangeListener().onChanged(result.getMetadata()); @@ -914,36 +909,8 @@ public class BrooklynBomOsgiArchiveInstaller { } @VisibleForTesting - boolean isBlacklistedForPersistence(ManagedBundle managedBundle) { - // We treat as "managed bundles" (to extract their catalog.bom) the contents of: - // - org.apache.brooklyn.core - // - org.apache.brooklyn.policy - // - org.apache.brooklyn.test-framework - // - org.apache.brooklyn.software-* - // - org.apache.brooklyn.library-catalog - // - org.apache.brooklyn.karaf-init (not sure why this one could end up in persisted state!) - // We don't want to persist the entire brooklyn distro! Therefore default is to blacklist those. - - if (blacklistBundlePersistencePredicate == null) { - String whitelistRegex = mgmt().getConfig().getConfig(PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX); - String blacklistRegex = mgmt().getConfig().getConfig(PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX); - - final Pattern whitelistPattern = (whitelistRegex != null) ? Pattern.compile(whitelistRegex) : null; - final Pattern blacklistPattern = (blacklistRegex != null) ? Pattern.compile(blacklistRegex) : null; - - blacklistBundlePersistencePredicate = input -> { - String bundleName = input.getSymbolicName(); - if (whitelistPattern != null && whitelistPattern.matcher(bundleName).matches()) { - return false; - } - if (blacklistPattern != null && blacklistPattern.matcher(bundleName).matches()) { - return true; - } - return false; - }; - } - - return blacklistBundlePersistencePredicate.test(managedBundle); + boolean isExcludedFromPersistence(ManagedBundle managedBundle) { + return osgiManager.isExcludedFromPersistence(managedBundle); } private static List<Bundle> findBundlesBySymbolicNameAndVersion(OsgiManager osgiManager, ManagedBundle desired) { diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java index dbb48c46f3..f6c16b3c02 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java @@ -37,6 +37,7 @@ public class OsgiBundleInstallationResult { Bundle bundle; ResultCode code; Runnable deferredStart; + Boolean rebinding; public enum ResultCode { INSTALLED_NEW_BUNDLE(false), @@ -117,4 +118,8 @@ public class OsgiBundleInstallationResult { typesInstalled.add(ci); catalogItemsInstalled.add(ci.getId()); } + + public void setRebinding(Boolean rebinding) { + this.rebinding = rebinding; + } } \ No newline at end of file diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java index 32588c6ee7..4455028291 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java @@ -18,24 +18,34 @@ */ package org.apache.brooklyn.core.mgmt.ha; -import com.google.common.annotations.Beta; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.Callable; -import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; import java.util.function.Supplier; +import java.util.regex.Pattern; import javax.annotation.Nullable; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle; import org.apache.brooklyn.api.framework.FrameworkLookup; import org.apache.brooklyn.api.mgmt.ManagementContext; @@ -46,12 +56,14 @@ import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.BrooklynVersion; import org.apache.brooklyn.core.catalog.internal.CatalogBundleLoader; import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.typereg.*; -import org.apache.brooklyn.core.typereg.BrooklynCatalogBundleResolver.BundleInstallationOptions; import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult.ResultCode; import org.apache.brooklyn.core.server.BrooklynServerConfig; import org.apache.brooklyn.core.server.BrooklynServerPaths; +import org.apache.brooklyn.core.typereg.BrooklynBomBundleCatalogBundleResolver; +import org.apache.brooklyn.core.typereg.BrooklynCatalogBundleResolver.BundleInstallationOptions; +import org.apache.brooklyn.core.typereg.BrooklynCatalogBundleResolvers; import org.apache.brooklyn.core.typereg.BundleUpgradeParser.CatalogUpgrades; +import org.apache.brooklyn.core.typereg.RegisteredTypePredicates; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.collections.MutableSet; @@ -75,7 +87,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; -import org.osgi.framework.FrameworkEvent; import org.osgi.framework.launch.Framework; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,6 +107,10 @@ public class OsgiManager { public static final ConfigKey<Boolean> OSGI_STARTUP_COMPLETE = ConfigKeys.newBooleanConfigKey("brooklyn.osgi.startup.complete"); + public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX = BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX; + public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_URL_EXCLUDE_REGEX = BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_URL_EXCLUDE_REGEX; + public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX = BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX; + /* see `Osgis` class for info on starting framework etc */ final ManagementContext mgmt; @@ -870,4 +885,43 @@ public class OsgiManager { return managedBundlesRecord.fileFor(mb); } + private volatile Predicate<ManagedBundle> bundlePersistenceExclusionFilterCache; + public boolean isExcludedFromPersistence(ManagedBundle managedBundle) { + // We treat as "managed bundles" (to extract their catalog.bom) the contents of: + // - org.apache.brooklyn.core + // - org.apache.brooklyn.policy + // - org.apache.brooklyn.test-framework + // - org.apache.brooklyn.software-* + // - org.apache.brooklyn.library-catalog + // - org.apache.brooklyn.karaf-init (not sure why this one could end up in persisted state!) + + // But we don't want to persist the entire brooklyn distro! Therefore default is to exclude those from persistence. + // Similarly for anything installed via mvn or classpath. + + if (bundlePersistenceExclusionFilterCache == null) { + String regexSymnameInclude = mgmt.getConfig().getConfig(PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX); + String regexSymnameIncludeLegacy = mgmt.getConfig().getConfig(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX); + String regexSymnameExclude = mgmt.getConfig().getConfig(PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX); + String regexSymnameExcludeLegacy = mgmt.getConfig().getConfig(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX); + String regexUrlExclude = mgmt.getConfig().getConfig(PERSIST_MANAGED_BUNDLE_URL_EXCLUDE_REGEX); + + final Pattern patternSymnameInclude = (regexSymnameInclude != null) ? Pattern.compile(regexSymnameInclude) : null; + final Pattern patternSymnameIncludeLegacy = (regexSymnameIncludeLegacy != null) ? Pattern.compile(regexSymnameIncludeLegacy) : null; + final Pattern patternUrlExclude = (regexUrlExclude != null) ? Pattern.compile(regexUrlExclude) : null; + final Pattern patternSymnameExclude = (regexSymnameExclude != null) ? Pattern.compile(regexSymnameExclude) : null; + final Pattern patternSymnameExcludeLegacy = (regexSymnameExcludeLegacy != null) ? Pattern.compile(regexSymnameExcludeLegacy) : null; + + bundlePersistenceExclusionFilterCache = input -> { + String bundleName = input.getSymbolicName(); + if (patternSymnameInclude != null && patternSymnameInclude.matcher(bundleName).matches()) return false; + if (patternSymnameIncludeLegacy != null && patternSymnameIncludeLegacy.matcher(bundleName).matches()) return false; + if (patternUrlExclude != null && input.getUrl()!=null && patternUrlExclude.matcher(input.getUrl()).matches()) return true; + if (patternSymnameExclude != null && patternSymnameExclude.matcher(bundleName).matches()) return true; + if (patternSymnameExcludeLegacy != null && patternSymnameExcludeLegacy.matcher(bundleName).matches()) return true; + return false; + }; + } + + return bundlePersistenceExclusionFilterCache.test(managedBundle); + } } diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java index 82fd7c5cda..ed769ad390 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java @@ -684,7 +684,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer futures.add(asyncUpdatePlaneId(newMemento.getPlaneId(), exceptionHandler)); for (BrooklynObjectType type: BrooklynPersistenceUtils.STANDARD_BROOKLYN_OBJECT_TYPE_PERSISTENCE_ORDER) { for (Map.Entry<String, String> entry : newMemento.getObjectsOfType(type).entrySet()) { - addPersistContentIfManagedBundle(type, entry.getKey(), entry.getValue(), futures, exceptionHandler, contextDetails); + addPersistContentIfManagedBundle(type, false, entry.getKey(), entry.getValue(), futures, exceptionHandler, contextDetails); futures.add(asyncPersist(type.getSubPathName(), type, entry.getKey(), entry.getValue(), exceptionHandler)); } } @@ -770,7 +770,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer for (BrooklynObjectType type: BrooklynPersistenceUtils.STANDARD_BROOKLYN_OBJECT_TYPE_PERSISTENCE_ORDER) { for (Memento item : delta.getObjectsOfType(type)) { if (!deletedIds.contains(item.getId())) { - addPersistContentIfManagedBundle(type, item.getId(), ""+item.getCatalogItemId()+"/"+item.getDisplayName(), futures, exceptionHandler, null); + addPersistContentIfManagedBundle(type, true, item.getId(), ""+item.getCatalogItemId()+"/"+item.getDisplayName(), futures, exceptionHandler, null); futures.add(asyncPersist(type.getSubPathName(), item, exceptionHandler)); } } @@ -800,7 +800,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer return lastErrors; } - private void addPersistContentIfManagedBundle(final BrooklynObjectType type, final String id, final String summaryOrContents, List<ListenableFuture<?>> futures, final PersistenceExceptionHandler exceptionHandler, final @Nullable RebindManager deltaContext) { + private void addPersistContentIfManagedBundle(final BrooklynObjectType type, final boolean isDelta, final String id, final String summaryOrContents, List<ListenableFuture<?>> futures, final PersistenceExceptionHandler exceptionHandler, final @Nullable RebindManager deltaContext) { if (type==BrooklynObjectType.MANAGED_BUNDLE) { if (mgmt==null) { throw new IllegalStateException("Cannot persist bundles without a management context"); @@ -818,16 +818,18 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer } if (mb instanceof BasicManagedBundle) { - if (((BasicManagedBundle)mb).getPersistenceNeeded()) { + if (!isDelta || ((BasicManagedBundle)mb).getPersistenceNeeded()) { futures.add( executor.submit(new Runnable() { @Override public void run() { - if (!((BasicManagedBundle)mb).getPersistenceNeeded()) { + if (isDelta && !((BasicManagedBundle)mb).getPersistenceNeeded()) { // someone else persisted this (race) return; } - persist(type.getSubPathName(), type, id+".jar", com.google.common.io.Files.asByteSource( - ((ManagementContextInternal)mgmt).getOsgiManager().get().getBundleFile(mb)), exceptionHandler); + if (!isBundleOmittedFromPersistence(mb)) { + persist(type.getSubPathName(), type, id + ".jar", com.google.common.io.Files.asByteSource( + ((ManagementContextInternal) mgmt).getOsgiManager().get().getBundleFile(mb)), exceptionHandler); + } ((BasicManagedBundle)mb).setPersistenceNeeded(false); } }) ); } @@ -835,6 +837,10 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer } } + private boolean isBundleOmittedFromPersistence(ManagedBundle mb) { + return ((ManagementContextInternal)mgmt).getOsgiManager().get().isExcludedFromPersistence(mb); + } + @Override public void waitForWritesCompleted(Duration timeout) throws InterruptedException, TimeoutException { boolean locked = lock.readLock().tryLock(timeout.toMillisecondsRoundingUp(), TimeUnit.MILLISECONDS); diff --git a/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java b/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java index b1d7331455..7ecfdc386c 100644 --- a/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java +++ b/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java @@ -18,13 +18,12 @@ */ package org.apache.brooklyn.core.server; -import static org.apache.brooklyn.core.config.ConfigKeys.newBooleanConfigKey; -import static org.apache.brooklyn.core.config.ConfigKeys.newStringConfigKey; - import java.net.URI; import java.util.List; import java.util.Map; +import com.google.common.collect.ImmutableList; +import com.google.common.reflect.TypeToken; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.StringConfigMap; @@ -36,8 +35,8 @@ import org.apache.brooklyn.util.time.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.collect.ImmutableList; -import com.google.common.reflect.TypeToken; +import static org.apache.brooklyn.core.config.ConfigKeys.newBooleanConfigKey; +import static org.apache.brooklyn.core.config.ConfigKeys.newStringConfigKey; /** Config keys for the brooklyn server */ public class BrooklynServerConfig { @@ -97,7 +96,7 @@ public class BrooklynServerConfig { "Whether a backup of in-memory state should be made to the backup persistence location on node demotion, " + "in case other nodes might write conflicting state", true); - /** @deprecated since 0.7.0, use {@link #PERSISTENCE_BACKUPS_ON_PROMOTION} and {@link #PERSISTENCE_BACKUPS_ON_DEMOTION}, + /** @deprecated since 0.7.0, use {@link #PERSISTENCE_BACKUPS_REQUIRED_ON_PROMOTION} and {@link #PERSISTENCE_BACKUPS_REQUIRED_ON_DEMOTION}, * which allow using a different target location and are supported on more environments (and now default to true) */ @Deprecated public static final ConfigKey<Boolean> PERSISTENCE_BACKUPS_REQUIRED = @@ -138,18 +137,31 @@ public class BrooklynServerConfig { public static final ConfigKey<Boolean> OSGI_CACHE_CLEAN = ConfigKeys.newBooleanConfigKey("brooklyn.osgi.cache.clean", "Whether to delete the OSGi directory before and after use; if unset, it will delete if the node ID forms part of the cache dir path (which by default it does) to avoid file leaks"); + public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX = ConfigKeys.newStringConfigKey( + "brooklyn.persistence.bundle.include.symbolicName.regex", + "Regex for bundle symbolic names explicitly allowed to be persisted, taking precedence over exclude list; " + + "bundles are included by default unless excluded, so things only need to be listed here if they want to override an exclusion", + null); + + public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_URL_EXCLUDE_REGEX = ConfigKeys.newStringConfigKey( + "brooklyn.persistence.bundle.exclude.url.regex", + "Regex for bundle URLs explicitly excluded from persistence, unless symbolic name is in explicit include list", + "(mvn|classpath):.*"); + + public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX = ConfigKeys.newStringConfigKey( + "brooklyn.persistence.bundle.exclude.symbolicName.regex", + "Regex for bundle symbolic names explicitly excluded from persistence (but include list takes precedence); " + + "if not explicitly excluded by this or the URL exclusion, managed bundles will by default be peristed", + "org\\.apache\\.brooklyn\\..*"); + + @Deprecated /** @deprecated in favour of {@link #PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX} */ public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX = ConfigKeys.newStringConfigKey( "brooklyn.persistence.bundle.whitelist", - "Regex for bundle symbolic names explicitly allowed to be persisted (taking precedence over blacklist); " - + "managed bundles will by default be peristed if not blacklisted; " - + "they do not need to be explicitly whitelisted.", - null); - + "Legacy name for "+PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX.getName()); + @Deprecated /** @deprecated in favour of {@link #PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX} */ public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX = ConfigKeys.newStringConfigKey( "brooklyn.persistence.bundle.blacklist", - "Regex for bundle symbolic names explicitly excluded from persistence (but whitelist takes precedence); " - + "if not explicitly blacklisted, managed bundles will by default be peristed", - "org\\.apache\\.brooklyn\\..*"); + "Legacy name for "+PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX.getName()); /** @see BrooklynServerPaths#getMgmtBaseDir(ManagementContext) */ public static String getMgmtBaseDir(ManagementContext mgmt) { diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java index 42f7dbd96d..e053daaaba 100644 --- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java +++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java @@ -47,6 +47,8 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage private String format; private String url; private Credentials credentials; + + /** pretty much redundant as it is put in the delta if changed, and included even if not needed when full checkpoint requested */ private transient boolean persistenceNeeded = false; /** Creates an empty one, with an ID, expecting other fields will be populated. */ @@ -282,7 +284,7 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage } public void setPersistenceNeeded(boolean val) { - persistenceNeeded |= val; + persistenceNeeded = val; } public boolean getPersistenceNeeded() { return persistenceNeeded; diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstallerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstallerTest.java index 8bd142e139..b37457eeb8 100644 --- a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstallerTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstallerTest.java @@ -38,33 +38,33 @@ public class BrooklynBomOsgiArchiveInstallerTest extends BrooklynMgmtUnitTestSup // BrooklynMgmtUnitTestSupport, which does not expose `useOsgi` or `osgiReuse` @Test - public void testBlacklistPersistingOrgApacheBrooklyn() throws Exception { - OsgiManager osgiManager = newMockOsgiManager(mgmt); + public void testBundlePersistenceExclusionOrgApacheBrooklyn() throws Exception { + OsgiManager osgiManager = new OsgiManager(mgmt); BrooklynBomOsgiArchiveInstaller installer = new BrooklynBomOsgiArchiveInstaller(osgiManager, Mockito.mock(ManagedBundle.class), new ByteArrayInputStream(new byte[0])); - assertTrue(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.core", "1.0.0"))); - assertTrue(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.mybundle", "1.0.0"))); - assertFalse(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.different", "1.0.0"))); + assertTrue(installer.isExcludedFromPersistence(newMockManagedBundle("org.apache.brooklyn.core", "1.0.0"))); + assertTrue(installer.isExcludedFromPersistence(newMockManagedBundle("org.apache.brooklyn.mybundle", "1.0.0"))); + assertFalse(installer.isExcludedFromPersistence(newMockManagedBundle("org.apache.different", "1.0.0"))); } @Test - public void testWhitelistPersistingBundle() throws Exception { - mgmt.getBrooklynProperties().put(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX, "org\\.apache\\.brooklyn\\.mywhitelistedbundle"); - OsgiManager osgiManager = newMockOsgiManager(mgmt); + public void testBundlePersistenceExclusionExplicitInclusion() throws Exception { + mgmt.getBrooklynProperties().put(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX, "org\\.apache\\.brooklyn\\.myincludebundle"); + OsgiManager osgiManager = new OsgiManager(mgmt); BrooklynBomOsgiArchiveInstaller installer = new BrooklynBomOsgiArchiveInstaller(osgiManager, Mockito.mock(ManagedBundle.class), new ByteArrayInputStream(new byte[0])); - assertTrue(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.core", "1.0.0"))); - assertFalse(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.mywhitelistedbundle", "1.0.0"))); + assertTrue(installer.isExcludedFromPersistence(newMockManagedBundle("org.apache.brooklyn.core", "1.0.0"))); + assertFalse(installer.isExcludedFromPersistence(newMockManagedBundle("org.apache.brooklyn.myincludebundle", "1.0.0"))); } @Test - public void testCustomBlacklistPersistingBundle() throws Exception { - mgmt.getBrooklynProperties().put(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX, "org\\.example\\.myblacklistprefix.*"); - OsgiManager osgiManager = newMockOsgiManager(mgmt); + public void testBundlePersistenceExclusionCustom() throws Exception { + mgmt.getBrooklynProperties().put(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX, "org\\.example\\.myexcludeprefix.*"); + OsgiManager osgiManager = new OsgiManager(mgmt); BrooklynBomOsgiArchiveInstaller installer = new BrooklynBomOsgiArchiveInstaller(osgiManager, Mockito.mock(ManagedBundle.class), new ByteArrayInputStream(new byte[0])); - assertTrue(installer.isBlacklistedForPersistence(newMockManagedBundle("org.example.myblacklistprefix.mysuffix", "1.0.0"))); - assertFalse(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.core", "1.0.0"))); + assertTrue(installer.isExcludedFromPersistence(newMockManagedBundle("org.example.myexcludeprefix.mysuffix", "1.0.0"))); + assertFalse(installer.isExcludedFromPersistence(newMockManagedBundle("org.apache.brooklyn.core", "1.0.0"))); } @Test