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:26 UTC
[07/22] incubator-brooklyn git commit: Partial rebind - basically
working, but for mgmt confusion
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);