/**
  * creates the given exception, but without propagating it, for use when caller will be wrapping
  */
 public static RuntimeException create(
     @Nullable String prefix, Collection<? extends Throwable> exceptions) {
   if (exceptions.size() == 1) {
     Throwable e = exceptions.iterator().next();
     if (Strings.isBlank(prefix)) return new PropagatedRuntimeException(e);
     return new PropagatedRuntimeException(prefix + ": " + Exceptions.collapseText(e), e);
   }
   if (exceptions.isEmpty()) {
     if (Strings.isBlank(prefix))
       return new CompoundRuntimeException("(empty compound exception)", exceptions);
     return new CompoundRuntimeException(prefix, exceptions);
   }
   if (Strings.isBlank(prefix))
     return new CompoundRuntimeException(
         exceptions.size()
             + " errors, including: "
             + Exceptions.collapseText(exceptions.iterator().next()),
         exceptions);
   return new CompoundRuntimeException(
       prefix
           + ", "
           + exceptions.size()
           + " errors including: "
           + Exceptions.collapseText(exceptions.iterator().next()),
       exceptions);
 }
  /**
   * Runs the given callable. Repeats until the operation succeeds or {@link #isExceptionRetryable}
   * indicates that the request cannot be retried.
   */
  protected <T> T runOperationWithRetry(Callable<T> operation) {
    int backoff = 64;
    Exception lastException = null;
    for (int retries = 0; retries < 100; retries++) {
      try {
        return operation.call();
      } catch (Exception e) {
        lastException = e;
        if (isExceptionRetryable.apply(e)) {
          LOG.debug("Attempt #{} failed to add security group: {}", retries + 1, e.getMessage());
          try {
            Thread.sleep(backoff);
          } catch (InterruptedException e1) {
            throw Exceptions.propagate(e1);
          }
          backoff = backoff << 1;
        } else {
          break;
        }
      }
    }

    throw new RuntimeException(
        "Unable to add security group rule; repeated errors from provider", lastException);
  }
  @Override
  public String execCommandTimeout(String command, Duration timeout) {
    ProcessTaskWrapper<String> task =
        SshEffectorTasks.ssh(command)
            .environmentVariables(
                ((AbstractSoftwareProcessSshDriver) getDriver()).getShellEnvironment())
            .configure(SshTool.PROP_ALLOCATE_PTY, true) // TODO configure globally
            .requiringZeroAndReturningStdout()
            .machine(getMachine())
            .summary(command)
            .newTask();

    try {
      String result =
          DynamicTasks.queueIfPossible(task)
              .executionContext(this)
              .orSubmitAsync()
              .asTask()
              .get(timeout);
      return result;
    } catch (TimeoutException te) {
      throw new IllegalStateException("Timed out running command: " + command);
    } catch (Exception e) {
      Integer exitCode = task.getExitCode();
      LOG.warn(
          "Command failed, return code {}: {}", exitCode == null ? -1 : exitCode, task.getStderr());
      throw Exceptions.propagate(e);
    }
  }
 private void copy(String src, File dst) {
   try {
     copy(new ReaderInputStream(new StringReader(src), "UTF-8"), dst);
   } catch (Exception e) {
     throw Exceptions.propagate(e);
   }
 }
