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 2015/02/09 16:36:20 UTC

[01/22] incubator-brooklyn git commit: Bind the socket after setting SO_REUSEADDR to true, behaviour is undefined the other way around

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master e59aac03b -> 4fc5a07ff


Bind the socket after setting SO_REUSEADDR to true, behaviour is undefined the other way around


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

Branch: refs/heads/master
Commit: 0b5a77d4f3f8b4e5c1975d67c9cfddbab8a629eb
Parents: fe42507
Author: Matt Champion <ma...@gmail.com>
Authored: Tue Jan 27 17:20:51 2015 +0000
Committer: Matt Champion <ma...@gmail.com>
Committed: Tue Jan 27 17:20:51 2015 +0000

----------------------------------------------------------------------
 .../src/main/java/brooklyn/util/net/Networking.java      | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0b5a77d4/utils/common/src/main/java/brooklyn/util/net/Networking.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/net/Networking.java b/utils/common/src/main/java/brooklyn/util/net/Networking.java
index 2067283..7132bef 100644
--- a/utils/common/src/main/java/brooklyn/util/net/Networking.java
+++ b/utils/common/src/main/java/brooklyn/util/net/Networking.java
@@ -104,14 +104,17 @@ public class Networking {
             ServerSocket ss = null;
             DatagramSocket ds = null;
             try {
+                // Check TCP port
                 ss = new ServerSocket();
                 ss.setSoTimeout(250);
-                ss.bind(new InetSocketAddress(localAddress, port));
                 ss.setReuseAddress(true);
-                
-                ds = new DatagramSocket(port);
+                ss.bind(new InetSocketAddress(localAddress, port));
+
+                // Check UDP port
+                ds = new DatagramSocket();
+                ds.setSoTimeout(250);
                 ds.setReuseAddress(true);
-                
+                ds.bind(new InetSocketAddress(localAddress, port));
             } catch (IOException e) {
                 return false;
             } finally {


[05/22] incubator-brooklyn git commit: Fixed off by one error. After MAX_PORT_NUMBER comparison port is incremented and checked. If not in valid range isPortAvailable throws an exception which is less descriptive than the one in nextAvailablePort.

Posted by he...@apache.org.
Fixed off by one error. After MAX_PORT_NUMBER comparison port is incremented and checked. If not in valid range isPortAvailable throws an exception which is less descriptive than the one in nextAvailablePort.


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

Branch: refs/heads/master
Commit: f673e19910eaf160b2ba1c93e0d6a0d23a265f27
Parents: 34439f4
Author: Matt Champion <ma...@gmail.com>
Authored: Tue Jan 27 20:58:43 2015 +0000
Committer: Matt Champion <ma...@gmail.com>
Committed: Tue Jan 27 20:58:43 2015 +0000

----------------------------------------------------------------------
 utils/common/src/main/java/brooklyn/util/net/Networking.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f673e199/utils/common/src/main/java/brooklyn/util/net/Networking.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/net/Networking.java b/utils/common/src/main/java/brooklyn/util/net/Networking.java
index 828bb46..7a7368c 100644
--- a/utils/common/src/main/java/brooklyn/util/net/Networking.java
+++ b/utils/common/src/main/java/brooklyn/util/net/Networking.java
@@ -151,8 +151,8 @@ public class Networking {
     public static int nextAvailablePort(int port) {
         checkArgument(port >= MIN_PORT_NUMBER && port <= MAX_PORT_NUMBER, "requested port %s is outside the valid range of %s to %s", port, MIN_PORT_NUMBER, MAX_PORT_NUMBER);
         int originalPort = port;
-        while (!isPortAvailable(port) && port <= MAX_PORT_NUMBER) port++;
-        if (port > MAX_PORT_NUMBER)
+        while (!isPortAvailable(port) && port < MAX_PORT_NUMBER) port++;
+        if (port >= MAX_PORT_NUMBER)
             throw new RuntimeException("unable to find a free port at or above " + originalPort);
         return port;
     }


[11/22] incubator-brooklyn git commit: Switch OSGi more entites sayHI effector to include version info

Posted by he...@apache.org.
Switch OSGi more entites sayHI effector to include version info

as per @aledsage's suggestion


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

Branch: refs/heads/master
Commit: 26811b9ae4f6e7102e30743998bf8be31ae9464a
Parents: 07aaa89
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Feb 5 18:36:15 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:13 2015 +0000

----------------------------------------------------------------------
 .../osgi/tests/more/MoreEntityImpl.java         |   2 +-
 .../osgi/tests/more/MoreEntityImpl.java         |   2 +-
 .../osgi/tests/more/MoreEntityImpl.java         |   2 +-
 .../rebind/ActivePartialRebindVersionTest.java  |  15 ++++++---------
 .../osgi/OsgiVersionMoreEntityTest.java         |  16 ++++++++++------
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 12452 -> 12428 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 12615 -> 12590 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 12757 -> 12729 bytes
 8 files changed, 19 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26811b9a/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java b/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
index 5eb1de5..80d6b97 100644
--- a/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
+++ b/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
@@ -38,7 +38,7 @@ public class MoreEntityImpl extends AbstractEntity implements MoreEntity {
     
     @Override
     public String sayHI(String name) {
-        return "Hi "+name.toUpperCase();
+        return "Hi "+name.toUpperCase()+" from V1";
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26811b9a/core/src/test/dependencies/osgi/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java b/core/src/test/dependencies/osgi/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
index 2788b8b..6200787 100644
--- a/core/src/test/dependencies/osgi/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
+++ b/core/src/test/dependencies/osgi/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
@@ -41,7 +41,7 @@ public class MoreEntityImpl extends AbstractEntity implements MoreEntity {
     
     /** Returns HO instead of HI (like v2 non-evil twin) or Hi (like v1) */
     public String sayHI(String name) {
-        return "HO "+name.toUpperCase();
+        return "HO "+name.toUpperCase()+" FROM V2 EVIL TWIN";
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26811b9a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
index 355c43a..a3952cf 100644
--- a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
+++ b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
@@ -41,7 +41,7 @@ public class MoreEntityImpl extends AbstractEntity implements MoreEntity {
     
     /** Unlike v1, this returns "HI " rather than "Hi " */
     public String sayHI(String name) {
-        return "HI "+name.toUpperCase();
+        return "HI "+name.toUpperCase()+" FROM V2";
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26811b9a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
index 46c1bb6..b239f1a 100644
--- a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
@@ -54,16 +54,13 @@ public class ActivePartialRebindVersionTest extends RebindTestFixtureWithApp {
         CatalogItem<?, ?> catV1 = OsgiVersionMoreEntityTest.addMoreEntityV1(origManagementContext, "1.0");
         Entity childV1 = OsgiVersionMoreEntityTest.addItemFromCatalog(origManagementContext, origApp, catV1);
         
-        // v1 says Hi Brooklyn
-        // v2 says HI Brooklyn
-        
-        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(childV1), "Hi BROOKLYN");
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(childV1);
         
         // simply adding to catalog doesn't change
         CatalogItem<?, ?> catV2 = OsgiVersionMoreEntityTest.addMoreEntityV2(origManagementContext, "1.1");
-        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(childV1), "Hi BROOKLYN");
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(childV1);
         Entity child2V2 = OsgiVersionMoreEntityTest.addItemFromCatalog(origManagementContext, origApp, catV2);
-        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(child2V2), "HI BROOKLYN");
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(child2V2);
         
         // now transform, with a version change
         CompoundTransformer transformer = CompoundTransformer.builder().changeCatalogItemId(
@@ -72,12 +69,12 @@ public class ActivePartialRebindVersionTest extends RebindTestFixtureWithApp {
         doPartialRebindByObjectById(transformer, childV1.getId());
 
         Entity childV2 = origManagementContext.lookup(childV1.getId(), Entity.class);
-        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(childV2), "HI BROOKLYN");
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(childV2);
         
         // _v1_ child also points to new implementation -- saying HI
-        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(childV1), "HI BROOKLYN");
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(childV1);
 
-        // in fact they are the same
+        // (in fact they are the same)
         Assert.assertTrue(childV1==childV2, "Expected same instance: "+childV1+" / "+childV2);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26811b9a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
index b4a3511..7bec58f 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
@@ -77,6 +77,10 @@ public class OsgiVersionMoreEntityTest {
     public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH;
     
     public static final String TEST_VERSION = "0.1.0";
+
+    public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1 = "Hi BROOKLYN from V1";
+    public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2 = "HI BROOKLYN FROM V2";
+    public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN = "HO BROOKLYN FROM V2 EVIL TWIN";
     
     protected LocalManagementContext mgmt;
     protected TestApplication app;
@@ -172,13 +176,13 @@ public class OsgiVersionMoreEntityTest {
     }
 
     public static void assertV1MethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-        Assert.assertEquals(doMethodCallBrooklyn(me), "Hi BROOKLYN");
+        Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1);
     }
     public static void assertV2MethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-        Assert.assertEquals(doMethodCallBrooklyn(me), "HI BROOKLYN");
+        Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2);
     }
     public static void assertV2EvilTwinMethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-        Assert.assertEquals(doMethodCallBrooklyn(me), "HO BROOKLYN");
+        Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN);
     }
 
     public static Object doMethodCallBrooklyn(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
@@ -186,13 +190,13 @@ public class OsgiVersionMoreEntityTest {
     }
 
     public static void assertV1EffectorCall(Entity me) {
-        Assert.assertEquals(doEffectorCallBrooklyn(me), "Hi BROOKLYN");
+        Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1);
     }
     public static void assertV2EffectorCall(Entity me) {
-        Assert.assertEquals(doEffectorCallBrooklyn(me), "HI BROOKLYN");
+        Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2);
     }
     public static void assertV2EvilTwinEffectorCall(Entity me) {
-        Assert.assertEquals(doEffectorCallBrooklyn(me), "HO BROOKLYN");
+        Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN);
     }
 
     public static String doEffectorCallBrooklyn(Entity me) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26811b9a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
index a71f428..9958cf1 100644
Binary files a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26811b9a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
index c75c092..1567f6e 100644
Binary files a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26811b9a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar
index 2d52340..1cd12b1 100644
Binary files a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar differ


[22/22] incubator-brooklyn git commit: This closes #506

Posted by he...@apache.org.
This closes #506


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

Branch: refs/heads/master
Commit: 4fc5a07ffeebd5dd172d328f44b6d2175693837a
Parents: 4027986 b13cb63
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Feb 9 15:36:05 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Feb 9 15:36:05 2015 +0000

----------------------------------------------------------------------
 .../basic/AbstractBrooklynObjectSpec.java       |  17 ++
 .../java/brooklyn/management/EntityManager.java |   2 +
 .../src/main/java/brooklyn/BrooklynVersion.java | 219 +++++++++++++---
 .../brooklyn/entity/basic/AbstractEntity.java   |   4 +-
 .../entity/group/DynamicClusterImpl.java        |  21 +-
 .../entity/proxying/EntityProxyImpl.java        |   2 +-
 .../entity/proxying/InternalEntityFactory.java  |  12 +-
 .../rebind/ActivePartialRebindIteration.java    | 163 ++++++++++++
 .../rebind/InitialFullRebindIteration.java      | 130 +++++++++
 .../entity/rebind/RebindContextImpl.java        |  13 +-
 .../rebind/RebindContextLookupContext.java      |  23 +-
 .../brooklyn/entity/rebind/RebindIteration.java | 262 +++++++++----------
 .../entity/rebind/RebindManagerImpl.java        |  80 ++++--
 .../BrooklynMementoPersisterToObjectStore.java  |   4 +
 .../rebind/persister/XmlMementoSerializer.java  | 161 +++++++++++-
 .../ha/HighAvailabilityManagerImpl.java         |  10 +-
 .../brooklyn/management/ha/OsgiManager.java     |  18 +-
 .../internal/AbstractManagementContext.java     |   6 +-
 .../internal/BrooklynObjectManagementMode.java  |  31 +++
 .../internal/BrooklynObjectManagerInternal.java |  36 +++
 .../internal/EntityManagementSupport.java       |   6 +-
 .../internal/EntityManagerInternal.java         |  15 +-
 .../management/internal/LocalEntityManager.java |  62 +++--
 .../internal/LocalLocationManager.java          |  49 ++--
 .../internal/LocationManagerInternal.java       |  14 +-
 .../internal/ManagementTransitionInfo.java      |  39 +--
 .../internal/ManagementTransitionMode.java      | 127 +++++++++
 .../internal/NonDeploymentEntityManager.java    |   1 -
 .../internal/NonDeploymentLocationManager.java  |   1 -
 .../main/java/brooklyn/util/http/HttpTool.java  |   5 +
 .../osgi/tests/more/MoreEntityImpl.java         |   2 +-
 .../osgi/tests/more/MoreEntityImpl.java         |   2 +-
 .../osgi/tests/more/MoreEntityImpl.java         |   2 +-
 .../test/java/brooklyn/BrooklynVersionTest.java |  49 +++-
 .../catalog/internal/CatalogTestUtils.java      |  46 ++++
 .../entity/group/DynamicClusterTest.java        |  14 +
 .../entity/rebind/ActivePartialRebindTest.java  | 108 ++++++++
 .../rebind/ActivePartialRebindVersionTest.java  | 119 +++++++++
 .../entity/rebind/RebindEntityTest.java         |  27 +-
 .../rebind/RebindLocalhostLocationTest.java     |  22 ++
 .../entity/rebind/RebindTestFixture.java        |  23 +-
 .../brooklyn/entity/rebind/RebindTestUtils.java |   8 +-
 .../BrooklynMementoPersisterTestFixture.java    |   6 +-
 .../persister/XmlMementoSerializerTest.java     |  31 +++
 .../ha/HighAvailabilityManagerInMemoryTest.java |  21 +-
 .../osgi/OsgiVersionMoreEntityTest.java         |  61 +++--
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 12452 -> 12428 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 12615 -> 12590 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 12757 -> 12729 bytes
 .../entity/database/mysql/MySqlNodeImpl.java    |   2 +-
 .../main/java/brooklyn/cli/AbstractMain.java    |  14 +-
 usage/cli/src/main/java/brooklyn/cli/Main.java  |  26 +-
 .../cli/src/test/java/brooklyn/cli/CliTest.java |   2 +-
 .../brooklyn/cli/CloudExplorerLiveTest.java     |  11 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |  15 +-
 .../brooklyn/launcher/BrooklynWebServer.java    |  13 +-
 .../brooklyn/launcher/WebAppRunnerTest.java     |   4 +-
 .../java/brooklyn/rest/BrooklynWebConfig.java   |   7 +-
 .../brooklyn/rest/resources/ScriptResource.java |   1 +
 .../brooklyn/rest/resources/ServerResource.java |  15 ++
 .../provider/ExplicitUsersSecurityProvider.java |   2 +
 .../rest/util/BrooklynRestResourceUtils.java    |   2 +-
 .../main/java/brooklyn/test/HttpTestUtils.java  |   4 +-
 .../brooklyn/util/exceptions/Exceptions.java    |   8 +-
 64 files changed, 1787 insertions(+), 413 deletions(-)
----------------------------------------------------------------------



[15/22] incubator-brooklyn git commit: special xml serialization for EntitySpec to support CatalogItem libraries

Posted by he...@apache.org.
special xml serialization for EntitySpec to support CatalogItem libraries


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

Branch: refs/heads/master
Commit: 0dc533d116cc92a7d5811338cec060a7868e64a0
Parents: 6156a77
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Feb 6 17:58:41 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:14 2015 +0000

----------------------------------------------------------------------
 .../basic/AbstractBrooklynObjectSpec.java       |  17 ++
 .../rebind/persister/XmlMementoSerializer.java  | 160 ++++++++++++++++++-
 .../persister/XmlMementoSerializerTest.java     |  32 ++++
 3 files changed, 208 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0dc533d1/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
index c0a4ccc..83db969 100644
--- a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
+++ b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
@@ -121,4 +121,21 @@ public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObj
         if (Modifier.isAbstract(val.getModifiers())) throw new IllegalStateException("Implementation "+val+" is abstract, but must be a non-abstract class");
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        if (obj==null) return false;
+        if (!obj.getClass().equals(getClass())) return false;
+        AbstractBrooklynObjectSpec<?,?> other = (AbstractBrooklynObjectSpec<?,?>)obj;
+        if (!Objects.equal(getDisplayName(), other.getDisplayName())) return false;
+        if (!Objects.equal(getCatalogItemId(), other.getCatalogItemId())) return false;
+        if (!Objects.equal(getType(), other.getType())) return false;
+        if (!Objects.equal(getTags(), other.getTags())) return false;
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(getCatalogItemId(), getDisplayName(), getType(), getTags());
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0dc533d1/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
index 5f3fb5c..78644b3 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
@@ -22,13 +22,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.IOException;
 import java.io.Writer;
+import java.util.NoSuchElementException;
+import java.util.Stack;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.basic.AbstractBrooklynObjectSpec;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.internal.CatalogBundleDto;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.Effector;
 import brooklyn.entity.Entity;
 import brooklyn.entity.Feed;
@@ -49,20 +54,27 @@ import brooklyn.event.basic.BasicConfigKey;
 import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContextSequential;
+import brooklyn.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
+import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
 import brooklyn.mementos.BrooklynMementoPersister.LookupContext;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.Policy;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.text.Strings;
 import brooklyn.util.xstream.XmlSerializer;
 
 import com.thoughtworks.xstream.converters.Converter;
 import com.thoughtworks.xstream.converters.MarshallingContext;
 import com.thoughtworks.xstream.converters.SingleValueConverter;
 import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
 import com.thoughtworks.xstream.core.ReferencingMarshallingContext;
 import com.thoughtworks.xstream.core.util.HierarchicalStreams;
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.io.path.PathTrackingReader;
 import com.thoughtworks.xstream.mapper.Mapper;
 import com.thoughtworks.xstream.mapper.MapperWrapper;
 
@@ -110,9 +122,9 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento
         xstream.registerConverter(new EntityConverter());
         xstream.registerConverter(new FeedConverter());
         xstream.registerConverter(new CatalogItemConverter());
+        xstream.registerConverter(new SpecConverter());
 
         xstream.registerConverter(new ManagementContextConverter());
-        
         xstream.registerConverter(new TaskConverter(xstream.getMapper()));
     
         //For compatibility with existing persistence stores content.
@@ -341,5 +353,151 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento
             return lookupContext.lookupManagementContext();
         }
     }
+
+    /** When reading/writing specs, it checks whether there is a catalog item id set and uses it to load */
+    public class SpecConverter extends ReflectionConverter {
+        SpecConverter() {
+            super(xstream.getMapper(), xstream.getReflectionProvider());
+        }
+        @Override
+        public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+            return AbstractBrooklynObjectSpec.class.isAssignableFrom(type);
+        }
+        @Override
+        public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
+            if (source == null) return;
+            AbstractBrooklynObjectSpec<?, ?> spec = (AbstractBrooklynObjectSpec<?, ?>) source;
+            String catalogItemId = spec.getCatalogItemId();
+            if (Strings.isNonBlank(catalogItemId)) {
+                // write this field first, so we can peek at it when we read
+                writer.startNode("catalogItemId");
+                writer.setValue(catalogItemId);
+                writer.endNode();
+                
+                // we're going to write the catalogItemId field twice :( but that's okay.
+                // better solution would be to have mark/reset on reader so we can peek for such a field;
+                // see comment below
+                super.marshal(source, writer, context);
+            } else {
+                super.marshal(source, writer, context);
+            }
+        }
+        @Override
+        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+            String catalogItemId = null;
+            instantiateNewInstanceSettingCache(reader, context);
+            
+            if (reader instanceof PathTrackingReader) {
+                // have to assume this is first; there is no mark/reset support on these readers
+                // (if there were then it would be easier, we could just look for that child anywhere,
+                // and not need a custom writer!)
+                if ("catalogItemId".equals( ((PathTrackingReader)reader).peekNextChild() )) {
+                    // cache the instance
+                    
+                    reader.moveDown();
+                    catalogItemId = reader.getValue();
+                    reader.moveUp();
+                }
+            }
+            boolean customLoaderSet = false;
+            try {
+                if (Strings.isNonBlank(catalogItemId)) {
+                    if (lookupContext==null) throw new NullPointerException("lookupContext required to load catalog item "+catalogItemId);
+                    CatalogItem<?, ?> cat = CatalogUtils.getCatalogItemOptionalVersion(lookupContext.lookupManagementContext(), catalogItemId);
+                    if (cat==null) throw new NoSuchElementException("catalog item: "+catalogItemId);
+                    BrooklynClassLoadingContext clcNew = CatalogUtils.newClassLoadingContext(lookupContext.lookupManagementContext(), cat);
+                    pushXstreamCustomClassLoader(clcNew);
+                    customLoaderSet = true;
+                }
+                
+                AbstractBrooklynObjectSpec<?, ?> result = (AbstractBrooklynObjectSpec<?, ?>) super.unmarshal(reader, context);
+                // we wrote it twice so this shouldn't be necessary; but if we fix it so we only write once, we'd need this
+                result.catalogItemId(catalogItemId);
+                return result;
+            } finally {
+                instance = null;
+                if (customLoaderSet) {
+                    popXstreamCustomClassLoader();
+                }
+            }
+        }
+
+        Object instance;
+        
+        @Override
+        protected Object instantiateNewInstance(HierarchicalStreamReader reader, UnmarshallingContext context) {
+            // the super calls getAttribute which requires that we have not yet done moveDown,
+            // so we do this earlier and cache it for when we call super.unmarshal
+            if (instance==null)
+                throw new IllegalStateException("Instance should be created and cached");
+            return instance;
+        }
+        protected void instantiateNewInstanceSettingCache(HierarchicalStreamReader reader, UnmarshallingContext context) {
+            instance = super.instantiateNewInstance(reader, context);
+        }
+    }
+    
+    Stack<BrooklynClassLoadingContext> contexts = new Stack<BrooklynClassLoadingContext>();
+    Stack<ClassLoader> cls = new Stack<ClassLoader>();
+    AtomicReference<Thread> xstreamLockOwner = new AtomicReference<Thread>();
+    int lockCount;
     
