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 2017/09/26 12:17:08 UTC

[3/9] brooklyn-server git commit: handle edge cases where importing OSGi-already-managed bundles to Brooklyn mgmt

handle edge cases where importing OSGi-already-managed bundles to Brooklyn mgmt


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/69ea9844
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/69ea9844
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/69ea9844

Branch: refs/heads/master
Commit: 69ea984467e79dc3554d0079a662648c5e9bd922
Parents: 3816fb7
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Sep 21 13:07:07 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Sep 21 13:17:07 2017 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  |  3 +-
 .../core/catalog/internal/CatalogUtils.java     | 27 ++++---
 .../core/mgmt/ha/OsgiArchiveInstaller.java      | 85 ++++++++++++++++----
 .../brooklyn/core/mgmt/ha/OsgiManager.java      | 36 +++++----
 4 files changed, 109 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/69ea9844/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index f42c0a2..c358cef 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -1782,7 +1782,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         //assume forceUpdate for backwards compatibility
         log.debug("Adding manual catalog item to "+mgmt+": "+item);
         checkNotNull(item, "item");
-        CatalogUtils.installLibraries(mgmt, item.getLibraries());
+        //don't activate bundles; only intended for legacy tests where that might not work
+        CatalogUtils.installLibraries(mgmt, item.getLibraries(), false);
         if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
         manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item));
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/69ea9844/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
index 471ce64..5621588 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -168,6 +168,11 @@ public class CatalogUtils {
      * Registers all bundles with the management context's OSGi framework.
      */
     public static void installLibraries(ManagementContext managementContext, @Nullable Collection<CatalogBundle> libraries) {
+        installLibraries(managementContext, libraries, true);
+    }
+    /** As {@link #installLibraries(ManagementContext, Collection)} but letting caller suppress the deferred start/install
+     * (for use in tests where bundles' BOMs aren't resolvable). */
+    public static void installLibraries(ManagementContext managementContext, @Nullable Collection<CatalogBundle> libraries, boolean startBundlesAndInstallToBrooklyn) {
         if (libraries == null) return;
 
         ManagementContextInternal mgmt = (ManagementContextInternal) managementContext;
@@ -190,16 +195,18 @@ public class CatalogUtils {
                 results.add(result);
             }
             Map<String, Throwable> errors = MutableMap.of();
-            for (OsgiBundleInstallationResult r: results) {
-                if (r.getDeferredStart()!=null) {
-                    try {
-                        r.getDeferredStart().run();
-                    } catch (Throwable t) {
-                        Exceptions.propagateIfFatal(t);
-                        // above will done rollback for the failed item, but we need consistent behaviour for all libraries;
-                        // for simplicity we simply have each bundle either fully installed or fully rolled back
-                        // (alternative would be to roll back everything)
-                        errors.put(r.getVersionedName().toString(), t);
+            if (startBundlesAndInstallToBrooklyn) {
+                for (OsgiBundleInstallationResult r: results) {
+                    if (r.getDeferredStart()!=null) {
+                        try {
+                            r.getDeferredStart().run();
+                        } catch (Throwable t) {
+                            Exceptions.propagateIfFatal(t);
+                            // above will done rollback for the failed item, but we need consistent behaviour for all libraries;
+                            // for simplicity we simply have each bundle either fully installed or fully rolled back
+                            // (alternative would be to roll back everything)
+                            errors.put(r.getVersionedName().toString(), t);
+                        }
                     }
                 }
             }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/69ea9844/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
index f00b96f..5f053e5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
@@ -23,6 +23,7 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
 import java.util.Collections;
 import java.util.Map;
 import java.util.TreeMap;
@@ -81,6 +82,7 @@ class OsgiArchiveInstaller {
     private boolean validateTypes = true;
     
     private File zipFile;
+    private boolean isBringingExistingOsgiInstalledBundleUnderBrooklynManagement = false;
     private Manifest discoveredManifest;
     private VersionedName discoveredBomVersionedName;
     OsgiBundleInstallationResult result;
@@ -178,8 +180,9 @@ class OsgiArchiveInstaller {
                             }
                             try {
                                 // do this in special try block, not below, so we can give a better error
-                                // (the user won't understnad the URL)
+                                // (the user won't understand the URL)
                                 zipIn = ResourceUtils.create(mgmt()).getResourceFromUrl(candidateUrl);
+                                isBringingExistingOsgiInstalledBundleUnderBrooklynManagement = true;
                             } catch (Exception e) {
                                 Exceptions.propagateIfFatal(e);
                                 throw new IllegalArgumentException("Could not find binary for already installed OSGi bundle "+existingOsgiInstalledBundle.get()+" (location "+candidateUrl+") when trying to promote "+suppliedKnownBundleMetadata+" to Brooklyn management", e);
@@ -360,19 +363,61 @@ class OsgiArchiveInstaller {
                 }
             } else {
                 result.metadata = inferredMetadata;
-                // no such managed bundle
+                // no such Brooklyn-managed bundle
                 Maybe<Bundle> b = Osgis.bundleFinder(osgiManager.framework).symbolicName(result.getMetadata().getSymbolicName()).version(result.getMetadata().getSuppliedVersionString()).find();
                 if (b.isPresent()) {
                     // bundle already installed to OSGi subsystem but brooklyn not aware of it;
-                    // this will often happen on a karaf restart so don't be too strict!
-                    // in this case let's uninstall it to make sure we have the right bundle and checksum
-                    // (in case where user has replaced a JAR file in persisted state,
-                    // or where they osgi installed something and are now uploading it or something else) 
-                    // but let's just assume it's the same; worst case if not user will
-                    // have to uninstall it then reinstall it to do the replacement
-                    // (means you can't just replace a JAR in persisted state however)
-                    log.debug("Brooklyn install of "+result.getMetadata().getVersionedName()+" detected already loaded in OSGi; uninstalling that to reinstall as Brooklyn-managed");
-                    b.get().uninstall();
+                    // this will often happen on a karaf restart where bundle was cached by karaf,
+                    // so we need to allow it. can also happen if brooklyn.libraries references an existing bundle.
+                    
+                    // determine if we are simply bringing existing installed under Brooklyn management (because url or binary content identical and not forced)
+                    // or if the bundle should be reinstalled/updated
+                    if (!force) {
+                        if (!isBringingExistingOsgiInstalledBundleUnderBrooklynManagement) {
+                            if (Objects.equal(b.get().getLocation(), suppliedKnownBundleMetadata.getUrl())) {
+                                // installation request was for identical location, so assume we are simply bringing under mgmt
+                                log.debug("Request to install "+inferredMetadata+" from same location "+b.get().getLocation()+
+                                    " as existing OSGi installed (but not Brooklyn-managed) bundle "+b.get()+", so skipping reinstall");
+                                isBringingExistingOsgiInstalledBundleUnderBrooklynManagement = true;
+                            } else {
+                                // different locations, but see if we can compare input stream contents
+                                // (prevents needless uninstall/reinstall of already installed bundles)
+                                try {
+                                    if (Streams.compare(new FileInputStream(zipFile), new URL(b.get().getLocation()).openStream())) {
+                                        log.debug("Request to install "+inferredMetadata+" has same contents"+
+                                            " as existing OSGi installed (but not Brooklyn-managed) bundle "+b.get()+", so skipping reinstall");
+                                        isBringingExistingOsgiInstalledBundleUnderBrooklynManagement = true;
+                                    } else {
+                                        log.debug("Request to install "+inferredMetadata+" has different contents"+
+                                            " as existing OSGi installed (but not Brooklyn-managed) bundle "+b.get()+", so will do reinstall");
+                                    }
+                                } catch (Exception e) {
+                                    Exceptions.propagateIfFatal(e);
+                                    // probably an invalid URL on installed bundle; that's allowed
+                                    log.debug("Request to install "+inferredMetadata+" could not compare contents"+
+                                        " with existing OSGi installed (but not Brooklyn-managed) bundle "+b.get()+", so will do reinstall (error "+e+" loading from "+b.get().getLocation()+")");
+                                }
+                            }
+                        }
+                    } else {
+                        if (isBringingExistingOsgiInstalledBundleUnderBrooklynManagement) {
+                            log.debug("Request to install "+inferredMetadata+" was forced, so forcing reinstallation "
+                                + "of existing OSGi installed (but not Brooklyn-managed) bundle "+b.get());
+                            isBringingExistingOsgiInstalledBundleUnderBrooklynManagement = false;
+                        }
+                    }
+                    
+                    if (isBringingExistingOsgiInstalledBundleUnderBrooklynManagement) {
+                        result.bundle = b.get();
+                        
+                    } else {
+                        // needs reinstallation
+                        // we could update instead of uninstall/reinstall
+                        // note however either way we won't be able to rollback if there is a failure
+                        log.debug("Brooklyn install of "+result.getMetadata().getVersionedName()+" detected already loaded in OSGi; uninstalling that to reinstall as Brooklyn-managed");
+                        b.get().uninstall();
+                        result.bundle = null;
+                    }
                 }
                 // normal install
                 updating = false;
@@ -381,8 +426,13 @@ class OsgiArchiveInstaller {
             startedInstallation = true;
             try (InputStream fin = new FileInputStream(zipFile)) {
                 if (!updating) {
-                    assert result.getBundle()==null;
-                    result.bundle = osgiManager.framework.getBundleContext().installBundle(result.getMetadata().getOsgiUniqueUrl(), fin);
+                    if (isBringingExistingOsgiInstalledBundleUnderBrooklynManagement) {
+                        assert result.getBundle()!=null;
+                        log.debug("Brooklyn install of "+result.getMetadata().getVersionedName()+" detected already loaded "+result.getBundle()+" in OSGi can be re-used, skipping OSGi install");
+                    } else {
+                        assert result.getBundle()==null;
+                        result.bundle = osgiManager.framework.getBundleContext().installBundle(result.getMetadata().getOsgiUniqueUrl(), fin);
+                    }
                 } else {
                     result.bundle.update(fin);
                 }
@@ -440,9 +490,12 @@ class OsgiArchiveInstaller {
                         ((BasicManagedBundle)result.getMetadata()).setPersistenceNeeded(true);
                         mgmt().getRebindManager().getChangeListener().onChanged(result.getMetadata());
                     } else {
-                        log.debug("Uninstalling bundle "+result.getVersionedName()+" (roll back of failed fresh install, no previous version to revert to)");
-                        osgiManager.uninstallUploadedBundle(result.getMetadata());
-                        
+                        if (isBringingExistingOsgiInstalledBundleUnderBrooklynManagement) {
+                            log.debug("Uninstalling bundle "+result.getVersionedName()+" from Brooklyn management only (rollback needed but it was already installed to OSGi)");
+                        } else {
+                            log.debug("Uninstalling bundle "+result.getVersionedName()+" (roll back of failed fresh install, no previous version to revert to)");
+                        }                        
+                        osgiManager.uninstallUploadedBundle(result.getMetadata(), false, isBringingExistingOsgiInstalledBundleUnderBrooklynManagement);
                         ((BasicManagedBundle)result.getMetadata()).setPersistenceNeeded(true);
                         mgmt().getRebindManager().getChangeListener().onUnmanaged(result.getMetadata());
                     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/69ea9844/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
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 603927a..995f7ed 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
@@ -393,6 +393,10 @@ public class OsgiManager {
      * This does not throw but returns a reference containing errors and result for caller to inspect and handle. 
      */
     public ReferenceWithError<OsgiBundleInstallationResult> uninstallUploadedBundle(ManagedBundle bundleMetadata, boolean force) {
+        return uninstallUploadedBundle(bundleMetadata, force, false);
+    }
+    
+    public ReferenceWithError<OsgiBundleInstallationResult> uninstallUploadedBundle(ManagedBundle bundleMetadata, boolean force, boolean leaveInOsgi) {
         OsgiBundleInstallationResult result = new OsgiBundleInstallationResult();
         result.metadata = bundleMetadata;
         List<Throwable> errors = MutableList.of();
@@ -425,22 +429,24 @@ public class OsgiManager {
                 errors.add(e);            
             }
             
-            Bundle bundle = framework.getBundleContext().getBundle(bundleMetadata.getOsgiUniqueUrl());
-            result.bundle = bundle;
-            if (bundle==null) {
-                Exception e = new IllegalStateException("No such bundle installed in OSGi when uninstalling: "+bundleMetadata);
-                if (!force) Exceptions.propagate(e);
-                log.warn(e.getMessage());
-                errors.add(e);
-            } else {
-                try {
-                    bundle.stop();
-                    bundle.uninstall();
-                } catch (BundleException e) {
-                    Exceptions.propagateIfFatal(e);
+            if (!leaveInOsgi) {
+                Bundle bundle = framework.getBundleContext().getBundle(bundleMetadata.getOsgiUniqueUrl());
+                result.bundle = bundle;
+                if (bundle==null) {
+                    Exception e = new IllegalStateException("No such bundle installed in OSGi when uninstalling: "+bundleMetadata);
                     if (!force) Exceptions.propagate(e);
-                    log.warn("Error stopping and uninstalling "+bundleMetadata+": "+e);
-                    errors.add(e);            
+                    log.warn(e.getMessage());
+                    errors.add(e);
+                } else {
+                    try {
+                        bundle.stop();
+                        bundle.uninstall();
+                    } catch (BundleException e) {
+                        Exceptions.propagateIfFatal(e);
+                        if (!force) Exceptions.propagate(e);
+                        log.warn("Error stopping and uninstalling "+bundleMetadata+": "+e);
+                        errors.add(e);            
+                    }
                 }
             }
         } catch (Exception e) {