Beispiel #5
0
  @Override
  public void release(DockerContainerLocation machine) {
    lock.readLock().lock();
    try {
      LOG.info("Releasing {}", machine);

      DynamicCluster cluster = dockerHost.getDockerContainerCluster();
      DockerContainer container = machine.getOwner();
      if (cluster.removeMember(container)) {
        LOG.info("Docker Host {}: member {} released", dockerHost.getDockerHostName(), machine);
      } else {
        LOG.warn(
            "Docker Host {}: member {} not found for release",
            dockerHost.getDockerHostName(),
            machine);
      }

      // Now close and unmange the container
      try {
        machine.close();
        container.stop();
      } catch (Exception e) {
        LOG.warn("Error stopping container: " + container, e);
        Exceptions.propagateIfFatal(e);
      } finally {
        Entities.unmanage(container);
      }
    } finally {
      lock.readLock().unlock();
    }
  }
  private Response launch(String yaml, EntitySpec<? extends Application> spec) {
    try {
      Application app = EntityManagementUtils.createUnstarted(mgmt(), spec);
      CreationResult<Application, Void> result = EntityManagementUtils.start(app);

      boolean isEntitled =
          Entitlements.isEntitled(
              mgmt().getEntitlementManager(),
              Entitlements.INVOKE_EFFECTOR,
              EntityAndItem.of(app, StringAndArgument.of(Startable.START.getName(), null)));

      if (!isEntitled) {
        throw WebResourceUtils.unauthorized(
            "User '%s' is not authorized to start application %s",
            Entitlements.getEntitlementContext().user(), spec.getType());
      }

      log.info("Launched from YAML: " + yaml + " -> " + app + " (" + result.task() + ")");

      URI ref = URI.create(app.getApplicationId());
      ResponseBuilder response = created(ref);
      if (result.task() != null) response.entity(TaskTransformer.FROM_TASK.apply(result.task()));
      return response.build();
    } catch (ConstraintViolationException e) {
      throw new UserFacingException(e);
    } catch (Exception e) {
      throw Exceptions.propagate(e);
    }
  }
  @Override
  public Response createPoly(byte[] inputToAutodetectType) {
    log.debug("Creating app from autodetecting input");

    boolean looksLikeLegacy = false;
    Exception legacyFormatException = null;
    // attempt legacy format
    try {
      ApplicationSpec appSpec = mapper().readValue(inputToAutodetectType, ApplicationSpec.class);
      if (appSpec.getType() != null || appSpec.getEntities() != null) {
        looksLikeLegacy = true;
      }
      return createFromAppSpec(appSpec);
    } catch (Exception e) {
      Exceptions.propagateIfFatal(e);
      legacyFormatException = e;
      log.debug("Input is not legacy ApplicationSpec JSON (will try others): " + e, e);
    }

    // TODO infer encoding from request
    String potentialYaml = new String(inputToAutodetectType);
    EntitySpec<? extends Application> spec = createEntitySpecForApplication(potentialYaml);

    // TODO not json - try ZIP, etc

    if (spec != null) {
      return launch(potentialYaml, spec);
    } else if (looksLikeLegacy) {
      throw Throwables.propagate(legacyFormatException);
    } else {
      return Response.serverError().entity("Unsupported format; not able to autodetect.").build();
    }
  }
  @Override
  public final T get() {
    if (log.isDebugEnabled())
      log.debug("Queuing task to resolve " + dsl + ", called by " + Tasks.current());

    EntityInternal entity =
        (EntityInternal) BrooklynTaskTags.getTargetOrContextEntity(Tasks.current());
    ExecutionContext exec =
        (entity != null)
            ? entity.getExecutionContext()
            : BasicExecutionContext.getCurrentExecutionContext();
    if (exec == null) {
      throw new IllegalStateException("No execution context available to resolve " + dsl);
    }

    Task<T> task = newTask();
    T result;
    try {
      result = exec.submit(task).get();
    } catch (InterruptedException | ExecutionException e) {
      Task<?> currentTask = Tasks.current();
      if (currentTask != null && currentTask.isCancelled()) {
        task.cancel(true);
      }
      throw Exceptions.propagate(e);
    }

    if (log.isDebugEnabled()) log.debug("Resolved " + result + " from " + dsl);
    return result;
  }
  @Override
  public void doStart(Collection<? extends Location> locs) {
    List<Location> locations = MutableList.of();

    sensors().set(SERVICE_UP, Boolean.FALSE);
    ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);

    LOG.info("Creating new MesosLocation");
    createLocation(MutableMap.<String, Object>of());

    // Start frameworks
    try {
      Group frameworks = sensors().get(MESOS_FRAMEWORKS);
      Entities.invokeEffectorList(
              this,
              frameworks.getMembers(),
              Startable.START,
              ImmutableMap.of("locations", locations))
          .getUnchecked();
    } catch (Exception e) {
      LOG.warn("Error starting frameworks", e);
      ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
      Exceptions.propagate(e);
    }

    super.doStart(locations);

    connectSensors();

    ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
    sensors().set(SERVICE_UP, Boolean.TRUE);
  }
 public static Map<String, Object> getSensorMap(String sensor, Iterable<Entity> descs) {
   if (Iterables.isEmpty(descs)) return Collections.emptyMap();
   Map<String, Object> result = MutableMap.of();
   Iterator<Entity> di = descs.iterator();
   Sensor<?> s = null;
   while (di.hasNext()) {
     Entity potentialSource = di.next();
     s = potentialSource.getEntityType().getSensor(sensor);
     if (s != null) break;
   }
   if (s == null) s = Sensors.newSensor(Object.class, sensor);
   if (!(s instanceof AttributeSensor<?>)) {
     log.warn("Cannot retrieve non-attribute sensor " + s + " for entities; returning empty map");
     return result;
   }
   for (Entity e : descs) {
     Object v = null;
     try {
       v = e.getAttribute((AttributeSensor<?>) s);
     } catch (Exception exc) {
       Exceptions.propagateIfFatal(exc);
       log.warn("Error retrieving sensor " + s + " for " + e + " (ignoring): " + exc);
     }
     if (v != null) result.put(e.getId(), v);
   }
   return result;
 }
 /**
  * as {@link #waitOnForExpiry(Object)} but catches and wraps InterruptedException as unchecked
  * RuntimeInterruptedExcedption
  */
 public boolean waitOnForExpiryUnchecked(Object waitTarget) {
   try {
     return waitOnForExpiry(waitTarget);
   } catch (InterruptedException e) {
     throw Exceptions.propagate(e);
   }
 }
 @Override
 public EntitySpec<? extends Application> createApplicationSpec(String plan) {
   try {
     CampPlatform camp = CampCatalogUtils.getCampPlatform(mgmt);
     BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
     AssemblyTemplate at = CampUtils.registerDeploymentPlan(plan, loader, camp);
     AssemblyTemplateInstantiator instantiator = CampUtils.getInstantiator(at);
     if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
       return ((AssemblyTemplateSpecInstantiator) instantiator)
           .createApplicationSpec(at, camp, loader);
     } else {
       // The unknown instantiator can create the app (Assembly), but not a spec.
       // Currently, all brooklyn plans should produce the above.
       if (at.getPlatformComponentTemplates() == null
           || at.getPlatformComponentTemplates().isEmpty()) {
         if (at.getCustomAttributes().containsKey("brooklyn.catalog"))
           throw new IllegalArgumentException(
               "Unrecognized application blueprint format: expected an application, not a brooklyn.catalog");
         throw new PlanNotRecognizedException(
             "Unrecognized application blueprint format: no services defined");
       }
       // map this (expected) error to a nicer message
       throw new PlanNotRecognizedException("Unrecognized application blueprint format");
     }
   } catch (Exception e) {
     // TODO how do we figure out that the plan is not supported vs. invalid to wrap in a
     // PlanNotRecognizedException?
     if (log.isDebugEnabled()) log.debug("Failed to create entity from CAMP spec:\n" + plan, e);
     throw Exceptions.propagate(e);
   }
 }
