You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2022/07/14 10:16:33 UTC

[brooklyn-server] 02/05: share catalog init / persist/rebind logic for installing bundles via API import

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 <al...@cloudsoft.io>
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();