@Override
  public Response createFromYaml(String yaml) {
    // First of all, see if it's a URL
    URI uri;
    try {
      uri = new URI(yaml);
    } catch (URISyntaxException e) {
      // It's not a URI then...
      uri = null;
    }
    if (uri != null) {
      log.debug("Create app called with URI; retrieving contents: {}", uri);
      yaml = ResourceUtils.create(mgmt()).getResourceAsString(uri.toString());
    }

    log.debug("Creating app from yaml:\n{}", yaml);
    EntitySpec<? extends Application> spec = createEntitySpecForApplication(yaml);

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

    return launch(yaml, spec);
  }
  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 delete(String application) {
   Application app = brooklyn().getApplication(application);
   if (!Entitlements.isEntitled(
       mgmt().getEntitlementManager(),
       Entitlements.INVOKE_EFFECTOR,
       Entitlements.EntityAndItem.of(
           app, StringAndArgument.of(Entitlements.LifecycleEffectors.DELETE, null)))) {
     throw WebResourceUtils.unauthorized(
         "User '%s' is not authorized to delete application %s",
         Entitlements.getEntitlementContext().user(), app);
   }
   Task<?> t = brooklyn().destroy(app);
   TaskSummary ts = TaskTransformer.FROM_TASK.apply(t);
   return status(ACCEPTED).entity(ts).build();
 }
 private ArrayNode entitiesIdAsArray(Iterable<? extends Entity> entities) {
   ArrayNode node = mapper().createArrayNode();
   for (Entity entity : entities) {
     if (Entitlements.isEntitled(
         mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
       node.add(entity.getId());
     }
   }
   return node;
 }
 private ArrayNode childEntitiesRecursiveAsArray(Entity entity) {
   ArrayNode node = mapper().createArrayNode();
   for (Entity e : entity.getChildren()) {
     if (Entitlements.isEntitled(
         mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
       node.add(recursiveTreeFromEntity(e));
     }
   }
   return node;
 }
  /**
   * Default restart implementation for an entity.
   *
   * <p>Stops processes if possible, then starts the entity again.
   */
  public void restart(ConfigBag parameters) {
    ServiceStateLogic.setExpectedState(entity(), Lifecycle.STOPPING);

    RestartMachineMode isRestartMachine =
        parameters.get(RestartSoftwareParameters.RESTART_MACHINE_TYPED);
    if (isRestartMachine == null) isRestartMachine = RestartMachineMode.AUTO;
    if (isRestartMachine == RestartMachineMode.AUTO)
      isRestartMachine =
          getDefaultRestartStopsMachine() ? RestartMachineMode.TRUE : RestartMachineMode.FALSE;

    // Calling preStopCustom without a corresponding postStopCustom invocation
    // doesn't look right so use a separate callback pair; Also depending on the arguments
    // stop() could be called which will call the {pre,post}StopCustom on its own.
    DynamicTasks.queue("pre-restart", new PreRestartTask());

    if (isRestartMachine == RestartMachineMode.FALSE) {
      DynamicTasks.queue("stopping (process)", new StopProcessesAtMachineTask());
    } else {
      Map<String, Object> stopMachineFlags = MutableMap.of();
      if (Entitlements.getEntitlementContext() != null) {
        stopMachineFlags.put(
            "tags",
            MutableSet.of(
                BrooklynTaskTags.tagForEntitlement(Entitlements.getEntitlementContext())));
      }
      Task<String> stopTask =
          Tasks.<String>builder()
              .displayName("stopping (machine)")
              .body(new StopMachineTask())
              .flags(stopMachineFlags)
              .build();
      DynamicTasks.queue(stopTask);
    }

    DynamicTasks.queue("starting", new StartInLocationsTask());
    restartChildren(parameters);
    DynamicTasks.queue("post-restart", new PostRestartTask());

    DynamicTasks.waitForLast();
    ServiceStateLogic.setExpectedState(entity(), Lifecycle.RUNNING);
  }
 private ArrayNode entitiesIdAndNameAsArray(Collection<? extends Entity> entities) {
   ArrayNode node = mapper().createArrayNode();
   for (Entity entity : entities) {
     if (Entitlements.isEntitled(
         mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
       ObjectNode holder = mapper().createObjectNode();
       holder.put("id", entity.getId());
       holder.put("name", entity.getDisplayName());
       node.add(holder);
     }
   }
   return node;
 }
  /** @deprecated since 0.7.0 see #create */
  @Deprecated
  protected Response createFromAppSpec(ApplicationSpec applicationSpec) {
    if (!Entitlements.isEntitled(
        mgmt().getEntitlementManager(), Entitlements.DEPLOY_APPLICATION, applicationSpec)) {
      throw WebResourceUtils.unauthorized(
          "User '%s' is not authorized to start application %s",
          Entitlements.getEntitlementContext().user(), applicationSpec);
    }

    checkApplicationTypesAreValid(applicationSpec);
    checkLocationsAreValid(applicationSpec);
    // TODO duplicate prevention
    List<Location> locations = brooklyn().getLocations(applicationSpec);
    Application app = brooklyn().create(applicationSpec);
    Task<?> t = brooklyn().start(app, locations);
    TaskSummary ts = TaskTransformer.FROM_TASK.apply(t);
    URI ref =
        uriInfo
            .getBaseUriBuilder()
            .path(ApplicationApi.class)
            .path(ApplicationApi.class, "get")
            .build(app.getApplicationId());
    return created(ref).entity(ts).build();
  }
  @Override
  public JsonNode fetch(String entityIds) {
    Map<String, JsonNode> jsonEntitiesById = MutableMap.of();
    for (Application application : mgmt().getApplications())
      jsonEntitiesById.put(application.getId(), fromEntity(application));
    if (entityIds != null) {
      for (String entityId : entityIds.split(",")) {
        Entity entity = mgmt().getEntityManager().getEntity(entityId.trim());
        while (entity != null && entity.getParent() != null) {
          if (Entitlements.isEntitled(
              mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
            jsonEntitiesById.put(entity.getId(), fromEntity(entity));
          }
          entity = entity.getParent();
        }
      }
    }

    ArrayNode result = mapper().createArrayNode();
    for (JsonNode n : jsonEntitiesById.values()) result.add(n);
    return result;
  }
  protected void doStop(ConfigBag parameters, Callable<StopMachineDetails<Integer>> stopTask) {
    preStopConfirmCustom();

    log.info("Stopping {} in {}", entity(), entity().getLocations());

    StopMode stopMachineMode = getStopMachineMode(parameters);
    StopMode stopProcessMode = parameters.get(StopSoftwareParameters.STOP_PROCESS_MODE);

    DynamicTasks.queue("pre-stop", new PreStopCustomTask());

    // BROOKLYN-263:
    // With this change the stop effector will wait for Location to provision so it can terminate
    // the machine, if a provisioning request is in-progress.
    //
    // The ProvisionMachineTask stores transient internal state in PROVISIONING_TASK_STATE and
    // PROVISIONED_MACHINE: it records when the provisioning is running and when done; and it
    // records the final machine. We record the machine in the internal sensor (rather than
    // just relying on getLocations) because the latter is set much later in the start()
    // process.
    //
    // This code is a big improvement (previously there was a several-minute window in some
    // clouds where a call to stop() would leave the machine running).
    //
    // However, there are still races. If the start() code has not yet reached the call to
    // location.obtain() then we won't wait, and the start() call won't know to abort. It's
    // fiddly to get that right, because we need to cope with restart() - so we mustn't leave
    // any state behind that will interfere with subsequent sequential calls to start().
    // There is some attempt to handle it by ProvisionMachineTask checking if the expectedState
    // is stopping/stopped.
    Maybe<MachineLocation> machine = Machines.findUniqueMachineLocation(entity().getLocations());
    ProvisioningTaskState provisioningState =
        entity().sensors().get(AttributesInternal.INTERNAL_PROVISIONING_TASK_STATE);

    if (machine.isAbsent() && provisioningState == ProvisioningTaskState.RUNNING) {
      Duration maxWait = entity().config().get(STOP_WAIT_PROVISIONING_TIMEOUT);
      log.info(
          "When stopping {}, waiting for up to {} for the machine to finish provisioning, before terminating it",
          entity(),
          maxWait);
      boolean success =
          Repeater.create("Wait for a machine to appear")
              .until(
                  new Callable<Boolean>() {
                    @Override
                    public Boolean call() throws Exception {
                      ProvisioningTaskState state =
                          entity()
                              .sensors()
                              .get(AttributesInternal.INTERNAL_PROVISIONING_TASK_STATE);
                      return (state != ProvisioningTaskState.RUNNING);
                    }
                  })
              .backoffTo(Duration.FIVE_SECONDS)
              .limitTimeTo(maxWait)
              .run();
      if (!success) {
        log.warn(
            "When stopping {}, timed out after {} waiting for the machine to finish provisioning - machine may we left running",
            entity(),
            maxWait);
      }
      machine = Maybe.ofDisallowingNull(entity().sensors().get(INTERNAL_PROVISIONED_MACHINE));
    }
    entity().sensors().remove(AttributesInternal.INTERNAL_PROVISIONING_TASK_STATE);
    entity().sensors().remove(INTERNAL_PROVISIONED_MACHINE);

    Task<List<?>> stoppingProcess = null;
    if (canStop(stopProcessMode, entity())) {
      stoppingProcess =
          Tasks.parallel(
              "stopping",
              Tasks.create("stopping (process)", new StopProcessesAtMachineTask()),
              Tasks.create("stopping (feeds)", new StopFeedsAtMachineTask()));
      DynamicTasks.queue(stoppingProcess);
    }

    Task<StopMachineDetails<Integer>> stoppingMachine = null;
    if (canStop(stopMachineMode, machine.isAbsent())) {
      // Release this machine (even if error trying to stop process - we rethrow that after)
      Map<String, Object> stopMachineFlags = MutableMap.of();
      if (Entitlements.getEntitlementContext() != null) {
        stopMachineFlags.put(
            "tags",
            MutableSet.of(
                BrooklynTaskTags.tagForEntitlement(Entitlements.getEntitlementContext())));
      }
      Task<StopMachineDetails<Integer>> stopMachineTask =
          Tasks.<StopMachineDetails<Integer>>builder()
              .displayName("stopping (machine)")
              .body(stopTask)
              .flags(stopMachineFlags)
              .build();
      stoppingMachine = DynamicTasks.queue(stopMachineTask);

      DynamicTasks.drain(entity().getConfig(STOP_PROCESS_TIMEOUT), false);

      // shutdown the machine if stopping process fails or takes too long
      synchronized (stoppingMachine) {
        // task also used as mutex by DST when it submits it; ensure it only submits once!
        if (!stoppingMachine.isSubmitted()) {
          // force the stoppingMachine task to run by submitting it here
          StringBuilder msg =
              new StringBuilder("Submitting machine stop early in background for ")
                  .append(entity());
          if (stoppingProcess == null) {
            msg.append(". Process stop skipped, pre-stop not finished?");
          } else {
            msg.append(" because process stop has ")
                .append((stoppingProcess.isDone() ? "finished abnormally" : "not finished"));
          }
          log.warn(msg.toString());
          Entities.submit(entity(), stoppingMachine);
        }
      }
    }

    try {
      // This maintains previous behaviour of silently squashing any errors on the stoppingProcess
      // task if the
      // stoppingMachine exits with a nonzero value
      boolean checkStopProcesses =
          (stoppingProcess != null
              && (stoppingMachine == null || stoppingMachine.get().value == 0));

      if (checkStopProcesses) {
        // TODO we should test for destruction above, not merely successful "stop", as things like
        // localhost and ssh won't be destroyed
        DynamicTasks.waitForLast();
        if (machine.isPresent()) {
          // throw early errors *only if* there is a machine and we have not destroyed it
          stoppingProcess.get();
        }
      }
    } catch (Throwable e) {
      ServiceStateLogic.setExpectedState(entity(), Lifecycle.ON_FIRE);
      Exceptions.propagate(e);
    }
    entity().sensors().set(SoftwareProcess.SERVICE_UP, false);
    ServiceStateLogic.setExpectedState(entity(), Lifecycle.STOPPED);

    DynamicTasks.queue("post-stop", new PostStopCustomTask());

    if (log.isDebugEnabled()) log.debug("Stopped software process entity " + entity());
  }