Beispiel #13
0
 protected void onUpdated() {
   try {
     emit(targetSensor, compute());
   } catch (Throwable t) {
     LOG.warn("Error calculating and setting aggregate for enricher " + this, t);
     throw Exceptions.propagate(t);
   }
 }
 private EntitySpec<? extends Application> createEntitySpecForApplication(String potentialYaml) {
   try {
     return EntityManagementUtils.createEntitySpecForApplication(mgmt(), potentialYaml);
   } catch (Exception e) {
     // An IllegalArgumentException for creating the entity spec gets wrapped in a ISE, and
     // possibly a Compound.
     // But we want to return a 400 rather than 500, so ensure we throw IAE.
     IllegalArgumentException iae =
         (IllegalArgumentException)
             Exceptions.getFirstThrowableOfType(e, IllegalArgumentException.class);
     if (iae != null) {
       throw new IllegalArgumentException("Cannot create spec for app: " + iae.getMessage(), e);
     } else {
       throw Exceptions.propagate(e);
     }
   }
 }
Beispiel #15
0
 public void waitForImage(String imageName) {
   try {
     CountDownLatch latch = images.get(imageName);
     if (latch != null) latch.await(15, TimeUnit.MINUTES);
   } catch (InterruptedException ie) {
     throw Exceptions.propagate(ie);
   }
 }
 /**
  * attempts to resolve hostnameTarget from origin
  *
  * @return null if it definitively can't be resolved, best-effort IP address if possible, or blank
  *     if we could not run ssh or make sense of the output
  */
 public static String getResolvedAddress(
     Entity entity, SshMachineLocation origin, String hostnameTarget) {
   ProcessTaskWrapper<Integer> task =
       SshTasks.newSshExecTaskFactory(origin, "ping -c 1 -t 1 " + hostnameTarget)
           .summary("checking resolution of " + hostnameTarget)
           .allowingNonZeroExitCode()
           .newTask();
   DynamicTasks.queueIfPossible(task).orSubmitAndBlock(entity).asTask().blockUntilEnded();
   if (task.asTask().isError()) {
     log.warn(
         "ping could not be run, at "
             + entity
             + " / "
             + origin
             + ": "
             + Tasks.getError(task.asTask()));
     return "";
   }
   if (task.getExitCode() == null || task.getExitCode() != 0) {
     if (task.getExitCode() != null && task.getExitCode() < 10) {
       // small number means ping failed to resolve or ping the hostname
       log.debug(
           "not able to resolve "
               + hostnameTarget
               + " from "
               + origin
               + " for "
               + entity
               + " because exit code was "
               + task.getExitCode());
       return null;
     }
     // large number means ping probably did not run
     log.warn(
         "ping not run as expected, at "
             + entity
             + " / "
             + origin
             + " (code "
             + task.getExitCode()
             + "):\n"
             + task.getStdout().trim()
             + " --- "
             + task.getStderr().trim());
     return "";
   }
   String out = task.getStdout();
   try {
     String line1 = Strings.getFirstLine(out);
     String ip = Strings.getFragmentBetween(line1, "(", ")");
     if (Strings.isNonBlank(ip)) return ip;
   } catch (Exception e) {
     Exceptions.propagateIfFatal(e);
     /* ignore non-parseable output */
   }
   if (out.contains("127.0.0.1")) return "127.0.0.1";
   return "";
 }
 @Override
 public InetAddress getAddress() {
   String address = getOwner().sensors().get(Attributes.ADDRESS);
   try {
     return InetAddress.getByName(address);
   } catch (UnknownHostException e) {
     throw Exceptions.propagate(e);
   }
 }
 private void copy(InputStream in, File tmpJar) {
   try {
     OutputStream out = new FileOutputStream(tmpJar);
     ByteStreams.copy(in, out);
     Streams.closeQuietly(in);
     Streams.closeQuietly(out);
   } catch (Exception e) {
     throw Exceptions.propagate(e);
   }
 }
  @Override
  public String getBroadcastAddress() {
    String sensorName = getConfig(BROADCAST_ADDRESS_SENSOR);
    if (Strings.isNonBlank(sensorName))
      return Entities.submit(
              this,
              DependentConfiguration.attributeWhenReady(this, Sensors.newStringSensor(sensorName)))
          .getUnchecked();

    String snitchName = getConfig(CassandraNode.ENDPOINT_SNITCH_NAME);
    if (snitchName.equals("Ec2MultiRegionSnitch") || snitchName.contains("MultiCloudSnitch")) {
      // http://www.datastax.com/documentation/cassandra/2.0/mobile/cassandra/architecture/architectureSnitchEC2MultiRegion_c.html
      // describes that the listen_address is set to the private IP, and the broadcast_address is
      // set to the public IP.
      return getAttribute(CassandraNode.ADDRESS);
    } else if (!getDriver().isClustered()) {
      return getListenAddress();
    } else {
      // In other situations, prefer the hostname, so other regions can see it
      // *Unless* hostname resolves at the target to a local-only interface which is different to
      // ADDRESS
      // (workaround for issue deploying to localhost)
      String hostname = getAttribute(CassandraNode.HOSTNAME);
      try {
        String resolvedAddress = getDriver().getResolvedAddress(hostname);
        if (resolvedAddress == null) {
          log.debug(
              "Cassandra using broadcast address "
                  + getListenAddress()
                  + " for "
                  + this
                  + " because hostname "
                  + hostname
                  + " could not be resolved at remote machine");
          return getListenAddress();
        }
        if (resolvedAddress.equals("127.0.0.1")) {
          log.debug(
              "Cassandra using broadcast address "
                  + getListenAddress()
                  + " for "
                  + this
                  + " because hostname "
                  + hostname
                  + " resolves to 127.0.0.1");
          return getListenAddress();
        }
        return hostname;
      } catch (Exception e) {
        Exceptions.propagateIfFatal(e);
        log.warn("Error resolving hostname " + hostname + " for " + this + ": " + e, e);
        return hostname;
      }
    }
  }
 public void rebootAndWait() {
   try {
     executePsScriptNoRetry(ImmutableList.of("Restart-Computer -Force"));
   } catch (Exception e) {
     // Restarting the computer will cause the command to fail; ignore the exception and continue
     Exceptions.propagateIfFatal(e);
   }
   waitForWinRmStatus(false, entity.getConfig(VanillaWindowsProcess.REBOOT_BEGUN_TIMEOUT));
   waitForWinRmStatus(true, entity.getConfig(VanillaWindowsProcess.REBOOT_COMPLETED_TIMEOUT))
       .getWithError();
 }
 @Override
 public InetAddress getNextAgentAddress(String agentId) {
   Entity agent = getManagementContext().getEntityManager().getEntity(agentId);
   String address =
       agent.sensors().get(CalicoNode.DOCKER_HOST).sensors().get(Attributes.SUBNET_ADDRESS);
   try {
     return InetAddress.getByName(address);
   } catch (UnknownHostException uhe) {
     throw Exceptions.propagate(uhe);
   }
 }
 @Override
 public boolean apply(Exception input) {
   @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
   AWSResponseException exception =
       Exceptions.getFirstThrowableOfType(input, AWSResponseException.class);
   if (exception != null) {
     String code = exception.getError().getCode();
     return AWS_ERRORS_TO_RETRY.contains(code);
   }
   return false;
 }
 /**
  * runs the tasks needed to start, wrapped by setting {@link Attributes#SERVICE_STATE_EXPECTED}
  * appropriately
  */
 public void start(Collection<? extends Location> locations) {
   ServiceStateLogic.setExpectedState(entity(), Lifecycle.STARTING);
   try {
     startInLocations(locations);
     DynamicTasks.waitForLast();
     ServiceStateLogic.setExpectedState(entity(), Lifecycle.RUNNING);
   } catch (Throwable t) {
     ServiceStateLogic.setExpectedState(entity(), Lifecycle.ON_FIRE);
     throw Exceptions.propagate(t);
   }
 }
