You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ge...@apache.org on 2017/04/28 10:32:04 UTC

[03/13] brooklyn-server git commit: osgi bundle persistence code written ... but not yet tested. need to write unit test for persistence, and do manual test against S3 or similar.

osgi bundle persistence code written ... but not yet tested.
need to write unit test for persistence, and do manual test against S3 or similar.

then the fun stuff, CLI push and upgrade workflow, bundles used in search path instead of catalog item id, bundles managed in REST/UI


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

Branch: refs/heads/master
Commit: e8b5fd053cd4434c66b63c9124d7aa0ef9cb1237
Parents: fbe99f1
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Apr 20 17:01:01 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Apr 21 12:45:35 2017 +0100

----------------------------------------------------------------------
 .../rebind/mementos/ManagedBundleMemento.java   |   1 +
 .../catalog/CatalogMakeOsgiBundleTest.java      |  13 ++-
 .../brooklyn/core/mgmt/ha/OsgiManager.java      |  85 ++++++++++++++-----
 .../BrooklynMementoPersisterToObjectStore.java  |  75 ++++++++++++++--
 .../mgmt/persist/BrooklynPersistenceUtils.java  |   3 +-
 .../rebind/ImmediateDeltaChangeListener.java    |   1 -
 .../rebind/dto/BasicManagedBundleMemento.java   |   7 +-
 .../core/typereg/BasicManagedBundle.java        |  30 ++++++-
 .../brooklyn/util/core/osgi/BundleMaker.java    |   7 +-
 .../HighAvailabilityManagerSplitBrainTest.java  |   2 +-
 .../ha/HighAvailabilityManagerTestFixture.java  |   2 +-
 .../brooklyn/core/mgmt/ha/HotStandbyTest.java   |   2 +-
 .../brooklyn/core/mgmt/ha/WarmStandbyTest.java  |   2 +-
 .../mgmt/osgi/OsgiVersionMoreEntityTest.java    |  17 ++++
 .../core/mgmt/rebind/RebindTestFixture.java     |   2 +-
 .../core/mgmt/rebind/RebindTestUtils.java       |   6 +-
 .../transformer/CompoundTransformerTest.java    |   4 +-
 .../util/core/osgi/BundleMakerTest.java         |   3 +-
 .../brooklyn/launcher/common/BasicLauncher.java |   4 +-
 .../CleanOrphanedLocationsIntegrationTest.java  |   4 +-
 .../rest/resources/CatalogResource.java         |  12 ++-
 .../brooklyn-test-osgi-com-example-entities.jar | Bin 22144 -> 22130 bytes
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 22075 -> 22067 bytes
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 16004 -> 15997 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 16906 -> 16903 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 13811 -> 14091 bytes
 26 files changed, 220 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/ManagedBundleMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/ManagedBundleMemento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/ManagedBundleMemento.java