+    /** Must be accompanied by a corresponding {@link #popXstreamCustomClassLoader()} when finished. */
+    @SuppressWarnings("deprecation")
+    protected void pushXstreamCustomClassLoader(BrooklynClassLoadingContext clcNew) {
+        acquireXstreamLock();
+        BrooklynClassLoadingContext oldClc;
+        if (!contexts.isEmpty()) {
+            oldClc = contexts.peek();
+        } else {
+            // TODO XmlMementoSerializer should take a BCLC instead of a CL
+            oldClc = JavaBrooklynClassLoadingContext.create(lookupContext.lookupManagementContext(), xstream.getClassLoader());
+        }
+        BrooklynClassLoadingContextSequential clcMerged = new BrooklynClassLoadingContextSequential(lookupContext.lookupManagementContext(),
+            oldClc, clcNew);
+        contexts.push(clcMerged);
+        cls.push(xstream.getClassLoader());
+        ClassLoader newCL = ClassLoaderFromBrooklynClassLoadingContext.of(clcMerged);
+        xstream.setClassLoader(newCL);
+    }
+
+    protected void popXstreamCustomClassLoader() {
+        synchronized (xstreamLockOwner) {
+            releaseXstreamLock();
+            xstream.setClassLoader(cls.pop());
+            contexts.pop();
+        }
+    }
+    
+    protected void acquireXstreamLock() {
+        synchronized (xstreamLockOwner) {
+            while (true) {
+                if (xstreamLockOwner.compareAndSet(null, Thread.currentThread()) || 
+                    Thread.currentThread().equals( xstreamLockOwner.get() )) {
+                    break;
+                }
+                try {
+                    xstreamLockOwner.wait(1000);
+                } catch (InterruptedException e) {
+                    throw Exceptions.propagate(e);
+                }
+            }
+            lockCount++;
+        }
+    }
+
+    protected void releaseXstreamLock() {
+        synchronized (xstreamLockOwner) {
+            if (lockCount<=0) {
+                throw new IllegalStateException("xstream not locked");
+            }
+            if (--lockCount == 0) {
+                if (!xstreamLockOwner.compareAndSet(Thread.currentThread(), null)) {
+                    Thread oldOwner = xstreamLockOwner.getAndSet(null);
+                    throw new IllegalStateException("xstream was locked by "+oldOwner+" but unlock attempt by "+Thread.currentThread());
+                }
+            }
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0dc533d1/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
index e0b4f4e..6083134 100644
--- a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
@@ -37,17 +37,22 @@ import brooklyn.basic.BrooklynObject;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.internal.CatalogItemBuilder;
 import brooklyn.catalog.internal.CatalogItemDtoAbstract;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.Entity;
 import brooklyn.entity.Feed;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.group.DynamicCluster;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.BrooklynObjectType;
 import brooklyn.location.Location;
 import brooklyn.location.LocationSpec;
 import brooklyn.management.ManagementContext;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
 import brooklyn.mementos.BrooklynMementoPersister.LookupContext;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.Policy;
+import brooklyn.test.entity.LocalManagementContextForTests;
 import brooklyn.test.entity.TestApplication;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.util.collections.MutableList;
@@ -129,6 +134,12 @@ public class XmlMementoSerializerTest {
     }
 
     @Test
+    public void testClass() throws Exception {
+        Class<?> t = XmlMementoSerializer.class;
+        assertSerializeAndDeserialize(t);
+    }
+
+    @Test
     public void testEntity() throws Exception {
         final TestApplication app = TestApplication.Factory.newManagedInstanceForTests();
         ManagementContext managementContext = app.getManagementContext();
@@ -180,6 +191,27 @@ public class XmlMementoSerializerTest {
     }
 
     @Test
+    public void testEntitySpec() throws Exception {
+        EntitySpec<?> obj = EntitySpec.create(TestEntity.class);
+        assertSerializeAndDeserialize(obj);
+    }
+    
+    @Test
+    public void testEntitySpecFromOsgi() throws Exception {
+        ManagementContext mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).build();
+        CatalogItem<?, ?> ci = OsgiVersionMoreEntityTest.addMoreEntityV1(mgmt, "1.0");
+        
+        EntitySpec<DynamicCluster> spec = EntitySpec.create(DynamicCluster.class)
+            .configure(DynamicCluster.INITIAL_SIZE, 1)
+            .configure(DynamicCluster.MEMBER_SPEC, CatalogUtils.createEntitySpec(mgmt, ci));
+
+        serializer.setLookupContext(new LookupContextImpl(mgmt,
+            ImmutableList.<Entity>of(), ImmutableList.<Location>of(), ImmutableList.<Policy>of(),
+            ImmutableList.<Enricher>of(), ImmutableList.<Feed>of(), ImmutableList.<CatalogItem<?,?>>of(), true));
+        assertSerializeAndDeserialize(spec);
+    }
+
+    @Test
     public void testImmutableCollectionsWithDanglingEntityRef() throws Exception {
         // If there's a dangling entity in an ImmutableList etc, then discard it entirely.
         // If we try to insert null then it fails, breaking the deserialization of that entire file.


[18/22] incubator-brooklyn git commit: some tests and comments exploring location unmanagement

Posted by he...@apache.org.
some tests and comments exploring location unmanagement

as there is a slow leak around locations, no one unmanages them after use by an entity


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

Branch: refs/heads/master
Commit: 3c97a5774e30be0e9e6b7dfa0fb0613b2cc419e3
Parents: 35142c8
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Feb 9 11:10:10 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Feb 9 11:10:10 2015 +0000

----------------------------------------------------------------------
 .../brooklyn/entity/basic/AbstractEntity.java   |  4 +--
 .../entity/rebind/RebindEntityTest.java         | 27 +++++++++++++++++++-
 .../rebind/RebindLocalhostLocationTest.java     | 22 ++++++++++++++++
 .../entity/rebind/RebindTestFixture.java        | 23 +++++++++++++----
 4 files changed, 68 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3c97a577/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index 215b13a..a004bc0 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -770,10 +770,10 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     public void removeLocations(Collection<? extends Location> removedLocations) {
         synchronized (locations) {
             List<Location> oldLocations = locations.get();
-            Set<Location> truelyRemovedLocations = Sets.intersection(ImmutableSet.copyOf(removedLocations), ImmutableSet.copyOf(oldLocations));
+            Set<Location> trulyRemovedLocations = Sets.intersection(ImmutableSet.copyOf(removedLocations), ImmutableSet.copyOf(oldLocations));
             locations.set(MutableList.<Location>builder().addAll(oldLocations).removeAll(removedLocations).buildImmutable());
             
-            for (Location loc : truelyRemovedLocations) {
+            for (Location loc : trulyRemovedLocations) {
                 emit(AbstractEntity.LOCATION_REMOVED, loc);
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3c97a577/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
index ab55346..9b1e05d 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
@@ -62,9 +62,11 @@ import brooklyn.event.basic.BasicSensorEvent;
 import brooklyn.event.basic.DependentConfiguration;
 import brooklyn.event.basic.Sensors;
 import brooklyn.location.Location;
+import brooklyn.location.LocationSpec;
 import brooklyn.location.basic.LocationConfigTest.MyLocation;
 import brooklyn.management.ha.ManagementNodeState;
 import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.mementos.BrooklynMementoManifest;
 import brooklyn.mementos.EntityMemento;
 import brooklyn.test.Asserts;
 import brooklyn.test.entity.TestApplication;
@@ -181,7 +183,30 @@ public class RebindEntityTest extends RebindTestFixtureWithApp {
         MyEntity newE = (MyEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(MyEntity.class));
         assertEquals(newE.getAttribute(myCustomAttribute), "myval");
     }
-    
+
+    @Test
+    public void testRestoresEntityLocationAndCleansUp() throws Exception {
+        MyLocation loc = origManagementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class));
+        origApp.createAndManageChild(EntitySpec.create(MyEntity.class).location(loc));
+        
+        newApp = rebind();
+        MyEntity newE = (MyEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(MyEntity.class));
+        
+        Assert.assertEquals(newE.getLocations().size(), 1); 
+        Location loc2 = Iterables.getOnlyElement(newE.getLocations());
+        Assert.assertEquals(loc, loc2);
+        Assert.assertFalse(loc==loc2);
+        
+        newApp.stop();
+        // TODO how to trigger automatic unmanagement? see notes in RebindLocalhostLocationTest
+        newManagementContext.getLocationManager().unmanage(loc2);
+        switchOriginalToNewManagementContext();
+        RebindTestUtils.waitForPersisted(origManagementContext);
+        
+        BrooklynMementoManifest mf = loadMementoManifest();
+        Assert.assertTrue(mf.getLocationIdToType().isEmpty(), "Expected no locations; had "+mf.getLocationIdToType());
+    }
+
     @Test
     public void testRestoresEntityIdAndDisplayName() throws Exception {
         MyEntity origE = origApp.createAndManageChild(EntitySpec.create(MyEntity.class)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3c97a577/core/src/test/java/brooklyn/entity/rebind/RebindLocalhostLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindLocalhostLocationTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindLocalhostLocationTest.java
index 16fc7fc..00e88d7 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindLocalhostLocationTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindLocalhostLocationTest.java
@@ -24,12 +24,14 @@ import java.util.Collections;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import brooklyn.location.LocationSpec;
 import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
 import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.mementos.BrooklynMementoManifest;
 import brooklyn.test.entity.TestApplication;
 
 import com.google.common.collect.ImmutableList;
@@ -79,5 +81,25 @@ public class RebindLocalhostLocationTest extends RebindTestFixtureWithApp {
         SshMachineLocation newChildLoc = (SshMachineLocation) Iterables.get(newLoc.getChildren(), 0);
         assertEquals(newChildLoc.execScript(Collections.<String,Object>emptyMap(), "mysummary", ImmutableList.of("true")), 0);
     }
+
+    @Test(groups="Integration")
+    public void testMachineCleansUp() throws Exception {
+        testMachineUsableAfterRebind();
+        newApp.stop();
+
+        switchOriginalToNewManagementContext();
+        
+        // TODO how should we automatically unmanage these?
+        // (in this test, locations are created manually, so probably should be destroyed manually, 
+        // but in most cases we should probably unmanage the location as part of the entity;
+        // could keep the entity ID only in the location, then safely reverse-check usages?)
+        // see related non-integration test in RebindEntityTest
+        origManagementContext.getLocationManager().unmanage(origLoc);
+        
+        RebindTestUtils.waitForPersisted(origManagementContext);
+        
+        BrooklynMementoManifest mf = loadMementoManifest();
+        Assert.assertTrue(mf.getLocationIdToType().isEmpty(), "Expected no locations; had "+mf.getLocationIdToType());
+    }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3c97a577/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
index 39004f6..8f1c1c6 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
@@ -107,7 +107,7 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
     protected void switchOriginalToNewManagementContext() {
         origManagementContext.getRebindManager().stopPersistence();
         for (Application e: origManagementContext.getApplications()) ((Startable)e).stop();
-        waitForTaskCountToBecome(origManagementContext, 0);
+        waitForTaskCountToBecome(origManagementContext, 0, true);
         origManagementContext.terminate();
         origManagementContext = (LocalManagementContext) newManagementContext;
         origApp = newApp;
@@ -116,19 +116,32 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
     }
 
     public static void waitForTaskCountToBecome(final ManagementContext mgmt, final int allowedMax) {
+        waitForTaskCountToBecome(mgmt, allowedMax, false);
+    }
+    
+    public static void waitForTaskCountToBecome(final ManagementContext mgmt, final int allowedMax, final boolean skipKnownBackgroundTasks) {
         Repeater.create().every(Duration.millis(20)).limitTimeTo(Duration.TEN_SECONDS).until(new Callable<Boolean>() {
             @Override
             public Boolean call() throws Exception {
                 ((LocalManagementContext)mgmt).getGarbageCollector().gcIteration();
                 long taskCountAfterAtOld = ((BasicExecutionManager)mgmt.getExecutionManager()).getNumIncompleteTasks();
                 List<Task<?>> tasks = ((BasicExecutionManager)mgmt.getExecutionManager()).getAllTasks();
-                int unendedTasks = 0;
+                int unendedTasks = 0, extraAllowedMax = 0;
                 for (Task<?> t: tasks) {
-                    if (!t.isDone()) unendedTasks++;
+                    if (!t.isDone()) {
+                        if (skipKnownBackgroundTasks) {
+                            if (t.toString().indexOf("ssh-location cache cleaner")>=0) {
+                                extraAllowedMax++;
+                            }
+                        }
+                        unendedTasks++;
+                    }
                 }
-                LOG.info("Count of incomplete tasks now "+taskCountAfterAtOld+", "+unendedTasks+" unended; tasks remembered are: "+
+                LOG.info("Count of incomplete tasks now "+taskCountAfterAtOld+", "+unendedTasks+" unended"
+                    + (extraAllowedMax>0 ? " ("+extraAllowedMax+" allowed)" : "")
+                    + "; tasks remembered are: "+
                     tasks);
-                return taskCountAfterAtOld<=allowedMax;
+                return taskCountAfterAtOld<=allowedMax+extraAllowedMax;
             }
         }).runRequiringTrue();
     }


[09/22] incubator-brooklyn git commit: Partial rebind - add test and refactor / tidy of new code

Posted by he...@apache.org.
Partial rebind - add test and refactor / tidy of new code


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

Branch: refs/heads/master
Commit: be6fd97ec5b318af02a7b5d663a9c7fe1b365c05
Parents: 3f7d750
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Feb 4 12:33:22 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:13 2015 +0000

----------------------------------------------------------------------
 .../entity/proxying/EntityProxyImpl.java        |   2 +-
 .../rebind/InitialFullRebindIteration.java      |   4 +-
 .../brooklyn/entity/rebind/RebindIteration.java |  51 +-------
 .../ha/HighAvailabilityManagerImpl.java         |   4 +-
 .../internal/BrooklynObjectManagementMode.java  |  30 +++++
 .../internal/BrooklynObjectManagerInternal.java |   1 -
 .../management/internal/LocalEntityManager.java |   2 -
 .../internal/LocalLocationManager.java          |   2 -
 .../internal/ManagementTransitionInfo.java      | 110 -----------------
 .../internal/ManagementTransitionMode.java      | 121 +++++++++++++++++++
 .../internal/NonDeploymentEntityManager.java    |   1 -
 .../internal/NonDeploymentLocationManager.java  |   1 -
 .../entity/rebind/ActivePartialRebindTest.java  |  84 +++++++++++++
 .../rebind/RebindOnlySomeEntitiesTest.java      |  44 -------
 .../brooklyn/util/exceptions/Exceptions.java    |   8 +-
 15 files changed, 250 insertions(+), 215 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java b/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
index 611eba3..7e5b009 100644
--- a/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
+++ b/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
@@ -44,7 +44,7 @@ import brooklyn.management.ManagementContext;
 import brooklyn.management.TaskAdaptable;
 import brooklyn.management.internal.EffectorUtils;
 import brooklyn.management.internal.EntityManagerInternal;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
+import brooklyn.management.internal.ManagementTransitionMode;
 import brooklyn.util.config.ConfigBag;
 import brooklyn.util.task.DynamicTasks;
 import brooklyn.util.task.TaskTags;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
index e416bbc..b045873 100644
--- a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
@@ -30,10 +30,10 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
 import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.management.internal.BrooklynObjectManagementMode;
 import brooklyn.management.internal.EntityManagerInternal;
 import brooklyn.management.internal.LocationManagerInternal;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
-import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
+import brooklyn.management.internal.ManagementTransitionMode;
 import brooklyn.mementos.BrooklynMementoPersister;
 import brooklyn.util.text.Strings;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index d786571..fd4fded 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -63,12 +63,12 @@ import brooklyn.location.basic.AbstractLocation;
 import brooklyn.location.basic.LocationInternal;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
 import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.management.internal.BrooklynObjectManagementMode;
 import brooklyn.management.internal.BrooklynObjectManagerInternal;
 import brooklyn.management.internal.EntityManagerInternal;
 import brooklyn.management.internal.LocationManagerInternal;
 import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
-import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
+import brooklyn.management.internal.ManagementTransitionMode;
 import brooklyn.mementos.BrooklynMemento;
 import brooklyn.mementos.BrooklynMementoManifest;
 import brooklyn.mementos.BrooklynMementoManifest.EntityMementoManifest;
@@ -652,29 +652,16 @@ public abstract class RebindIteration {
     private <T extends BrooklynObject> ManagementTransitionMode updateTransitionMode(BrooklynObjectManagerInternal<T> boManager, T bo) {
         ManagementTransitionMode oldTransitionMode = boManager.getLastManagementTransitionMode(bo.getId());
         
-//        boManager.setManagementTransitionMode(bo, 
-//            RebindManagerImpl.computeMode(managementContext, bo, oldMode, rebindContext.isReadOnly(bo), isRebindingActiveAgain()) );
-
-//        isRebindingActiveAgain();
-        
-        ManagementTransitionMode newTransitionMode;
         Boolean isNowReadOnly = rebindContext.isReadOnly(bo);
         BrooklynObjectManagementMode modeBefore, modeAfter; 
         if (oldTransitionMode==null) {
             modeBefore = BrooklynObjectManagementMode.UNMANAGED_PERSISTED;
-//            // not previously known
-//            if (Boolean.TRUE.equals(isNowReadOnly)) {
-//                newMode = ManagementTransitionMode.REBINDING_READONLY;
-//            } else {
-//                // TODO is this needed?
-//                return ManagementTransitionMode.REBINDING_CREATING;
-//            }
         } else {
             modeBefore = oldTransitionMode.getModeAfter();
         }
 
         if (isRebindingActiveAgain()) {
-            Preconditions.checkState(!Boolean.FALSE.equals(isNowReadOnly));
+            Preconditions.checkState(!Boolean.TRUE.equals(isNowReadOnly));
             Preconditions.checkState(modeBefore==BrooklynObjectManagementMode.MANAGED_PRIMARY);
             modeAfter = BrooklynObjectManagementMode.MANAGED_PRIMARY;
         } else if (isNowReadOnly) {
@@ -682,37 +669,9 @@ public abstract class RebindIteration {
         } else {
             modeAfter = BrooklynObjectManagementMode.MANAGED_PRIMARY;
         }
-        newTransitionMode = ManagementTransitionMode.transitioning(modeBefore, modeAfter);
-
-        boManager.setManagementTransitionMode(bo, newTransitionMode);
-
-        // XXX old logic, from RebindManagerImpl.computeMode, for reference:
-//          if (wasReadOnly==null) {
-//              // not known
-//              if (Boolean.TRUE.equals(isNowReadOnly)) return ManagementTransitionMode.REBINDING_READONLY;
-//              else {
-//                  // TODO is this needed?
-//                  return ManagementTransitionMode.REBINDING_CREATING;
-//              }
-//          } else {
-//              if (isRebindingActiveAgain) {
-//                  if (wasReadOnly || isNowReadOnly)
-//                      throw new IllegalStateException("Cannot be rebinding again to something where read-only before/after is "+wasReadOnly+"/"+isNowReadOnly);
-//                  return ManagementTransitionMode.REBINDING_ACTIVE_AGAIN;
-//              } else if (wasReadOnly && isNowReadOnly)
-//                  return ManagementTransitionMode.REBINDING_READONLY;
-//              else if (wasReadOnly)
-//                  return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY;
-//              else if (isNowReadOnly)
-//                  return ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY;
-//              else {
-//                  if (isRebindingActiveAgain)
-//                  // for the most part we handle this correctly, although there may be leaks; see HighAvailabilityManagerInMemoryTest.testLocationsStillManagedCorrectlyAfterDoublePromotion
-//                  LOG.warn("Node "+(mgmt!=null ? mgmt.getManagementNodeId() : null)+" rebinding as master when already master (discouraged, may have stale references); for: "+item);
-//                  return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY;
-//              }
-//          }
         
+        ManagementTransitionMode newTransitionMode = ManagementTransitionMode.transitioning(modeBefore, modeAfter);
+        boManager.setManagementTransitionMode(bo, newTransitionMode);
         return oldTransitionMode;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
index bf8c390..bc5c398 100644
--- a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
@@ -54,11 +54,11 @@ import brooklyn.location.Location;
 import brooklyn.management.Task;
 import brooklyn.management.ha.BasicMasterChooser.AlphabeticMasterChooser;
 import brooklyn.management.ha.ManagementPlaneSyncRecordPersister.Delta;
+import brooklyn.management.internal.BrooklynObjectManagementMode;
 import brooklyn.management.internal.LocalEntityManager;
 import brooklyn.management.internal.LocationManagerInternal;
 import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
-import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
+import brooklyn.management.internal.ManagementTransitionMode;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
new file mode 100644
index 0000000..a005c2d
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.management.internal;
+
+public enum BrooklynObjectManagementMode {
+    /** item does not exist, not in memory, nor persisted (e.g. creating for first time, or finally destroying) */
+    NONEXISTENT, 
+    /** item exists or existed elsewhere, i.e. there is persisted state, but is not loaded here */
+    UNMANAGED_PERSISTED, 
+    /** item is loaded but read-only (ie not actively managed here) */
+    LOADED_READ_ONLY, 
+    /** item is actively managed here */
+    MANAGED_PRIMARY 
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
index 912e84b..93045be 100644
--- a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
+++ b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
@@ -19,7 +19,6 @@
 package brooklyn.management.internal;
 
 import brooklyn.basic.BrooklynObject;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
 
 public interface BrooklynObjectManagerInternal<T extends BrooklynObject> {
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
index aada104..3e9e4c0 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
@@ -54,8 +54,6 @@ import brooklyn.entity.trait.Startable;
 import brooklyn.internal.storage.BrooklynStorage;
 import brooklyn.management.AccessController;
 import brooklyn.management.Task;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
-import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.policy.Policy;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java b/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
index fec09f4..cc44bf8 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
@@ -42,8 +42,6 @@ import brooklyn.location.basic.AbstractLocation;
 import brooklyn.location.basic.LocationInternal;
 import brooklyn.management.AccessController;
 import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
-import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
 import brooklyn.util.config.ConfigBag;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.exceptions.RuntimeInterruptedException;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
index 6ce714a..550c977 100644
--- a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
+++ b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
@@ -20,121 +20,11 @@ package brooklyn.management.internal;
 
 import brooklyn.management.ManagementContext;
 
-import com.google.common.base.Preconditions;
-
 public class ManagementTransitionInfo {
 
     final ManagementContext mgmtContext;
     final ManagementTransitionMode mode;
     
-    public enum BrooklynObjectManagementMode {
-        /** item does not exist, not in memory, nor persisted (e.g. creating for first time, or finally destroying) */
-        NONEXISTENT, 
-        /** item exists or existed elsewhere, i.e. there is persisted state, but is not loaded here */
-        UNMANAGED_PERSISTED, 
-        
-        @Deprecated /** @deprecated marking places where we aren't sure */
-        /** either nonexistent or persisted by unmanaged */
-        ITEM_UNKNOWN, 
-        
-        /** item is loaded but read-only (ie not actively managed here) */
-        LOADED_READ_ONLY, 
-        /** item is actively managed here */
-        MANAGED_PRIMARY 
-    }
-    
-    public static class ManagementTransitionMode {
-
-        // XXX
-//-        CREATING(false, false, false),
-//-        DESTROYING(false, false, false),
-//-        REBINDING_READONLY(true, true, true),
-//-        REBINDING_NO_LONGER_PRIMARY(false, true, true), 
-//-        REBINDING_BECOMING_PRIMARY(true, false, true),
-//-        REBINDING_DESTROYED(true, true, true),
-//-        REBINDING_CREATING(false, false, true);
-//-        
-//-        private final boolean wasReadOnly;
-//-        private final boolean isReadOnly;
-//-        private final boolean isRebinding;
-
-//        /** Item is being created fresh, for the first time */ 
-//        CREATING(NONEXISTENT, MANAGED_PRIMARY),
-//        /** Item is being destroyed / stopping permanently */ 
-//        DESTROYING(MANAGED_PRIMARY, NONEXISTENT),
-//        
-//        /** Item is being mirrored (refreshed or created) here from a serialized/specified state */
-//        REBINDING_READONLY(LOADED_READ_ONLY, LOADED_READ_ONLY),
-//        /** Item management is stopping here, going elsewhere */
-//        REBINDING_NO_LONGER_PRIMARY(MANAGED_PRIMARY, LOADED_READ_ONLY), 
-//        /** Item management is starting here, having previously been running elsewhere */
-//        REBINDING_BECOMING_PRIMARY(LOADED_READ_ONLY, MANAGED_PRIMARY),
-//        /** Item has been managed here, and is being re-read for management again (e.g. applying a transform) */
-//        REBINDING_ACTIVE_AGAIN(MANAGED_PRIMARY, MANAGED_PRIMARY),
-//        /** Item was being mirrored but has now been destroyed  */
-//        REBINDING_DESTROYED(LOADED_READ_ONLY, NONEXISTENT),
-//
-//        /** Item management is starting here, from persisted state */
-//        REBINDING_CREATING(NodeManagementMode.UNMANAGED_PERSISTED, NodeManagementMode.MANAGED_PRIMARY);
-        
-//        private final static ManagementTransitionTargetMode NONE = ManagementTransitionTargetMode.NONE;
-        private final BrooklynObjectManagementMode modeBefore, modeAfter;
-
-        private ManagementTransitionMode(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
-            this.modeBefore = modeBefore;
-            this.modeAfter = modeAfter;
-        }
-        
-        public static ManagementTransitionMode transitioning(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
-            return new ManagementTransitionMode(Preconditions.checkNotNull(modeBefore, "modeBefore"), Preconditions.checkNotNull(modeAfter, "modeAfter"));
-        }
-
-        @Deprecated /** @deprecated marking places where we aren't sure */
-        public static ManagementTransitionMode guessing(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
-            return transitioning(modeBefore, modeAfter);
-        }
-
-        public BrooklynObjectManagementMode getModeBefore() {
-            return modeBefore;
-        }
-        
-        public BrooklynObjectManagementMode getModeAfter() {
-            return modeAfter;
-        }
-        
-        public boolean wasNotLoaded() {
-            return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT || getModeBefore()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED || getModeBefore()==BrooklynObjectManagementMode.ITEM_UNKNOWN;
-        }
-
-        public boolean isNoLongerLoaded() {
-            return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT || getModeAfter()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED || getModeAfter()==BrooklynObjectManagementMode.ITEM_UNKNOWN;
-        }
-
-        public boolean wasPrimary() {
-            return getModeBefore()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
-        }
-        
-        public boolean isPrimary() {
-            return getModeAfter()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
-        }
-
-        public boolean wasReadOnly() {
-            return getModeBefore()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
-        }
-        
-        public boolean isReadOnly() {
-            return getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
-        }
-
-        public boolean isDestroying() {
-            return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT;
-        }
-
-        public boolean isCreating() {
-            return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT;
-        }
-    }
-    
     public ManagementTransitionInfo(ManagementContext mgmtContext, ManagementTransitionMode mode) {
         this.mgmtContext = mgmtContext;
         this.mode = mode;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java b/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
new file mode 100644
index 0000000..3c630e1
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.management.internal;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class ManagementTransitionMode {
+
+    private static final Logger log = LoggerFactory.getLogger(ManagementTransitionMode.class);
+    
+    private final BrooklynObjectManagementMode modeBefore, modeAfter;
+
+    private ManagementTransitionMode(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+        this.modeBefore = modeBefore;
+        this.modeAfter = modeAfter;
+    }
+    
+    public static ManagementTransitionMode transitioning(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+        return new ManagementTransitionMode(Preconditions.checkNotNull(modeBefore, "modeBefore"), Preconditions.checkNotNull(modeAfter, "modeAfter"));
+    }
+
+    @Deprecated /** @deprecated marking places where we aren't sure */
+    public static ManagementTransitionMode guessing(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+        return transitioning(modeBefore, modeAfter);
+    }
+
+    /** @return the mode this object was previously managed as */
+    public BrooklynObjectManagementMode getModeBefore() {
+        return modeBefore;
+    }
+    
+    /** @return the mode this object is now being managed as */
+    public BrooklynObjectManagementMode getModeAfter() {
+        return modeAfter;
+    }
+    
+    /** This management node was previously not loaded here, 
+     * either it did not exist (and is just being created) or it was in persisted state but
+     * not loaded at this node. */
+    public boolean wasNotLoaded() {
+        return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT || getModeBefore()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED;
+    }
+
+    /** This management node is now not going to be loaded here, either it is being destroyed
+     * (not known anywhere, not even persisted) or simply forgotten here */
+    public boolean isNoLongerLoaded() {
+        return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT || getModeAfter()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED;
+    }
+
+    /** This management node was the master for the given object */
+    public boolean wasPrimary() {
+        return getModeBefore()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
+    }
+
+    /** This management node is now the master for the given object */
+    public boolean isPrimary() {
+        return getModeAfter()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
+    }
+
+    /** Object was previously loaded as read-only at this management node;
+     * active management was occurring elsewhere (or not at all)
+     */
+    public boolean wasReadOnly() {
+        return getModeBefore()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
+    }
+    
+    /** Object is now being loaded as read-only at this management node;
+     * expect active management to be occurring elsewhere
+     */
+    public boolean isReadOnly() {
+        return getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
+    }
+    
+    /** Object is being created:
+     * previously did not exist (not even in persisted state);
+     * implies that we are the active manager creating it,
+     * i.e. {@link #getModeAfter()} should indicate {@link BrooklynObjectManagementMode#MANAGED_PRIMARY}.
+     * (if we're read-only and the manager has just created it, 
+     * {@link #getModeBefore()} should indicate {@link BrooklynObjectManagementMode#UNMANAGED_PERSISTED})
+     */
+    public boolean isCreating() {
+        if (getModeBefore()!=BrooklynObjectManagementMode.NONEXISTENT)
+            return false;
+        
+        if (getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY) {
+            log.warn("isCreating set on RO object; highly irregular!");
+        }
+        return true;
+    }
+
+    /** Object is being destroyed:
+     * either destroyed elsewhere and we're catching up (in read-only mode),
+     * or we've been the active manager and are destroying it */
+    public boolean isDestroying() {
+        return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT;
+    }
+    
+    @Override
+    public String toString() {
+        return ManagementTransitionMode.class.getSimpleName()+"["+getModeBefore()+"->"+getModeAfter()+"]";
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java
index c3720b1..281a3a4 100644
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java
+++ b/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java
@@ -27,7 +27,6 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.proxying.EntityTypeRegistry;
 import brooklyn.management.ManagementContext;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.policy.Policy;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java
index a11d876..31f9670 100644
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java
+++ b/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java
@@ -25,7 +25,6 @@ import java.util.Map;
 import brooklyn.location.Location;
 import brooklyn.location.LocationSpec;
 import brooklyn.management.ManagementContext;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
 
 public class NonDeploymentLocationManager implements LocationManagerInternal {
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
new file mode 100644
index 0000000..52cd3b1
--- /dev/null
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.rebind;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.basic.BrooklynObject;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.text.Strings;
+
+public class ActivePartialRebindTest extends RebindTestFixtureWithApp {
+
+    private static final Logger log = LoggerFactory.getLogger(ActivePartialRebindTest.class);
+    
+    protected void doPartialRebindByObjectById(String ...ids) {
+        RebindManagerImpl rm = (RebindManagerImpl) origManagementContext.getRebindManager();
+        rm.testRebindNodeXXX(ids);        
+    }
+    
+    @Test
+    public void testRebindOneSimple() throws Exception {
+        TestEntity c1 = origApp.addChild(EntitySpec.create(TestEntity.class));
+        Entities.manage(c1);
+        AbstractEntity c1r = Entities.deproxy(c1);
+        
+        doPartialRebindByObjectById(c1.getId());
+        
+        BrooklynObject c2 = origManagementContext.lookup(c1.getId());
+        AbstractEntity c2r = Entities.deproxy((Entity)c2);
+        
+        Assert.assertTrue(c2 == c1, "Proxy instance should be the same: "+c1+" / "+c2);
+        Assert.assertFalse(c2r == c1r, "Real instance should NOT be the same: "+c1r+" / "+c2r);
+    }
+
+    @Test(groups="Integration")
+    public void testRebindCheckingMemoryLeak() throws Exception {
+        TestEntity c1 = origApp.addChild(EntitySpec.create(TestEntity.class));
+        Entities.manage(c1);
+        c1.setConfig(TestEntity.CONF_NAME, Strings.makeRandomId(1000000));
+        
+        gcAndLog("before");
+        long used0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
+        for (int i=0; i<500; i++) {
+            doPartialRebindByObjectById(c1.getId());
+            origManagementContext.getGarbageCollector().gcIteration();
+            gcAndLog("iteration "+i);
+            if (i==5) used0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 
+        }
+        gcAndLog("after");
+        long used1 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
+
+        Assert.assertTrue(used1 - used0 < 5000000, "Expected leak of less than 5M; leak was: from "+Strings.makeJavaSizeString(used0)+" to "+Strings.makeJavaSizeString(used1));
+    }
+
+    private void gcAndLog(String prefix) {
+        origManagementContext.getGarbageCollector().gcIteration();
+        System.gc(); System.gc();
+        log.info(prefix+": "+origManagementContext.getGarbageCollector().getUsageString());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/core/src/test/java/brooklyn/entity/rebind/RebindOnlySomeEntitiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindOnlySomeEntitiesTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindOnlySomeEntitiesTest.java
deleted file mode 100644
index a7b54b7..0000000
--- a/core/src/test/java/brooklyn/entity/rebind/RebindOnlySomeEntitiesTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.rebind;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotSame;
-
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.test.entity.TestEntity;
-
-public class RebindOnlySomeEntitiesTest extends RebindTestFixtureWithApp {
-
-    @Test
-    public void testRebindOnlySomeSimple() throws Exception {
-        TestEntity c1 = origApp.addChild(EntitySpec.create(TestEntity.class));
-        Entities.manage(c1);
-        
-        // XXX
-        newApp = rebind();
-        
-        assertNotSame(newApp, origApp);
-        assertEquals(newApp.getId(), origApp.getId());
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/be6fd97e/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java b/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java
index 10126e3..066ecea 100644
--- a/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java
+++ b/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java
@@ -57,8 +57,10 @@ public class Exceptions {
     private static List<Class<? extends Throwable>> BORING_PREFIX_THROWABLE_EXACT_TYPES = ImmutableList.<Class<? extends Throwable>>of(
         IllegalStateException.class, RuntimeException.class, CompoundRuntimeException.class);
 
-    /** Returns whether this is throwable either known to be boring or to have an unuseful prefix */
+    /** Returns whether this is throwable either known to be boring or to have an unuseful prefix;
+     * null is *not* boring. */
     public static boolean isPrefixBoring(Throwable t) {
+        if (t==null) return false;
         if (isBoring(t))
             return true;
         for (Class<? extends Throwable> type: BORING_PREFIX_THROWABLE_EXACT_TYPES)
@@ -165,7 +167,7 @@ public class Exceptions {
         }
         // if no messages so far (ie we will be the toString) then remove boring prefixes from the message
         Throwable messagesCause = collapsed;
-        while (isPrefixBoring(messagesCause) && Strings.isBlank(message)) {
+        while (messagesCause!=null && isPrefixBoring(messagesCause) && Strings.isBlank(message)) {
             collapseCount++;
             if (Strings.isNonBlank(messagesCause.getMessage())) {
                 message = messagesCause.getMessage();
@@ -178,7 +180,7 @@ public class Exceptions {
         if (collapseCount==0 && !includeAllCausalMessages)
             return source;
         
-        if (collapseCount==0) {
+        if (collapseCount==0 && messagesCause!=null) {
             message = messagesCause.toString();
             messagesCause = messagesCause.getCause();
         }


[08/22] incubator-brooklyn git commit: Partial rebind - test that version has successfully changed

Posted by he...@apache.org.
Partial rebind - test that version has successfully changed


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

Branch: refs/heads/master
Commit: 07aaa8994237c2ef260d1996660b94fd04064b71
Parents: be6fd97
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Feb 5 18:28:29 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:13 2015 +0000

----------------------------------------------------------------------
 .../rebind/ActivePartialRebindIteration.java    | 21 +++--
 .../rebind/InitialFullRebindIteration.java      |  9 +--
 .../brooklyn/entity/rebind/RebindIteration.java |  9 ++-
 .../entity/rebind/RebindManagerImpl.java        | 15 +++-
 .../brooklyn/management/ha/OsgiManager.java     |  4 +-
 .../entity/rebind/ActivePartialRebindTest.java  |  8 +-
 .../rebind/ActivePartialRebindVersionTest.java  | 84 ++++++++++++++++++++
 .../brooklyn/entity/rebind/RebindTestUtils.java |  8 +-
 .../osgi/OsgiVersionMoreEntityTest.java         | 40 ++++++++--
 9 files changed, 160 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
index fdcc810..56c467f 100644
--- a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
@@ -74,7 +74,8 @@ public class ActivePartialRebindIteration extends RebindIteration {
     }
     
     public void applyTransformer(CompoundTransformer transformer) {
-        transformers.add(transformer);
+        if (transformer!=null)
+            transformers.add(transformer);
     }
     
     @Override
@@ -88,10 +89,7 @@ public class ActivePartialRebindIteration extends RebindIteration {
         Builder mementoRawBuilder = BrooklynMementoRawData.builder();
 
         /*
-         * TODO detail...
-         * This unmanages and re-manages. Not sure if that's ideal.
-         * Probably we should try to pause it, or switch to a model
-         * where each entity can be managed by any node.
+         * Unmanagement is done as part of the "manage" call, entity by entity.
          */
 
         objectsToRebindFinal = MutableSet.of();
@@ -107,7 +105,6 @@ public class ActivePartialRebindIteration extends RebindIteration {
             }
         }
         
-        // TODO unmanage? pause?
         // get serialization
         for (BrooklynObject bo: objectsToRebindFinal) {
             Memento m = ((BrooklynObjectInternal)bo).getRebindSupport().getMemento();
@@ -115,13 +112,10 @@ public class ActivePartialRebindIteration extends RebindIteration {
             String mr = ((BrooklynMementoPersisterToObjectStore)p).getMementoSerializer().toString(m);
             mementoRawBuilder.put(BrooklynObjectType.of(bo), bo.getId(), mr);
         }
-
         // then rebuild
         mementoRawData = mementoRawBuilder.build();
-        // TODO see comment in InitialFullRebindIteration
-        mementoManifest = persistenceStoreAccess.loadMementoManifest(mementoRawData, exceptionHandler);
 
-        determineStateFromManifestFiles();
+        preprocessManifestFiles();
 
         // skip this phase, as catalog is not being changed
         // (and we don't want to unload things)
@@ -138,8 +132,11 @@ public class ActivePartialRebindIteration extends RebindIteration {
     }
 
     @Override
-    protected void determineStateFromManifestFiles() {
-        super.determineStateFromManifestFiles();
+    protected void preprocessManifestFiles() throws Exception {
+        for (CompoundTransformer transformer: transformers) {
+            mementoRawData = transformer.transform(mementoRawData);
+        }
+        super.preprocessManifestFiles();
         overwritingMaster = true;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
index b045873..9906f30 100644
--- a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
@@ -78,15 +78,10 @@ public class InitialFullRebindIteration extends RebindIteration {
 
     protected void loadManifestFiles() throws Exception {
         checkEnteringPhase(1);
-        Preconditions.checkState(mementoRawData==null && mementoManifest==null, "Memento data should not yet be set when calling this");
-        
+        Preconditions.checkState(mementoRawData==null, "Memento raw data should not yet be set when calling this");
         mementoRawData = persistenceStoreAccess.loadMementoRawData(exceptionHandler);
         
-        // TODO building the manifests should be part of this class (or parent)
-        // it does not have anything to do with the persistence store!
-        mementoManifest = persistenceStoreAccess.loadMementoManifest(mementoRawData, exceptionHandler);
-
-        determineStateFromManifestFiles();
+        preprocessManifestFiles();
         
         if (mode!=ManagementNodeState.HOT_STANDBY && mode!=ManagementNodeState.HOT_BACKUP) {
             if (!isEmpty) { 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index fd4fded..3582030 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -278,9 +278,16 @@ public abstract class RebindIteration {
             throw new IllegalStateException("Phase mismatch: should be phase "+targetPhase+" but is currently "+phase);
     }
     
-    protected void determineStateFromManifestFiles() {
+    protected void preprocessManifestFiles() throws Exception {
         checkContinuingPhase(1);
 
+        Preconditions.checkState(mementoRawData!=null, "Memento raw data should be set when calling this");
+        Preconditions.checkState(mementoManifest==null, "Memento data should not yet be set when calling this");
+        
+        // TODO building the manifests should be part of this class (or parent)
+        // it does not have anything to do with the persistence store!
+        mementoManifest = persistenceStoreAccess.loadMementoManifest(mementoRawData, exceptionHandler);
+        
         overwritingMaster = false;
         isEmpty = mementoManifest.isEmpty();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 9e30f7e..e6f4aea 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -20,6 +20,7 @@ package brooklyn.entity.rebind;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
@@ -43,6 +44,7 @@ import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
 import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
 import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils.CreateBackupMode;
 import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
+import brooklyn.entity.rebind.transformer.CompoundTransformer;
 import brooklyn.internal.BrooklynFeatureEnablement;
 import brooklyn.management.ExecutionContext;
 import brooklyn.management.Task;
@@ -362,7 +364,8 @@ public class RebindManagerImpl implements RebindManager {
         if (persistenceStoreAccess != null) persistenceStoreAccess.stop(true);
     }
     
-    public void testRebindNodeXXX(String ...objectsToRebindIds) {
+        
+    public void rebindPartialActive(CompoundTransformer transformer, Iterator<BrooklynObject> objectsToRebind) {
         final ClassLoader classLoader = 
             managementContext.getCatalog().getRootClassLoader();
         final RebindExceptionHandler exceptionHandler = 
@@ -378,15 +381,19 @@ public class RebindManagerImpl implements RebindManager {
         ActivePartialRebindIteration iteration = new ActivePartialRebindIteration(this, mode, classLoader, exceptionHandler,
             rebindActive, readOnlyRebindCount, rebindMetrics, persistenceStoreAccess);
 
+        iteration.setObjectIterator(objectsToRebind);
+        iteration.applyTransformer(transformer);
+        iteration.run();
+    }
+    
+    public void rebindPartialActive(CompoundTransformer transformer, String ...objectsToRebindIds) {
         List<BrooklynObject> objectsToRebind = MutableList.of();
         for (String objectId: objectsToRebindIds) {
             BrooklynObject obj = managementContext.lookup(objectId);
             if (obj instanceof Entity) obj = Entities.deproxy((Entity)obj);
             objectsToRebind.add(obj);
         }
-        
-        iteration.setObjectIterator(objectsToRebind.iterator());
-        iteration.run();
+        rebindPartialActive(transformer, objectsToRebind.iterator());
     }
     
     protected ManagementNodeState getRebindMode() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
index a3cbba2..260f5ff 100644
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -32,6 +32,7 @@ import org.osgi.framework.launch.Framework;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.BrooklynVersion;
 import brooklyn.catalog.CatalogItem.CatalogBundle;
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.BrooklynServerPaths;
@@ -215,7 +216,8 @@ public class OsgiManager {
 
                 Throwable cause = e.getCause();
                 if (cause != null && cause.getMessage().contains("Unresolved constraint in bundle")) {
-                    log.warn("Unresolved constraint resolving OSGi bundle "+catalogBundle+" to load "+type+": "+cause.getMessage());
+                    log.warn("Unresolved constraint resolving OSGi bundle "+catalogBundle+" to load "+type+": "+cause.getMessage()+
+                        (BrooklynVersion.isDevelopmentEnvironment() ? " (may be due to IDE / dev env; try a maven build)" : ""));
                     if (log.isDebugEnabled()) log.debug("Trace for OSGi resolution failure", e);
                 }
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
index 52cd3b1..80e13b6 100644
--- a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
@@ -35,9 +35,9 @@ public class ActivePartialRebindTest extends RebindTestFixtureWithApp {
 
     private static final Logger log = LoggerFactory.getLogger(ActivePartialRebindTest.class);
     
-    protected void doPartialRebindByObjectById(String ...ids) {
+    protected void doPartialRebindOfIds(String ...objectsToRebindIds) {
         RebindManagerImpl rm = (RebindManagerImpl) origManagementContext.getRebindManager();
-        rm.testRebindNodeXXX(ids);        
+        rm.rebindPartialActive(null, objectsToRebindIds);        
     }
     
     @Test
@@ -46,7 +46,7 @@ public class ActivePartialRebindTest extends RebindTestFixtureWithApp {
         Entities.manage(c1);
         AbstractEntity c1r = Entities.deproxy(c1);
         
-        doPartialRebindByObjectById(c1.getId());
+        doPartialRebindOfIds(c1.getId());
         
         BrooklynObject c2 = origManagementContext.lookup(c1.getId());
         AbstractEntity c2r = Entities.deproxy((Entity)c2);
@@ -64,7 +64,7 @@ public class ActivePartialRebindTest extends RebindTestFixtureWithApp {
         gcAndLog("before");
         long used0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
         for (int i=0; i<500; i++) {
-            doPartialRebindByObjectById(c1.getId());
+            doPartialRebindOfIds(c1.getId());
             origManagementContext.getGarbageCollector().gcIteration();
             gcAndLog("iteration "+i);
             if (i==5) used0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
new file mode 100644
index 0000000..46c1bb6
--- /dev/null
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.rebind;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.entity.Entity;
+import brooklyn.entity.rebind.transformer.CompoundTransformer;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.osgi.OsgiTestResources;
+import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
+
+public class ActivePartialRebindVersionTest extends RebindTestFixtureWithApp {
+
+    @SuppressWarnings("unused")
+    private static final Logger log = LoggerFactory.getLogger(ActivePartialRebindVersionTest.class);
+    
+    protected LocalManagementContext createOrigManagementContext() {
+        return RebindTestUtils.managementContextBuilder(mementoDir, classLoader)
+                .persistPeriodMillis(getPersistPeriodMillis())
+                .forLive(useLiveManagementContext())
+                .emptyCatalog(useEmptyCatalog())
+                .enableOsgi(true)
+                .buildStarted();
+    }
+    
+    protected void doPartialRebindByObjectById(CompoundTransformer transformer, String ...objectsToRebindIds) {
+        RebindManagerImpl rm = (RebindManagerImpl) origManagementContext.getRebindManager();
+        rm.rebindPartialActive(transformer, objectsToRebindIds);        
+    }
+    
+    @Test
+    public void testSwitchingVersions() throws Exception {
+        CatalogItem<?, ?> catV1 = OsgiVersionMoreEntityTest.addMoreEntityV1(origManagementContext, "1.0");
+        Entity childV1 = OsgiVersionMoreEntityTest.addItemFromCatalog(origManagementContext, origApp, catV1);
+        
+        // v1 says Hi Brooklyn
+        // v2 says HI Brooklyn
+        
+        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(childV1), "Hi BROOKLYN");
+        
+        // simply adding to catalog doesn't change
+        CatalogItem<?, ?> catV2 = OsgiVersionMoreEntityTest.addMoreEntityV2(origManagementContext, "1.1");
+        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(childV1), "Hi BROOKLYN");
+        Entity child2V2 = OsgiVersionMoreEntityTest.addItemFromCatalog(origManagementContext, origApp, catV2);
+        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(child2V2), "HI BROOKLYN");
+        
+        // now transform, with a version change
+        CompoundTransformer transformer = CompoundTransformer.builder().changeCatalogItemId(
+            OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, "1.0",
+            OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, "1.1").build();
+        doPartialRebindByObjectById(transformer, childV1.getId());
+
+        Entity childV2 = origManagementContext.lookup(childV1.getId(), Entity.class);
+        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(childV2), "HI BROOKLYN");
+        
+        // _v1_ child also points to new implementation -- saying HI
+        Assert.assertEquals(OsgiVersionMoreEntityTest.doEffectorCallBrooklyn(childV1), "HI BROOKLYN");
+
+        // in fact they are the same
+        Assert.assertTrue(childV1==childV2, "Expected same instance: "+childV1+" / "+childV2);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
index daafe58..ea901af 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
@@ -145,6 +145,7 @@ public class RebindTestUtils {
         PersistenceObjectStore objectStore;
         Duration persistPeriod = Duration.millis(100);
         boolean forLive;
+        boolean enableOsgi = false;
         boolean emptyCatalog;
         
         ManagementContextBuilder(File mementoDir, ClassLoader classLoader) {
@@ -178,6 +179,11 @@ public class RebindTestUtils {
             return this;
         }
 
+        public ManagementContextBuilder enableOsgi(boolean val) {
+            this.enableOsgi = val;
+            return this;
+        }
+
         public ManagementContextBuilder emptyCatalog() {
             this.emptyCatalog = true;
             return this;
@@ -199,7 +205,7 @@ public class RebindTestUtils {
             if (forLive) {
                 unstarted = new LocalManagementContext(properties);
             } else {
-                unstarted = new LocalManagementContextForTests(properties);
+                unstarted = LocalManagementContextForTests.builder(true).useProperties(properties).disableOsgi(!enableOsgi).build();
             }
             
             objectStore.injectManagementContext(unstarted);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/07aaa899/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
index e8d9860..b4a3511 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
@@ -24,7 +24,6 @@ import java.lang.reflect.InvocationTargetException;
 import java.util.Arrays;
 import java.util.List;
 
-import brooklyn.test.TestResourceUnavailableException;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.launch.Framework;
@@ -44,16 +43,19 @@ import brooklyn.entity.effector.Effectors;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.proxying.InternalEntityFactory;
 import brooklyn.entity.proxying.InternalPolicyFactory;
+import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
 import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.policy.PolicySpec;
+import brooklyn.test.TestResourceUnavailableException;
 import brooklyn.test.entity.LocalManagementContextForTests;
 import brooklyn.test.entity.TestApplication;
 import brooklyn.util.guava.Maybe;
 import brooklyn.util.os.Os;
 import brooklyn.util.osgi.Osgis;
 
+import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
@@ -128,8 +130,12 @@ public class OsgiVersionMoreEntityTest {
     protected CatalogItem<?, ?> addCatalogItemWithTypeAsName(String type, String version, String ...libraries) {
         return addCatalogItemWithNameAndType(type, version, type, libraries);
     }
-    @SuppressWarnings("deprecation")
     protected CatalogItem<?, ?> addCatalogItemWithNameAndType(String symName, String version, String type, String ...libraries) {
+        return addCatalogItemWithNameAndType(mgmt, symName, version, type, libraries);
+    }
+
+    @SuppressWarnings("deprecation")
+    static CatalogItem<?, ?> addCatalogItemWithNameAndType(ManagementContext mgmt, String symName, String version, String type, String ...libraries) {
         CatalogEntityItemDto c1 = newCatalogItemWithNameAndType(symName, version, type, libraries);
         mgmt.getCatalog().addItem(c1);
         CatalogItem<?, ?> c2 = mgmt.getCatalog().getCatalogItem(type, version);
@@ -148,15 +154,20 @@ public class OsgiVersionMoreEntityTest {
         return c1;
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
     protected Entity addItemFromCatalog(CatalogItem<?, ?> c2) {
+        return addItemFromCatalog(mgmt, app, c2);
+    }
+    
+    @Beta
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static Entity addItemFromCatalog(ManagementContext mgmt, TestApplication parent, CatalogItem<?, ?> c2) {
         BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, c2);
         EntitySpec spec = EntitySpec.create( (Class)loader.loadClass(c2.getJavaType()) );
         // not a great test as we set the ID here; but:
         // YAML test will do better;
         // and we can check that downstream items are loaded correctly
         spec.catalogItemId(c2.getId());
-        Entity me = app.createAndManageChild(spec);
+        Entity me = parent.createAndManageChild(spec);
         return me;
     }
 
@@ -188,14 +199,27 @@ public class OsgiVersionMoreEntityTest {
         return me.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), ImmutableMap.of("name", "brooklyn")).getUnchecked();
     }
 
+    public static CatalogItem<?, ?> addMoreEntityV1(ManagementContext mgmt, String versionToRegister) {
+        return addCatalogItemWithNameAndType(mgmt, 
+            OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+            versionToRegister,
+            OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+            BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+    }
+    public static CatalogItem<?, ?> addMoreEntityV2(ManagementContext mgmt, String versionToRegister) {
+        return addCatalogItemWithNameAndType(mgmt,
+            OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+            versionToRegister,
+            OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+            BROOKLYN_TEST_MORE_ENTITIES_V2_URL,
+            BROOKLYN_TEST_OSGI_ENTITIES_URL);
+    }
+    
     @Test
     public void testMoreEntitiesV1() throws Exception {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
 
-        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
-                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
-                TEST_VERSION,
-                BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        CatalogItem<?, ?> c2 = addMoreEntityV1(mgmt, TEST_VERSION);
         
         // test load and instantiate
         Entity me = addItemFromCatalog(c2);


[10/22] incubator-brooklyn git commit: Partial rebind - using new explicit BrooklynObjectManagementMode

Posted by he...@apache.org.
Partial rebind - using new explicit BrooklynObjectManagementMode


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

Branch: refs/heads/master
Commit: 3f7d7508e125d751933dc40914d72441ce27381e
Parents: 0fb0c63
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Feb 3 12:48:22 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:13 2015 +0000

----------------------------------------------------------------------
 .../rebind/InitialFullRebindIteration.java      |   7 +-
 .../brooklyn/entity/rebind/RebindIteration.java |  75 ++++++++++-
 .../entity/rebind/RebindManagerImpl.java        |  44 -------
 .../ha/HighAvailabilityManagerImpl.java         |   8 +-
 .../internal/BrooklynObjectManagerInternal.java |  37 ++++++
 .../internal/EntityManagementSupport.java       |   2 +-
 .../internal/EntityManagerInternal.java         |  15 +--
 .../management/internal/LocalEntityManager.java |  41 +++---
 .../internal/LocalLocationManager.java          |  49 ++++---
 .../internal/LocationManagerInternal.java       |  14 +-
 .../internal/ManagementTransitionInfo.java      | 131 +++++++++++++++----
 11 files changed, 275 insertions(+), 148 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
index 9b08392..e416bbc 100644
--- a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
@@ -33,6 +33,7 @@ import brooklyn.management.ha.ManagementNodeState;
 import brooklyn.management.internal.EntityManagerInternal;
 import brooklyn.management.internal.LocationManagerInternal;
 import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
+import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
 import brooklyn.mementos.BrooklynMementoPersister;
 import brooklyn.util.text.Strings;
 
@@ -113,7 +114,8 @@ public class InitialFullRebindIteration extends RebindIteration {
         if (!oldLocations.isEmpty()) BrooklynLogging.log(LOG, overwritingMaster ? BrooklynLogging.LoggingLevel.WARN : BrooklynLogging.LoggingLevel.DEBUG, 
             "Destroying unused locations on rebind: "+oldLocations);
         for (String oldLocationId: oldLocations) {
-           locationManager.unmanage(locationManager.getLocation(oldLocationId), ManagementTransitionMode.REBINDING_DESTROYED); 
+           locationManager.unmanage(locationManager.getLocation(oldLocationId), ManagementTransitionMode.guessing(
+               BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT)); 
         }
     }
 
@@ -123,7 +125,8 @@ public class InitialFullRebindIteration extends RebindIteration {
         if (!oldEntities.isEmpty()) BrooklynLogging.log(LOG, overwritingMaster ? BrooklynLogging.LoggingLevel.WARN : BrooklynLogging.LoggingLevel.DEBUG, 
             "Destroying unused entities on rebind: "+oldEntities);
         for (String oldEntityId: oldEntities) {
-           entityManager.unmanage(entityManager.getEntity(oldEntityId), ManagementTransitionMode.REBINDING_DESTROYED); 
+           entityManager.unmanage(entityManager.getEntity(oldEntityId), ManagementTransitionMode.guessing(
+               BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index b4288c7..d786571 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -63,10 +63,12 @@ import brooklyn.location.basic.AbstractLocation;
 import brooklyn.location.basic.LocationInternal;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
 import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.management.internal.BrooklynObjectManagerInternal;
 import brooklyn.management.internal.EntityManagerInternal;
 import brooklyn.management.internal.LocationManagerInternal;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
+import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
 import brooklyn.mementos.BrooklynMemento;
 import brooklyn.mementos.BrooklynMementoManifest;
 import brooklyn.mementos.BrooklynMementoManifest.EntityMementoManifest;
@@ -600,8 +602,7 @@ public abstract class RebindIteration {
         LocationManagerInternal locationManager = (LocationManagerInternal)managementContext.getLocationManager();
         Set<String> oldLocations = Sets.newLinkedHashSet(locationManager.getLocationIds());
         for (Location location: rebindContext.getLocations()) {
-            ManagementTransitionMode oldMode = locationManager.getLastManagementTransitionMode(location.getId());
-            locationManager.setManagementTransitionMode(location, RebindManagerImpl.computeMode(managementContext, location, oldMode, rebindContext.isReadOnly(location), isRebindingActiveAgain()) );
+            ManagementTransitionMode oldMode = updateTransitionMode(locationManager, location);
             if (oldMode!=null)
                 oldLocations.remove(location.getId());
         }
@@ -623,8 +624,7 @@ public abstract class RebindIteration {
         EntityManagerInternal entityManager = (EntityManagerInternal)managementContext.getEntityManager();
         Set<String> oldEntities = Sets.newLinkedHashSet(entityManager.getEntityIds());
         for (Entity entity: rebindContext.getEntities()) {
-            ManagementTransitionMode oldMode = entityManager.getLastManagementTransitionMode(entity.getId());
-            entityManager.setManagementTransitionMode(entity, RebindManagerImpl.computeMode(managementContext, entity, oldMode, rebindContext.isReadOnly(entity), isRebindingActiveAgain()) );
+            ManagementTransitionMode oldMode = updateTransitionMode(entityManager, entity);
             if (oldMode!=null)
                 oldEntities.remove(entity.getId());
         }
@@ -649,6 +649,73 @@ public abstract class RebindIteration {
         this.applications = apps;
     }
 
+    private <T extends BrooklynObject> ManagementTransitionMode updateTransitionMode(BrooklynObjectManagerInternal<T> boManager, T bo) {
+        ManagementTransitionMode oldTransitionMode = boManager.getLastManagementTransitionMode(bo.getId());
+        
+//        boManager.setManagementTransitionMode(bo, 
+//            RebindManagerImpl.computeMode(managementContext, bo, oldMode, rebindContext.isReadOnly(bo), isRebindingActiveAgain()) );
+
+//        isRebindingActiveAgain();
+        
+        ManagementTransitionMode newTransitionMode;
+        Boolean isNowReadOnly = rebindContext.isReadOnly(bo);
+        BrooklynObjectManagementMode modeBefore, modeAfter; 
+        if (oldTransitionMode==null) {
+            modeBefore = BrooklynObjectManagementMode.UNMANAGED_PERSISTED;
+//            // not previously known
+//            if (Boolean.TRUE.equals(isNowReadOnly)) {
+//                newMode = ManagementTransitionMode.REBINDING_READONLY;
+//            } else {
+//                // TODO is this needed?
+//                return ManagementTransitionMode.REBINDING_CREATING;
+//            }
+        } else {
+            modeBefore = oldTransitionMode.getModeAfter();
+        }
+
+        if (isRebindingActiveAgain()) {
+            Preconditions.checkState(!Boolean.FALSE.equals(isNowReadOnly));
+            Preconditions.checkState(modeBefore==BrooklynObjectManagementMode.MANAGED_PRIMARY);
+            modeAfter = BrooklynObjectManagementMode.MANAGED_PRIMARY;
+        } else if (isNowReadOnly) {
+            modeAfter = BrooklynObjectManagementMode.LOADED_READ_ONLY;
+        } else {
+            modeAfter = BrooklynObjectManagementMode.MANAGED_PRIMARY;
+        }
+        newTransitionMode = ManagementTransitionMode.transitioning(modeBefore, modeAfter);
+
+        boManager.setManagementTransitionMode(bo, newTransitionMode);
+
+        // XXX old logic, from RebindManagerImpl.computeMode, for reference:
+//          if (wasReadOnly==null) {
+//              // not known
+//              if (Boolean.TRUE.equals(isNowReadOnly)) return ManagementTransitionMode.REBINDING_READONLY;
+//              else {
+//                  // TODO is this needed?
+//                  return ManagementTransitionMode.REBINDING_CREATING;
+//              }
+//          } else {
+//              if (isRebindingActiveAgain) {
+//                  if (wasReadOnly || isNowReadOnly)
+//                      throw new IllegalStateException("Cannot be rebinding again to something where read-only before/after is "+wasReadOnly+"/"+isNowReadOnly);
+//                  return ManagementTransitionMode.REBINDING_ACTIVE_AGAIN;
+//              } else if (wasReadOnly && isNowReadOnly)
+//                  return ManagementTransitionMode.REBINDING_READONLY;
+//              else if (wasReadOnly)
+//                  return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY;
+//              else if (isNowReadOnly)
+//                  return ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY;
+//              else {
+//                  if (isRebindingActiveAgain)
+//                  // for the most part we handle this correctly, although there may be leaks; see HighAvailabilityManagerInMemoryTest.testLocationsStillManagedCorrectlyAfterDoublePromotion
+//                  LOG.warn("Node "+(mgmt!=null ? mgmt.getManagementNodeId() : null)+" rebinding as master when already master (discouraged, may have stale references); for: "+item);
+//                  return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY;
+//              }
+//          }
+        
+        return oldTransitionMode;
+    }
+
     protected abstract boolean isRebindingActiveAgain();
 
     protected Collection<String> getMementoRootEntities() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 608f75c..9e30f7e 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -45,13 +45,11 @@ import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils.CreateBackupMod
 import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
 import brooklyn.internal.BrooklynFeatureEnablement;
 import brooklyn.management.ExecutionContext;
-import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
 import brooklyn.management.ha.HighAvailabilityManagerImpl;
 import brooklyn.management.ha.ManagementNodeState;
 import brooklyn.management.ha.MementoCopyMode;
 import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
 import brooklyn.mementos.BrooklynMementoPersister;
 import brooklyn.mementos.BrooklynMementoRawData;
 import brooklyn.mementos.TreeNode;
@@ -533,48 +531,6 @@ public class RebindManagerImpl implements RebindManager {
         return iteration.getApplications();
     }
 
-    @Deprecated /** @deprecated since 0.7.0, use method with more args */
-    static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, ManagementTransitionMode oldMode, boolean isNowReadOnly) {
-        return computeMode(mgmt, item, oldMode==null ? null : oldMode.wasReadOnly(), isNowReadOnly, false);
-    }
-
-    @Deprecated /** @deprecated since 0.7.0, use method with more args */
-    static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, Boolean wasReadOnly, boolean isNowReadOnly) {
-        return computeMode(mgmt, item, wasReadOnly, isNowReadOnly, false);
-    }
-
-    static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, ManagementTransitionMode oldMode, boolean isNowReadOnly, boolean isRebindingActiveAgain) {
-        return computeMode(mgmt, item, oldMode==null ? null : oldMode.wasReadOnly(), isNowReadOnly, isRebindingActiveAgain);
-    }
-
-    static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, Boolean wasReadOnly, boolean isNowReadOnly, boolean isRebindingActiveAgain) {
-        if (wasReadOnly==null) {
-            // not known
-            if (Boolean.TRUE.equals(isNowReadOnly)) return ManagementTransitionMode.REBINDING_READONLY;
-            else {
-                // TODO is this needed?
-                return ManagementTransitionMode.REBINDING_CREATING;
-            }
-        } else {
-            if (isRebindingActiveAgain) {
-                if (wasReadOnly || isNowReadOnly)
-                    throw new IllegalStateException("Cannot be rebinding again to something where read-only before/after is "+wasReadOnly+"/"+isNowReadOnly);
-                return ManagementTransitionMode.REBINDING_ACTIVE_AGAIN;
-            } else if (wasReadOnly && isNowReadOnly)
-                return ManagementTransitionMode.REBINDING_READONLY;
-            else if (wasReadOnly)
-                return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY;
-            else if (isNowReadOnly)
-                return ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY;
-            else {
-                if (isRebindingActiveAgain)
-                // for the most part we handle this correctly, although there may be leaks; see HighAvailabilityManagerInMemoryTest.testLocationsStillManagedCorrectlyAfterDoublePromotion
-                LOG.warn("Node "+(mgmt!=null ? mgmt.getManagementNodeId() : null)+" rebinding as master when already master (discouraged, may have stale references); for: "+item);
-                return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY;
-            }
-        }
-    }
-
     /**
      * Sorts the map of nodes, so that a node's parent is guaranteed to come before that node
      * (unless the parent is missing).

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
index dda9e19..bf8c390 100644
--- a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
@@ -58,6 +58,7 @@ import brooklyn.management.internal.LocalEntityManager;
 import brooklyn.management.internal.LocationManagerInternal;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
+import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
@@ -499,7 +500,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
             // could perhaps promote standby items on some transitions; but for now we stop the old read-only and re-load them
             // TODO ideally there'd be an incremental rebind as well as an incremental persist
             managementContext.getRebindManager().stopReadOnly();
-            clearManagedItems(ManagementTransitionMode.REBINDING_DESTROYED);
+            clearManagedItems(ManagementTransitionMode.transitioning(BrooklynObjectManagementMode.LOADED_READ_ONLY, BrooklynObjectManagementMode.UNMANAGED_PERSISTED));
         }
     }
 
@@ -841,7 +842,10 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
         }
         boolean wasMaster = (getInternalNodeState() == ManagementNodeState.MASTER);
         if (wasMaster) backupOnDemotionIfNeeded();
-        ManagementTransitionMode mode = (wasMaster ? ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY : ManagementTransitionMode.REBINDING_DESTROYED);
+        // TODO target may be RO ?
+        ManagementTransitionMode mode = ManagementTransitionMode.transitioning(
+            wasMaster ? BrooklynObjectManagementMode.MANAGED_PRIMARY : BrooklynObjectManagementMode.LOADED_READ_ONLY,
+            BrooklynObjectManagementMode.UNMANAGED_PERSISTED);
 
         nodeStateTransitionComplete = false;
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
new file mode 100644
index 0000000..912e84b
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.management.internal;
+
+import brooklyn.basic.BrooklynObject;
+import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
+
+public interface BrooklynObjectManagerInternal<T extends BrooklynObject> {
+
+    ManagementTransitionMode getLastManagementTransitionMode(String itemId);
+    void setManagementTransitionMode(T item, ManagementTransitionMode mode);
+
+    /** 
+     * Begins management for the given rebinded root, recursively; 
+     * if rebinding as a read-only copy, {@link #setReadOnly(T, boolean)} should be called prior to this.
+     */
+    void manageRebindedRoot(T item);
+    
+    void unmanage(final T e, final ManagementTransitionMode info);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java b/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
index fa5de94..4bea56e 100644
--- a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
+++ b/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
@@ -296,7 +296,7 @@ public class EntityManagementSupport {
         // TODO framework stopping events - no more sensors, executions, etc
         // (elaborate or remove ^^^ ? -AH, Sept 2014)
         
-        if (!isReadOnly()) {
+        if (!isReadOnly() && info.getMode().isDestroying()) {
             // if we support remote parent of local child, the following call will need to be properly remoted
             if (entity.getParent()!=null) entity.getParent().removeChild(entity.getProxyIfAvailable());
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java b/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java
index e134b23..d3a619b 100644
--- a/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java
+++ b/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java
@@ -20,26 +20,13 @@ package brooklyn.management.internal;
 
 import brooklyn.entity.Application;
 import brooklyn.entity.Entity;
-import brooklyn.location.Location;
 import brooklyn.management.EntityManager;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
 
-public interface EntityManagerInternal extends EntityManager {
+public interface EntityManagerInternal extends EntityManager, BrooklynObjectManagerInternal<Entity> {
 
     /** gets all entities currently known to the application, including entities that are not yet managed */
     Iterable<Entity> getAllEntitiesInApplication(Application application);
 
     public Iterable<String> getEntityIds();
     
-    ManagementTransitionMode getLastManagementTransitionMode(String itemId);
-    void setManagementTransitionMode(Entity item, ManagementTransitionMode mode);
-
-    /** 
-     * Begins management for the given rebinded root, recursively; 
-     * if rebinding as a read-only copy, {@link #setReadOnly(Location, boolean)} should be called prior to this.
-     */
-    void manageRebindedRoot(Entity item);
-    
-    void unmanage(final Entity e, final ManagementTransitionMode info);
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
index 87d8a3a..aada104 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
@@ -55,6 +55,7 @@ import brooklyn.internal.storage.BrooklynStorage;
 import brooklyn.management.AccessController;
 import brooklyn.management.Task;
 import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
+import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.policy.Policy;
@@ -269,7 +270,7 @@ public class LocalEntityManager implements EntityManagerInternal {
                     new Exception("source of duplicate management of "+e));
             return;
         }
-        manageRecursive(e, ManagementTransitionMode.CREATING);
+        manageRecursive(e, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.NONEXISTENT, BrooklynObjectManagementMode.MANAGED_PRIMARY));
     }
 
     @Override
@@ -306,7 +307,7 @@ public class LocalEntityManager implements EntityManagerInternal {
             }
             
             if (it.getManagementSupport().isDeployed()) {
-                if (mode==ManagementTransitionMode.CREATING) {
+                if (mode.wasNotLoaded()) {
                     // silently bail out
                     return false;
                 } else {
@@ -341,7 +342,7 @@ public class LocalEntityManager implements EntityManagerInternal {
     
     @Override
     public void unmanage(final Entity e) {
-        unmanage(e, ManagementTransitionMode.DESTROYING);
+        unmanage(e, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT));
     }
     
     public void unmanage(final Entity e, final ManagementTransitionMode mode) {
@@ -354,23 +355,23 @@ public class LocalEntityManager implements EntityManagerInternal {
         
         if (hasBeenReplaced) {
             // we are unmanaging an old instance after having replaced it
-            // (called from manage(...)
+            // don't unmanage or even clear its fields, because there might be references to it
             
-            if (mode==ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY) {
-                // when migrating away, these all need to be called
+            if (mode.wasReadOnly()) {
+                // if coming *from* read only; nothing needed
+            } else {
+                if (!mode.wasPrimary()) {
+                    log.warn("Unexpected mode "+mode+" for unmanage-replace "+e+" (applying anyway)");
+                }
+                // migrating away or in-place active partial rebind:
                 ((EntityInternal)e).getManagementSupport().onManagementStopping(info);
                 stopTasks(e);
                 ((EntityInternal)e).getManagementSupport().onManagementStopped(info);
-            } else {
-                // should be coming *from* read only; nothing needed
-                if (!mode.wasReadOnly()) {
-                    log.warn("Should not be unmanaging "+e+" in mode "+mode+"; ignoring");
-                }
             }
             // do not remove from maps below, bail out now
             return;
             
-        } else if (mode==ManagementTransitionMode.REBINDING_DESTROYED) {
+        } else if (mode.wasReadOnly() && mode.isDestroying()) {
             // we are unmanaging an instance (secondary) for which the primary has been destroyed elsewhere
             ((EntityInternal)e).getManagementSupport().onManagementStopping(info);
             unmanageNonRecursive(e);
@@ -379,7 +380,7 @@ public class LocalEntityManager implements EntityManagerInternal {
             managementContext.getRebindManager().getChangeListener().onUnmanaged(e);
             if (managementContext.getGarbageCollector() != null) managementContext.getGarbageCollector().onUnmanaged(e);
             
-        } else if (mode==ManagementTransitionMode.DESTROYING) {
+        } else if (mode.wasPrimary() && mode.isDestroying()) {
             // we are unmanaging an instance either because it is being destroyed (primary), 
             // or due to an explicit call (shutting down all things, read-only and primary);
             // in either case, should be recursive
@@ -545,11 +546,11 @@ public class LocalEntityManager implements EntityManagerInternal {
         Object old = preManagedEntitiesById.put(e.getId(), realE);
         preRegisteredEntitiesById.remove(e.getId());
         
-        if (old!=null && mode==ManagementTransitionMode.CREATING) {
+        if (old!=null && mode.wasNotLoaded()) {
             if (old.equals(e)) {
-                log.warn("{} redundant call to pre-start management of entity {}; ignoring", this, e);
+                log.warn("{} redundant call to pre-start management of entity {}, mode {}; ignoring", new Object[] { this, e, mode });
             } else {
-                throw new IllegalStateException("call to pre-manage entity "+e+" but different entity "+old+" already known under that id at "+this);
+                throw new IllegalStateException("call to pre-manage entity "+e+" ("+mode+") but different entity "+old+" already known under that id at "+this);
             }
             return false;
         } else {
@@ -567,11 +568,11 @@ public class LocalEntityManager implements EntityManagerInternal {
     private synchronized boolean manageNonRecursive(Entity e, ManagementTransitionMode mode) {
         Entity old = entitiesById.get(e.getId());
         
-        if (old!=null && mode==ManagementTransitionMode.CREATING) {
+        if (old!=null && mode.wasNotLoaded()) {
             if (old.equals(e)) {
                 log.warn("{} redundant call to start management of entity {}; ignoring", this, e);
             } else {
-                throw new IllegalStateException("call to manage entity "+e+" but different entity "+old+" already known under that id at "+this);
+                throw new IllegalStateException("call to manage entity "+e+" ("+mode+") but different entity "+old+" already known under that id at "+this);
             }
             return false;
         }
@@ -583,8 +584,8 @@ public class LocalEntityManager implements EntityManagerInternal {
         Entity oldProxy = entityProxiesById.get(e.getId());
         Entity proxyE;
         if (oldProxy!=null) {
-            if (mode==ManagementTransitionMode.CREATING) {
-                throw new IllegalStateException("call to manage entity "+e+" but already had proxy "+oldProxy+" already known under that id at "+this);
+            if (mode.wasNotLoaded()) {
+                throw new IllegalStateException("call to manage entity "+e+" from unloaded state ("+mode+") but already had proxy "+oldProxy+" already known under that id at "+this);
             }
             // make the old proxy point at this new delegate
             // (some other tricks done in the call below)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java b/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
index b873363..fec09f4 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
@@ -43,6 +43,7 @@ import brooklyn.location.basic.LocationInternal;
 import brooklyn.management.AccessController;
 import brooklyn.management.entitlement.Entitlements;
 import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
+import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode;
 import brooklyn.util.config.ConfigBag;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.exceptions.RuntimeInterruptedException;
@@ -194,7 +195,7 @@ public class LocalLocationManager implements LocationManagerInternal {
             log.warn("Parent location "+parent+" of "+loc+" is not managed; attempting to manage it (in future this may be disallowed)");
             return manage(parent);
         } else {
-            return manageRecursive(loc, ManagementTransitionMode.CREATING);
+            return manageRecursive(loc, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.NONEXISTENT, BrooklynObjectManagementMode.MANAGED_PRIMARY));
         }
     }
     
@@ -214,7 +215,7 @@ public class LocalLocationManager implements LocationManagerInternal {
         long count = LOCATION_CNT.incrementAndGet();
         if (log.isDebugEnabled()) {
             String msg = "Managing location " + loc + " ("+initialMode+"), from " + Tasks.current()+" / "+Entitlements.getEntitlementContext();
-            LoggingLevel level = (initialMode==ManagementTransitionMode.REBINDING_READONLY ? LoggingLevel.TRACE : LoggingLevel.DEBUG);
+            LoggingLevel level = (!initialMode.wasNotLoaded() || initialMode.isReadOnly() ? LoggingLevel.TRACE : LoggingLevel.DEBUG);
             if (count % 100 == 0) {
                 // include trace periodically in case we get leaks or too much location management
                 BrooklynLogging.log(log, level,
@@ -231,7 +232,7 @@ public class LocalLocationManager implements LocationManagerInternal {
             }
             
             if (it.isManaged()) {
-                if (mode==ManagementTransitionMode.CREATING) {
+                if (mode.wasNotLoaded()) {
                     // silently bail out
                     return false;
                 } else {
@@ -242,9 +243,9 @@ public class LocalLocationManager implements LocationManagerInternal {
             boolean result = manageNonRecursive(it, mode);
             if (result) {
                 it.setManagementContext(managementContext);
-                if (!mode.isReadOnly()) {
+                if (mode.isPrimary()) {
                     it.onManagementStarted();
-                    if (!mode.wasReadOnly() && !mode.isRebinding()) {
+                    if (mode.isCreating()) {
                         // Never record event on rebind; this isn't the location (e.g. the VM) being "created"
                         // so don't tell listeners that.
                         // TODO The location-event history should be persisted; currently it is lost on
@@ -261,7 +262,7 @@ public class LocalLocationManager implements LocationManagerInternal {
     
     @Override
     public void unmanage(final Location loc) {
-        unmanage(loc, ManagementTransitionMode.DESTROYING);
+        unmanage(loc, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT));
     }
     
     public void unmanage(final Location loc, final ManagementTransitionMode mode) {
@@ -274,26 +275,34 @@ public class LocalLocationManager implements LocationManagerInternal {
         if (hasBeenReplaced) {
             // we are unmanaging an old instance after having replaced it; 
             // don't unmanage or even clear its fields, because there might be references to it
-            if (mode==ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY) {
-                // when migrating away, these all need to be called
+            
+            if (mode.wasReadOnly()) {
+                // if coming *from* read only; nothing needed
+            } else {
+                if (!mode.wasPrimary()) {
+                    log.warn("Unexpected mode "+mode+" for unmanage-replace "+loc+" (applying anyway)");
+                }
+                // migrating away or in-place active partial rebind:
                 managementContext.getRebindManager().getChangeListener().onUnmanaged(loc);
                 if (managementContext.gc != null) managementContext.gc.onUnmanaged(loc);
-            } else {
-                // should be coming *from* read only; nothing needed
-                if (!mode.wasReadOnly())
-                    log.warn("Should not be unmanaging "+loc+" in mode "+mode+"; ignoring");
             }
             // do not remove from maps below, bail out now
             return;
 
-        } else if (mode==ManagementTransitionMode.REBINDING_DESTROYED || mode==ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY) {
+        } else if ((mode.isReadOnly() && mode.wasPrimary()) || (mode.isDestroying() && mode.wasReadOnly())) {
+            if (mode.isReadOnly() && mode.wasPrimary()) {
+                // TODO shouldn't this fall into "hasBeenReplaced" above?
+                log.debug("Unmanaging on demotion: "+loc+" ("+mode+")");
+            }
             // we are unmanaging an instance whose primary management is elsewhere (either we were secondary, or we are being demoted)
             unmanageNonRecursiveRemoveFromRecords(loc, mode);
             managementContext.getRebindManager().getChangeListener().onUnmanaged(loc);
             if (managementContext.gc != null) managementContext.gc.onUnmanaged(loc);
             unmanageNonRecursiveClearItsFields(loc, mode);
+        } else if (mode.isDestroying()) {
+
+            // TODO isUnloading???
             
-        } else if (mode==ManagementTransitionMode.DESTROYING) {
             // we are unmanaging an instance either because it is being destroyed (primary), 
             // or due to an explicit call (shutting down all things, read-only and primary);
             // in either case, should be recursive
@@ -307,11 +316,11 @@ public class LocalLocationManager implements LocationManagerInternal {
                     if (mode==null) {
                         // ad hoc creation e.g. tests
                         log.debug("Missing transition mode for "+it+" when unmanaging; assuming primary/destroying");
-                        mode = ManagementTransitionMode.DESTROYING;
+                        mode = ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT);
                     }
-                    if (!mode.isReadOnly()) it.onManagementStopped();
+                    if (mode.wasPrimary()) it.onManagementStopped();
                     managementContext.getRebindManager().getChangeListener().onUnmanaged(it);
-                    if (!mode.isReadOnly()) recordLocationEvent(it, Lifecycle.DESTROYED);
+                    if (mode.isDestroying()) recordLocationEvent(it, Lifecycle.DESTROYED);
                     if (managementContext.gc != null) managementContext.gc.onUnmanaged(it);
                 }
                 unmanageNonRecursiveClearItsFields(loc, mode);
@@ -319,6 +328,8 @@ public class LocalLocationManager implements LocationManagerInternal {
             } });
             
         } else {
+            // what about to unmanaged_persisted?
+            
             log.warn("Invalid mode for unmanage: "+mode+" on "+loc+" (ignoring)");
         }
         
@@ -367,7 +378,7 @@ public class LocalLocationManager implements LocationManagerInternal {
 
         locationTypes.put(loc.getId(), loc.getClass().getName());
         
-        if (old!=null && mode==ManagementTransitionMode.CREATING) {
+        if (old!=null && mode.wasNotLoaded()) {
             if (old.equals(loc)) {
                 log.warn("{} redundant call to start management of location {}", this, loc);
             } else {
@@ -386,7 +397,7 @@ public class LocalLocationManager implements LocationManagerInternal {
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     private synchronized void unmanageNonRecursiveClearItsFields(Location loc, ManagementTransitionMode mode) {
-        if (mode==ManagementTransitionMode.DESTROYING) {
+        if (mode.isDestroying()) {
             ((AbstractLocation)loc).setParent(null, true);
             
             Location parent = ((AbstractLocation)loc).getParent();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java b/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java
index 96e2ff3..4b0d959 100644
--- a/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java
+++ b/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java
@@ -20,21 +20,9 @@ package brooklyn.management.internal;
 
 import brooklyn.location.Location;
 import brooklyn.management.LocationManager;
-import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
 
-public interface LocationManagerInternal extends LocationManager {
+public interface LocationManagerInternal extends LocationManager, BrooklynObjectManagerInternal<Location> {
 
     public Iterable<String> getLocationIds();
 
-    ManagementTransitionMode getLastManagementTransitionMode(String itemId);
-    void setManagementTransitionMode(Location item, ManagementTransitionMode mode);
-
-    /** 
-     * Begins management for the given rebinded root, recursively; 
-     * if rebinding as a read-only copy, {@link #setReadOnly(Location, boolean)} should be called prior to this.
-     */
-    void manageRebindedRoot(Location item);
-
-    void unmanage(final Location item, final ManagementTransitionMode info);
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
index 6d27fed..6ce714a 100644
--- a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
+++ b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
@@ -20,46 +20,119 @@ package brooklyn.management.internal;
 
 import brooklyn.management.ManagementContext;
 
+import com.google.common.base.Preconditions;
+
 public class ManagementTransitionInfo {
 
     final ManagementContext mgmtContext;
-    
     final ManagementTransitionMode mode;
     
-    /** true if this transition is an entity whose mastering is migrating from one node to another;
-     * false if the brooklyn mgmt plane is just starting managing of this entity for the very first time  
-     */
+    public enum BrooklynObjectManagementMode {
+        /** item does not exist, not in memory, nor persisted (e.g. creating for first time, or finally destroying) */
+        NONEXISTENT, 
+        /** item exists or existed elsewhere, i.e. there is persisted state, but is not loaded here */
+        UNMANAGED_PERSISTED, 
+        
+        @Deprecated /** @deprecated marking places where we aren't sure */
+        /** either nonexistent or persisted by unmanaged */
+        ITEM_UNKNOWN, 
+        
+        /** item is loaded but read-only (ie not actively managed here) */
+        LOADED_READ_ONLY, 
+        /** item is actively managed here */
+        MANAGED_PRIMARY 
+    }
+    
+    public static class ManagementTransitionMode {
 
-    public enum ManagementTransitionMode {
-        /** Item is being created fresh, for the first time */ 
-        CREATING(false, false, false),
-        /** Item is being destroyed / stopping permanently */ 
-        DESTROYING(false, false, false),
+        // XXX
+//-        CREATING(false, false, false),
+//-        DESTROYING(false, false, false),
+//-        REBINDING_READONLY(true, true, true),
+//-        REBINDING_NO_LONGER_PRIMARY(false, true, true), 
+//-        REBINDING_BECOMING_PRIMARY(true, false, true),
+//-        REBINDING_DESTROYED(true, true, true),
+//-        REBINDING_CREATING(false, false, true);
+//-        
+//-        private final boolean wasReadOnly;
+//-        private final boolean isReadOnly;
+//-        private final boolean isRebinding;
+
+//        /** Item is being created fresh, for the first time */ 
+//        CREATING(NONEXISTENT, MANAGED_PRIMARY),
+//        /** Item is being destroyed / stopping permanently */ 
+//        DESTROYING(MANAGED_PRIMARY, NONEXISTENT),
+//        
+//        /** Item is being mirrored (refreshed or created) here from a serialized/specified state */
+//        REBINDING_READONLY(LOADED_READ_ONLY, LOADED_READ_ONLY),
+//        /** Item management is stopping here, going elsewhere */
+//        REBINDING_NO_LONGER_PRIMARY(MANAGED_PRIMARY, LOADED_READ_ONLY), 
+//        /** Item management is starting here, having previously been running elsewhere */
+//        REBINDING_BECOMING_PRIMARY(LOADED_READ_ONLY, MANAGED_PRIMARY),
+//        /** Item has been managed here, and is being re-read for management again (e.g. applying a transform) */
+//        REBINDING_ACTIVE_AGAIN(MANAGED_PRIMARY, MANAGED_PRIMARY),
+//        /** Item was being mirrored but has now been destroyed  */
+//        REBINDING_DESTROYED(LOADED_READ_ONLY, NONEXISTENT),
+//
+//        /** Item management is starting here, from persisted state */
+//        REBINDING_CREATING(NodeManagementMode.UNMANAGED_PERSISTED, NodeManagementMode.MANAGED_PRIMARY);
         
-        /** Item is being mirrored (or refreshed) here from a serialized/specified state */
-        REBINDING_READONLY(true, true, true),
-        /** Item management is stopping here, going elsewhere */
-        REBINDING_NO_LONGER_PRIMARY(false, true, true), 
-        /** Item management is starting here, having previously been running elsewhere */
-        REBINDING_BECOMING_PRIMARY(true, false, true),
-        /** Item was being mirrored but has now been destroyed  */
-        REBINDING_DESTROYED(true, true, true),
-        /** Item management is starting here, where not sure what previous running state was */
-        REBINDING_CREATING(false, false, true);
+//        private final static ManagementTransitionTargetMode NONE = ManagementTransitionTargetMode.NONE;
+        private final BrooklynObjectManagementMode modeBefore, modeAfter;
+
+        private ManagementTransitionMode(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+            this.modeBefore = modeBefore;
+            this.modeAfter = modeAfter;
+        }
         
-        private final boolean wasReadOnly;
-        private final boolean isReadOnly;
-        private final boolean isRebinding;
+        public static ManagementTransitionMode transitioning(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+            return new ManagementTransitionMode(Preconditions.checkNotNull(modeBefore, "modeBefore"), Preconditions.checkNotNull(modeAfter, "modeAfter"));
+        }
+
+        @Deprecated /** @deprecated marking places where we aren't sure */
+        public static ManagementTransitionMode guessing(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+            return transitioning(modeBefore, modeAfter);
+        }
+
+        public BrooklynObjectManagementMode getModeBefore() {
+            return modeBefore;
+        }
         
-        ManagementTransitionMode(boolean wasReadOnly, boolean isReadOnly, boolean isRebinding) {
-            this.wasReadOnly = wasReadOnly;
-            this.isReadOnly = isReadOnly;
-            this.isRebinding = isRebinding;
+        public BrooklynObjectManagementMode getModeAfter() {
+            return modeAfter;
         }
         
-        public boolean wasReadOnly() { return wasReadOnly; }
-        public boolean isReadOnly() { return isReadOnly; }
-        public boolean isRebinding() { return isRebinding; }
+        public boolean wasNotLoaded() {
+            return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT || getModeBefore()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED || getModeBefore()==BrooklynObjectManagementMode.ITEM_UNKNOWN;
+        }
+
+        public boolean isNoLongerLoaded() {
+            return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT || getModeAfter()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED || getModeAfter()==BrooklynObjectManagementMode.ITEM_UNKNOWN;
+        }
+
+        public boolean wasPrimary() {
+            return getModeBefore()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
+        }
+        
+        public boolean isPrimary() {
+            return getModeAfter()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
+        }
+
+        public boolean wasReadOnly() {
+            return getModeBefore()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
+        }
+        
+        public boolean isReadOnly() {
+            return getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
+        }
+
+        public boolean isDestroying() {
+            return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT;
+        }
+
+        public boolean isCreating() {
+            return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT;
+        }
     }
     
     public ManagementTransitionInfo(ManagementContext mgmtContext, ManagementTransitionMode mode) {


[06/22] incubator-brooklyn git commit: This closes #478

Posted by he...@apache.org.
This closes #478


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

Branch: refs/heads/master
Commit: 0d078c9c97a4989923cf1063b6bd61484efb532f
Parents: 92e9d0b d423522
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Feb 6 22:11:36 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:11:36 2015 +0000

----------------------------------------------------------------------
 .../src/main/java/brooklyn/BrooklynVersion.java | 222 +++++++++++++++----
 .../main/java/brooklyn/util/http/HttpTool.java  |   5 +
 .../test/java/brooklyn/BrooklynVersionTest.java |  49 +++-
 .../main/java/brooklyn/cli/AbstractMain.java    |  14 +-
 usage/cli/src/main/java/brooklyn/cli/Main.java  |  26 ++-
 .../cli/src/test/java/brooklyn/cli/CliTest.java |   2 +-
 .../brooklyn/cli/CloudExplorerLiveTest.java     |  11 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |  15 +-
 .../brooklyn/launcher/BrooklynWebServer.java    |  13 +-
 .../brooklyn/launcher/WebAppRunnerTest.java     |   4 +-
 .../java/brooklyn/rest/BrooklynWebConfig.java   |   7 +-
 .../brooklyn/rest/resources/ServerResource.java |  15 ++
 .../provider/ExplicitUsersSecurityProvider.java |   2 +
 .../main/java/brooklyn/test/HttpTestUtils.java  |   4 +-
 14 files changed, 328 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d078c9c/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
----------------------------------------------------------------------


[14/22] incubator-brooklyn git commit: better dev-environment detection and osgi error reporting

Posted by he...@apache.org.
better dev-environment detection and osgi error reporting


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

Branch: refs/heads/master
Commit: 45820728671c18e183e0e296a197fc5d46305d0a
Parents: 689f051
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Feb 6 17:56:38 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:14 2015 +0000

----------------------------------------------------------------------
 .../src/main/java/brooklyn/BrooklynVersion.java | 11 ++++-------
 .../brooklyn/management/ha/OsgiManager.java     | 20 ++++++++++++++++----
 2 files changed, 20 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/45820728/core/src/main/java/brooklyn/BrooklynVersion.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/BrooklynVersion.java b/core/src/main/java/brooklyn/BrooklynVersion.java
index 3e7645a..0cdf375 100644
--- a/core/src/main/java/brooklyn/BrooklynVersion.java
+++ b/core/src/main/java/brooklyn/BrooklynVersion.java
@@ -197,20 +197,17 @@ public class BrooklynVersion {
   private static boolean computeIsDevelopmentEnvironment() {
       Enumeration<URL> paths;
       try {
-          paths = BrooklynVersion.class.getClassLoader().getResources(MANIFEST_PATH);
+          paths = BrooklynVersion.class.getClassLoader().getResources("brooklyn/BrooklynVersion.class");
       } catch (IOException e) {
           // shouldn't happen
           throw Exceptions.propagate(e);
       }
       while (paths.hasMoreElements()) {
           URL u = paths.nextElement();
-          if (u.getPath().endsWith("core/target/classes/META-INF/MANIFEST.MF")) {
+          if (u.getPath().endsWith("core/target/classes/brooklyn/BrooklynVersion.class")) {
               try {
-                  ManifestHelper mh = Osgis.ManifestHelper.forManifest(u.openStream());
-                  if (BROOKLYN_CORE_SYMBOLIC_NAME.equals(mh.getSymbolicName())) {
-                      log.debug("Brooklyn debug environment detected; core manifest is at: "+u);
-                      return true;
-                  }
+                  log.debug("Brooklyn debug environment detected; BrooklynVersion class is at: "+u);
+                  return true;
               } catch (Exception e) {
                   Exceptions.propagateIfFatal(e);
                   log.warn("Error reading manifest to determine whether this is a development environment: "+e, e);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/45820728/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
index 260f5ff..d699da3 100644
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -23,6 +23,7 @@ import java.net.URL;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -39,6 +40,7 @@ import brooklyn.config.BrooklynServerPaths;
 import brooklyn.config.ConfigKey;
 import brooklyn.management.ManagementContext;
 import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.guava.Maybe;
 import brooklyn.util.os.Os;
@@ -46,6 +48,7 @@ import brooklyn.util.os.Os.DeletionResult;
 import brooklyn.util.osgi.Osgis;
 import brooklyn.util.osgi.Osgis.BundleFinder;
 import brooklyn.util.repeat.Repeater;
+import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 
 import com.google.common.base.Throwables;
@@ -187,6 +190,7 @@ public class OsgiManager {
     }
     public <T> Maybe<Class<T>> tryResolveClass(String type, Iterable<CatalogBundle> catalogBundles) {
         Map<CatalogBundle,Throwable> bundleProblems = MutableMap.of();
+        Set<String> extraMessages = MutableSet.of();
         for (CatalogBundle catalogBundle: catalogBundles) {
             try {
                 Maybe<Bundle> bundle = findBundle(catalogBundle);
@@ -216,8 +220,14 @@ public class OsgiManager {
 
                 Throwable cause = e.getCause();
                 if (cause != null && cause.getMessage().contains("Unresolved constraint in bundle")) {
-                    log.warn("Unresolved constraint resolving OSGi bundle "+catalogBundle+" to load "+type+": "+cause.getMessage()+
-                        (BrooklynVersion.isDevelopmentEnvironment() ? " (may be due to IDE / dev env; try a maven build)" : ""));
+                    if (BrooklynVersion.INSTANCE.getVersionFromOsgiManifest()==null) {
+                        extraMessages.add("No brooklyn-core OSGi manifest available. OSGi will not work.");
+                    }
+                    if (BrooklynVersion.isDevelopmentEnvironment()) {
+                        extraMessages.add("Your development environment may not have created necessary files. Doing a maven build then retrying may fix the issue.");
+                    }
+                    if (!extraMessages.isEmpty()) log.warn(Strings.join(extraMessages, " "));
+                    log.warn("Unresolved constraint resolving OSGi bundle "+catalogBundle+" to load "+type+": "+cause.getMessage());
                     if (log.isDebugEnabled()) log.debug("Trace for OSGi resolution failure", e);
                 }
             }
@@ -227,9 +237,11 @@ public class OsgiManager {
             if (error instanceof ClassNotFoundException && error.getCause()!=null && error.getCause().getMessage()!=null) {
                 error = Exceptions.collapseIncludingAllCausalMessages(error);
             }
-            return Maybe.absent("Unable to resolve class "+type+" in "+Iterables.getOnlyElement(bundleProblems.keySet()), error);
+            return Maybe.absent("Unable to resolve class "+type+" in "+Iterables.getOnlyElement(bundleProblems.keySet())
+                + (extraMessages.isEmpty() ? "" : " ("+Strings.join(extraMessages, " ")+")"), error);
         } else {
-            return Maybe.absent(Exceptions.create("Unable to resolve class "+type+": "+bundleProblems, bundleProblems.values()));
+            return Maybe.absent(Exceptions.create("Unable to resolve class "+type+": "+bundleProblems
+                + (extraMessages.isEmpty() ? "" : " ("+Strings.join(extraMessages, " ")+")"), bundleProblems.values()));
         }
     }
 


[16/22] incubator-brooklyn git commit: add convenience method for creating spec from catalog item

Posted by he...@apache.org.
add convenience method for creating spec from catalog item


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

Branch: refs/heads/master
Commit: 6156a7743bdeacadfd533ead28b4c7460fdc7610
Parents: 4582072
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Feb 6 17:57:41 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:14 2015 +0000

----------------------------------------------------------------------
 .../java/brooklyn/catalog/internal/CatalogUtils.java    | 10 ++++++++++
 .../management/osgi/OsgiVersionMoreEntityTest.java      | 12 +-----------
 2 files changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6156a774/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
index ed4d06d..9741672 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
@@ -34,6 +34,7 @@ import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
 import brooklyn.config.BrooklynLogging;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
@@ -227,4 +228,13 @@ public class CatalogUtils {
         }
     }
 
+    @Beta
+    public static EntitySpec<?> createEntitySpec(ManagementContext mgmt, CatalogItem<?, ?> catalogItem) {
+        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, catalogItem);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        EntitySpec<?> spec = EntitySpec.create( (Class)loader.loadClass(catalogItem.getJavaType()) );
+        spec.catalogItemId(catalogItem.getId());
+        return spec;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6156a774/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
index 7bec58f..4e1bb94 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
@@ -55,7 +55,6 @@ import brooklyn.util.guava.Maybe;
 import brooklyn.util.os.Os;
 import brooklyn.util.osgi.Osgis;
 
-import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
@@ -162,17 +161,8 @@ public class OsgiVersionMoreEntityTest {
         return addItemFromCatalog(mgmt, app, c2);
     }
     
-    @Beta
-    @SuppressWarnings({ "unchecked", "rawtypes" })
     public static Entity addItemFromCatalog(ManagementContext mgmt, TestApplication parent, CatalogItem<?, ?> c2) {
-        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, c2);
-        EntitySpec spec = EntitySpec.create( (Class)loader.loadClass(c2.getJavaType()) );
-        // not a great test as we set the ID here; but:
-        // YAML test will do better;
-        // and we can check that downstream items are loaded correctly
-        spec.catalogItemId(c2.getId());
-        Entity me = parent.createAndManageChild(spec);
-        return me;
+        return parent.createAndManageChild( CatalogUtils.createEntitySpec(mgmt, c2) );
     }
 
     public static void assertV1MethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {


[17/22] incubator-brooklyn git commit: fix proxy leak on extra promotion to master

Posted by he...@apache.org.
fix proxy leak on extra promotion to master


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

Branch: refs/heads/master
Commit: 35142c8049d3068775f448d6c48edeb365f53bfa
Parents: 71c82da
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Feb 9 10:23:20 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Feb 9 10:23:20 2015 +0000

----------------------------------------------------------------------
 .../entity/proxying/InternalEntityFactory.java  | 12 ++++++++-
 .../rebind/InitialFullRebindIteration.java      |  8 ++++++
 .../internal/EntityManagementSupport.java       |  4 ++-
 .../entity/rebind/ActivePartialRebindTest.java  | 26 +++++++++++++++++++-
 .../ha/HighAvailabilityManagerInMemoryTest.java | 21 +++++++++++++++-
 5 files changed, 67 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35142c80/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
index 40885b4..880d07a 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
@@ -358,7 +358,17 @@ public class InternalEntityFactory extends InternalFactory {
         checkState(interfaces != null && !Iterables.isEmpty(interfaces), "must have at least one interface for entity %s:%s", clazz, entityId);
         
         T entity = constructEntityImpl(clazz, ImmutableMap.<String, Object>of(), entityId);
-        if (((AbstractEntity)entity).getProxy() == null) ((AbstractEntity)entity).setProxy(createEntityProxy(interfaces, entity));
+        if (((AbstractEntity)entity).getProxy() == null) {
+            Entity proxy = managementContext.getEntityManager().getEntity(entity.getId());
+            if (proxy==null) {
+                // normal case, proxy does not exist
+                proxy = createEntityProxy(interfaces, entity);
+            } else {
+                // only if rebinding to existing; don't create a new proxy, then we have proxy explosion
+                // but callers must be careful that the entity's proxy does not yet point to it
+            }
+            ((AbstractEntity)entity).setProxy(proxy);
+        }
         return entity;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35142c80/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
index 9906f30..44ef922 100644
--- a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
@@ -94,6 +94,14 @@ public class InitialFullRebindIteration extends RebindIteration {
                 // this is discouraged if we were already master
                 Entity anEntity = Iterables.getFirst(managementContext.getEntityManager().getEntities(), null);
                 if (anEntity!=null && !((EntityInternal)anEntity).getManagementSupport().isReadOnly()) {
+                    // NB: there is some complexity which can happen in this situation; "initial-full" rebind really expected everything is being
+                    // initially bound from persisted state, and completely so; "active-partial" is much more forgiving.
+                    // one big difference is in behaviour of management: it is recursive for most situations, and initial-full assumes recursive,
+                    // but primary-primary is *not* recursive;
+                    // as a result some "new" entities created during rebind might be left unmanaged; they should get GC'd,
+                    // but it's possible the new entity impl or even a new proxy could leak.
+                    // see HighAvailabilityManagerInMemoryTest.testLocationsStillManagedCorrectlyAfterDoublePromotion
+                    // (i've plugged the known such leaks, but still something to watch out for); -Alex 2015-02
                     overwritingMaster = true;
                     LOG.warn("Rebind requested for "+mode+" node "+managementContext.getManagementNodeId()+" "
                         + "when it already has active state; discouraged, "

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35142c80/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java b/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
index 4bea56e..eb9a27f 100644
--- a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
+++ b/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
@@ -268,7 +268,9 @@ public class EntityManagementSupport {
     public void onManagementStopping(ManagementTransitionInfo info) {
         synchronized (this) {
             if (managementContext != info.getManagementContext()) {
-                throw new IllegalStateException("Has different management context: "+managementContext+"; expected "+info.getManagementContext());
+                throw new IllegalStateException("onManagementStopping encountered different management context for "+entity+
+                    (!wasDeployed() ? " (wasn't deployed)" : !isDeployed() ? " (no longer deployed)" : "")+
+                    ": "+managementContext+"; expected "+info.getManagementContext());
             }
             Stopwatch startTime = Stopwatch.createStarted();
             while (!managementFailed.get() && nonDeploymentManagementContext!=null && 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35142c80/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
index 80e13b6..414ca25 100644
--- a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
@@ -27,6 +27,7 @@ import brooklyn.basic.BrooklynObject;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.util.text.Strings;
@@ -41,7 +42,7 @@ public class ActivePartialRebindTest extends RebindTestFixtureWithApp {
     }
     
     @Test
-    public void testRebindOneSimple() throws Exception {
+    public void testRebindChildSimple() throws Exception {
         TestEntity c1 = origApp.addChild(EntitySpec.create(TestEntity.class));
         Entities.manage(c1);
         AbstractEntity c1r = Entities.deproxy(c1);
@@ -55,6 +56,29 @@ public class ActivePartialRebindTest extends RebindTestFixtureWithApp {
         Assert.assertFalse(c2r == c1r, "Real instance should NOT be the same: "+c1r+" / "+c2r);
     }
 
+    @Test
+    public void testRebindParentSimple() throws Exception {
+        TestEntity c1 = origApp.addChild(EntitySpec.create(TestEntity.class));
+        Entities.manage(c1);
+        
+        AbstractEntity origAppr = Entities.deproxy(origApp);
+        
+        doPartialRebindOfIds(origApp.getId());
+        
+        BrooklynObject app2 = origManagementContext.lookup(origApp.getId());
+        AbstractEntity app2r = Entities.deproxy((Entity)app2);
+        
+        Assert.assertTrue(app2 == origApp, "Proxy instance should be the same: "+app2+" / "+origApp);
+        Assert.assertFalse(app2r == origAppr, "Real instance should NOT be the same: "+app2r+" / "+origAppr);
+        
+        Assert.assertTrue(c1.getManagementSupport().isDeployed());
+        
+        // check that child of parent is not a new unmanaged entity
+        Entity c1b = origApp.getChildren().iterator().next();
+        Assert.assertTrue(c1.getManagementSupport().isDeployed());
+        Assert.assertTrue( ((EntityInternal)c1b).getManagementSupport().isDeployed(), "Not deployed: "+c1b );
+    }
+
     @Test(groups="Integration")
     public void testRebindCheckingMemoryLeak() throws Exception {
         TestEntity c1 = origApp.addChild(EntitySpec.create(TestEntity.class));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35142c80/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java
index 7c9f213..c647f19 100644
--- a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java
+++ b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java
@@ -27,6 +27,7 @@ import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import brooklyn.entity.Entity;
+import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.persister.InMemoryObjectStore;
 import brooklyn.entity.rebind.persister.PersistenceObjectStore;
@@ -34,6 +35,7 @@ import brooklyn.location.Location;
 import brooklyn.location.NoMachinesAvailableException;
 import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
 import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.test.entity.TestApplication;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.util.collections.MutableList;
@@ -76,15 +78,22 @@ public class HighAvailabilityManagerInMemoryTest extends HighAvailabilityManager
         Collection<Location> lm = managementContext.getLocationManager().getLocations();
         log.info("Locs managed are: "+lm);
         log.info("            objs: "+identities(lm));
+        Assert.assertNotNull(entity.getManagementSupport().getManagementContext());
+        Assert.assertNotNull( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext());
+        Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().isDeployed());
+        checkEntitiesHealthy(app, entity);
         
         managementContext.getRebindManager().forcePersistNow(true, null);
-        log.info("DODGY extra promoteToMaster");
+        log.info("Test deliberately doing unnecessary extra promoteToMaster");
         ha.promoteToMaster();
         
         log.info("Entities managed are: "+managementContext.getEntityManager().getEntities());
         Collection<Location> lle = entity.getLocations();
         log.info("Locs at entity(old) are: "+lle);
         log.info("                   objs: "+identities(lle));
+        // check entities -- the initial-full promotion previously re-created items, 
+        // and plugged them in as children, but only managed the roots
+        checkEntitiesHealthy(app, entity);
         
         // assert what's in the location manager is accurate
         Collection<Location> llmm = managementContext.getLocationManager().getLocations();
@@ -108,6 +117,16 @@ public class HighAvailabilityManagerInMemoryTest extends HighAvailabilityManager
         
     }
 
+    private void checkEntitiesHealthy(TestApplication app, TestEntity entity) {
+        Assert.assertNotNull(app.getManagementSupport().getManagementContext());
+        Assert.assertTrue( app.getManagementSupport().getManagementContext().isRunning() );
+        
+        Assert.assertNotNull(entity.getManagementSupport().getManagementContext());
+        Assert.assertNotNull( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext() );
+        Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().isDeployed());
+        Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext() instanceof LocalManagementContext );
+    }
+
     @Test(groups="Integration", invocationCount=50)
     public void testLocationsStillManagedCorrectlyAfterDoublePromotionManyTimes() throws NoMachinesAvailableException {
         testLocationsStillManagedCorrectlyAfterDoublePromotion();


[19/22] incubator-brooklyn git commit: Partial rebind - address code review comments

Posted by he...@apache.org.
Partial rebind - address code review comments


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

Branch: refs/heads/master
Commit: 491ca49efdfe4f8a7bb2bf5cbba5cd592bf4798a
Parents: 3c97a57
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Feb 9 12:32:29 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Feb 9 12:32:29 2015 +0000

----------------------------------------------------------------------
 .../src/main/java/brooklyn/BrooklynVersion.java |  4 +-
 .../brooklyn/catalog/internal/CatalogUtils.java | 10 -----
 .../rebind/ActivePartialRebindIteration.java    | 35 ++++++++-------
 .../rebind/InitialFullRebindIteration.java      | 12 ++---
 .../brooklyn/entity/rebind/RebindIteration.java | 14 +++++-
 .../entity/rebind/RebindManagerImpl.java        |  2 +-
 .../test/java/brooklyn/BrooklynVersionTest.java |  2 +-
 .../catalog/internal/CatalogTestUtils.java      | 46 ++++++++++++++++++++
 .../entity/group/DynamicClusterTest.java        | 14 ++++++
 .../entity/rebind/ActivePartialRebindTest.java  |  2 +-
 .../rebind/ActivePartialRebindVersionTest.java  |  4 +-
 .../persister/XmlMementoSerializerTest.java     |  5 +--
 .../osgi/OsgiVersionMoreEntityTest.java         |  3 +-
 13 files changed, 104 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/main/java/brooklyn/BrooklynVersion.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/BrooklynVersion.java b/core/src/main/java/brooklyn/BrooklynVersion.java
index 0cdf375..3496d9e 100644
--- a/core/src/main/java/brooklyn/BrooklynVersion.java
+++ b/core/src/main/java/brooklyn/BrooklynVersion.java
@@ -67,7 +67,7 @@ public class BrooklynVersion {
       // we read the maven pom metadata and osgi metadata and make sure it's sensible
       // everything is put into a single map for now (good enough, but should be cleaned up)
       readPropertiesFromMavenResource(BrooklynVersion.class.getClassLoader());
-      readPropertiesFromOsgiResource(BrooklynVersion.class.getClassLoader(), "org.apache.brooklyn.core");
+      readPropertiesFromOsgiResource(BrooklynVersion.class.getClassLoader(), BROOKLYN_CORE_SYMBOLIC_NAME);
       // TODO there is also build-metadata.properties used in ServerResource /v1/server/version endpoint
       // see comments on that about folding it into this class instead
 
@@ -227,7 +227,7 @@ public class BrooklynVersion {
   }
 
   public static String get() {
-    return getVersionFromStatic();
+      return INSTANCE.getVersion();
   }
   
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
index 9741672..ed4d06d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
@@ -34,7 +34,6 @@ import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
 import brooklyn.config.BrooklynLogging;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
@@ -228,13 +227,4 @@ public class CatalogUtils {
         }
     }
 
-    @Beta
-    public static EntitySpec<?> createEntitySpec(ManagementContext mgmt, CatalogItem<?, ?> catalogItem) {
-        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, catalogItem);
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        EntitySpec<?> spec = EntitySpec.create( (Class)loader.loadClass(catalogItem.getJavaType()) );
-        spec.catalogItemId(catalogItem.getId());
-        return spec;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
index d3c4f5f..ff315ca 100644
--- a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
@@ -74,18 +74,23 @@ public class ActivePartialRebindIteration extends RebindIteration {
     }
     
     public void applyTransformer(CompoundTransformer transformer) {
-        if (transformer!=null)
-            transformers.add(transformer);
+        transformers.add(Preconditions.checkNotNull(transformer, "transformer"));
     }
     
     @Override
     protected void doRun() throws Exception {
-        checkEnteringPhase(1);
-        Preconditions.checkState(readOnlyRebindCount.get()==Integer.MIN_VALUE, "Partial rebind in read-only mode not supported");
+        Preconditions.checkState(rebindManager.getRebindMode()==ManagementNodeState.MASTER, "Partial rebind only supported in master mode, not "+rebindManager.getRebindMode());
+        Preconditions.checkState(readOnlyRebindCount.get()==Integer.MIN_VALUE, "Rebind count should be MIN when running in master mode");
         Preconditions.checkNotNull(objectsToRebindInitial, "Objects to rebind must be set");
 
         LOG.debug("Partial rebind Rebinding ("+mode+") from "+rebindManager.getPersister().getBackingStoreDescription()+"...");
 
+        super.doRun();
+    }
+    
+    @Override
+    protected void loadManifestFiles() throws Exception {
+        checkEnteringPhase(1);
         Builder mementoRawBuilder = BrooklynMementoRawData.builder();
 
         /*
@@ -116,21 +121,8 @@ public class ActivePartialRebindIteration extends RebindIteration {
         mementoRawData = mementoRawBuilder.build();
 
         preprocessManifestFiles();
-
-        // skip this phase, as catalog is not being changed
-        // (and we don't want to unload things)
-//        rebuildCatalog();
-        phase++;
-        
-        instantiateLocationsAndEntities();
-        instantiateMementos();
-        instantiateAdjuncts(instantiator); 
-        reconstructEverything();
-        associateAdjunctsWithEntities();
-        manageTheObjects();
-        finishingUp();
     }
-
+    
     @Override
     protected void preprocessManifestFiles() throws Exception {
         for (CompoundTransformer transformer: transformers) {
@@ -141,6 +133,13 @@ public class ActivePartialRebindIteration extends RebindIteration {
     }
 
     @Override
+    protected void rebuildCatalog() {
+        checkEnteringPhase(2);
+        
+        // skip; old catalog items should be re-used
+    }
+    
+    @Override
     protected Collection<String> getMementoRootEntities() {
         // all entities are roots here, because we are not recursing
         return memento.getEntityIds();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
index 44ef922..a84d34b 100644
--- a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
@@ -60,22 +60,16 @@ public class InitialFullRebindIteration extends RebindIteration {
         return false;
     }
     
+    @Override
     protected void doRun() throws Exception {
         LOG.debug("Rebinding ("+mode+
             (readOnlyRebindCount.get()>Integer.MIN_VALUE ? ", iteration "+readOnlyRebindCount : "")+
             ") from "+rebindManager.getPersister().getBackingStoreDescription()+"...");
 
-        loadManifestFiles();
-        rebuildCatalog();
-        instantiateLocationsAndEntities();
-        instantiateMementos();
-        instantiateAdjuncts(instantiator); 
-        reconstructEverything();
-        associateAdjunctsWithEntities();
-        manageTheObjects();
-        finishingUp();
+        super.doRun();
     }
 
+    @Override
     protected void loadManifestFiles() throws Exception {
         checkEnteringPhase(1);
         Preconditions.checkState(mementoRawData==null, "Memento raw data should not yet be set when calling this");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 3582030..3d22d0b 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -232,7 +232,19 @@ public abstract class RebindIteration {
         return rebindContext;
     }
     
-    protected abstract void doRun() throws Exception;
+    protected void doRun() throws Exception {
+        loadManifestFiles();
+        rebuildCatalog();
+        instantiateLocationsAndEntities();
+        instantiateMementos();
+        instantiateAdjuncts(instantiator); 
+        reconstructEverything();
+        associateAdjunctsWithEntities();
+        manageTheObjects();
+        finishingUp();
+    }
+    
+    protected abstract void loadManifestFiles() throws Exception;
     
     public void run() {
         if (iterationStarted.getAndSet(true)) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index e6f4aea..ca85a03 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -382,7 +382,7 @@ public class RebindManagerImpl implements RebindManager {
             rebindActive, readOnlyRebindCount, rebindMetrics, persistenceStoreAccess);
 
         iteration.setObjectIterator(objectsToRebind);
-        iteration.applyTransformer(transformer);
+        if (transformer!=null) iteration.applyTransformer(transformer);
         iteration.run();
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/test/java/brooklyn/BrooklynVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/BrooklynVersionTest.java b/core/src/test/java/brooklyn/BrooklynVersionTest.java
index 887d8e4..9683600 100644
--- a/core/src/test/java/brooklyn/BrooklynVersionTest.java
+++ b/core/src/test/java/brooklyn/BrooklynVersionTest.java
@@ -63,7 +63,7 @@ public class BrooklynVersionTest {
       log.info("sha1: "+sha1);
       if (Strings.isNonBlank(sha1) || BrooklynVersion.isDevelopmentEnvironment())
           return;
-      // we might not have a SHA1 if it's a standalone source build; just log warn in that case
+      // we might not have a SHA1 if it's a standalone (non-git) source build; just log warn in that case
       log.warn("This build does not have git SHA1 information.");
       // (can't assert anything, except that sha1 lookup doesn't NPE)
   }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/test/java/brooklyn/catalog/internal/CatalogTestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogTestUtils.java b/core/src/test/java/brooklyn/catalog/internal/CatalogTestUtils.java
new file mode 100644
index 0000000..14005a5
--- /dev/null
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogTestUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.catalog.internal;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+
+import com.google.common.annotations.Beta;
+
+public class CatalogTestUtils {
+
+    /** creates entity spec with the java type of a catalog item;
+     * would be nice to have this in {@link CatalogUtils},
+     * but the logic for parsing the yaml is buried in camp code,
+     * so it's a little bit hard to make this a first class method.
+     * <p>
+     * (this impl ignores many things, including config and location.)
+     */
+    @Beta
+    public static EntitySpec<?> createEssentialEntitySpec(ManagementContext mgmt, CatalogItem<?, ?> catalogItem) {
+        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, catalogItem);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        EntitySpec<?> spec = EntitySpec.create( (Class)loader.loadClass(catalogItem.getJavaType()) );
+        spec.catalogItemId(catalogItem.getId());
+        return spec;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java b/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java
index ad5394a..8f953a4 100644
--- a/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java
+++ b/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java
@@ -46,6 +46,7 @@ import org.testng.annotations.Test;
 import brooklyn.entity.BrooklynAppUnitTestSupport;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.BasicEntity;
 import brooklyn.entity.basic.BrooklynTaskTags;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityFactory;
@@ -64,6 +65,7 @@ import brooklyn.test.EntityTestUtils;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.test.entity.TestEntityImpl;
 import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.QuorumCheck.QuorumChecks;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.time.Time;
 
@@ -875,6 +877,18 @@ public class DynamicClusterTest extends BrooklynAppUnitTestSupport {
         assertEquals(cluster.getMembers().size(), 1);
     }
 
+    @Test
+    public void testWithNonStartableEntity() throws Exception {
+        DynamicCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
+                .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(BasicEntity.class))
+                .configure(DynamicCluster.UP_QUORUM_CHECK, QuorumChecks.alwaysTrue())
+                .configure(DynamicCluster.INITIAL_SIZE, 2));
+        cluster.start(ImmutableList.of(loc));
+        
+        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        assertTrue(cluster.getAttribute(Attributes.SERVICE_UP));
+    }
+
     private Throwable unwrapException(Throwable e) {
         if (e instanceof ExecutionException) {
             return unwrapException(e.getCause());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
index 414ca25..f43cbe5 100644
--- a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindTest.java
@@ -87,7 +87,7 @@ public class ActivePartialRebindTest extends RebindTestFixtureWithApp {
         
         gcAndLog("before");
         long used0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
-        for (int i=0; i<500; i++) {
+        for (int i=0; i<200; i++) {
             doPartialRebindOfIds(c1.getId());
             origManagementContext.getGarbageCollector().gcIteration();
             gcAndLog("iteration "+i);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
index 9eec02b..e9594b9 100644
--- a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
@@ -24,7 +24,7 @@ import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import brooklyn.catalog.CatalogItem;
-import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.catalog.internal.CatalogTestUtils;
 import brooklyn.entity.Entity;
 import brooklyn.entity.group.DynamicCluster;
 import brooklyn.entity.proxying.EntitySpec;
@@ -94,7 +94,7 @@ public class ActivePartialRebindVersionTest extends RebindTestFixtureWithApp {
 //            + "  entitySpec: { type: "+catV1.getId()+" }\n", true);
         DynamicCluster cluster = origApp.createAndManageChild(EntitySpec.create(DynamicCluster.class)
             .configure(DynamicCluster.INITIAL_SIZE, 1)
-            .configure(DynamicCluster.MEMBER_SPEC, CatalogUtils.createEntitySpec(origManagementContext, catV1))
+            .configure(DynamicCluster.MEMBER_SPEC, CatalogTestUtils.createEssentialEntitySpec(origManagementContext, catV1))
             );
         cluster.start(MutableList.of(origApp.newSimulatedLocation()));
         Entity childV1 = MutableList.copyOf(cluster.getChildren()).get(1);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
index 6083134..a57c9eb 100644
--- a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
@@ -37,7 +37,7 @@ import brooklyn.basic.BrooklynObject;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.internal.CatalogItemBuilder;
 import brooklyn.catalog.internal.CatalogItemDtoAbstract;
-import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.catalog.internal.CatalogTestUtils;
 import brooklyn.entity.Entity;
 import brooklyn.entity.Feed;
 import brooklyn.entity.basic.Entities;
@@ -47,7 +47,6 @@ import brooklyn.entity.rebind.BrooklynObjectType;
 import brooklyn.location.Location;
 import brooklyn.location.LocationSpec;
 import brooklyn.management.ManagementContext;
-import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
 import brooklyn.mementos.BrooklynMementoPersister.LookupContext;
 import brooklyn.policy.Enricher;
@@ -203,7 +202,7 @@ public class XmlMementoSerializerTest {
         
         EntitySpec<DynamicCluster> spec = EntitySpec.create(DynamicCluster.class)
             .configure(DynamicCluster.INITIAL_SIZE, 1)
-            .configure(DynamicCluster.MEMBER_SPEC, CatalogUtils.createEntitySpec(mgmt, ci));
+            .configure(DynamicCluster.MEMBER_SPEC, CatalogTestUtils.createEssentialEntitySpec(mgmt, ci));
 
         serializer.setLookupContext(new LookupContextImpl(mgmt,
             ImmutableList.<Entity>of(), ImmutableList.<Location>of(), ImmutableList.<Policy>of(),

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/491ca49e/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
index 4e1bb94..967bb6d 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
@@ -36,6 +36,7 @@ import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.internal.CatalogEntityItemDto;
 import brooklyn.catalog.internal.CatalogItemBuilder;
 import brooklyn.catalog.internal.CatalogItemDtoAbstract;
+import brooklyn.catalog.internal.CatalogTestUtils;
 import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.Entities;
@@ -162,7 +163,7 @@ public class OsgiVersionMoreEntityTest {
     }
     
     public static Entity addItemFromCatalog(ManagementContext mgmt, TestApplication parent, CatalogItem<?, ?> c2) {
-        return parent.createAndManageChild( CatalogUtils.createEntitySpec(mgmt, c2) );
+        return parent.createAndManageChild( CatalogTestUtils.createEssentialEntitySpec(mgmt, c2) );
     }
 
     public static void assertV1MethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {


[21/22] incubator-brooklyn git commit: This closes #480

Posted by he...@apache.org.
This closes #480


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

Branch: refs/heads/master
Commit: 4027986a4a09a9d993ff3188545f5f22888c2cd5
Parents: e59aac0 f673e19
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Feb 9 15:36:01 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Feb 9 15:36:01 2015 +0000

----------------------------------------------------------------------
 .../main/java/brooklyn/util/net/Networking.java | 29 +++++++-------------
 1 file changed, 10 insertions(+), 19 deletions(-)
----------------------------------------------------------------------



[02/22] incubator-brooklyn git commit: CLI better default, port/https control, and version reporting

Posted by he...@apache.org.
CLI better default, port/https control, and version reporting

* adds config key for web-console port
* adds CLI for https
* port defaults to 8443+ if no port specified and using https
* default if no CLI options is to show help and an error
* some https test fixes
* discovers and reports Brooklyn OSGi metadata in log, including git SHA1 (and `brooklyn info`)


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

Branch: refs/heads/master
Commit: d423522cacf97c3fefa0df3c641718a49f9103a5
Parents: ec74489
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Jan 27 17:47:41 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Jan 27 17:47:41 2015 +0000

----------------------------------------------------------------------
 .../src/main/java/brooklyn/BrooklynVersion.java | 222 +++++++++++++++----
 .../main/java/brooklyn/util/http/HttpTool.java  |   5 +
 .../test/java/brooklyn/BrooklynVersionTest.java |  49 +++-
 .../main/java/brooklyn/cli/AbstractMain.java    |  14 +-
 usage/cli/src/main/java/brooklyn/cli/Main.java  |  26 ++-
 .../cli/src/test/java/brooklyn/cli/CliTest.java |   2 +-
 .../brooklyn/cli/CloudExplorerLiveTest.java     |  11 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |  15 +-
 .../brooklyn/launcher/BrooklynWebServer.java    |  13 +-
 .../brooklyn/launcher/WebAppRunnerTest.java     |   4 +-
 .../java/brooklyn/rest/BrooklynWebConfig.java   |   7 +-
 .../brooklyn/rest/resources/ServerResource.java |  15 ++
 .../provider/ExplicitUsersSecurityProvider.java |   2 +
 .../main/java/brooklyn/test/HttpTestUtils.java  |   4 +-
 14 files changed, 328 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/core/src/main/java/brooklyn/BrooklynVersion.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/BrooklynVersion.java b/core/src/main/java/brooklyn/BrooklynVersion.java
index 8ef6a61..3e7645a 100644
--- a/core/src/main/java/brooklyn/BrooklynVersion.java
+++ b/core/src/main/java/brooklyn/BrooklynVersion.java
@@ -19,80 +19,218 @@
 package brooklyn;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static java.lang.String.format;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
 import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.jar.Attributes;
+
+import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.osgi.Osgis;
+import brooklyn.util.osgi.Osgis.ManifestHelper;
+import brooklyn.util.text.Strings;
+
+/**
+ * Wraps the version of Brooklyn.
+ * <p>
+ * Also retrieves the SHA-1 from any OSGi bundle, and checks that the maven and osgi versions match.
+ */
 public class BrooklynVersion {
 
   private static final Logger log = LoggerFactory.getLogger(BrooklynVersion.class);
   
-  private static final String VERSION_RESOURCE_FILE = "META-INF/maven/io.brooklyn/brooklyn-core/pom.properties";
-  private static final String VERSION_PROPERTY_NAME = "version";
+  private static final String MVN_VERSION_RESOURCE_FILE = "META-INF/maven/org.apache.brooklyn/brooklyn-core/pom.properties";
+  private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
+  private static final String BROOKLYN_CORE_SYMBOLIC_NAME = "org.apache.brooklyn.core";
+  
+  private static final String MVN_VERSION_PROPERTY_NAME = "version";
+  private static final String OSGI_VERSION_PROPERTY_NAME = Attributes.Name.IMPLEMENTATION_VERSION.toString();
+  private static final String OSGI_SHA1_PROPERTY_NAME = "Implementation-SHA-1";
+
 
+  private final static String VERSION_FROM_STATIC = "0.7.0-SNAPSHOT"; // BROOKLYN_VERSION
+  private static final AtomicReference<Boolean> IS_DEV_ENV = new AtomicReference<Boolean>();
+  
   public static final BrooklynVersion INSTANCE = new BrooklynVersion();
+  
+  private final Properties versionProperties = new Properties();
+  
+  public BrooklynVersion() {
+      // we read the maven pom metadata and osgi metadata and make sure it's sensible
+      // everything is put into a single map for now (good enough, but should be cleaned up)
+      readPropertiesFromMavenResource(BrooklynVersion.class.getClassLoader());
+      readPropertiesFromOsgiResource(BrooklynVersion.class.getClassLoader(), "org.apache.brooklyn.core");
+      // TODO there is also build-metadata.properties used in ServerResource /v1/server/version endpoint
+      // see comments on that about folding it into this class instead
 
-  private final String versionFromClasspath;
-  // static useful when running from the IDE
-  // TODO is the classpath version ever useful? should we always use the static?
-  private final String versionFromStatic = "0.7.0-SNAPSHOT"; // BROOKLYN_VERSION
-  private final String version;
+      checkVersions();
+  }
 
-  public BrooklynVersion() {
-    this.versionFromClasspath = readVersionPropertyFromClasspath(BrooklynVersion.class.getClassLoader());
-    if (isValid(versionFromClasspath)) {
-        this.version = versionFromClasspath;
-        if (!this.version.equals(versionFromStatic)) {
-            // should always be the same, and we can drop classpath detection ...
-            log.warn("Version detected from classpath as "+versionFromClasspath+" (preferring that), but in code it is recorded as "+versionFromStatic);
-        }
-    } else {
-        this.version = versionFromStatic;
-    }
+  public void checkVersions() {
+      String mvnVersion = getVersionFromMavenProperties();
+      if (mvnVersion!=null && !VERSION_FROM_STATIC.equals(mvnVersion)) {
+          throw new IllegalStateException("Version error: maven "+mvnVersion+" / code "+VERSION_FROM_STATIC);
+      }
+      
+      String osgiVersion = versionProperties.getProperty(OSGI_VERSION_PROPERTY_NAME);
+      // TODO does the OSGi version include other slightly differ gubbins/style ?
+      if (osgiVersion!=null && !VERSION_FROM_STATIC.equals(osgiVersion)) {
+          throw new IllegalStateException("Version error: osgi "+osgiVersion+" / code "+VERSION_FROM_STATIC);
+      }
   }
-  
+
+  /** Returns version as inferred from classpath/osgi, if possible, or 0.0.0-SNAPSHOT.
+   * See also {@link #getVersionFromMavenProperties()} and {@link #getVersionFromOsgiManifest()}.
+   * @deprecated since 0.7.0, in favour of the more specific methods (and does anyone need that default value?)
+   */
+  @Deprecated
   public String getVersionFromClasspath() {
-    return versionFromClasspath;
+      String v = getVersionFromMavenProperties();
+      if (Strings.isNonBlank(v)) return v;
+      v = getVersionFromOsgiManifest();
+      if (Strings.isNonBlank(v)) return v;
+      return "0.0.0-SNAPSHOT";
   }
   
-  public String getVersion() {
-    return version;
+  @Nullable
+  public String getVersionFromMavenProperties() {
+      return versionProperties.getProperty(MVN_VERSION_PROPERTY_NAME);
+  }
+
+  @Nullable
+  public String getVersionFromOsgiManifest() {
+      return versionProperties.getProperty(OSGI_VERSION_PROPERTY_NAME);
   }
   
-  public String getVersionFromStatic() {
-    return versionFromStatic;
+  @Nullable
+  /** SHA1 of the last commit to brooklyn at the time this build was made.
+   * For SNAPSHOT builds of course there may have been further non-committed changes. */
+  public String getSha1FromOsgiManifest() {
+      return versionProperties.getProperty(OSGI_SHA1_PROPERTY_NAME);
   }
-
-  public boolean isSnapshot() {
-      return (getVersion().indexOf("-SNAPSHOT")>=0);
+  
+  public String getVersion() {
+    return VERSION_FROM_STATIC;
   }
   
-  private static boolean isValid(String v) {
-    if (v==null) return false;
-    if (v.equals("0.0.0") || v.equals("0.0")) return false;
-    if (v.startsWith("0.0.0-") || v.startsWith("0.0-")) return false;
-    return true;
+  public boolean isSnapshot() {
+      return (getVersion().indexOf("-SNAPSHOT")>=0);
   }
-
-  private String readVersionPropertyFromClasspath(ClassLoader resourceLoader) {
-    Properties versionProperties = new Properties();
+    
+  private void readPropertiesFromMavenResource(ClassLoader resourceLoader) {
     try {
-      InputStream versionStream = resourceLoader.getResourceAsStream(VERSION_RESOURCE_FILE);
-      if (versionStream==null) return null;
+      InputStream versionStream = resourceLoader.getResourceAsStream(MVN_VERSION_RESOURCE_FILE);
+      if (versionStream==null) {
+          if (isDevelopmentEnvironment()) {
+              // allowed for dev env
+              log.trace("No maven resource file "+MVN_VERSION_RESOURCE_FILE+" available");
+          } else {
+              log.warn("No maven resource file "+MVN_VERSION_RESOURCE_FILE+" available");
+          }
+          return;
+      }
       versionProperties.load(checkNotNull(versionStream));
-    } catch (IOException exception) {
-      throw new IllegalStateException(format("Unable to load version resource file '%s'", VERSION_RESOURCE_FILE), exception);
+    } catch (IOException e) {
+      log.warn("Error reading maven resource file "+MVN_VERSION_RESOURCE_FILE+": "+e, e);
     }
-    return checkNotNull(versionProperties.getProperty(VERSION_PROPERTY_NAME), VERSION_PROPERTY_NAME);
+  }
+
+  /** reads properties from brooklyn-core's manifest */
+  private void readPropertiesFromOsgiResource(ClassLoader resourceLoader, String symbolicName) {
+      Enumeration<URL> paths;
+      try {
+          paths = BrooklynVersion.class.getClassLoader().getResources(MANIFEST_PATH);
+      } catch (IOException e) {
+          // shouldn't happen
+          throw Exceptions.propagate(e);
+      }
+      while (paths.hasMoreElements()) {
+          URL u = paths.nextElement();
+          try {
+              ManifestHelper mh = Osgis.ManifestHelper.forManifest(u.openStream());
+              if (BROOKLYN_CORE_SYMBOLIC_NAME.equals(mh.getSymbolicName())) {
+                  Attributes attrs = mh.getManifest().getMainAttributes();
+                  for (Object key: attrs.keySet()) {
+                      // key is an Attribute.Name; toString converts to string
+                      versionProperties.put(key.toString(), attrs.getValue(key.toString()));
+                  }
+                  return;
+              }
+          } catch (Exception e) {
+              Exceptions.propagateIfFatal(e);
+              log.warn("Error reading OSGi manifest from "+u+" when determining version properties: "+e, e);
+          }
+      }
+      if (isDevelopmentEnvironment()) {
+          // allowed for dev env
+          log.trace("No OSGi manifest available to determine version properties");
+      } else {
+          log.warn("No OSGi manifest available to determine version properties");
+      }
+  }
+
+  /** 
+   * Returns whether this is a Brooklyn dev environment,
+   * specifically core/target/classes/ is on the classpath for the org.apache.brooklyn.core project.
+   * <p>
+   * In a packaged or library build of Brooklyn (normal usage) this should return false,
+   * and all OSGi components should be available.
+   */
+  public static boolean isDevelopmentEnvironment() {
+      Boolean isDevEnv = IS_DEV_ENV.get();
+      if (isDevEnv!=null) return isDevEnv;
+      synchronized (IS_DEV_ENV) {
+          isDevEnv = computeIsDevelopmentEnvironment();
+          IS_DEV_ENV.set(isDevEnv);
+          return isDevEnv;
+      }
+  }
+  
+  private static boolean computeIsDevelopmentEnvironment() {
+      Enumeration<URL> paths;
+      try {
+          paths = BrooklynVersion.class.getClassLoader().getResources(MANIFEST_PATH);
+      } catch (IOException e) {
+          // shouldn't happen
+          throw Exceptions.propagate(e);
+      }
+      while (paths.hasMoreElements()) {
+          URL u = paths.nextElement();
+          if (u.getPath().endsWith("core/target/classes/META-INF/MANIFEST.MF")) {
+              try {
+                  ManifestHelper mh = Osgis.ManifestHelper.forManifest(u.openStream());
+                  if (BROOKLYN_CORE_SYMBOLIC_NAME.equals(mh.getSymbolicName())) {
+                      log.debug("Brooklyn debug environment detected; core manifest is at: "+u);
+                      return true;
+                  }
+              } catch (Exception e) {
+                  Exceptions.propagateIfFatal(e);
+                  log.warn("Error reading manifest to determine whether this is a development environment: "+e, e);
+              }
+          }
+      }
+      return false;
+  }
+
+  public void logSummary() {
+      log.debug("Brooklyn version "+getVersion()+" (git SHA1 "+getSha1FromOsgiManifest()+")");
+  }
+
+  /** @deprecated since 0.7.0, redundant with {@link #get()} */ @Deprecated
+  public static String getVersionFromStatic() {
+      return VERSION_FROM_STATIC;
   }
 
   public static String get() {
-    return INSTANCE.version;
+    return getVersionFromStatic();
   }
   
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/core/src/main/java/brooklyn/util/http/HttpTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/http/HttpTool.java b/core/src/main/java/brooklyn/util/http/HttpTool.java
index b57c157..a812cfc 100644
--- a/core/src/main/java/brooklyn/util/http/HttpTool.java
+++ b/core/src/main/java/brooklyn/util/http/HttpTool.java
@@ -65,6 +65,7 @@ import org.apache.http.util.EntityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.util.crypto.SslTrustUtils;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.net.URLParamEncoder;
 import brooklyn.util.text.Strings;
@@ -80,6 +81,10 @@ public class HttpTool {
 
     private static final Logger LOG = LoggerFactory.getLogger(HttpTool.class);
 
+    /** Apache HTTP commons utility for trusting all.
+     * <p>
+     * For generic java HTTP usage, see {@link SslTrustUtils#trustAll(java.net.URLConnection)} 
+     * and static constants in the same class. */
     public static class TrustAllStrategy implements TrustStrategy {
         @Override
         public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/core/src/test/java/brooklyn/BrooklynVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/BrooklynVersionTest.java b/core/src/test/java/brooklyn/BrooklynVersionTest.java
index ef9f9a6..887d8e4 100644
--- a/core/src/test/java/brooklyn/BrooklynVersionTest.java
+++ b/core/src/test/java/brooklyn/BrooklynVersionTest.java
@@ -19,18 +19,63 @@
 package brooklyn;
 
 import static org.testng.Assert.assertEquals;
+
+import java.net.URL;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import brooklyn.util.text.Strings;
+
 public class BrooklynVersionTest {
 
+  private static final Logger log = LoggerFactory.getLogger(BrooklynVersionTest.class);
+    
   @Test
   public void testGetVersion() {
-      assertEquals(BrooklynVersion.get(), BrooklynVersion.INSTANCE.getVersionFromStatic());
+      assertEquals(BrooklynVersion.get(), BrooklynVersion.INSTANCE.getVersion());
   }
     
   @Test
   public void testGetHardcodedClasspathVersion() {
-    assertEquals(BrooklynVersion.INSTANCE.getVersionFromClasspath(), "0.0.0-SNAPSHOT");
+      @SuppressWarnings("deprecation")
+      String v = BrooklynVersion.INSTANCE.getVersionFromClasspath();
+      Assert.assertTrue(BrooklynVersion.get().equals(v) || "0.0.0-SNAPSHOT".equals(v), v);
+  }
+  
+  @Test
+  public void testGetFromMaven() {
+      String v = BrooklynVersion.INSTANCE.getVersionFromMavenProperties();
+      Assert.assertTrue(v==null || BrooklynVersion.get().equals(v), v);
+  }
+  
+  @Test
+  public void testGetFromOsgi() {
+      String v = BrooklynVersion.INSTANCE.getVersionFromOsgiManifest();
+      Assert.assertTrue(v==null || BrooklynVersion.get().equals(v), v);
+  }
+  
+  @Test
+  public void testGetOsgiSha1() {
+      String sha1 = BrooklynVersion.INSTANCE.getSha1FromOsgiManifest();
+      log.info("sha1: "+sha1);
+      if (Strings.isNonBlank(sha1) || BrooklynVersion.isDevelopmentEnvironment())
+          return;
+      // we might not have a SHA1 if it's a standalone source build; just log warn in that case
+      log.warn("This build does not have git SHA1 information.");
+      // (can't assert anything, except that sha1 lookup doesn't NPE)
+  }
+  
+  @Test
+  public void testDevEnv() {
+      URL sp = getClass().getClassLoader().getResource("brooklyn/config/sample.properties");
+      if (sp==null) Assert.fail("Can't find test resources");
+      
+      log.info("Test for dev env: "+"Dev env? "+BrooklynVersion.isDevelopmentEnvironment()+"; path "+sp);
+      Assert.assertEquals(sp.getPath().endsWith("classes/brooklyn/config/sample.properties"), BrooklynVersion.isDevelopmentEnvironment(),
+          "Dev env? "+BrooklynVersion.isDevelopmentEnvironment()+"; path "+sp);
   }
   
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java b/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java
index d2b9169..1378c82 100644
--- a/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java
+++ b/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java
@@ -165,10 +165,13 @@ public abstract class AbstractMain {
 
             System.out.println(BANNER);
             System.out.println("Version:  " + BrooklynVersion.get());
+            if (BrooklynVersion.INSTANCE.isSnapshot()) {
+                System.out.println("Git SHA1: " + BrooklynVersion.INSTANCE.getSha1FromOsgiManifest());
+            }
             System.out.println("Website:  http://brooklyn.incubator.apache.org");
             System.out.println("Source:   https://github.com/apache/incubator-brooklyn");
             System.out.println();
-            System.out.println("Copyright 2011-2014 The Apache Software Foundation.");
+            System.out.println("Copyright 2011-2015 The Apache Software Foundation.");
             System.out.println("Licensed under the Apache 2.0 License");
             System.out.println();
 
@@ -176,6 +179,15 @@ public abstract class AbstractMain {
         }
     }
 
+    public static class DefaultInfoCommand extends InfoCommand {
+        @Override
+        public Void call() throws Exception {
+            super.call();
+            System.out.println("ERROR: No command specified.");
+            System.out.println();
+            throw new ParseException("No command specified.");
+        }
+    }
 
     /** method intended for overriding when the script filename is different 
      * @return the name of the script the user has invoked */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/cli/src/main/java/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/Main.java b/usage/cli/src/main/java/brooklyn/cli/Main.java
index 8b9480a..7a79721 100644
--- a/usage/cli/src/main/java/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/brooklyn/cli/Main.java
@@ -31,11 +31,13 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
 import java.util.Collection;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.BrooklynVersion;
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.cli.CloudExplorer.BlobstoreGetBlobCommand;
 import brooklyn.cli.CloudExplorer.BlobstoreListContainerCommand;
@@ -103,6 +105,8 @@ public class Main extends AbstractMain {
     public static final Logger log = LoggerFactory.getLogger(Main.class);
 
     public static void main(String... args) {
+        log.debug("Launching Brooklyn via CLI, with "+Arrays.toString(args));
+        BrooklynVersion.INSTANCE.logSummary();
         new Main().execCli(args);
     }
 
@@ -207,9 +211,14 @@ public class Main extends AbstractMain {
         public String locations;
 
         @Option(name = { "-p", "--port" }, title = "port number",
-                description = "Specifies the port to be used by the Brooklyn Management Console")
-        public String port = "8081+";
+                description = "Specifies the port to be used by the Brooklyn Management Console; "
+                    + "default is 8081+ for http, 8443+ for https.")
+        public String port;
 
+        @Option(name = { "--https" },
+            description = "Specifies that the server should start on https.")
+        public boolean useHttps = false;
+        
         @Option(name = { "-nc", "--noConsole" },
                 description = "Whether to start the web console")
         public boolean noConsole = false;
@@ -519,12 +528,19 @@ public class Main extends AbstractMain {
             BrooklynLauncher launcher;
             launcher = BrooklynLauncher.newInstance();
             launcher.localBrooklynPropertiesFile(localBrooklynProperties)
-                    .webconsolePort(port)
-                    .webconsole(!noConsole)
                     .ignorePersistenceErrors(ignorePersistenceErrors)
                     .ignoreWebErrors(ignoreWebErrors)
                     .ignoreAppErrors(ignoreAppErrors)
                     .locations(Strings.isBlank(locations) ? ImmutableList.<String>of() : JavaStringEscapes.unwrapJsonishListIfPossible(locations));
+            
+            launcher.webconsole(!noConsole);
+            if (useHttps) {
+                // true sets it; false (not set) leaves it blank and falls back to config key
+                // (no way currently to override config key, but that could be added)
+                launcher.webconsoleHttps(useHttps);
+            }
+            launcher.webconsolePort(port);
+            
             if (noGlobalBrooklynProperties) {
                 log.debug("Configuring to disable global brooklyn.properties");
                 launcher.globalBrooklynPropertiesFile(null);
@@ -825,7 +841,7 @@ public class Main extends AbstractMain {
     protected CliBuilder<BrooklynCommand> cliBuilder() {
         CliBuilder<BrooklynCommand> builder = Cli.<BrooklynCommand>builder(cliScriptName())
                 .withDescription("Brooklyn Management Service")
-                .withDefaultCommand(InfoCommand.class)
+                .withDefaultCommand(DefaultInfoCommand.class)
                 .withCommands(
                         HelpCommand.class,
                         InfoCommand.class,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/cli/src/test/java/brooklyn/cli/CliTest.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/test/java/brooklyn/cli/CliTest.java b/usage/cli/src/test/java/brooklyn/cli/CliTest.java
index 8af432d..79e1b56 100644
--- a/usage/cli/src/test/java/brooklyn/cli/CliTest.java
+++ b/usage/cli/src/test/java/brooklyn/cli/CliTest.java
@@ -267,7 +267,7 @@ public class CliTest {
         assertTrue(details.contains("app=null"), details);   
         assertTrue(details.contains("script=null"), details);
         assertTrue(details.contains("location=null"), details);
-        assertTrue(details.contains("port=8081"), details);
+        assertTrue(details.contains("port=null"), details);
         assertTrue(details.contains("noConsole=false"), details);
         assertTrue(details.contains("noConsoleSecurity=false"), details);
         assertTrue(details.contains("noShutdownOnExit=false"), details);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java b/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java
index 3d3b140..6069f74 100644
--- a/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java
+++ b/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java
@@ -21,6 +21,7 @@ package brooklyn.cli;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 import io.airlift.command.Cli;
+import io.airlift.command.ParseException;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -28,6 +29,7 @@ import java.io.InputStream;
 import java.io.PrintStream;
 import java.util.List;
 
+import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.Test;
 
@@ -49,8 +51,13 @@ public class CloudExplorerLiveTest {
     }
 
     @Test
-    public void testNoArgsReturnsInfo() throws Exception {
-        call(new String[0]);
+    public void testNoArgsThrows() throws Exception {
+        try {
+            call(new String[0]);
+            Assert.fail("No args should fail");
+        } catch (ParseException e) {
+            Assert.assertTrue(e.toString().contains("No command specified"), ""+e);
+        }
     }
 
     // A user running these tests might not have any instances; so don't assert that there will be one

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 64326c9..9cc8ea2 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@ -144,6 +144,7 @@ public class BrooklynLauncher {
     private boolean startWebApps = true;
     private boolean startBrooklynNode = false;
     private PortRange port = null;
+    private Boolean useHttps = null;
     private InetAddress bindAddress = null;
     private InetAddress publicAddress = null;
     private Map<String,String> webApps = new LinkedHashMap<String,String>();
@@ -335,12 +336,13 @@ public class BrooklynLauncher {
      * As {@link #webconsolePort(PortRange)} taking a string range
      */
     public BrooklynLauncher webconsolePort(String port) {
+        if (port==null) return webconsolePort((PortRange)null);
         return webconsolePort(PortRanges.fromString(port));
     }
 
     /**
      * Specifies the port where the web console (and any additional webapps specified) will listen;
-     * default "8081+" (or "8443+" for https) being the first available >= 8081.
+     * default (null) means "8081+" being the first available >= 8081 (or "8443+" for https).
      */ 
     public BrooklynLauncher webconsolePort(PortRange port) {
         this.port = port;
@@ -348,6 +350,14 @@ public class BrooklynLauncher {
     }
 
     /**
+     * Specifies whether the webconsole should use https.
+     */ 
+    public BrooklynLauncher webconsoleHttps(Boolean useHttps) {
+        this.useHttps = useHttps;
+        return this;
+    }
+
+    /**
      * Specifies the NIC where the web console (and any additional webapps specified) will be bound;
      * default 0.0.0.0, unless no security is specified (e.g. users) in which case it is localhost.
      */ 
@@ -721,7 +731,8 @@ public class BrooklynLauncher {
             webServer = new BrooklynWebServer(webconsoleFlags, managementContext);
             webServer.setBindAddress(bindAddress);
             webServer.setPublicAddress(publicAddress);
-            webServer.setPort(port);
+            if (port!=null) webServer.setPort(port);
+            if (useHttps!=null) webServer.setHttpsEnabled(useHttps);
             webServer.putAttributes(brooklynProperties);
             if (skipSecurityFilter != Boolean.TRUE) {
                 webServer.setSecurityFilter(BrooklynPropertiesSecurityFilter.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
index a2595cd..97e93b4 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
@@ -212,6 +212,9 @@ public class BrooklynWebServer {
     }
 
     public BrooklynWebServer setPort(Object port) {
+        if (port==null) {
+            this.requestedPort = null;
+        }
         if (getActualPort()>0)
             throw new IllegalStateException("Can't set port after port has been assigned to server (using "+getActualPort()+")");
         this.requestedPort = TypeCoercions.coerce(port, PortRange.class);
@@ -223,6 +226,11 @@ public class BrooklynWebServer {
         return webappTempDir;
     }
     
+    public BrooklynWebServer setHttpsEnabled(Boolean httpsEnabled) {
+        this.httpsEnabled = httpsEnabled;
+        return this;
+    }
+    
     public boolean getHttpsEnabled() {
         if (httpsEnabled!=null) return httpsEnabled;
         httpsEnabled = managementContext.getConfig().getConfig(BrooklynWebConfig.HTTPS_REQUIRED);
@@ -338,7 +346,10 @@ public class BrooklynWebServer {
         if (actualPort == -1){
             PortRange portRange = requestedPort;
             if (portRange==null) {
-                portRange = getHttpsEnabled()? httpsPort : httpPort;
+                portRange = managementContext.getConfig().getConfig(BrooklynWebConfig.WEB_CONSOLE_PORT);
+            }
+            if (portRange==null) {
+                portRange = getHttpsEnabled() ? httpsPort : httpPort;
             }
             actualPort = LocalhostMachineProvisioningLocation.obtainPort(getAddress(), portRange);
             if (actualPort == -1) 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java b/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java
index cc44db7..cc2af2b 100644
--- a/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java
+++ b/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java
@@ -70,7 +70,7 @@ public class WebAppRunnerTest {
         Map attributes = MutableMap.copyOf( (Map) bigProps.get("attributes") );
         bigProps.put("attributes", attributes);
 
-        BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newDefault();
+        BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
         brooklynProperties.putAll(bigProps);
         brooklynProperties.put("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider");
         brooklynProperties.put("brooklyn.webconsole.security.https.required","false");
@@ -145,7 +145,7 @@ public class WebAppRunnerTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
 
         BrooklynLauncher launcher = BrooklynLauncher.newInstance()
-                .globalBrooklynPropertiesFile(null)
+                .brooklynProperties(BrooklynProperties.Factory.newEmpty())
                 .brooklynProperties("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider")
                 .webapp("/hello", "hello-world.war")
                 .start();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java b/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java
index 67fd069..289837a 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java
@@ -22,6 +22,7 @@ import brooklyn.config.ConfigKey;
 import brooklyn.config.ConfigMap;
 import brooklyn.config.ConfigPredicates;
 import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.location.PortRange;
 import brooklyn.rest.security.provider.DelegatingSecurityProvider;
 import brooklyn.rest.security.provider.ExplicitUsersSecurityProvider;
 
@@ -67,7 +68,11 @@ public class BrooklynWebConfig {
 
     public final static ConfigKey<Boolean> HTTPS_REQUIRED = ConfigKeys.newBooleanConfigKey(
             BASE_NAME+".security.https.required",
-            "Whether HTTPS is required", false); 
+            "Whether HTTPS is required; false here can be overridden by CLI option", false); 
+
+    public final static ConfigKey<PortRange> WEB_CONSOLE_PORT = ConfigKeys.newConfigKey(PortRange.class,
+        BASE_NAME+".port",
+        "Port/range for the web console to listen on; can be overridden by CLI option");
 
     public final static ConfigKey<String> KEYSTORE_URL = ConfigKeys.newStringConfigKey(
             BASE_NAME+".security.keystore.url",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
index eeed1b8..8eaf321 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
@@ -219,6 +219,21 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
 
     @Override
     public VersionSummary getVersion() {
+        // TODO reconcile this with BrooklynVersion reading from the OSGi manifest
+        // @ahgittin / @sjcorbett to decide, is there need for this in addition to the OSGi manifest?
+        // TODO as part of this call should we have a strategy for reporting downstream builds in this call?
+        // for instance, we could look for
+        // * ALL "brooklyn-build-metadata.properties" files on the classpath
+        // * and/or ALL items on classpath with a custom header (eg "Brooklyn-OSGi-Feature-Name: My Project") in MANIFEST.MF
+        // i tend to favour the latter as MANIFEST.MF is already recognised; is there a reason to introduce a new file?
+        // whichever we do, i think:
+        // * "build-metadata.properties" is probably the wrong name
+        // * we should include brooklyn.version and a build timestamp in this file
+        // * the authority for brooklyn should probably be core rather than brooklyn-rest-server
+        
+        // TODO in version summary, maybe also have:
+        // features: [ { name: my-project, version: 0.1.0-SNAPSHOT, git-sha1: xxx }, ... ]
+        // osgi: [ /* similar metadata extracted from all active osgi bundles */ ]
         InputStream input = ResourceUtils.create().getResourceFromUrl("classpath://build-metadata.properties");
         Properties properties = new Properties();
         String gitSha1 = null, gitBranch = null;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java b/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java
index fc5e3c6..e09a42c 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java
@@ -57,6 +57,8 @@ public class ExplicitUsersSecurityProvider extends AbstractSecurityProvider impl
         allowedUsers = new LinkedHashSet<String>();
         String users = properties.getConfig(BrooklynWebConfig.USERS);
         if (users == null) {
+            // TODO unfortunately this is only activated *when* someone tries to log in
+            // (NB it seems like this class is not even instantiated until first log in)
             LOG.warn("REST has no users configured; no one will be able to log in!");
         } else if ("*".equals(users)) {
             LOG.info("REST allowing any user (so long as valid password is set)");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java
index ceee367..71eff35 100644
--- a/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java
+++ b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java
@@ -39,12 +39,12 @@ import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLSession;
 
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 
 import brooklyn.util.collections.MutableMap;
+import brooklyn.util.crypto.SslTrustUtils;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.stream.Streams;
 import brooklyn.util.time.Time;
@@ -326,7 +326,7 @@ public class HttpTestUtils {
     
     public static String getContent(String url) {
         try {
-            return DefaultGroovyMethods.getText(new URL(url).openStream());
+            return Streams.readFullyString(SslTrustUtils.trustAll(new URL(url).openConnection()).getInputStream());
         } catch (Exception e) {
             throw Throwables.propagate(e);
         }


[13/22] incubator-brooklyn git commit: allow DynamicCluster to hold things which aren't Startable

Posted by he...@apache.org.
allow DynamicCluster to hold things which aren't Startable


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

Branch: refs/heads/master
Commit: 689f0512fda78cd02f7cdf3425a2b55c99c3ff74
Parents: 26811b9
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Feb 6 17:56:06 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:14 2015 +0000

----------------------------------------------------------------------
 .../entity/group/DynamicClusterImpl.java        | 21 +++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/689f0512/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
index bccdf35..b21f9fc 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
@@ -130,12 +130,14 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
 
     private static final Function<Collection<Entity>, Entity> defaultRemovalStrategy = new Function<Collection<Entity>, Entity>() {
         @Override public Entity apply(Collection<Entity> contenders) {
-            // choose newest entity that is stoppable
+            // choose newest entity that is stoppable, or if none are stoppable take the newest non-stoppable
             long newestTime = 0;
             Entity newest = null;
 
             for (Entity contender : contenders) {
-                if (contender instanceof Startable && contender.getCreationTime() > newestTime) {
+                boolean newer = contender.getCreationTime() > newestTime;
+                if ((contender instanceof Startable && newer) || 
+                    (!(newest instanceof Startable) && ((contender instanceof Startable) || newer))) {
                     newest = contender;
                     newestTime = contender.getCreationTime();
                 }
@@ -550,7 +552,7 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
     /**
      * {@inheritDoc}
      *
-     * <strong>Note</strong> for sub-clases; this method can be called while synchronized on {@link #mutex}.
+     * <strong>Note</strong> for sub-classes; this method can be called while synchronized on {@link #mutex}.
      */
     @Override
     public Collection<Entity> resizeByDelta(int delta) {
@@ -588,6 +590,7 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
     }
 
     /** <strong>Note</strong> for sub-clases; this method can be called while synchronized on {@link #mutex}. */
+    @SuppressWarnings("unchecked")
     protected Collection<Entity> shrink(int delta) {
         Preconditions.checkArgument(delta < 0, "Must call shrink with negative delta.");
         int size = getCurrentSize();
@@ -601,8 +604,7 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
         Collection<Entity> removedEntities = pickAndRemoveMembers(delta * -1);
 
         // FIXME symmetry in order of added as child, managed, started, and added to group
-        // FIXME assume stoppable; use logic of grow?
-        Task<?> invoke = Entities.invokeEffector(this, removedEntities, Startable.STOP, Collections.<String,Object>emptyMap());
+        Task<?> invoke = Entities.invokeEffector(this, (Iterable<Entity>)(Iterable<?>)Iterables.filter(removedEntities, Startable.class), Startable.STOP, Collections.<String,Object>emptyMap());
         try {
             invoke.get();
             return removedEntities;
@@ -639,9 +641,11 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
             Entity entity = addNode(loc, flags);
             addedEntities.add(entity);
             addedEntityLocations.put(entity, loc);
-            Map<String, ?> args = ImmutableMap.of("locations", ImmutableList.of(loc));
-            Task<Void> task = Effectors.invocation(entity, Startable.START, args).asTask();
-            tasks.put(entity, task);
+            if (entity instanceof Startable) {
+                Map<String, ?> args = ImmutableMap.of("locations", ImmutableList.of(loc));
+                Task<Void> task = Effectors.invocation(entity, Startable.START, args).asTask();
+                tasks.put(entity, task);
+            }
         }
 
         Task<List<?>> parallel = Tasks.parallel("starting "+tasks.size()+" node"+Strings.s(tasks.size())+" (parallel)", tasks.values());
@@ -823,7 +827,6 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
         if (LOG.isDebugEnabled()) LOG.debug("Removing a node from {}", this);
         Entity entity = getRemovalStrategy().apply(members);
         Preconditions.checkNotNull(entity, "No entity chosen for removal from "+getId());
-        Preconditions.checkState(entity instanceof Startable, "Chosen entity for removal not stoppable: cluster="+this+"; choice="+entity);
 
         removeMember(entity);
         return Maybe.of(entity);


[03/22] incubator-brooklyn git commit: Ensure that the datagram socket is created in an unbound state

Posted by he...@apache.org.
Ensure that the datagram socket is created in an unbound state


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

Branch: refs/heads/master
Commit: 5004bfee4c1ad6f98f3a61b9f697022ef59de70f
Parents: 0b5a77d
Author: Matt Champion <ma...@gmail.com>
Authored: Tue Jan 27 20:40:30 2015 +0000
Committer: Matt Champion <ma...@gmail.com>
Committed: Tue Jan 27 20:40:30 2015 +0000

----------------------------------------------------------------------
 utils/common/src/main/java/brooklyn/util/net/Networking.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5004bfee/utils/common/src/main/java/brooklyn/util/net/Networking.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/net/Networking.java b/utils/common/src/main/java/brooklyn/util/net/Networking.java
index 7132bef..2c7e4ff 100644
--- a/utils/common/src/main/java/brooklyn/util/net/Networking.java
+++ b/utils/common/src/main/java/brooklyn/util/net/Networking.java
@@ -111,7 +111,7 @@ public class Networking {
                 ss.bind(new InetSocketAddress(localAddress, port));
 
                 // Check UDP port
-                ds = new DatagramSocket();
+                ds = new DatagramSocket(null);
                 ds.setSoTimeout(250);
                 ds.setReuseAddress(true);
                 ds.bind(new InetSocketAddress(localAddress, port));


[07/22] incubator-brooklyn git commit: Partial rebind - basically working, but for mgmt confusion

Posted by he...@apache.org.
Partial rebind - basically working, but for mgmt confusion

makes RebindIteration abstract, with InitialFullRI having the old (full) behaviour,
and new ActivePartialRebindIteration supporting a subset of nodes;
minor fixes elsewhere to prevent problems


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

Branch: refs/heads/master
Commit: 0fb0c633d269f48cf474c036b8c14bfaba03b5c5
Parents: 0d078c9
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jan 29 11:26:13 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:12 2015 +0000

----------------------------------------------------------------------
 .../rebind/ActivePartialRebindIteration.java    | 161 ++++++++++++++
 .../rebind/InitialFullRebindIteration.java      | 130 ++++++++++++
 .../rebind/RebindContextLookupContext.java      |  24 +++
 .../brooklyn/entity/rebind/RebindIteration.java | 208 +++++++------------
 .../entity/rebind/RebindManagerImpl.java        |  58 +++++-
 .../BrooklynMementoPersisterToObjectStore.java  |   4 +
 .../internal/AbstractManagementContext.java     |   6 +-
 .../rebind/RebindOnlySomeEntitiesTest.java      |  44 ++++
 .../entity/database/mysql/MySqlNodeImpl.java    |   2 +-
 .../brooklyn/rest/resources/ScriptResource.java |   1 +
 .../rest/util/BrooklynRestResourceUtils.java    |   2 +-
 11 files changed, 500 insertions(+), 140 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
new file mode 100644
index 0000000..fdcc810
--- /dev/null
+++ b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.rebind;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.basic.BrooklynObject;
+import brooklyn.basic.BrooklynObjectInternal;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
+import brooklyn.entity.rebind.transformer.CompoundTransformer;
+import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.mementos.BrooklynMementoPersister;
+import brooklyn.mementos.BrooklynMementoRawData;
+import brooklyn.mementos.BrooklynMementoRawData.Builder;
+import brooklyn.mementos.Memento;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableSet;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Pauses a set of existing entities, writes their state, applies a transformation, then reads them back.
+ */
+public class ActivePartialRebindIteration extends RebindIteration {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ActivePartialRebindIteration.class);
+    
+    protected Iterator<BrooklynObject> objectsToRebindInitial;
+    protected Collection<BrooklynObject> objectsToRebindFinal;
+    protected List<CompoundTransformer> transformers = MutableList.of();
+    
+    public ActivePartialRebindIteration(RebindManagerImpl rebindManager, 
+            ManagementNodeState mode,
+            ClassLoader classLoader, RebindExceptionHandler exceptionHandler,
+            Semaphore rebindActive, AtomicInteger readOnlyRebindCount, PersistenceActivityMetrics rebindMetrics, BrooklynMementoPersister persistenceStoreAccess
+            ) {
+        super(rebindManager, mode, classLoader, exceptionHandler, rebindActive, readOnlyRebindCount, rebindMetrics, persistenceStoreAccess);
+    }
+
+    @Override
+    protected boolean isRebindingActiveAgain() {
+        return true;
+    }
+    
+    public void setObjectIterator(Iterator<BrooklynObject> objectsToRebind) {
+        this.objectsToRebindInitial = objectsToRebind;
+    }
+    
+    public void applyTransformer(CompoundTransformer transformer) {
+        transformers.add(transformer);
+    }
+    
+    @Override
+    protected void doRun() throws Exception {
+        checkEnteringPhase(1);
+        Preconditions.checkState(readOnlyRebindCount.get()==Integer.MIN_VALUE, "Partial rebind in read-only mode not supported");
+        Preconditions.checkNotNull(objectsToRebindInitial, "Objects to rebind must be set");
+
+        LOG.debug("Partial rebind Rebinding ("+mode+") from "+rebindManager.getPersister().getBackingStoreDescription()+"...");
+
+        Builder mementoRawBuilder = BrooklynMementoRawData.builder();
+
+        /*
+         * TODO detail...
+         * This unmanages and re-manages. Not sure if that's ideal.
+         * Probably we should try to pause it, or switch to a model
+         * where each entity can be managed by any node.
+         */
+
+        objectsToRebindFinal = MutableSet.of();
+        while (objectsToRebindInitial.hasNext()) {
+            BrooklynObject bo = objectsToRebindInitial.next();
+            objectsToRebindFinal.add(bo);
+            
+            if (bo instanceof Entity) {
+                // if it's an entity, add all adjuncts. (if doing some sort of pause, that's maybe not necessary...)
+                objectsToRebindFinal.addAll( ((EntityInternal)bo).getPolicies() );
+                objectsToRebindFinal.addAll( ((EntityInternal)bo).getEnrichers() );
+                objectsToRebindFinal.addAll( ((EntityInternal)bo).feeds().getFeeds() );
+            }
+        }
+        
+        // TODO unmanage? pause?
+        // get serialization
+        for (BrooklynObject bo: objectsToRebindFinal) {
+            Memento m = ((BrooklynObjectInternal)bo).getRebindSupport().getMemento();
+            BrooklynMementoPersister p = rebindManager.getPersister();
+            String mr = ((BrooklynMementoPersisterToObjectStore)p).getMementoSerializer().toString(m);
+            mementoRawBuilder.put(BrooklynObjectType.of(bo), bo.getId(), mr);
+        }
+
+        // then rebuild
+        mementoRawData = mementoRawBuilder.build();
+        // TODO see comment in InitialFullRebindIteration
+        mementoManifest = persistenceStoreAccess.loadMementoManifest(mementoRawData, exceptionHandler);
+
+        determineStateFromManifestFiles();
+
+        // skip this phase, as catalog is not being changed
+        // (and we don't want to unload things)
+//        rebuildCatalog();
+        phase++;
+        
+        instantiateLocationsAndEntities();
+        instantiateMementos();
+        instantiateAdjuncts(instantiator); 
+        reconstructEverything();
+        associateAdjunctsWithEntities();
+        manageTheObjects();
+        finishingUp();
+    }
+
+    @Override
+    protected void determineStateFromManifestFiles() {
+        super.determineStateFromManifestFiles();
+        overwritingMaster = true;
+    }
+
+    @Override
+    protected Collection<String> getMementoRootEntities() {
+        // TODO must parents
+        return memento.getEntityIds();
+    }
+    
+    @Override
+    protected void cleanupOldLocations(Set<String> oldLocations) {
+        // not applicable here
+    }
+    @Override
+    protected void cleanupOldEntities(Set<String> oldEntities) {
+        // not applicable here
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
new file mode 100644
index 0000000..9b08392
--- /dev/null
+++ b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.rebind;
+
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.BrooklynLogging;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
+import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.management.internal.EntityManagerInternal;
+import brooklyn.management.internal.LocationManagerInternal;
+import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
+import brooklyn.mementos.BrooklynMementoPersister;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Does an un-bind (if necessary) and re-bind for a subset of items.  
+ */
+public class InitialFullRebindIteration extends RebindIteration {
+
+    private static final Logger LOG = LoggerFactory.getLogger(InitialFullRebindIteration.class);
+    
+    public InitialFullRebindIteration(RebindManagerImpl rebindManager, 
+            ManagementNodeState mode,
+            ClassLoader classLoader, RebindExceptionHandler exceptionHandler,
+            Semaphore rebindActive, AtomicInteger readOnlyRebindCount, PersistenceActivityMetrics rebindMetrics, BrooklynMementoPersister persistenceStoreAccess
+            ) {
+        super(rebindManager, mode, classLoader, exceptionHandler, rebindActive, readOnlyRebindCount, rebindMetrics, persistenceStoreAccess);
+    }
+
+    @Override
+    protected boolean isRebindingActiveAgain() {
+        return false;
+    }
+    
+    protected void doRun() throws Exception {
+        LOG.debug("Rebinding ("+mode+
+            (readOnlyRebindCount.get()>Integer.MIN_VALUE ? ", iteration "+readOnlyRebindCount : "")+
+            ") from "+rebindManager.getPersister().getBackingStoreDescription()+"...");
+
+        loadManifestFiles();
+        rebuildCatalog();
+        instantiateLocationsAndEntities();
+        instantiateMementos();
+        instantiateAdjuncts(instantiator); 
+        reconstructEverything();
+        associateAdjunctsWithEntities();
+        manageTheObjects();
+        finishingUp();
+    }
+
+    protected void loadManifestFiles() throws Exception {
+        checkEnteringPhase(1);
+        Preconditions.checkState(mementoRawData==null && mementoManifest==null, "Memento data should not yet be set when calling this");
+        
+        mementoRawData = persistenceStoreAccess.loadMementoRawData(exceptionHandler);
+        
+        // TODO building the manifests should be part of this class (or parent)
+        // it does not have anything to do with the persistence store!
+        mementoManifest = persistenceStoreAccess.loadMementoManifest(mementoRawData, exceptionHandler);
+
+        determineStateFromManifestFiles();
+        
+        if (mode!=ManagementNodeState.HOT_STANDBY && mode!=ManagementNodeState.HOT_BACKUP) {
+            if (!isEmpty) { 
+                LOG.info("Rebinding from "+getPersister().getBackingStoreDescription()+" for "+Strings.toLowerCase(Strings.toString(mode))+" "+managementContext.getManagementNodeId()+"...");
+            } else {
+                LOG.info("Rebind check: no existing state; will persist new items to "+getPersister().getBackingStoreDescription());
+            }
+
+            if (!managementContext.getEntityManager().getEntities().isEmpty() || !managementContext.getLocationManager().getLocations().isEmpty()) {
+                // this is discouraged if we were already master
+                Entity anEntity = Iterables.getFirst(managementContext.getEntityManager().getEntities(), null);
+                if (anEntity!=null && !((EntityInternal)anEntity).getManagementSupport().isReadOnly()) {
+                    overwritingMaster = true;
+                    LOG.warn("Rebind requested for "+mode+" node "+managementContext.getManagementNodeId()+" "
+                        + "when it already has active state; discouraged, "
+                        + "will likely overwrite: "+managementContext.getEntityManager().getEntities()+" and "+managementContext.getLocationManager().getLocations()+" and more");
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void cleanupOldLocations(Set<String> oldLocations) {
+        LocationManagerInternal locationManager = (LocationManagerInternal)managementContext.getLocationManager();
+        if (!oldLocations.isEmpty()) BrooklynLogging.log(LOG, overwritingMaster ? BrooklynLogging.LoggingLevel.WARN : BrooklynLogging.LoggingLevel.DEBUG, 
+            "Destroying unused locations on rebind: "+oldLocations);
+        for (String oldLocationId: oldLocations) {
+           locationManager.unmanage(locationManager.getLocation(oldLocationId), ManagementTransitionMode.REBINDING_DESTROYED); 
+        }
+    }
+
+    @Override
+    protected void cleanupOldEntities(Set<String> oldEntities) {
+        EntityManagerInternal entityManager = (EntityManagerInternal)managementContext.getEntityManager();
+        if (!oldEntities.isEmpty()) BrooklynLogging.log(LOG, overwritingMaster ? BrooklynLogging.LoggingLevel.WARN : BrooklynLogging.LoggingLevel.DEBUG, 
+            "Destroying unused entities on rebind: "+oldEntities);
+        for (String oldEntityId: oldEntities) {
+           entityManager.unmanage(entityManager.getEntity(oldEntityId), ManagementTransitionMode.REBINDING_DESTROYED); 
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java b/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
index 6392a5f..05730d7 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
@@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.basic.BrooklynObject;
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.Entity;
 import brooklyn.entity.Feed;
 import brooklyn.location.Location;
@@ -43,14 +44,19 @@ public class RebindContextLookupContext implements LookupContext {
     
     protected final RebindContextImpl rebindContext;
     protected final RebindExceptionHandler exceptionHandler;
+    protected final boolean lookInManagementContext;
     
     public RebindContextLookupContext(RebindContextImpl rebindContext, RebindExceptionHandler exceptionHandler) {
         this(null, rebindContext, exceptionHandler);
     }
     public RebindContextLookupContext(ManagementContext managementContext, RebindContextImpl rebindContext, RebindExceptionHandler exceptionHandler) {
+        this(managementContext, rebindContext, exceptionHandler, false);
+    }
+    public RebindContextLookupContext(ManagementContext managementContext, RebindContextImpl rebindContext, RebindExceptionHandler exceptionHandler, boolean lookInManagementContext) {
         this.managementContext = managementContext;
         this.rebindContext = rebindContext;
         this.exceptionHandler = exceptionHandler;
+        this.lookInManagementContext = lookInManagementContext;
     }
     
     @Override public ManagementContext lookupManagementContext() {
@@ -60,6 +66,9 @@ public class RebindContextLookupContext implements LookupContext {
     @Override public Entity lookupEntity(String id) {
         Entity result = rebindContext.getEntity(id);
         if (result == null) {
+            result = managementContext.lookup(id, Entity.class);
+        }
+        if (result == null) {
             result = exceptionHandler.onDanglingEntityRef(id);
         }
         return result;
@@ -68,6 +77,9 @@ public class RebindContextLookupContext implements LookupContext {
     @Override public Location lookupLocation(String id) {
         Location result = rebindContext.getLocation(id);
         if (result == null) {
+            result = managementContext.lookup(id, Location.class);
+        }
+        if (result == null) {
             result = exceptionHandler.onDanglingLocationRef(id);
         }
         return result;
@@ -76,6 +88,9 @@ public class RebindContextLookupContext implements LookupContext {
     @Override public Policy lookupPolicy(String id) {
         Policy result = rebindContext.getPolicy(id);
         if (result == null) {
+            result = managementContext.lookup(id, Policy.class);
+        }
+        if (result == null) {
             result = exceptionHandler.onDanglingPolicyRef(id);
         }
         return result;
@@ -84,6 +99,9 @@ public class RebindContextLookupContext implements LookupContext {
     @Override public Enricher lookupEnricher(String id) {
         Enricher result = rebindContext.getEnricher(id);
         if (result == null) {
+            result = managementContext.lookup(id, Enricher.class);
+        }
+        if (result == null) {
             result = exceptionHandler.onDanglingEnricherRef(id);
         }
         return result;
@@ -92,6 +110,9 @@ public class RebindContextLookupContext implements LookupContext {
     @Override public Feed lookupFeed(String id) {
         Feed result = rebindContext.getFeed(id);
         if (result == null) {
+            result = managementContext.lookup(id, Feed.class);
+        }
+        if (result == null) {
             result = exceptionHandler.onDanglingFeedRef(id);
         }
         return result;
@@ -101,6 +122,9 @@ public class RebindContextLookupContext implements LookupContext {
     public CatalogItem<?, ?> lookupCatalogItem(String id) {
         CatalogItem<?, ?> result = rebindContext.getCatalogItem(id);
         if (result == null) {
+            result = CatalogUtils.getCatalogItemOptionalVersion(managementContext, id);
+        }
+        if (result == null) {
             result = exceptionHandler.onDanglingCatalogItemRef(id);
         }
         return result;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 26ec642..b4288c7 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -25,7 +25,6 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.Callable;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -99,7 +98,6 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
@@ -144,59 +142,58 @@ Multi-phase deserialization:
       context entity of the Tasks.current() task.
    4. Propagate the context catalog item ID to children, adjuncts if they don't have one already.
 */
-public class RebindIteration {
+public abstract class RebindIteration {
 
     private static final Logger LOG = LoggerFactory.getLogger(RebindIteration.class);
     
-    private final RebindManagerImpl rebindManager;
+    protected final RebindManagerImpl rebindManager;
     
-    private final ClassLoader classLoader;
-    private final RebindExceptionHandler exceptionHandler;
-    private final ManagementNodeState mode;
-    private final ManagementContextInternal managementContext;
-
-    private final Semaphore rebindActive; 
-    private final AtomicInteger readOnlyRebindCount;
-    private final PersistenceActivityMetrics rebindMetrics;
-    private final BrooklynMementoPersister persistenceStoreAccess;
+    protected final ClassLoader classLoader;
+    protected final RebindExceptionHandler exceptionHandler;
+    protected final ManagementNodeState mode;
+    protected final ManagementContextInternal managementContext;
+
+    protected final Semaphore rebindActive; 
+    protected final AtomicInteger readOnlyRebindCount;
+    protected final PersistenceActivityMetrics rebindMetrics;
+    protected final BrooklynMementoPersister persistenceStoreAccess;
     
-    private final AtomicBoolean iterationStarted = new AtomicBoolean();
-    private final RebindContextImpl rebindContext;
-    private final Reflections reflections;
-    private final LookupContext lookupContext;
-    private final BrooklynObjectInstantiator instantiator;
+    protected final AtomicBoolean iterationStarted = new AtomicBoolean();
+    protected final RebindContextImpl rebindContext;
+    protected final Reflections reflections;
+    protected final LookupContext lookupContext;
+    protected final BrooklynObjectInstantiator instantiator;
     
     // populated in the course of a run
     
     // set on run start
     
-    private Stopwatch timer;
+    protected Stopwatch timer;
     /** phase is used to ensure our steps are run as we've expected, and documented (in javadoc at top).
      * it's worth the extra effort due to the complication and the subtleties. */
-    private int phase = 0;
+    protected int phase = 0;
 
     // set in first phase
     
-    private BrooklynMementoRawData mementoRawData;
-    private BrooklynMementoManifest mementoManifest;
-    private Boolean overwritingMaster;
-    private Boolean isEmpty;
+    protected BrooklynMementoRawData mementoRawData;
+    protected BrooklynMementoManifest mementoManifest;
+    protected Boolean overwritingMaster;
+    protected Boolean isEmpty;
 
     // set later on
     
-    private BrooklynMemento memento;
+    protected BrooklynMemento memento;
 
     // set near the end
     
-    private List<Application> applications;
+    protected List<Application> applications;
 
-    
     public RebindIteration(RebindManagerImpl rebindManager, 
             ManagementNodeState mode,
             ClassLoader classLoader, RebindExceptionHandler exceptionHandler,
             Semaphore rebindActive, AtomicInteger readOnlyRebindCount, PersistenceActivityMetrics rebindMetrics, BrooklynMementoPersister persistenceStoreAccess
             ) {
-        // NB: there is no particularly deep meaning in what is passed in vs what is lookup up from the RebindManager which calls us
+        // NB: there is no particularly deep meaning in what is passed in vs what is looked up from the RebindManager which calls us
         // (this is simply a refactoring of previous code to a new class)
         
         this.rebindManager = rebindManager;
@@ -214,6 +211,7 @@ public class RebindIteration {
         rebindContext = new RebindContextImpl(exceptionHandler, classLoader);
         reflections = new Reflections(classLoader);
         lookupContext = new RebindContextLookupContext(managementContext, rebindContext, exceptionHandler);
+        // TODO there seems to be a lot of redundancy between RebindContext and LookupContext; do we need both?
         rebindContext.setLookupContext(lookupContext);
         instantiator = new BrooklynObjectInstantiator(classLoader, rebindContext, reflections);
         
@@ -232,26 +230,9 @@ public class RebindIteration {
         return rebindContext;
     }
     
-    public void runFullRebind() {
-        runWithLock(new Callable<Void>() {
-           public Void call() throws Exception {
-               
-               loadManifestFiles();
-               rebuildCatalog();
-               instantiateLocationsAndEntities();
-               instantiateMementos();
-               instantiateAdjuncts(instantiator); 
-               reconstructEverything();
-               associateAdjunctsWithEntities();
-               manageTheObjects();
-               finishingUp();
-               
-               return null;
-           }
-        });
-    }
+    protected abstract void doRun() throws Exception;
     
-    protected void runWithLock(Callable<?> target) {
+    public void run() {
         if (iterationStarted.getAndSet(true)) {
             throw new IllegalStateException("Iteration "+this+" has already run; create a new instance for another rebind pass.");
         }
@@ -266,7 +247,7 @@ public class RebindIteration {
             timer = Stopwatch.createStarted();
             exceptionHandler.onStart(rebindContext);
 
-            target.call();
+            doRun();
             
             exceptionHandler.onDone();
             
@@ -295,52 +276,14 @@ public class RebindIteration {
             throw new IllegalStateException("Phase mismatch: should be phase "+targetPhase+" but is currently "+phase);
     }
     
-    protected void loadManifestFiles() throws Exception {
-        checkEnteringPhase(1);
-
-        //The manifest contains full catalog items mementos. Reading them at this stage means that
-        //we don't support references to entities/locations withing tags.
-
-        LOG.debug("Rebinding ("+mode+
-            (readOnlyRebindCount.get()>Integer.MIN_VALUE ? ", iteration "+readOnlyRebindCount : "")+
-            ") from "+rebindManager.getPersister().getBackingStoreDescription()+"...");
-
-        if (mementoRawData!=null || mementoManifest!=null)
-            throw new IllegalStateException("Memento data is already set");
-        
-        mementoRawData = persistenceStoreAccess.loadMementoRawData(exceptionHandler);
-        mementoManifest = persistenceStoreAccess.loadMementoManifest(mementoRawData, exceptionHandler);
-
-        determineStateFromManifestFiles();
-    }
-
     protected void determineStateFromManifestFiles() {
         checkContinuingPhase(1);
 
         overwritingMaster = false;
         isEmpty = mementoManifest.isEmpty();
-
-        if (mode!=ManagementNodeState.HOT_STANDBY && mode!=ManagementNodeState.HOT_BACKUP) {
-            if (!isEmpty) { 
-                LOG.info("Rebinding from "+getPersister().getBackingStoreDescription()+" for "+Strings.toLowerCase(Strings.toString(mode))+" "+managementContext.getManagementNodeId()+"...");
-            } else {
-                LOG.info("Rebind check: no existing state; will persist new items to "+getPersister().getBackingStoreDescription());
-            }
-
-            if (!managementContext.getEntityManager().getEntities().isEmpty() || !managementContext.getLocationManager().getLocations().isEmpty()) {
-                // this is discouraged if we were already master
-                Entity anEntity = Iterables.getFirst(managementContext.getEntityManager().getEntities(), null);
-                if (anEntity!=null && !((EntityInternal)anEntity).getManagementSupport().isReadOnly()) {
-                    overwritingMaster = true;
-                    LOG.warn("Rebind requested for "+mode+" node "+managementContext.getManagementNodeId()+" "
-                        + "when it already has active state; discouraged, "
-                        + "will likely overwrite: "+managementContext.getEntityManager().getEntities()+" and "+managementContext.getLocationManager().getLocations()+" and more");
-                }
-            }
-        }
     }
 
-    private void rebuildCatalog() {
+    protected void rebuildCatalog() {
         
         // build catalog early so we can load other things
         checkEnteringPhase(2);
@@ -415,7 +358,7 @@ public class RebindIteration {
         }
     }
 
-    private void instantiateLocationsAndEntities() {
+    protected void instantiateLocationsAndEntities() {
 
         checkEnteringPhase(3);
         
@@ -454,14 +397,14 @@ public class RebindIteration {
         }
     }
 
-    private void instantiateMementos() throws IOException {
+    protected void instantiateMementos() throws IOException {
         
         checkEnteringPhase(4);
         
         memento = persistenceStoreAccess.loadMemento(mementoRawData, lookupContext, exceptionHandler);
     }
 
-    private void instantiateAdjuncts(BrooklynObjectInstantiator instantiator) {
+    protected void instantiateAdjuncts(BrooklynObjectInstantiator instantiator) {
         
         checkEnteringPhase(5);
         
@@ -517,7 +460,7 @@ public class RebindIteration {
         }
     }
 
-    private void reconstructEverything() {
+    protected void reconstructEverything() {
         
         checkEnteringPhase(6);
         
@@ -622,7 +565,7 @@ public class RebindIteration {
         }
     }
 
-    private void associateAdjunctsWithEntities() {
+    protected void associateAdjunctsWithEntities() {
         
         checkEnteringPhase(7);
 
@@ -649,7 +592,7 @@ public class RebindIteration {
         }
     }
 
-    private void manageTheObjects() {
+    protected void manageTheObjects() {
 
         checkEnteringPhase(8);
         
@@ -658,7 +601,7 @@ public class RebindIteration {
         Set<String> oldLocations = Sets.newLinkedHashSet(locationManager.getLocationIds());
         for (Location location: rebindContext.getLocations()) {
             ManagementTransitionMode oldMode = locationManager.getLastManagementTransitionMode(location.getId());
-            locationManager.setManagementTransitionMode(location, RebindManagerImpl.computeMode(managementContext, location, oldMode, rebindContext.isReadOnly(location)) );
+            locationManager.setManagementTransitionMode(location, RebindManagerImpl.computeMode(managementContext, location, oldMode, rebindContext.isReadOnly(location), isRebindingActiveAgain()) );
             if (oldMode!=null)
                 oldLocations.remove(location.getId());
         }
@@ -672,12 +615,8 @@ public class RebindIteration {
                 }
             }
         }
-        // destroy old
-        if (!oldLocations.isEmpty()) BrooklynLogging.log(LOG, overwritingMaster ? BrooklynLogging.LoggingLevel.WARN : BrooklynLogging.LoggingLevel.DEBUG, 
-            "Destroying unused locations on rebind: "+oldLocations);
-        for (String oldLocationId: oldLocations) {
-           locationManager.unmanage(locationManager.getLocation(oldLocationId), ManagementTransitionMode.REBINDING_DESTROYED); 
-        }
+        // TODO could also see about purging unreferenced locations
+        cleanupOldLocations(oldLocations);
         
         // Manage the top-level apps (causing everything under them to become managed)
         logRebindingDebug("RebindManager managing entities");
@@ -685,36 +624,41 @@ public class RebindIteration {
         Set<String> oldEntities = Sets.newLinkedHashSet(entityManager.getEntityIds());
         for (Entity entity: rebindContext.getEntities()) {
             ManagementTransitionMode oldMode = entityManager.getLastManagementTransitionMode(entity.getId());
-            entityManager.setManagementTransitionMode(entity, RebindManagerImpl.computeMode(managementContext,entity, oldMode, rebindContext.isReadOnly(entity)) );
+            entityManager.setManagementTransitionMode(entity, RebindManagerImpl.computeMode(managementContext, entity, oldMode, rebindContext.isReadOnly(entity), isRebindingActiveAgain()) );
             if (oldMode!=null)
                 oldEntities.remove(entity.getId());
         }
         List<Application> apps = Lists.newArrayList();
-        for (String appId : memento.getApplicationIds()) {
-            Entity entity = rebindContext.getEntity(appId);
+        for (String rootId : getMementoRootEntities()) {
+            Entity entity = rebindContext.getEntity(rootId);
             if (entity == null) {
                 // usually because of creation-failure, when not using fail-fast
-                exceptionHandler.onNotFound(BrooklynObjectType.ENTITY, appId);
+                exceptionHandler.onNotFound(BrooklynObjectType.ENTITY, rootId);
             } else {
                 try {
                     entityManager.manageRebindedRoot(entity);
                 } catch (Exception e) {
                     exceptionHandler.onManageFailed(BrooklynObjectType.ENTITY, entity, e);
                 }
-                apps.add((Application)entity);
+                if (entity instanceof Application)
+                    apps.add((Application)entity);
             }
         }
-        // destroy old
-        if (!oldLocations.isEmpty()) BrooklynLogging.log(LOG, overwritingMaster ? BrooklynLogging.LoggingLevel.WARN : BrooklynLogging.LoggingLevel.DEBUG, 
-            "Destroying unused entities on rebind: "+oldEntities);
-        for (String oldEntityId: oldEntities) {
-           entityManager.unmanage(entityManager.getEntity(oldEntityId), ManagementTransitionMode.REBINDING_DESTROYED); 
-        }
+        cleanupOldEntities(oldEntities);
 
         this.applications = apps;
     }
 
-    private void finishingUp() {
+    protected abstract boolean isRebindingActiveAgain();
+
+    protected Collection<String> getMementoRootEntities() {
+        return memento.getApplicationIds();
+    }
+
+    protected abstract void cleanupOldLocations(Set<String> oldLocations);
+    protected abstract void cleanupOldEntities(Set<String> oldEntities);
+
+    protected void finishingUp() {
         
         checkContinuingPhase(8);
         
@@ -733,10 +677,10 @@ public class RebindIteration {
         }
 
         // Return the top-level applications
-        logRebindingDebug("RebindManager complete; apps: {}", memento.getApplicationIds());
+        logRebindingDebug("RebindManager complete; apps: {}", getMementoRootEntities());
     }
 
-    private void noteErrors(final RebindExceptionHandler exceptionHandler, Exception primaryException) {
+    protected void noteErrors(final RebindExceptionHandler exceptionHandler, Exception primaryException) {
         List<Exception> exceptions = exceptionHandler.getExceptions();
         List<String> warnings = exceptionHandler.getWarnings();
         if (primaryException!=null || !exceptions.isEmpty() || !warnings.isEmpty()) {
@@ -748,7 +692,7 @@ public class RebindIteration {
         }
     }
     
-    private String findCatalogItemId(ClassLoader cl, Map<String, EntityMementoManifest> entityIdToManifest, EntityMementoManifest entityManifest) {
+    protected String findCatalogItemId(ClassLoader cl, Map<String, EntityMementoManifest> entityIdToManifest, EntityMementoManifest entityManifest) {
         if (entityManifest.getCatalogItemId() != null) {
             return entityManifest.getCatalogItemId();
         }
@@ -813,19 +757,19 @@ public class RebindIteration {
         return null;
     }
 
-    private class BrooklynObjectInstantiator {
+    protected class BrooklynObjectInstantiator {
 
-        private final ClassLoader classLoader;
-        private final RebindContextImpl rebindContext;
-        private final Reflections reflections;
+        protected final ClassLoader classLoader;
+        protected final RebindContextImpl rebindContext;
+        protected final Reflections reflections;
         
-        private BrooklynObjectInstantiator(ClassLoader classLoader, RebindContextImpl rebindContext, Reflections reflections) {
+        protected BrooklynObjectInstantiator(ClassLoader classLoader, RebindContextImpl rebindContext, Reflections reflections) {
             this.classLoader = classLoader;
             this.rebindContext = rebindContext;
             this.reflections = reflections;
         }
 
-        private Entity newEntity(String entityId, String entityType, String catalogItemId) {
+        protected Entity newEntity(String entityId, String entityType, String catalogItemId) {
             Class<? extends Entity> entityClazz = load(Entity.class, entityType, catalogItemId, entityId);
 
             Entity entity;
@@ -868,17 +812,17 @@ public class RebindIteration {
             return entity;
         }
 
-        private void setCatalogItemId(BrooklynObject item, String catalogItemId) {
+        protected void setCatalogItemId(BrooklynObject item, String catalogItemId) {
             if (catalogItemId!=null) {
                 ((BrooklynObjectInternal)item).setCatalogItemId(catalogItemId);
             }
         }
 
-        private <T extends BrooklynObject> Class<? extends T> load(Class<T> bType, Memento memento) {
+        protected <T extends BrooklynObject> Class<? extends T> load(Class<T> bType, Memento memento) {
             return load(bType, memento.getType(), memento.getCatalogItemId(), memento.getId());
         }
         @SuppressWarnings("unchecked")
-        private <T extends BrooklynObject> Class<? extends T> load(Class<T> bType, String jType, String catalogItemId, String contextSuchAsId) {
+        protected <T extends BrooklynObject> Class<? extends T> load(Class<T> bType, String jType, String catalogItemId, String contextSuchAsId) {
             checkNotNull(jType, "Type of %s (%s) must not be null", contextSuchAsId, bType.getSimpleName());
             if (catalogItemId != null) {
                 BrooklynClassLoadingContext loader = getLoadingContextFromCatalogItemId(catalogItemId, classLoader, rebindContext);
@@ -909,7 +853,7 @@ public class RebindIteration {
             }
         }
 
-        private BrooklynClassLoadingContext getLoadingContextFromCatalogItemId(String catalogItemId, ClassLoader classLoader, RebindContext rebindContext) {
+        protected BrooklynClassLoadingContext getLoadingContextFromCatalogItemId(String catalogItemId, ClassLoader classLoader, RebindContext rebindContext) {
             Preconditions.checkNotNull(catalogItemId, "catalogItemId required (should not be null)");
             CatalogItem<?, ?> catalogItem = rebindContext.lookup().lookupCatalogItem(catalogItemId);
             if (catalogItem != null) {
@@ -922,7 +866,7 @@ public class RebindIteration {
         /**
          * Constructs a new location, passing to its constructor the location id and all of memento.getFlags().
          */
-        private Location newLocation(String locationId, String locationType) {
+        protected Location newLocation(String locationId, String locationType) {
             Class<? extends Location> locationClazz = reflections.loadClass(locationType, Location.class);
 
             if (InternalFactory.isNewStyle(locationClazz)) {
@@ -953,7 +897,7 @@ public class RebindIteration {
         /**
          * Constructs a new policy, passing to its constructor the policy id and all of memento.getConfig().
          */
-        private Policy newPolicy(PolicyMemento memento) {
+        protected Policy newPolicy(PolicyMemento memento) {
             String id = memento.getId();
             Class<? extends Policy> policyClazz = load(Policy.class, memento.getType(), memento.getCatalogItemId(), id);
             
@@ -986,7 +930,7 @@ public class RebindIteration {
         /**
          * Constructs a new enricher, passing to its constructor the enricher id and all of memento.getConfig().
          */
-        private Enricher newEnricher(EnricherMemento memento) {
+        protected Enricher newEnricher(EnricherMemento memento) {
             Class<? extends Enricher> enricherClazz = load(Enricher.class, memento);
             String id = memento.getId();
 
@@ -1019,7 +963,7 @@ public class RebindIteration {
         /**
          * Constructs a new enricher, passing to its constructor the enricher id and all of memento.getConfig().
          */
-        private Feed newFeed(FeedMemento memento) {
+        protected Feed newFeed(FeedMemento memento) {
             Class<? extends Feed> feedClazz = load(Feed.class, memento);
             String id = memento.getId();
 
@@ -1039,7 +983,7 @@ public class RebindIteration {
         }
 
         @SuppressWarnings({ "rawtypes" })
-        private CatalogItem<?, ?> newCatalogItem(CatalogItemMemento memento) {
+        protected CatalogItem<?, ?> newCatalogItem(CatalogItemMemento memento) {
             String id = memento.getId();
             // catalog item subtypes are internal to brooklyn, not in osgi
             String itemType = checkNotNull(memento.getType(), "catalog item type of %s must not be null in memento", id);
@@ -1047,7 +991,7 @@ public class RebindIteration {
             return invokeConstructor(reflections, clazz, new Object[]{});
         }
 
-        private <T> T invokeConstructor(Reflections reflections, Class<T> clazz, Object[]... possibleArgs) {
+        protected <T> T invokeConstructor(Reflections reflections, Class<T> clazz, Object[]... possibleArgs) {
             for (Object[] args : possibleArgs) {
                 try {
                     Optional<T> v = Reflections.invokeConstructorWithArgs(clazz, args, true);
@@ -1071,7 +1015,7 @@ public class RebindIteration {
     }
 
     /** logs at debug, except during subsequent read-only rebinds, in which it logs trace */
-    private void logRebindingDebug(String message, Object... args) {
+    protected void logRebindingDebug(String message, Object... args) {
         if (shouldLogRebinding()) {
             LOG.debug(message, args);
         } else {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index b1a02c1..608f75c 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -36,7 +36,9 @@ import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.ConfigKey;
 import brooklyn.enricher.basic.AbstractEnricher;
 import brooklyn.entity.Application;
+import brooklyn.entity.Entity;
 import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
 import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
 import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
 import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils.CreateBackupMode;
@@ -53,6 +55,7 @@ import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitio
 import brooklyn.mementos.BrooklynMementoPersister;
 import brooklyn.mementos.BrooklynMementoRawData;
 import brooklyn.mementos.TreeNode;
+import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.collections.QuorumCheck;
 import brooklyn.util.collections.QuorumCheck.QuorumChecks;
@@ -361,6 +364,33 @@ public class RebindManagerImpl implements RebindManager {
         if (persistenceStoreAccess != null) persistenceStoreAccess.stop(true);
     }
     
+    public void testRebindNodeXXX(String ...objectsToRebindIds) {
+        final ClassLoader classLoader = 
+            managementContext.getCatalog().getRootClassLoader();
+        final RebindExceptionHandler exceptionHandler = 
+            RebindExceptionHandlerImpl.builder()
+                .danglingRefFailureMode(danglingRefFailureMode)
+                .danglingRefQuorumRequiredHealthy(danglingRefsQuorumRequiredHealthy)
+                .rebindFailureMode(rebindFailureMode)
+                .addPolicyFailureMode(addPolicyFailureMode)
+                .loadPolicyFailureMode(loadPolicyFailureMode)
+                .build();
+        final ManagementNodeState mode = getRebindMode();
+
+        ActivePartialRebindIteration iteration = new ActivePartialRebindIteration(this, mode, classLoader, exceptionHandler,
+            rebindActive, readOnlyRebindCount, rebindMetrics, persistenceStoreAccess);
+
+        List<BrooklynObject> objectsToRebind = MutableList.of();
+        for (String objectId: objectsToRebindIds) {
+            BrooklynObject obj = managementContext.lookup(objectId);
+            if (obj instanceof Entity) obj = Entities.deproxy((Entity)obj);
+            objectsToRebind.add(obj);
+        }
+        
+        iteration.setObjectIterator(objectsToRebind.iterator());
+        iteration.run();
+    }
+    
     protected ManagementNodeState getRebindMode() {
         if (managementContext==null) throw new IllegalStateException("Invalid "+this+": no management context");
         if (!(managementContext.getHighAvailabilityManager() instanceof HighAvailabilityManagerImpl))
@@ -489,10 +519,10 @@ public class RebindManagerImpl implements RebindManager {
     }
     
     protected List<Application> rebindImpl(final ClassLoader classLoader, final RebindExceptionHandler exceptionHandler, ManagementNodeState mode) {
-        RebindIteration iteration = new RebindIteration(this, mode, classLoader, exceptionHandler,
+        RebindIteration iteration = new InitialFullRebindIteration(this, mode, classLoader, exceptionHandler,
             rebindActive, readOnlyRebindCount, rebindMetrics, persistenceStoreAccess);
         
-        iteration.runFullRebind();
+        iteration.run();
         
         if (firstRebindAppCount==null) {
             firstRebindAppCount = iteration.getApplications().size();
@@ -503,23 +533,41 @@ public class RebindManagerImpl implements RebindManager {
         return iteration.getApplications();
     }
 
+    @Deprecated /** @deprecated since 0.7.0, use method with more args */
     static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, ManagementTransitionMode oldMode, boolean isNowReadOnly) {
-        return computeMode(mgmt, item, oldMode==null ? null : oldMode.wasReadOnly(), isNowReadOnly);
+        return computeMode(mgmt, item, oldMode==null ? null : oldMode.wasReadOnly(), isNowReadOnly, false);
     }
 
+    @Deprecated /** @deprecated since 0.7.0, use method with more args */
     static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, Boolean wasReadOnly, boolean isNowReadOnly) {
+        return computeMode(mgmt, item, wasReadOnly, isNowReadOnly, false);
+    }
+
+    static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, ManagementTransitionMode oldMode, boolean isNowReadOnly, boolean isRebindingActiveAgain) {
+        return computeMode(mgmt, item, oldMode==null ? null : oldMode.wasReadOnly(), isNowReadOnly, isRebindingActiveAgain);
+    }
+
+    static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, Boolean wasReadOnly, boolean isNowReadOnly, boolean isRebindingActiveAgain) {
         if (wasReadOnly==null) {
             // not known
             if (Boolean.TRUE.equals(isNowReadOnly)) return ManagementTransitionMode.REBINDING_READONLY;
-            else return ManagementTransitionMode.REBINDING_CREATING;
+            else {
+                // TODO is this needed?
+                return ManagementTransitionMode.REBINDING_CREATING;
+            }
         } else {
-            if (wasReadOnly && isNowReadOnly)
+            if (isRebindingActiveAgain) {
+                if (wasReadOnly || isNowReadOnly)
+                    throw new IllegalStateException("Cannot be rebinding again to something where read-only before/after is "+wasReadOnly+"/"+isNowReadOnly);
+                return ManagementTransitionMode.REBINDING_ACTIVE_AGAIN;
+            } else if (wasReadOnly && isNowReadOnly)
                 return ManagementTransitionMode.REBINDING_READONLY;
             else if (wasReadOnly)
                 return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY;
             else if (isNowReadOnly)
                 return ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY;
             else {
+                if (isRebindingActiveAgain)
                 // for the most part we handle this correctly, although there may be leaks; see HighAvailabilityManagerInMemoryTest.testLocationsStillManagedCorrectlyAfterDoublePromotion
                 LOG.warn("Node "+(mgmt!=null ? mgmt.getManagementNodeId() : null)+" rebinding as master when already master (discouraged, may have stale references); for: "+item);
                 return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index 1d8a685..d84bf05 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -143,6 +143,10 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
             }}));
     }
 
+    public MementoSerializer<Object> getMementoSerializer() {
+        return getSerializerWithStandardClassLoader();
+    }
+    
     protected MementoSerializer<Object> getSerializerWithStandardClassLoader() {
         return serializerWithStandardClassLoader;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
index 322de27..14fe100 100644
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -443,7 +443,11 @@ public abstract class AbstractManagementContext implements ManagementContextInte
         Object result;
         result = getEntityManager().getEntity(id);
         if (result!=null && type.isInstance(result)) return (T)result;
-        // TODO policies, etc
+        
+        result = getLocationManager().getLocation(id);
+        if (result!=null && type.isInstance(result)) return (T)result;
+
+        // TODO policies, enrichers, feeds
         return null;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/core/src/test/java/brooklyn/entity/rebind/RebindOnlySomeEntitiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindOnlySomeEntitiesTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindOnlySomeEntitiesTest.java
new file mode 100644
index 0000000..a7b54b7
--- /dev/null
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindOnlySomeEntitiesTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.rebind;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotSame;
+
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.test.entity.TestEntity;
+
+public class RebindOnlySomeEntitiesTest extends RebindTestFixtureWithApp {
+
+    @Test
+    public void testRebindOnlySomeSimple() throws Exception {
+        TestEntity c1 = origApp.addChild(EntitySpec.create(TestEntity.class));
+        Entities.manage(c1);
+        
+        // XXX
+        newApp = rebind();
+        
+        assertNotSame(newApp, origApp);
+        assertEquals(newApp.getId(), origApp.getId());
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
index 07aacd5..4f8606a 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
@@ -93,8 +93,8 @@ public class MySqlNodeImpl extends SoftwareProcessImpl implements MySqlNode {
          * So can extract lots of sensors from that.
          */
         Maybe<SshMachineLocation> machine = Locations.findUniqueSshMachineLocation(getLocations());
-        String cmd = getDriver().getStatusCmd();
         if (machine.isPresent()) {
+            String cmd = getDriver().getStatusCmd();
             feed = SshFeed.builder()
                     .entity(this)
                     .period(Duration.FIVE_SECONDS)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/usage/rest-server/src/main/java/brooklyn/rest/resources/ScriptResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/ScriptResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/ScriptResource.java
index 84909da..9a8cef9 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/ScriptResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/ScriptResource.java
@@ -75,6 +75,7 @@ public class ScriptResource extends AbstractBrooklynRestResource implements Scri
             if (session!=null)
                 session.setAttribute(USER_LAST_VALUE_SESSION_ATTRIBUTE, value);
         } catch (Throwable t) {
+            log.warn("Problem in user-supplied script: "+t, t);
             problem = t;
         } finally {
             stdout.end();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0fb0c633/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
index b2fd4a5..2dbed30 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -146,7 +146,7 @@ public class BrooklynRestResourceUtils {
             
             if (app==null || app.equals(findTopLevelApplication(e))) return e;
             throw WebResourceUtils.preconditionFailed("Application '%s' specified does not match application '%s' to which entity '%s' (%s) is associated", 
-                    application, e.getApplication().getId(), entity, e);
+                    application, e.getApplication()==null ? null : e.getApplication().getId(), entity, e);
         }
         if (application==null)
             throw WebResourceUtils.notFound("Cannot find entity '%s': no known ID and application not supplied for searching", entity);


[20/22] incubator-brooklyn git commit: partial rebind - more code review, esp much better javadoc

Posted by he...@apache.org.
partial rebind - more code review, esp much better javadoc


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

Branch: refs/heads/master
Commit: b13cb63a4a23e847a3595a79a6fa2aab2609008a
Parents: 491ca49
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Feb 9 14:23:18 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Feb 9 14:23:18 2015 +0000

----------------------------------------------------------------------
 .../java/brooklyn/management/EntityManager.java    |  2 ++
 .../rebind/ActivePartialRebindIteration.java       |  8 +++++++-
 .../brooklyn/entity/rebind/RebindContextImpl.java  | 13 +++++++------
 .../entity/rebind/RebindContextLookupContext.java  |  9 +--------
 .../brooklyn/entity/rebind/RebindIteration.java    |  9 ++-------
 .../brooklyn/entity/rebind/RebindManagerImpl.java  | 17 +++++++++++++++--
 .../rebind/persister/XmlMementoSerializer.java     |  1 +
 .../internal/BrooklynObjectManagementMode.java     |  1 +
 .../internal/ManagementTransitionInfo.java         |  2 ++
 .../internal/ManagementTransitionMode.java         |  6 ++++++
 .../BrooklynMementoPersisterTestFixture.java       |  6 ++----
 11 files changed, 46 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/api/src/main/java/brooklyn/management/EntityManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/management/EntityManager.java b/api/src/main/java/brooklyn/management/EntityManager.java
index 5a709fa..2780c1a 100644
--- a/api/src/main/java/brooklyn/management/EntityManager.java
+++ b/api/src/main/java/brooklyn/management/EntityManager.java
@@ -113,6 +113,8 @@ public interface EntityManager {
      * this might push it out to one or more remote management nodes.
      * Manage an entity.
      */
+    // TODO manage and unmanage without arguments should be changed to take an explicit ManagementTransitionMode
+    // (but that class is not currently in the API project)
     void manage(Entity e);
     
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
index ff315ca..76e600a 100644
--- a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
@@ -46,7 +46,8 @@ import brooklyn.util.collections.MutableSet;
 import com.google.common.base.Preconditions;
 
 /**
- * Pauses a set of existing entities, writes their state, applies a transformation, then reads them back.
+ * Replaces a set of existing entities (and their adjunts) and locations:
+ * writes their state, applies a transformation, then reads the state back.
  */
 public class ActivePartialRebindIteration extends RebindIteration {
 
@@ -88,6 +89,11 @@ public class ActivePartialRebindIteration extends RebindIteration {
         super.doRun();
     }
     
+    /** Rather than loading from the remote persistence store (as {@link InitialFullRebindIteration} does),
+     * this constructs the memento data by serializing the objects we are replacing. 
+     * TODO: Currently this does not do any pausing or unmanagement or guarding write access,
+     * so there is a short window for data loss between this write and the subsequent read.
+     */
     @Override
     protected void loadManifestFiles() throws Exception {
         checkEnteringPhase(1);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
index a581c7d..b7eba1a 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
@@ -28,6 +28,7 @@ import brooklyn.catalog.CatalogItem;
 import brooklyn.entity.Entity;
 import brooklyn.entity.Feed;
 import brooklyn.location.Location;
+import brooklyn.management.ManagementContext;
 import brooklyn.mementos.BrooklynMementoPersister.LookupContext;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.Policy;
@@ -45,14 +46,18 @@ public class RebindContextImpl implements RebindContext {
     private final Map<String, CatalogItem<?, ?>> catalogItems = Maps.newLinkedHashMap();
     
     private final ClassLoader classLoader;
+    @SuppressWarnings("unused")
+    private final ManagementContext mgmt;
     private final RebindExceptionHandler exceptionHandler;
-    private LookupContext lookupContext;
+    private final LookupContext lookupContext;
     
     private boolean allAreReadOnly = false;
     
-    public RebindContextImpl(RebindExceptionHandler exceptionHandler, ClassLoader classLoader) {
+    public RebindContextImpl(ManagementContext mgmt, RebindExceptionHandler exceptionHandler, ClassLoader classLoader) {
+        this.mgmt = checkNotNull(mgmt, "mgmt");
         this.exceptionHandler = checkNotNull(exceptionHandler, "exceptionHandler");
         this.classLoader = checkNotNull(classLoader, "classLoader");
+        this.lookupContext = new RebindContextLookupContext(mgmt, this, exceptionHandler);
     }
 
     public void registerEntity(String id, Entity entity) {
@@ -171,10 +176,6 @@ public class RebindContextImpl implements RebindContext {
         return allAreReadOnly;
     }
 
-    public void setLookupContext(LookupContext lookupContext) {
-        this.lookupContext = lookupContext;
-    }
-    
     @Override
     public LookupContext lookup() {
         return lookupContext;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java b/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
index 05730d7..7024bfe 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
@@ -34,6 +34,7 @@ import brooklyn.mementos.BrooklynMementoPersister.LookupContext;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.Policy;
 
+/** Looks in {@link RebindContext} <i>and</i> {@link ManagementContext} to find entities, locations, etc. */
 public class RebindContextLookupContext implements LookupContext {
     
     @SuppressWarnings("unused")
@@ -44,19 +45,11 @@ public class RebindContextLookupContext implements LookupContext {
     
     protected final RebindContextImpl rebindContext;
     protected final RebindExceptionHandler exceptionHandler;
-    protected final boolean lookInManagementContext;
     
-    public RebindContextLookupContext(RebindContextImpl rebindContext, RebindExceptionHandler exceptionHandler) {
-        this(null, rebindContext, exceptionHandler);
-    }
     public RebindContextLookupContext(ManagementContext managementContext, RebindContextImpl rebindContext, RebindExceptionHandler exceptionHandler) {
-        this(managementContext, rebindContext, exceptionHandler, false);
-    }
-    public RebindContextLookupContext(ManagementContext managementContext, RebindContextImpl rebindContext, RebindExceptionHandler exceptionHandler, boolean lookInManagementContext) {
         this.managementContext = managementContext;
         this.rebindContext = rebindContext;
         this.exceptionHandler = exceptionHandler;
-        this.lookInManagementContext = lookInManagementContext;
     }
     
     @Override public ManagementContext lookupManagementContext() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 3d22d0b..de956ae 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -73,7 +73,6 @@ import brooklyn.mementos.BrooklynMemento;
 import brooklyn.mementos.BrooklynMementoManifest;
 import brooklyn.mementos.BrooklynMementoManifest.EntityMementoManifest;
 import brooklyn.mementos.BrooklynMementoPersister;
-import brooklyn.mementos.BrooklynMementoPersister.LookupContext;
 import brooklyn.mementos.BrooklynMementoRawData;
 import brooklyn.mementos.CatalogItemMemento;
 import brooklyn.mementos.EnricherMemento;
@@ -163,7 +162,6 @@ public abstract class RebindIteration {
     protected final AtomicBoolean iterationStarted = new AtomicBoolean();
     protected final RebindContextImpl rebindContext;
     protected final Reflections reflections;
-    protected final LookupContext lookupContext;
     protected final BrooklynObjectInstantiator instantiator;
     
     // populated in the course of a run
@@ -210,11 +208,8 @@ public abstract class RebindIteration {
         this.persistenceStoreAccess = persistenceStoreAccess;
         
         managementContext = rebindManager.getManagementContext();
-        rebindContext = new RebindContextImpl(exceptionHandler, classLoader);
+        rebindContext = new RebindContextImpl(managementContext, exceptionHandler, classLoader);
         reflections = new Reflections(classLoader);
-        lookupContext = new RebindContextLookupContext(managementContext, rebindContext, exceptionHandler);
-        // TODO there seems to be a lot of redundancy between RebindContext and LookupContext; do we need both?
-        rebindContext.setLookupContext(lookupContext);
         instantiator = new BrooklynObjectInstantiator(classLoader, rebindContext, reflections);
         
         if (mode==ManagementNodeState.HOT_STANDBY || mode==ManagementNodeState.HOT_BACKUP) {
@@ -422,7 +417,7 @@ public abstract class RebindIteration {
         
         checkEnteringPhase(4);
         
-        memento = persistenceStoreAccess.loadMemento(mementoRawData, lookupContext, exceptionHandler);
+        memento = persistenceStoreAccess.loadMemento(mementoRawData, rebindContext.lookup(), exceptionHandler);
     }
 
     protected void instantiateAdjuncts(BrooklynObjectInstantiator instantiator) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index ca85a03..5d155cb 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -68,6 +68,8 @@ import brooklyn.util.time.Duration;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.collect.Iterators;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
@@ -368,6 +370,10 @@ public class RebindManagerImpl implements RebindManager {
     public void rebindPartialActive(CompoundTransformer transformer, Iterator<BrooklynObject> objectsToRebind) {
         final ClassLoader classLoader = 
             managementContext.getCatalog().getRootClassLoader();
+        // TODO we might want different exception handling for partials;
+        // failure at various points should leave proxies in a sensible state,
+        // either pointing at old or at new, though this is relatively untested,
+        // and some things e.g. policies might not be properly started
         final RebindExceptionHandler exceptionHandler = 
             RebindExceptionHandlerImpl.builder()
                 .danglingRefFailureMode(danglingRefFailureMode)
@@ -381,7 +387,15 @@ public class RebindManagerImpl implements RebindManager {
         ActivePartialRebindIteration iteration = new ActivePartialRebindIteration(this, mode, classLoader, exceptionHandler,
             rebindActive, readOnlyRebindCount, rebindMetrics, persistenceStoreAccess);
 
-        iteration.setObjectIterator(objectsToRebind);
+        iteration.setObjectIterator(Iterators.transform(objectsToRebind,
+            new Function<BrooklynObject,BrooklynObject>() {
+                @Override
+                public BrooklynObject apply(BrooklynObject obj) {
+                    // entities must be deproxied
+                    if (obj instanceof Entity) obj = Entities.deproxy((Entity)obj);
+                    return obj;
+                }
+            }));
         if (transformer!=null) iteration.applyTransformer(transformer);
         iteration.run();
     }
@@ -390,7 +404,6 @@ public class RebindManagerImpl implements RebindManager {
         List<BrooklynObject> objectsToRebind = MutableList.of();
         for (String objectId: objectsToRebindIds) {
             BrooklynObject obj = managementContext.lookup(objectId);
-            if (obj instanceof Entity) obj = Entities.deproxy((Entity)obj);
             objectsToRebind.add(obj);
         }
         rebindPartialActive(transformer, objectsToRebind.iterator());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
index 78644b3..0d88bea 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
@@ -496,6 +496,7 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento
                     Thread oldOwner = xstreamLockOwner.getAndSet(null);
                     throw new IllegalStateException("xstream was locked by "+oldOwner+" but unlock attempt by "+Thread.currentThread());
                 }
+                xstreamLockOwner.notifyAll();
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
index a005c2d..dd9d8bc 100644
--- a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
+++ b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
@@ -18,6 +18,7 @@
  */
 package brooklyn.management.internal;
 
+/** Indicates how an entity/location/adjunct is treated at a given {@link ManagementContext} */
 public enum BrooklynObjectManagementMode {
     /** item does not exist, not in memory, nor persisted (e.g. creating for first time, or finally destroying) */
     NONEXISTENT, 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
index 550c977..8b3c43d 100644
--- a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
+++ b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
@@ -20,6 +20,8 @@ package brooklyn.management.internal;
 
 import brooklyn.management.ManagementContext;
 
+/** Stores a management transition mode, and the management context. */
+// TODO does this class really pull its weight?
 public class ManagementTransitionInfo {
 
     final ManagementContext mgmtContext;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java b/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
index 3c630e1..1d25902 100644
--- a/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
+++ b/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
@@ -23,6 +23,12 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
 
+/**
+ * Records details of a management transition, specifically the {@link BrooklynObjectManagementMode} before and after,
+ * and allows easy checking of various aspects of that.
+ * <p>
+ * This helps make code readable and keep correct logic if we expand/change the management modes.
+ */
 public class ManagementTransitionMode {
 
     private static final Logger log = LoggerFactory.getLogger(ManagementTransitionMode.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b13cb63a/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java
index 3306a32..9c608f2 100644
--- a/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java
@@ -36,7 +36,6 @@ import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
 import brooklyn.entity.rebind.RebindContextImpl;
-import brooklyn.entity.rebind.RebindContextLookupContext;
 import brooklyn.entity.rebind.RebindManager.RebindFailureMode;
 import brooklyn.entity.rebind.RebindTestUtils;
 import brooklyn.entity.rebind.RecordingRebindExceptionHandler;
@@ -104,14 +103,13 @@ public abstract class BrooklynMementoPersisterTestFixture {
         RebindTestUtils.waitForPersisted(localManagementContext);
         
         RecordingRebindExceptionHandler failFast = new RecordingRebindExceptionHandler(RebindFailureMode.FAIL_FAST, RebindFailureMode.FAIL_FAST);
-        RebindContextImpl rebindContext = new RebindContextImpl(failFast, classLoader);
-        RebindContextLookupContext lookupContext = new RebindContextLookupContext(localManagementContext, rebindContext, failFast);
+        RebindContextImpl rebindContext = new RebindContextImpl(localManagementContext, failFast, classLoader);
         // here we force these two to be reegistered in order to resolve the enricher and policy
         // (normally rebind will do that after loading the manifests, but in this test we are just looking at persistence/manifest)
         rebindContext.registerEntity(app.getId(), app);
         rebindContext.registerEntity(entity.getId(), entity);
         
-        BrooklynMemento reloadedMemento = persister.loadMemento(null, lookupContext, failFast);
+        BrooklynMemento reloadedMemento = persister.loadMemento(null, rebindContext.lookup(), failFast);
         return reloadedMemento;
     }
     


[12/22] incubator-brooklyn git commit: test that changing version applies to specs

Posted by he...@apache.org.
test that changing version applies to specs


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

Branch: refs/heads/master
Commit: 71c82da572ae28d73c31f1c102f4ac4c5a7f2280
Parents: 0dc533d
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Feb 6 17:59:49 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Feb 6 22:12:14 2015 +0000

----------------------------------------------------------------------
 .../rebind/ActivePartialRebindIteration.java    |  2 +-
 .../management/internal/LocalEntityManager.java | 21 +++++++---
 .../rebind/ActivePartialRebindVersionTest.java  | 44 ++++++++++++++++++--
 3 files changed, 57 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/71c82da5/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
index 56c467f..d3c4f5f 100644
--- a/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/ActivePartialRebindIteration.java
@@ -142,7 +142,7 @@ public class ActivePartialRebindIteration extends RebindIteration {
 
     @Override
     protected Collection<String> getMementoRootEntities() {
-        // TODO must parents
+        // all entities are roots here, because we are not recursing
         return memento.getEntityIds();
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/71c82da5/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
index 3e9e4c0..cd66e5b 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
@@ -65,9 +65,9 @@ import brooklyn.util.task.Tasks;
 import brooklyn.util.time.CountdownTimer;
 import brooklyn.util.time.Duration;
 
-import com.google.common.base.Preconditions;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
@@ -285,7 +285,7 @@ public class LocalEntityManager implements EntityManagerInternal {
         }
 
         final List<EntityInternal> allEntities =  Lists.newArrayList();
-        recursively(e, new Predicate<EntityInternal>() { public boolean apply(EntityInternal it) {
+        Predicate<EntityInternal> manageEntity = new Predicate<EntityInternal>() { public boolean apply(EntityInternal it) {
             ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
             if (mode==null) {
                 setManagementTransitionMode(it, mode = initialMode);
@@ -309,9 +309,13 @@ public class LocalEntityManager implements EntityManagerInternal {
                     // silently bail out
                     return false;
                 } else {
-                    // on rebind, should not have any deployed instances
-                    log.warn("Already deployed "+it+" when managing "+mode+"/"+initialMode+"; ignoring this and all descendants");
-                    return false;
+                    if (mode.wasPrimary() && mode.isPrimary()) {
+                        // active partial rebind; continue
+                    } else {
+                        // on rebind, should not have any deployed instances
+                        log.warn("Already deployed "+it+" when managing "+mode+"/"+initialMode+"; ignoring this and all descendants");
+                        return false;
+                    }
                 }
             }
             
@@ -325,7 +329,12 @@ public class LocalEntityManager implements EntityManagerInternal {
             preManageNonRecursive(it, mode);
             it.getManagementSupport().onManagementStarting( new ManagementTransitionInfo(managementContext, mode) ); 
             return manageNonRecursive(it, mode);
-        } });
+        } };
+        if (initialMode.wasPrimary() && initialMode.isPrimary()) {
+            manageEntity.apply( (EntityInternal)e );
+        } else {
+            recursively(e, manageEntity);
+        }
         
         for (EntityInternal it : allEntities) {
             if (!it.getManagementSupport().isFullyManaged()) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/71c82da5/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
index b239f1a..9eec02b 100644
--- a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
@@ -24,11 +24,14 @@ import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.Entity;
+import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.transformer.CompoundTransformer;
 import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.osgi.OsgiTestResources;
 import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
+import brooklyn.util.collections.MutableList;
 
 public class ActivePartialRebindVersionTest extends RebindTestFixtureWithApp {
 
@@ -64,8 +67,8 @@ public class ActivePartialRebindVersionTest extends RebindTestFixtureWithApp {
         
         // now transform, with a version change
         CompoundTransformer transformer = CompoundTransformer.builder().changeCatalogItemId(
-            OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, "1.0",
-            OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, "1.1").build();
+            catV1.getSymbolicName(), catV1.getVersion(),
+            catV2.getSymbolicName(), catV2.getVersion()).build();
         doPartialRebindByObjectById(transformer, childV1.getId());
 
         Entity childV2 = origManagementContext.lookup(childV1.getId(), Entity.class);
@@ -78,4 +81,39 @@ public class ActivePartialRebindVersionTest extends RebindTestFixtureWithApp {
         Assert.assertTrue(childV1==childV2, "Expected same instance: "+childV1+" / "+childV2);
     }
 
+    @Test
+    public void testSwitchingVersionsInCluster() throws Exception {
+        CatalogItem<?, ?> catV1 = OsgiVersionMoreEntityTest.addMoreEntityV1(origManagementContext, "1.0");
+        CatalogItem<?, ?> catV2 = OsgiVersionMoreEntityTest.addMoreEntityV2(origManagementContext, "1.1");
+        
+        // could do a yaml test in a downstream project (no camp available here)
+//        CreationResult<List<Entity>, List<String>> clusterR = EntityManagementUtils.addChildren(origApp, 
+//              "services:\n"
+//            + "- type: "+DynamicCluster.class.getName()+"\n"
+//            + "  initialSize: 1\n"
+//            + "  entitySpec: { type: "+catV1.getId()+" }\n", true);
+        DynamicCluster cluster = origApp.createAndManageChild(EntitySpec.create(DynamicCluster.class)
+            .configure(DynamicCluster.INITIAL_SIZE, 1)
+            .configure(DynamicCluster.MEMBER_SPEC, CatalogUtils.createEntitySpec(origManagementContext, catV1))
+            );
+        cluster.start(MutableList.of(origApp.newSimulatedLocation()));
+        Entity childV1 = MutableList.copyOf(cluster.getChildren()).get(1);
+        
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(childV1);
+        
+        // now transform, with a version change
+        CompoundTransformer transformer = CompoundTransformer.builder().changeCatalogItemId(
+            catV1.getSymbolicName(), catV1.getVersion(),
+            catV2.getSymbolicName(), catV2.getVersion()).build();
+        doPartialRebindByObjectById(transformer, cluster.getId(), childV1.getId());
+
+        // existing child now points to new implementation -- saying HI
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(childV1);
+
+        // and scale out new child also gets new impl
+        cluster.resize(2);
+        Entity child2 = MutableList.copyOf(cluster.getChildren()).get(2);
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(child2);
+    }
+
 }


[04/22] incubator-brooklyn git commit: Removed unnecessary double checking of free port

Posted by he...@apache.org.
Removed unnecessary double checking of free port


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

Branch: refs/heads/master
Commit: 34439f4a2ac0c13781a8485c4d6d308fb744de47
Parents: 5004bfe
Author: Matt Champion <ma...@gmail.com>
Authored: Tue Jan 27 20:43:58 2015 +0000
Committer: Matt Champion <ma...@gmail.com>
Committed: Tue Jan 27 20:43:58 2015 +0000

----------------------------------------------------------------------
 .../src/main/java/brooklyn/util/net/Networking.java   | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/34439f4a/utils/common/src/main/java/brooklyn/util/net/Networking.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/net/Networking.java b/utils/common/src/main/java/brooklyn/util/net/Networking.java
index 2c7e4ff..828bb46 100644
--- a/utils/common/src/main/java/brooklyn/util/net/Networking.java
+++ b/utils/common/src/main/java/brooklyn/util/net/Networking.java
@@ -87,17 +87,6 @@ public class Networking {
 
         Stopwatch watch = Stopwatch.createStarted();
         try {
-            try {
-                Socket s = new Socket();
-                s.setSoTimeout(250);
-                s.connect(new InetSocketAddress(localAddressNotAny, port), 250);
-                try {
-                    s.close();
-                } catch (Exception e) {}
-                return false;
-            } catch (Exception e) {
-                //expected - shouldn't be able to connect
-            }
             //despite http://stackoverflow.com/questions/434718/sockets-discover-port-availability-using-java
             //(recommending the following) it isn't 100% reliable (e.g. nginx will happily coexist with ss+ds)
             //so we also do the above check
@@ -130,8 +119,7 @@ public class Networking {
                     }
                 }
             }
-            
-            
+
             if (localAddress==null || ANY_NIC.equals(localAddress)) {
                 // sometimes 0.0.0.0 can be bound to even if 127.0.0.1 has the port as in use;
                 // check all interfaces if 0.0.0.0 was requested