Beispiel #24
0
 @Override
 public void close() throws IOException {
   LOG.info("Close called on Docker host {}: {}", machine, this);
   try {
     machine.close();
   } catch (Exception e) {
     LOG.info("{}: Closing Docker host: {}", e.getMessage(), this);
     throw Exceptions.propagate(e);
   } finally {
     LOG.info("Docker host closed: {}", this);
   }
 }
 @Override
 public void close() throws IOException {
   LOG.debug("Close called on Marathon task: {}", this);
   try {
     if (marathonTask.sensors().get(MarathonTask.SERVICE_UP)) {
       LOG.info("Stopping Marathon task entity for {}: {}", this, marathonTask);
       marathonTask.stop();
     }
     LOG.info("Marathon task closed: {}", this);
   } catch (Exception e) {
     LOG.warn("Error closing Marathon task {}: {}", this, e.getMessage());
     throw Exceptions.propagate(e);
   }
 }
 @Override
 public void onManagementStarting() {
   super.onManagementStarting();
   sensors().set(TOPIC_NAME, getName());
   try {
     String virtualHost = getParent().getVirtualHost();
     exchange =
         new ObjectName(
             format(
                 "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=\"%s\",name=\"%s\",ExchangeType=topic",
                 virtualHost, getExchangeName()));
   } catch (MalformedObjectNameException e) {
     throw Exceptions.propagate(e);
   }
 }
  /** builds remote keystores, stores config keys/certs, and copies necessary files across */
  public void install() {
    try {
      // build truststore and keystore
      FluentKeySigner signer = getBrooklynRootSigner();
      KeyPair jmxAgentKey = SecureKeys.newKeyPair();
      X509Certificate jmxAgentCert = signer.newCertificateFor("jmxmp-agent", jmxAgentKey);

      agentKeyStore = SecureKeys.newKeyStore();
      agentKeyStore.setKeyEntry(
          "jmxmp-agent",
          jmxAgentKey.getPrivate(),
          // TODO jmx.ssl.agent.keyPassword
          "".toCharArray(),
          new Certificate[] {jmxAgentCert});
      ByteArrayOutputStream agentKeyStoreBytes = new ByteArrayOutputStream();
      agentKeyStore.store(
          agentKeyStoreBytes,
          // TODO jmx.ssl.agent.keyStorePassword
          "".toCharArray());

      agentTrustStore = SecureKeys.newKeyStore();
      agentTrustStore.setCertificateEntry("brooklyn", getJmxAccessCert());
      ByteArrayOutputStream agentTrustStoreBytes = new ByteArrayOutputStream();
      agentTrustStore.store(agentTrustStoreBytes, "".toCharArray());

      // install the truststore and keystore and rely on JmxSupport to install the agent
      Tasks.setBlockingDetails("Copying keystore and truststore to the server.");
      try {
        jmxSupport
            .getMachine()
            .get()
            .copyTo(
                new ByteArrayInputStream(agentKeyStoreBytes.toByteArray()),
                getJmxSslKeyStoreFilePath());
        jmxSupport
            .getMachine()
            .get()
            .copyTo(
                new ByteArrayInputStream(agentTrustStoreBytes.toByteArray()),
                getJmxSslTrustStoreFilePath());
      } finally {
        Tasks.resetBlockingDetails();
      }

    } catch (Exception e) {
      throw Exceptions.propagate(e);
    }
  }
 /**
  * Returns a wrapped map, if the object is YAML which parses as a map; otherwise returns absent
  * capable of throwing an error with more details
  */
 @SuppressWarnings("unchecked")
 public static Maybe<Map<?, ?>> getAsYamlMap(Object planData) {
   if (!(planData instanceof String)) return Maybe.absent("not a string");
   Iterable<Object> result;
   try {
     result = Yamls.parseAll((String) planData);
   } catch (Exception e) {
     Exceptions.propagateIfFatal(e);
     return Maybe.absent(e);
   }
   Iterator<Object> ri = result.iterator();
   if (!ri.hasNext()) return Maybe.absent("YAML has no elements in it");
   Object r1 = ri.next();
   if (ri.hasNext()) return Maybe.absent("YAML has multiple elements in it");
   if (r1 instanceof Map) return (Maybe<Map<?, ?>>) (Maybe<?>) Maybe.of(r1);
   return Maybe.absent("YAML does not contain a map");
 }
  private <T> T resolve(ConfigKey<T> key, Object value) {
    Object transformed = transform(key, value);

    Object result;
    if (transformed instanceof DeferredSupplier) {
      ExecutionContext exec = mgmt.getServerExecutionContext();
      try {
        result = Tasks.resolveValue(transformed, key.getType(), exec);
      } catch (ExecutionException | InterruptedException e) {
        throw Exceptions.propagate(e);
      }
    } else {
      result = transformed;
    }

    return TypeCoercions.coerce(result, key.getTypeToken());
  }
  @Override
  public List<Application> rebind(
      ClassLoader classLoaderO,
      RebindExceptionHandler exceptionHandlerO,
      ManagementNodeState modeO) {
    final ClassLoader classLoader =
        classLoaderO != null ? classLoaderO : managementContext.getCatalogClassLoader();
    final RebindExceptionHandler exceptionHandler =
        exceptionHandlerO != null
            ? exceptionHandlerO
            : RebindExceptionHandlerImpl.builder()
                .danglingRefFailureMode(danglingRefFailureMode)
                .danglingRefQuorumRequiredHealthy(danglingRefsQuorumRequiredHealthy)
                .rebindFailureMode(rebindFailureMode)
                .addConfigFailureMode(addConfigFailureMode)
                .addPolicyFailureMode(addPolicyFailureMode)
                .loadPolicyFailureMode(loadPolicyFailureMode)
                .build();
    final ManagementNodeState mode = modeO != null ? modeO : getRebindMode();

    if (mode != ManagementNodeState.MASTER
        && mode != ManagementNodeState.HOT_STANDBY
        && mode != ManagementNodeState.HOT_BACKUP)
      throw new IllegalStateException(
          "Must be either master or hot standby/backup to rebind (mode " + mode + ")");

    ExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext();
    if (ec == null) {
      ec = managementContext.getServerExecutionContext();
      Task<List<Application>> task =
          ec.submit(
              new Callable<List<Application>>() {
                @Override
                public List<Application> call() throws Exception {
                  return rebindImpl(classLoader, exceptionHandler, mode);
                }
              });
      try {
        return task.get();
      } catch (Exception e) {
        throw Exceptions.propagate(e);
      }
    } else {
      return rebindImpl(classLoader, exceptionHandler, mode);
    }
  }