index f2ec818..7e487ff 100644
--- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/ManagedBundleMemento.java
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/ManagedBundleMemento.java
@@ -28,5 +28,6 @@ public interface ManagedBundleMemento extends Memento {
     String getUrl();
     
     ByteSource getJarContent();
+    void setJarContent(ByteSource byteSource);
 
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
index a08c7b6..6f7117e 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.camp.brooklyn.catalog;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.InputStream;
 import java.util.Collection;
 import java.util.List;
@@ -39,6 +40,7 @@ import org.apache.brooklyn.core.entity.EntityAsserts;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
@@ -169,8 +171,15 @@ public class CatalogMakeOsgiBundleTest extends AbstractYamlTest {
     }
 
     private void installBundle(File jf) {
-        Bundle bundle = bm.installBundle(jf, true);
-        bundlesToRemove.add(bundle);
+        try (FileInputStream fin = new FileInputStream(jf)) {
+            BasicManagedBundle bundleMetadata = new BasicManagedBundle();
+            Bundle bundle =
+                ((LocalManagementContext)mgmt()).getOsgiManager().get().installUploadedBundle(bundleMetadata, fin);
+            bundlesToRemove.add(bundle);
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+
     }
     
     @Test

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/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 c64a131..37ba4ce 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
@@ -19,6 +19,8 @@
 package org.apache.brooklyn.core.mgmt.ha;
 
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.Arrays;
@@ -39,6 +41,7 @@ import org.apache.brooklyn.core.BrooklynVersion;
 import org.apache.brooklyn.core.mgmt.persist.OsgiClassPrefixer;
 import org.apache.brooklyn.core.server.BrooklynServerConfig;
 import org.apache.brooklyn.core.server.BrooklynServerPaths;
+import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.osgi.Osgis;
@@ -50,6 +53,7 @@ import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.os.Os;
 import org.apache.brooklyn.util.os.Os.DeletionResult;
 import org.apache.brooklyn.util.repeat.Repeater;
+import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Duration;
 import org.osgi.framework.Bundle;
@@ -121,33 +125,63 @@ public class OsgiManager {
         return ImmutableMap.copyOf(managedBundles);
     }
     
-    public void installUploadedBundle(ManagedBundle bundleMetadata, InputStream zip) {
+    public Bundle installUploadedBundle(ManagedBundle bundleMetadata, InputStream zipIn) {
         try {
-            if (checkBundleInstalledThrowIfInconsistent(bundleMetadata)) {
-                return;
+            Bundle alreadyBundle = checkBundleInstalledThrowIfInconsistent(bundleMetadata, false);
+            if (alreadyBundle!=null) {
+                return alreadyBundle;
             }
 
-            Bundle bundleInstalled = framework.getBundleContext().installBundle(bundleMetadata.getOsgiUniqueUrl(), zip);
+            File zipF = Os.newTempFile("brooklyn-bundle-transient-"+bundleMetadata, "zip");
+            FileOutputStream fos = new FileOutputStream(zipF);
+            Streams.copy(zipIn, fos);
+            zipIn.close();
+            fos.close();
+            
+            Bundle bundleInstalled = framework.getBundleContext().installBundle(bundleMetadata.getOsgiUniqueUrl(), 
+                new FileInputStream(zipF));
             checkCorrectlyInstalled(bundleMetadata, bundleInstalled);
+            if (!bundleMetadata.isNameResolved()) {
+                ((BasicManagedBundle)bundleMetadata).setSymbolicName(bundleInstalled.getSymbolicName());
+                ((BasicManagedBundle)bundleMetadata).setVersion(bundleInstalled.getVersion().toString());
+            }
+            ((BasicManagedBundle)bundleMetadata).setTempLocalFileWhenJustUploaded(zipF);
             
             synchronized (managedBundles) {
                 managedBundles.put(bundleMetadata.getId(), bundleMetadata);
             }
+            mgmt.getRebindManager().getChangeListener().onChanged(bundleMetadata);
+            
+            bundleInstalled.start();
+            // benefits of start:
+            // a) we get wiring issues thrown here, and
+            // b) catalog.bom in root will be scanned synchronously here
+            // however drawbacks:
+            // c) other code doesn't always do it (see eg BundleMaker)
+            // d) heavier-weight earlier
+            // e) tests in IDE break (but mvn fine)
+            
+            return bundleInstalled;
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
             throw new IllegalStateException("Bundle "+bundleMetadata+" failed to install: " + e.getMessage(), e);
         }
     }
     
-    public synchronized void registerBundle(CatalogBundle bundleMetadata) {
+    // TODO uninstall bundle, and call change listener onRemoved ?
+    // TODO on snapshot install, uninstall old equivalent snapshots (items in use might stay in use though?)
+    
+    public synchronized Bundle registerBundle(CatalogBundle bundleMetadata) {
         try {
-            if (checkBundleInstalledThrowIfInconsistent(bundleMetadata)) {
-                return;
+            Bundle alreadyBundle = checkBundleInstalledThrowIfInconsistent(bundleMetadata, true);
+            if (alreadyBundle!=null) {
+                return alreadyBundle;
             }
 
             Bundle bundleInstalled = Osgis.install(framework, bundleMetadata.getUrl());
 
             checkCorrectlyInstalled(bundleMetadata, bundleInstalled);
+            return bundleInstalled;
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
             throw new IllegalStateException("Bundle from "+bundleMetadata.getUrl()+" failed to install: " + e.getMessage(), e);
@@ -166,41 +200,48 @@ public class OsgiManager {
                 .version(b.getVersion().toString())
                 .findAll();
         if (matches.isEmpty()) {
-            log.error("OSGi could not find bundle "+nv+" in search after installing it from "+bundle.getUrl());
+            log.error("OSGi could not find bundle "+nv+" in search after installing it from "+bundle);
         } else if (matches.size()==1) {
             log.debug("Bundle from "+bundle.getUrl()+" successfully installed as " + nv + " ("+b+")");
         } else {
-            log.warn("OSGi has multiple bundles matching "+nv+", when just installed from "+bundle.getUrl()+": "+matches+"; "
-                + "brooklyn will prefer the URL-based bundle for top-level references but any dependencies or "
-                + "import-packages will be at the mercy of OSGi. "
-                + "It is recommended to use distinct versions for different bundles, and the same URL for the same bundles.");
+            log.warn("OSGi has multiple bundles matching "+nv+", when installing "+bundle+"; not guaranteed which versions will be consumed");
+            // TODO for snapshot versions we should indicate which one is best to use
         }
     }
 
-    private boolean checkBundleInstalledThrowIfInconsistent(OsgiBundleWithUrl bundle) {
-        String bundleUrl = bundle.getUrl();
+    /** return already-installed bundle or null */
+    private Bundle checkBundleInstalledThrowIfInconsistent(OsgiBundleWithUrl bundleMetadata, boolean requireUrlIfNotAlreadyPresent) {
+        String bundleUrl = bundleMetadata.getUrl();
         if (bundleUrl != null) {
             Maybe<Bundle> installedBundle = Osgis.bundleFinder(framework).requiringFromUrl(bundleUrl).find();
             if (installedBundle.isPresent()) {
                 Bundle b = installedBundle.get();
                 String nv = b.getSymbolicName()+":"+b.getVersion().toString();
-                if (!isBundleNameEqualOrAbsent(bundle, b)) {
-                    throw new IllegalStateException("User requested bundle " + bundle + " but already installed as "+nv);
+                if (!isBundleNameEqualOrAbsent(bundleMetadata, b)) {
+                    throw new IllegalStateException("User requested bundle " + bundleMetadata + " but already installed as "+nv);
                 } else {
                     log.trace("Bundle from "+bundleUrl+" already installed as "+nv+"; not re-registering");
                 }
-                return true;
+                return b;
             }
         } else {
-            Maybe<Bundle> installedBundle = Osgis.bundleFinder(framework).symbolicName(bundle.getSymbolicName()).version(bundle.getVersion()).find();
+            Maybe<Bundle> installedBundle;
+            if (bundleMetadata.isNameResolved()) {
+                installedBundle = Osgis.bundleFinder(framework).symbolicName(bundleMetadata.getSymbolicName()).version(bundleMetadata.getVersion()).find();
+            } else {
+                installedBundle = Maybe.absent("Bundle metadata does not have URL nor does it have both name and version");
+            }
             if (installedBundle.isPresent()) {
-                log.trace("Bundle "+bundle+" installed from "+installedBundle.get().getLocation());
+                log.trace("Bundle "+bundleMetadata+" installed from "+installedBundle.get().getLocation());
             } else {
-                throw new IllegalStateException("Bundle "+bundle+" not previously registered, but URL is empty.");
+                if (requireUrlIfNotAlreadyPresent) {
+                    throw new IllegalStateException("Bundle "+bundleMetadata+" not previously registered, but URL is empty.",
+                        Maybe.Absent.getException(installedBundle));
+                }
             }
-            return true;
+            return installedBundle.orNull();
         }
-        return false;
+        return null;
     }
 
     public static boolean isBundleNameEqualOrAbsent(OsgiBundleWithUrl bundle, Bundle b) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
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 25ef2b0..f0af9d1 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
@@ -20,6 +20,7 @@ package org.apache.brooklyn.core.mgmt.persist;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -36,6 +37,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.annotation.Nullable;
 
+import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.rebind.PersistenceExceptionHandler;
 import org.apache.brooklyn.api.mgmt.rebind.RebindExceptionHandler;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMemento;
@@ -47,22 +49,27 @@ import org.apache.brooklyn.api.mgmt.rebind.mementos.ManagedBundleMemento;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.BrooklynObjectType;
+import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.StringConfigMap;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.mgmt.classloading.ClassLoaderFromBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.persist.PersistenceObjectStore.StoreObjectAccessor;
 import org.apache.brooklyn.core.mgmt.persist.PersistenceObjectStore.StoreObjectAccessorWithLock;
 import org.apache.brooklyn.core.mgmt.rebind.PeriodicDeltaChangeListener;
 import org.apache.brooklyn.core.mgmt.rebind.dto.BrooklynMementoImpl;
 import org.apache.brooklyn.core.mgmt.rebind.dto.BrooklynMementoManifestImpl;
+import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.xstream.XmlUtil;
 import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Duration;
 import org.apache.brooklyn.util.time.Time;
@@ -74,6 +81,7 @@ import com.google.common.base.Objects;
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
+import com.google.common.io.ByteSource;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
@@ -112,6 +120,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
     private volatile boolean writesAllowed = false;
     private volatile boolean writesShuttingDown = false;
     private StringConfigMap brooklynProperties;
+    private ManagementContext mgmt = null;
     
     private List<Delta> queuedDeltas = new CopyOnWriteArrayList<BrooklynMementoPersister.Delta>();
     
@@ -121,6 +130,17 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
      */
     private final ReadWriteLock lock = new ReentrantReadWriteLock(true);
 
+    public BrooklynMementoPersisterToObjectStore(PersistenceObjectStore objectStore, ManagementContext mgmt) {
+        this(objectStore, mgmt, mgmt.getCatalogClassLoader());
+    }
+    
+    public BrooklynMementoPersisterToObjectStore(PersistenceObjectStore objectStore, ManagementContext mgmt, ClassLoader classLoader) {
+        this(objectStore, ((ManagementContextInternal)mgmt).getBrooklynProperties(), classLoader);
+        this.mgmt = mgmt;
+    }
+    
+    /** @deprecated since 0.12.0 use constructor taking management context */
+    @Deprecated
     public BrooklynMementoPersisterToObjectStore(PersistenceObjectStore objectStore, StringConfigMap brooklynProperties, ClassLoader classLoader) {
         this.objectStore = checkNotNull(objectStore, "objectStore");
         this.brooklynProperties = brooklynProperties;
@@ -263,10 +283,8 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
         Stopwatch stopwatch = Stopwatch.createStarted();
         try {
             for (BrooklynObjectType type: BrooklynPersistenceUtils.STANDARD_BROOKLYN_OBJECT_TYPE_PERSISTENCE_ORDER) {
-                // TODO exclude bundles
                 subPathDataBuilder.putAll(type, makeIdSubPathMap(objectStore.listContentsWithSubPath(type.getSubPathName())));
             }
-            // TODO bundles
             
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
@@ -306,6 +324,11 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
                 if (!Objects.equal(id, safeXmlId))
                     LOG.warn("ID mismatch on "+type.toCamelCase()+", "+id+" from path, "+safeXmlId+" from xml");
                 
+                if (type == BrooklynObjectType.MANAGED_BUNDLE) {
+                    // TODO write to temp file
+                    String jarData = read(contentsSubpath+".jar");
+                    builder.bundleJar(id, ByteSource.wrap(jarData.getBytes()));
+                }
                 builder.put(type, xmlId, contents);
             }
         };
@@ -329,10 +352,8 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
     }
 
     @Override
-    public BrooklynMementoManifest loadMementoManifest(BrooklynMementoRawData mementoData, final RebindExceptionHandler exceptionHandler) throws IOException {
-        if (mementoData==null)
-            mementoData = loadMementoRawData(exceptionHandler);
-        
+    public BrooklynMementoManifest loadMementoManifest(BrooklynMementoRawData mementoDataR, final RebindExceptionHandler exceptionHandler) throws IOException {
+        final BrooklynMementoRawData mementoData = mementoDataR==null ? loadMementoRawData(exceptionHandler) : mementoDataR;
         final BrooklynMementoManifestImpl.Builder builder = BrooklynMementoManifestImpl.builder();
 
         builder.planeId(mementoData.getPlaneId());
@@ -376,7 +397,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
                         try {
                             ManagedBundleMemento memento = (ManagedBundleMemento) getSerializerWithStandardClassLoader().fromString(contents);
                             builder.bundle( memento );
-                            // TODO load and set contents
+                            memento.setJarContent(mementoData.getBundleJars().get(objectId));
                         } catch (Exception e) {
                             exceptionHandler.onLoadMementoFailed(type, "memento "+objectId+" early catalog deserialization error", e);
                         }
@@ -541,8 +562,8 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
             
             futures.add(asyncUpdatePlaneId(newMemento.getPlaneId(), exceptionHandler));
             for (BrooklynObjectType type: BrooklynPersistenceUtils.STANDARD_BROOKLYN_OBJECT_TYPE_PERSISTENCE_ORDER) {
-                // TODO handle bundles separately
                 for (Map.Entry<String, String> entry : newMemento.getObjectsOfType(type).entrySet()) {
+                    addPersistContentIfManagedBundle(type, entry.getKey(), futures, exceptionHandler);
                     futures.add(asyncPersist(type.getSubPathName(), type, entry.getKey(), entry.getValue(), exceptionHandler));
                 }
             }
@@ -619,7 +640,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())) {
-                        // TODO if type is bundle then persist the actual bundle first
+                        addPersistContentIfManagedBundle(type, item.getId(), futures, exceptionHandler);
                         futures.add(asyncPersist(type.getSubPathName(), item, exceptionHandler));
                     }
                 }
@@ -627,6 +648,9 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
             for (BrooklynObjectType type: BrooklynPersistenceUtils.STANDARD_BROOKLYN_OBJECT_TYPE_PERSISTENCE_ORDER) {
                 for (String id : delta.getRemovedIdsOfType(type)) {
                     futures.add(asyncDelete(type.getSubPathName(), id, exceptionHandler));
+                    if (type==BrooklynObjectType.MANAGED_BUNDLE) {
+                        futures.add(asyncDelete(type.getSubPathName(), id+".jar", exceptionHandler));
+                    }
                 }
             }
             
@@ -645,6 +669,39 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
         }
     }
 
+    private void addPersistContentIfManagedBundle(BrooklynObjectType type, String id, List<ListenableFuture<?>> futures, PersistenceExceptionHandler exceptionHandler) {
+        if (type==BrooklynObjectType.MANAGED_BUNDLE) {
+            if (mgmt==null) {
+                throw new IllegalStateException("Cannot persist bundles without a mangaement context");
+            }
+            final ManagedBundle mb = ((ManagementContextInternal)mgmt).getOsgiManager().get().getManagedBundles().get(id);
+            if (mb==null) {
+                LOG.warn("Cannot find managed bundle for added bundle "+id+"; ignoring");
+            }
+            if (mb.getUrl()==null) {
+                LOG.trace("No URL for managed bundle for bundle "+id+", so not persisting");
+                return;
+            }
+            
+            String jarContent = Streams.readFullyStringAndClose(new ResourceUtils("persist").getResourceFromUrl(mb.getUrl()));
+            
+            // erase the URL once persisted - this prevents it from re-persisting
+            // (could introduce multiple or a transient field instead?)
+            if (mb instanceof BasicManagedBundle) {
+                final File f = ((BasicManagedBundle)mb).getTempLocalFileWhenJustUploaded();
+                if (f!=null) {
+                    futures.add(asyncPersist(type.getSubPathName(), type, id+".jar", jarContent, exceptionHandler));
+                    executor.submit(new Runnable() {
+                        @Override
+                        public void run() {
+                            ((BasicManagedBundle)mb).setTempLocalFileWhenJustUploaded(null);
+                            f.delete();
+                        }});
+                }
+            }
+        }
+    }
+
     @Override
     public void waitForWritesCompleted(Duration timeout) throws InterruptedException, TimeoutException {
         boolean locked = lock.readLock().tryLock(timeout.toMillisecondsRoundingUp(), TimeUnit.MILLISECONDS);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynPersistenceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynPersistenceUtils.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynPersistenceUtils.java
index 7463eb0..c509208 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynPersistenceUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynPersistenceUtils.java
@@ -108,8 +108,7 @@ public class BrooklynPersistenceUtils {
             PersistenceObjectStore destinationObjectStore) {
         BrooklynMementoPersisterToObjectStore persister = new BrooklynMementoPersisterToObjectStore(
             destinationObjectStore,
-            ((ManagementContextInternal)managementContext).getBrooklynProperties(),
-            managementContext.getCatalogClassLoader());
+            managementContext);
         PersistenceExceptionHandler exceptionHandler = PersistenceExceptionHandlerImpl.builder().build();
         persister.enableWriteAccess();
         persister.checkpoint(memento, exceptionHandler);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/ImmediateDeltaChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/ImmediateDeltaChangeListener.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/ImmediateDeltaChangeListener.java
index 2b59e7c..3d77f41 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/ImmediateDeltaChangeListener.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/ImmediateDeltaChangeListener.java
@@ -70,7 +70,6 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
         onChanged(instance);
     }
 
-    // TODO ensure this, and onChanged, are called
     @Override
     public void onUnmanaged(BrooklynObject instance) {
         if (running && persister != null) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicManagedBundleMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicManagedBundleMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicManagedBundleMemento.java
index 078fb7c..505e7c8 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicManagedBundleMemento.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicManagedBundleMemento.java
@@ -74,7 +74,7 @@ public class BasicManagedBundleMemento extends AbstractMemento implements Manage
     private String symbolicName;
     private String version;
     private String url;
-    private ByteSource jarContent;
+    transient private ByteSource jarContent;
 
     @SuppressWarnings("unused") // For deserialisation
     private BasicManagedBundleMemento() {}
@@ -105,6 +105,11 @@ public class BasicManagedBundleMemento extends AbstractMemento implements Manage
     public ByteSource getJarContent() {
         return jarContent;
     }
+    
+    @Override
+    public void setJarContent(ByteSource byteSource) {
+        this.jarContent = byteSource;
+    }
 
     @Override
     protected void setCustomFields(Map<String, Object> fields) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
----------------------------------------------------------------------
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 4223e79..8d92794 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
@@ -18,6 +18,7 @@
  */
 package org.apache.brooklyn.core.typereg;
 
+import java.io.File;
 import java.util.Map;
 
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
@@ -27,6 +28,7 @@ import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.objs.AbstractBrooklynObject;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 
+import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
@@ -36,10 +38,10 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage
     private String symbolicName;
     private String version;
     private String url;
+    private transient File localFileWhenJustUploaded;
 
-    // for deserializing (not sure if needed?)
-    @SuppressWarnings("unused")
-    private BasicManagedBundle() {}
+    /** Creates an empty one, with an ID, expecting other fields will be populated. */
+    public BasicManagedBundle() {}
 
     public BasicManagedBundle(String name, String version, String url) {
         if (name == null && version == null) {
@@ -64,16 +66,38 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage
         return symbolicName;
     }
 
+    public void setSymbolicName(String symbolicName) {
+        this.symbolicName = symbolicName;
+    }
+    
     @Override
     public String getVersion() {
         return version;
     }
 
+    public void setVersion(String version) {
+        this.version = version;
+    }
+    
     @Override
     public String getUrl() {
         return url;
     }
 
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    /** This is cached on the object when just uploaded, then deleted after it has been persisted. */
+    @Beta
+    public void setTempLocalFileWhenJustUploaded(File localFileWhenJustUploaded) {
+        this.localFileWhenJustUploaded = localFileWhenJustUploaded;
+    }
+    @Beta
+    public File getTempLocalFileWhenJustUploaded() {
+        return localFileWhenJustUploaded;
+    }
+    
     @Override
     public String getOsgiUniqueUrl() {
         return "brooklyn:"+getId();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java b/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java
index efe1d0e..b590cee 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java
@@ -36,6 +36,7 @@ import java.util.zip.ZipOutputStream;
 import javax.annotation.Nonnull;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
@@ -259,8 +260,10 @@ public class BundleMaker {
     }
     
     /** installs the given JAR file as an OSGi bundle; all manifest info should be already set up.
-     * bundle-start semantics are TBD. */
-    @Beta
+     * bundle-start semantics are TBD.
+     * 
+     * @deprecated since 0.12.0, use {@link OsgiManager#installUploadedBundle(org.apache.brooklyn.api.typereg.ManagedBundle, InputStream)}*/
+    @Deprecated
     public Bundle installBundle(File f, boolean start) {
         try {
             Bundle b = Osgis.install( framework, "file://"+f.getAbsolutePath() );

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerSplitBrainTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerSplitBrainTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerSplitBrainTest.java
index ef3e0a4..d7d9ac9 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerSplitBrainTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerSplitBrainTest.java
@@ -108,7 +108,7 @@ public class HighAvailabilityManagerSplitBrainTest {
             objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
             persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
             ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
-            BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
+            BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt, classLoader);
             mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
             ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())
                 .setPollPeriod(Duration.PRACTICALLY_FOREVER)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerTestFixture.java
index 732ab81..506d50b 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerTestFixture.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HighAvailabilityManagerTestFixture.java
@@ -93,7 +93,7 @@ public abstract class HighAvailabilityManagerTestFixture {
         ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
         BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(
                 objectStore, 
-                managementContext.getBrooklynProperties(), 
+                managementContext, 
                 classLoader);
         managementContext.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
         manager = ((HighAvailabilityManagerImpl)managementContext.getHighAvailabilityManager())

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HotStandbyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HotStandbyTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HotStandbyTest.java
index 4b4e446..4fefddd 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HotStandbyTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/HotStandbyTest.java
@@ -102,7 +102,7 @@ public class HotStandbyTest {
             objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
             persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
             ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
-            BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
+            BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt, classLoader);
             ((RebindManagerImpl)mgmt.getRebindManager()).setPeriodicPersistPeriod(persistOrRebindPeriod);
             mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
             ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/WarmStandbyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/WarmStandbyTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/WarmStandbyTest.java
index 830f472..7aa7353 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/WarmStandbyTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/WarmStandbyTest.java
@@ -79,7 +79,7 @@ public class WarmStandbyTest {
             objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
             persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
             ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
-            BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
+            BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt, classLoader);
             mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
             ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())
                 .setPollPeriod(Duration.PRACTICALLY_FOREVER)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
index 62025f5..c4b9fdf 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
@@ -23,12 +23,14 @@ import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.core.catalog.internal.CatalogEntityItemDto;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
@@ -42,8 +44,11 @@ import org.apache.brooklyn.core.objs.proxy.InternalEntityFactory;
 import org.apache.brooklyn.core.objs.proxy.InternalPolicyFactory;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.typereg.BasicManagedBundle;
+import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.osgi.OsgiTestBase;
 import org.apache.brooklyn.util.core.osgi.Osgis;
 import org.apache.brooklyn.util.guava.Maybe;
@@ -216,6 +221,18 @@ public class OsgiVersionMoreEntityTest {
             BROOKLYN_TEST_MORE_ENTITIES_V2_URL,
             BROOKLYN_TEST_OSGI_ENTITIES_URL);
     }
+
+    @Test
+    public void testBrooklynManagedBundleInstall() throws Exception {
+        BasicManagedBundle mb = new BasicManagedBundle();
+        Bundle b = ((ManagementContextInternal)mgmt).getOsgiManager().get().installUploadedBundle(mb, 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL));
+        Assert.assertEquals(mb.getSymbolicName(), b.getSymbolicName());
+        
+        Map<String, ManagedBundle> bundles = ((ManagementContextInternal)mgmt).getOsgiManager().get().getManagedBundles();
+        Asserts.assertSize(bundles.keySet(), 1);
+        Assert.assertEquals(mb.getId(), Iterables.getOnlyElement( bundles.keySet() ));
+    }
     
     @Test
     public void testMoreEntitiesV1() throws Exception {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
index 41d51c2..4ede973 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
@@ -350,7 +350,7 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
         objectStore.prepareForSharedUse(PersistMode.AUTO, HighAvailabilityMode.DISABLED);
         BrooklynMementoPersisterToObjectStore persister = new BrooklynMementoPersisterToObjectStore(
                 objectStore,
-                ((ManagementContextInternal)newManagementContext).getBrooklynProperties(),
+                newManagementContext,
                 classLoader);
         RebindExceptionHandler exceptionHandler = new RecordingRebindExceptionHandler(RebindManager.RebindFailureMode.FAIL_AT_END, RebindManager.RebindFailureMode.FAIL_AT_END);
         BrooklynMementoManifest mementoManifest = persister.loadMementoManifest(null, exceptionHandler);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestUtils.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestUtils.java
index 4e18336..7271d3e 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestUtils.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestUtils.java
@@ -253,7 +253,7 @@ public class RebindTestUtils {
             objectStore.prepareForSharedUse(PersistMode.AUTO, haMode);
             BrooklynMementoPersisterToObjectStore newPersister = new BrooklynMementoPersisterToObjectStore(
                     objectStore, 
-                    unstarted.getBrooklynProperties(), 
+                    unstarted, 
                     classLoader);
             ((RebindManagerImpl) unstarted.getRebindManager()).setPeriodicPersistPeriod(persistPeriod);
             unstarted.getRebindManager().setPersister(newPersister, PersistenceExceptionHandlerImpl.builder().build());
@@ -455,7 +455,7 @@ public class RebindTestUtils {
             
             BrooklynMementoPersisterToObjectStore newPersister = new BrooklynMementoPersisterToObjectStore(
                     objectStore,
-                    newManagementContext.getBrooklynProperties(),
+                    newManagementContext,
                     classLoader);
             newManagementContext.getRebindManager().setPersister(newPersister, PersistenceExceptionHandlerImpl.builder().build());
         } else {
@@ -533,7 +533,7 @@ public class RebindTestUtils {
             store = new FileBasedObjectStore(dir);
             store.injectManagementContext(mgmt);
             store.prepareForSharedUse(PersistMode.AUTO, HighAvailabilityMode.HOT_STANDBY);
-            persister = new BrooklynMementoPersisterToObjectStore(store, BrooklynProperties.Factory.newEmpty(), RebindTestUtils.class.getClassLoader());
+            persister = new BrooklynMementoPersisterToObjectStore(store, mgmt, RebindTestUtils.class.getClassLoader());
             BrooklynMementoRawData data = persister.loadMementoRawData(RebindExceptionHandlerImpl.builder().build());
             List<BrooklynObjectType> types = ImmutableList.of(BrooklynObjectType.ENTITY, BrooklynObjectType.LOCATION, 
                     BrooklynObjectType.POLICY, BrooklynObjectType.ENRICHER, BrooklynObjectType.FEED, 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java
index f2b3418..02dfadb 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java
@@ -452,9 +452,7 @@ public class CompoundTransformerTest extends RebindTestFixtureWithApp {
         objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
 
         BrooklynMementoPersisterToObjectStore persister = new BrooklynMementoPersisterToObjectStore(
-                objectStore,
-                ((ManagementContextInternal)origManagementContext).getBrooklynProperties(),
-                origManagementContext.getCatalog().getRootClassLoader());
+                objectStore, origManagementContext);
         persister.enableWriteAccess();
 
         PersistenceExceptionHandler exceptionHandler = PersistenceExceptionHandlerImpl.builder().build();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/core/src/test/java/org/apache/brooklyn/util/core/osgi/BundleMakerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/osgi/BundleMakerTest.java b/core/src/test/java/org/apache/brooklyn/util/core/osgi/BundleMakerTest.java
index 599531d..a23fab3 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/osgi/BundleMakerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/osgi/BundleMakerTest.java
@@ -36,10 +36,8 @@ import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 import java.util.zip.ZipOutputStream;
 
-import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.os.Os;
 import org.apache.brooklyn.util.stream.Streams;
 import org.osgi.framework.Bundle;
@@ -214,6 +212,7 @@ public class BundleMakerTest extends BrooklynMgmtUnitTestSupport {
         assertJarContents(generatedJar, ImmutableMap.of(JarFile.MANIFEST_NAME, expectedManifest, "myfile.txt", "mytext", "subdir/myfile2.txt", "mytext2"));
     }
     
+    @SuppressWarnings("deprecation")
     @Test
     public void testInstallBundle() throws Exception {
         Map<String, String> manifest = ImmutableMap.of(

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BasicLauncher.java
----------------------------------------------------------------------
diff --git a/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BasicLauncher.java b/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BasicLauncher.java
index afad4c9..2a7a924 100644
--- a/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BasicLauncher.java
+++ b/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BasicLauncher.java
@@ -584,9 +584,7 @@ public class BasicLauncher<T extends BasicLauncher<T>> {
                 RebindManager rebindManager = managementContext.getRebindManager();
                 
                 BrooklynMementoPersisterToObjectStore persister = new BrooklynMementoPersisterToObjectStore(
-                    objectStore,
-                    ((ManagementContextInternal)managementContext).getBrooklynProperties(),
-                    managementContext.getCatalogClassLoader());
+                    objectStore, managementContext);
                 PersistenceExceptionHandler persistenceExceptionHandler = PersistenceExceptionHandlerImpl.builder().build();
                 ((RebindManagerImpl) rebindManager).setPeriodicPersistPeriod(persistPeriod);
                 rebindManager.setPersister(persister, persistenceExceptionHandler);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/launcher/src/test/java/org/apache/brooklyn/launcher/CleanOrphanedLocationsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/launcher/src/test/java/org/apache/brooklyn/launcher/CleanOrphanedLocationsIntegrationTest.java b/launcher/src/test/java/org/apache/brooklyn/launcher/CleanOrphanedLocationsIntegrationTest.java
index 4d59735..09d938d 100644
--- a/launcher/src/test/java/org/apache/brooklyn/launcher/CleanOrphanedLocationsIntegrationTest.java
+++ b/launcher/src/test/java/org/apache/brooklyn/launcher/CleanOrphanedLocationsIntegrationTest.java
@@ -131,9 +131,7 @@ public class CleanOrphanedLocationsIntegrationTest extends AbstractCleanOrphaned
                 PersistMode.AUTO, HighAvailabilityMode.HOT_STANDBY);
 
         BrooklynMementoPersisterToObjectStore persister = new BrooklynMementoPersisterToObjectStore(
-                objectStore,
-                ((ManagementContextInternal)mgmt).getBrooklynProperties(),
-                mgmt.getCatalogClassLoader());
+                objectStore, mgmt);
 
         RebindManager rebindManager = mgmt.getRebindManager();
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index c2e800a..677b84f 100644
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.rest.resources;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.URI;
@@ -55,6 +56,8 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
+import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
 import org.apache.brooklyn.rest.api.CatalogApi;
 import org.apache.brooklyn.rest.domain.ApiError;
@@ -226,7 +229,14 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
             
             f2 = bm.copyAddingManifest(f, mf);
             
-            Bundle bundle = bm.installBundle(f2, true);
+            BasicManagedBundle bundleMetadata = new BasicManagedBundle(bundleNameInMF, bundleVersionInMF, null);
+            Bundle bundle;
+            try (FileInputStream f2in = new FileInputStream(f2)) {
+                bundle =
+                    ((LocalManagementContext)mgmt()).getOsgiManager().get().installUploadedBundle(bundleMetadata, f2in);
+            } catch (Exception e) {
+                throw Exceptions.propagate(e);
+            }
 
             Iterable<? extends CatalogItem<?, ?>> catalogItems = MutableList.of();
             

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar
index c476d9d..86dfd8b 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
index a9a2ecc..60fece6 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
index b30775e..9994cfb 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
index 0dc12b1..3d1ce7b 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8b5fd05/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar
index 2c0e3a6..f00a115 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar differ