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 d198f6381517842ca766be7dcc83ea943e5ab1ee Author: Alex Heneveld <[email protected]> AuthorDate: Wed Jul 13 12:20:42 2022 +0100 share catalog init / persist/rebind logic for installing bundles via API import fixes test failing in previous commit --- .../catalog/internal/CatalogInitialization.java | 74 ++++++++++++---------- .../brooklyn/core/mgmt/rebind/RebindIteration.java | 73 +++++++++++---------- .../brooklyn/rest/resources/ServerResource.java | 45 +++++++------ 3 files changed, 103 insertions(+), 89 deletions(-) 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 ed116dc4ec..14f95d2bab 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 @@ -254,39 +254,12 @@ public class CatalogInitialization implements ManagementContextInjectable { throw new IllegalStateException("Catalog initialization already run for initial catalog by mechanism other than populating persisted state; mode="+mode); } - // Always install the bundles from persisted state; installed (but not started) prior to catalog, - // so that OSGi unique IDs might be picked up when initial catalog is populated - Map<InstallableManagedBundle, OsgiBundleInstallationResult> persistenceInstalls = installPersistedBundlesDontStart(persistedState.getBundles(), exceptionHandler, rebindLogger); - - // now we install and start the bundles from the catalog; - // 2021-12-03 now this only will look for classes in active bundles, so it won't resolve persisted bundles - // and we can safely filter them out later - populateInitialCatalogImpl(true); - - final Maybe<OsgiManager> maybesOsgiManager = managementContext.getOsgiManager(); - if (maybesOsgiManager.isAbsent()) { - // Can't find any bundles to tell if there are upgrades. Could be running tests; do no filtering. - CatalogUpgrades.storeInManagementContext(CatalogUpgrades.EMPTY, managementContext); - } else { - final OsgiManager osgiManager = maybesOsgiManager.get(); - final BundleContext bundleContext = osgiManager.getFramework().getBundleContext(); - final CatalogUpgrades catalogUpgrades = - catalogUpgradeScanner.scan(osgiManager, bundleContext, rebindLogger); - CatalogUpgrades.storeInManagementContext(catalogUpgrades, managementContext); - } - - PersistedCatalogState filteredPersistedState = filterBundlesAndCatalogInPersistedState(persistedState, rebindLogger); - - // 2021-09-14 previously we effectively installed here, after populating; but now we do it earlier and then uninstall if needed, to preserve IDs -// Map<InstallableManagedBundle, OsgiBundleInstallationResult> persistenceInstalls = installPersistedBundlesDontStart(filteredPersistedState.getBundles(), exceptionHandler, rebindLogger); - - try { - startPersistedBundles(filteredPersistedState, persistenceInstalls, exceptionHandler, rebindLogger); - BrooklynCatalog catalog = managementContext.getCatalog(); - catalog.addCatalogLegacyItemsOnRebind(filteredPersistedState.getLegacyCatalogItems()); - } finally { - hasRunPersistenceInitialization = true; - } + installPersistedBundles(persistedState, () -> { + // now we install and start the bundles from the catalog; + // 2021-12-03 now this only will look for classes in active bundles, so it won't resolve persisted bundles + // and we can safely filter them out later + populateInitialCatalogImpl(true); + }, exceptionHandler, rebindLogger); if (mode == ManagementNodeState.MASTER) { // TODO ideally this would remain false until it has *persisted* the changed catalog; @@ -303,6 +276,41 @@ public class CatalogInitialization implements ManagementContextInjectable { } } + /** shared routine between above "normal" initialization, and special addition via ServerResource.import */ + @Beta + public void installPersistedBundles(PersistedCatalogState persistedState, Runnable beforeDeferredStartAndSetRunPersistence, RebindExceptionHandler exceptionHandler, RebindLogger rebindLogger) { + // Always install the bundles from persisted state; installed (but not started) prior to catalog, + // so that OSGi unique IDs might be picked up when initial catalog is populated + Map<InstallableManagedBundle, OsgiBundleInstallationResult> persistenceInstalls = installPersistedBundlesDontStart(persistedState.getBundles(), exceptionHandler, rebindLogger); + + if (beforeDeferredStartAndSetRunPersistence!=null) beforeDeferredStartAndSetRunPersistence.run(); + + final Maybe<OsgiManager> maybesOsgiManager = managementContext.getOsgiManager(); + if (maybesOsgiManager.isAbsent()) { + // Can't find any bundles to tell if there are upgrades. Could be running tests; do no filtering. + CatalogUpgrades.storeInManagementContext(CatalogUpgrades.EMPTY, managementContext); + } else { + final OsgiManager osgiManager = maybesOsgiManager.get(); + final BundleContext bundleContext = osgiManager.getFramework().getBundleContext(); + final CatalogUpgrades catalogUpgrades = + catalogUpgradeScanner.scan(osgiManager, bundleContext, rebindLogger); + CatalogUpgrades.storeInManagementContext(catalogUpgrades, managementContext); + } + + PersistedCatalogState filteredPersistedState = filterBundlesAndCatalogInPersistedState(persistedState, rebindLogger); + + // 2021-09-14 previously we effectively installed here, after populating; but now we do it earlier and then uninstall if needed, to preserve IDs +// Map<InstallableManagedBundle, OsgiBundleInstallationResult> persistenceInstalls = installPersistedBundlesDontStart(filteredPersistedState.getBundles(), exceptionHandler, rebindLogger); + + try { + startPersistedBundles(filteredPersistedState, persistenceInstalls, exceptionHandler, rebindLogger); + BrooklynCatalog catalog = managementContext.getCatalog(); + catalog.addCatalogLegacyItemsOnRebind(filteredPersistedState.getLegacyCatalogItems()); + } finally { + if (beforeDeferredStartAndSetRunPersistence!=null) hasRunPersistenceInitialization = true; + } + } + /** * Populates the initial catalog, but not via an official code-path. * diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java index 9e5aa1c4a9..a3f609ab35 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java @@ -32,6 +32,7 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import com.google.common.annotations.Beta; import org.apache.brooklyn.api.catalog.BrooklynCatalog; import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.entity.Application; @@ -333,6 +334,33 @@ public abstract class RebindIteration { isEmpty = mementoManifest.isEmpty(); } + @Beta + public static class InstallableManagedBundleImpl implements CatalogInitialization.InstallableManagedBundle { + private final ManagedBundleMemento memento; + private final ManagedBundle managedBundle; + + public InstallableManagedBundleImpl(ManagedBundleMemento memento, ManagedBundle managedBundle) { + this.memento = memento; + this.managedBundle = managedBundle; + } + + @Override + public ManagedBundle getManagedBundle() { + return managedBundle; + } + + @Override + public Supplier<InputStream> getInputStreamSource() throws IOException { + return InputStreamSource.ofRenewableSupplier("JAR for " + memento, () -> { + try { + return memento.getJarContent().openStream(); + } catch (IOException e) { + throw Exceptions.propagate(e); + } + }); + } + } + protected void installBundlesAndRebuildCatalog() { // Build catalog early so we can load other things. // Reads the persisted catalog contents, and passes it all to CatalogInitialization, which decides what to do with it. @@ -350,32 +378,6 @@ public abstract class RebindIteration { } }; - class InstallableManagedBundleImpl implements CatalogInitialization.InstallableManagedBundle { - private final ManagedBundleMemento memento; - private final ManagedBundle managedBundle; - - InstallableManagedBundleImpl(ManagedBundleMemento memento, ManagedBundle managedBundle) { - this.memento = memento; - this.managedBundle = managedBundle; - } - - @Override - public ManagedBundle getManagedBundle() { - return managedBundle; - } - - @Override - public Supplier<InputStream> getInputStreamSource() throws IOException { - return InputStreamSource.ofRenewableSupplier("JAR for " + memento, () -> { - try { - return memento.getJarContent().openStream(); - } catch (IOException e) { - throw Exceptions.propagate(e); - } - }); - } - } - Map<VersionedName, InstallableManagedBundle> bundles = new LinkedHashMap<>(); Collection<CatalogItem<?, ?>> legacyCatalogItems = new ArrayList<>(); @@ -1411,13 +1413,6 @@ public abstract class RebindIteration { return invokeConstructor(reflections, clazz, new Object[]{}); } - protected ManagedBundle newManagedBundle(ManagedBundleMemento memento) { - ManagedBundle result = new BasicManagedBundle(memento.getSymbolicName(), memento.getVersion(), memento.getUrl(), - memento.getFormat(), null, memento.getChecksum(), memento.getDeleteable()); - FlagUtils.setFieldsFromFlags(ImmutableMap.of("id", memento.getId()), result); - return result; - } - protected <T> T invokeConstructor(Reflections reflections, Class<T> clazz, Object[]... possibleArgs) { for (Object[] args : possibleArgs) { try { @@ -1442,6 +1437,10 @@ public abstract class RebindIteration { throw new IllegalStateException("Cannot instantiate instance of type " + clazz + "; expected constructor signature not found (" + args + ")"); } + + protected ManagedBundle newManagedBundle(ManagedBundleMemento bundleMemento) { + return RebindIteration.newManagedBundle(bundleMemento); + } } protected BrooklynMementoPersister getPersister() { @@ -1489,4 +1488,12 @@ public abstract class RebindIteration { return (readOnlyRebindCount.get() < 5) || (readOnlyRebindCount.get() % 1000 == 0); } + @Beta + public static ManagedBundle newManagedBundle(ManagedBundleMemento memento) { + ManagedBundle result = new BasicManagedBundle(memento.getSymbolicName(), memento.getVersion(), memento.getUrl(), + memento.getFormat(), null, memento.getChecksum(), memento.getDeleteable()); + FlagUtils.setFieldsFromFlags(ImmutableMap.of("id", memento.getId()), result); + return result; + } + } diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java index 812ede244d..d183670265 100644 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java @@ -47,8 +47,10 @@ import org.apache.brooklyn.api.mgmt.rebind.RebindManager; import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoManifest; import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoRawData; import org.apache.brooklyn.api.mgmt.rebind.mementos.ManagedBundleMemento; +import org.apache.brooklyn.api.typereg.ManagedBundle; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.BrooklynVersion; +import org.apache.brooklyn.core.catalog.internal.CatalogInitialization; import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.config.Sanitizer; import org.apache.brooklyn.core.entity.Attributes; @@ -64,6 +66,7 @@ import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; import org.apache.brooklyn.core.mgmt.persist.*; import org.apache.brooklyn.core.mgmt.rebind.PersistenceExceptionHandlerImpl; +import org.apache.brooklyn.core.mgmt.rebind.RebindIteration; import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl; import org.apache.brooklyn.core.server.BrooklynServerPaths; import org.apache.brooklyn.rest.api.ServerApi; @@ -83,6 +86,7 @@ import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.exceptions.ReferenceWithError; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.os.Os; +import org.apache.brooklyn.util.osgi.VersionedName; import org.apache.brooklyn.util.stream.InputStreamSource; import org.apache.brooklyn.util.text.Identifiers; import org.apache.brooklyn.util.text.Strings; @@ -96,6 +100,8 @@ import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; import com.google.common.collect.FluentIterable; +import static org.apache.brooklyn.api.mgmt.ha.ManagementNodeState.INITIALIZING; + public class ServerResource extends AbstractBrooklynRestResource implements ServerApi { private static final int SHUTDOWN_TIMEOUT_CHECK_INTERVAL = 200; @@ -436,7 +442,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv throw WebResourceUtils.forbidden(USER_OPERATION_NOT_AUTHORIZED_MSG, Entitlements.getEntitlementContext().user()); Maybe<ManagementContext> mm = mgmtMaybe(); - if (mm.isAbsent()) return ManagementNodeState.INITIALIZING; + if (mm.isAbsent()) return INITIALIZING; return mm.get().getHighAvailabilityManager().getNodeState(); } @@ -609,30 +615,23 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv ((RebindManagerImpl)rebindManager).newExceptionHandler()); // install bundles to active management context - for (Map.Entry<String, ByteSource> bundleJar : newMementoRawData.getBundleJars().entrySet()){ - ManagedBundleMemento memento = mementoManifest.getBundle(bundleJar.getKey()); - log.debug("Installing "+memento+" as part of persisted state import"); - ReferenceWithError<OsgiBundleInstallationResult> bundleInstallResult = ((ManagementContextInternal)mgmt()).getOsgiManager().get() - .install(InputStreamSource.of("Persistence import - bundle install - "+memento, bundleJar.getValue().read()), "", false, memento.getDeleteable()); - - if (bundleInstallResult.hasError()) { - log.debug("Unable to create "+memento+", format '', throwing: "+bundleInstallResult.getError().getMessage(), bundleInstallResult.getError()); - String errorMsg = ""; - if (bundleInstallResult.getWithoutError()!=null) { - errorMsg = bundleInstallResult.getWithoutError().getMessage(); - } else { - errorMsg = Strings.isNonBlank(bundleInstallResult.getError().getMessage()) ? bundleInstallResult.getError().getMessage() : bundleInstallResult.getError().toString(); - } - throw new Exception(errorMsg); + Map<VersionedName, CatalogInitialization.InstallableManagedBundle> bundles = new LinkedHashMap<>(); + for (Map.Entry<String, ByteSource> bundleJar : newMementoRawData.getBundleJars().entrySet()) { + ManagedBundleMemento bundleMemento = mementoManifest.getBundle(bundleJar.getKey()); + ManagedBundle b = RebindIteration.newManagedBundle(bundleMemento); + bundles.put(b.getVersionedName(), new RebindIteration.InstallableManagedBundleImpl(bundleMemento, b)); + log.debug("Installing "+bundleMemento+" for "+b+" as part of persisted state import"); + } + CatalogInitialization.PersistedCatalogState persistedCatalogState = new CatalogInitialization.PersistedCatalogState(bundles, Collections.emptySet()); + CatalogInitialization.RebindLogger rebindLogger = new CatalogInitialization.RebindLogger() { + @Override public void debug(String message, Object... args) { + log.debug(message, args); } - if (!OsgiBundleInstallationResult.ResultCode.IGNORING_BUNDLE_AREADY_INSTALLED.equals(bundleInstallResult.get().getCode()) && !OsgiBundleInstallationResult.ResultCode.UPDATED_EXISTING_BUNDLE.equals(bundleInstallResult.get().getCode())) { - BundleInstallationRestResult result = TypeTransformer.bundleInstallationResult(bundleInstallResult.get(), mgmt(), brooklyn(), ui); - log.debug("Installed "+memento+" as part of persisted state import: "+result); - } else { - log.debug("Installation of " + memento + " reported: " + bundleInstallResult.get()); + @Override public void info(String message, Object... args) { + log.warn(message, args); } - } - + }; + mgmtInternal().getCatalogInitialization().installPersistedBundles(persistedCatalogState, null, ((RebindManagerImpl)mgmt().getRebindManager()).newExceptionHandler(), rebindLogger); // store persisted items and rebind to load applications BrooklynMementoRawData.Builder result = BrooklynMementoRawData.builder();
