@Override
 public Map<String, String> getShellEnvironment() {
   return MutableMap.<String, String>builder()
       .putAll(super.getShellEnvironment())
       .put("PORT", Integer.toString(getHttpPort()))
       .build();
 }
  /**
   * Given an enricher, extracts its state for serialization.
   *
   * @deprecated since 0.7.0, see {@link #newBasicMemento(BrooklynObject)}
   */
  @Deprecated
  public static EnricherMemento newEnricherMemento(Enricher enricher) {
    BasicEnricherMemento.Builder builder = BasicEnricherMemento.builder();
    populateBrooklynObjectMementoBuilder(enricher, builder);

    // TODO persist config keys as well? Or only support those defined on policy class;
    // current code will lose the ConfigKey type on rebind for anything not defined on class.
    // Whereas entities support that.
    // TODO Do we need the "nonPersistableFlagNames" that locations use?
    Map<ConfigKey<?>, Object> config = ((AbstractEnricher) enricher).getConfigMap().getAllConfig();
    for (Map.Entry<ConfigKey<?>, Object> entry : config.entrySet()) {
      ConfigKey<?> key = checkNotNull(entry.getKey(), "config=%s", config);
      Object value = configValueToPersistable(entry.getValue());
      builder.config.put(key.getName(), value);
    }

    Map<String, Object> persistableFlags =
        MutableMap.<String, Object>builder()
            .putAll(
                FlagUtils.getFieldsWithFlagsExcludingModifiers(
                    enricher, Modifier.STATIC ^ Modifier.TRANSIENT))
            .remove("id")
            .remove("name")
            .build();
    builder.config.putAll(persistableFlags);

    return builder.build();
  }
 protected void runTest(Map<String, ?> flags) throws Exception {
   String tag = getClass().getSimpleName().toLowerCase();
   Map<String, ?> allFlags =
       MutableMap.<String, Object>builder()
           .put("tags", ImmutableList.of(tag))
           .putAll(flags)
           .build();
   jcloudsLocation = ctx.getLocationRegistry().getLocationManaged(PROVIDER, allFlags);
   doTest(jcloudsLocation);
 }
  /** @deprecated since 0.7.0; use {@link #newBasicMemento(BrooklynObject)} instead */
  @Deprecated
  public static BasicLocationMemento.Builder newLocationMementoBuilder(Location location) {
    BasicLocationMemento.Builder builder = BasicLocationMemento.builder();
    populateBrooklynObjectMementoBuilder(location, builder);

    Set<String> nonPersistableFlagNames =
        MutableMap.<String, Object>builder()
            .putAll(FlagUtils.getFieldsWithFlagsWithModifiers(location, Modifier.TRANSIENT))
            .putAll(FlagUtils.getFieldsWithFlagsWithModifiers(location, Modifier.STATIC))
            .put("id", String.class)
            .filterValues(Predicates.not(Predicates.instanceOf(ConfigKey.class)))
            .build()
            .keySet();
    Map<String, Object> persistableFlags =
        MutableMap.<String, Object>builder()
            .putAll(
                FlagUtils.getFieldsWithFlagsExcludingModifiers(
                    location, Modifier.STATIC ^ Modifier.TRANSIENT))
            .removeAll(nonPersistableFlagNames)
            .build();
    ConfigBag persistableConfig =
        new ConfigBag()
            .copy(((LocationInternal) location).config().getLocalBag())
            .removeAll(nonPersistableFlagNames);

    builder.copyConfig(persistableConfig);
    builder.locationConfig.putAll(persistableFlags);

    Location parentLocation = location.getParent();
    builder.parent = (parentLocation != null) ? parentLocation.getId() : null;

    for (Location child : location.getChildren()) {
      builder.children.add(child.getId());
    }

    return builder;
  }
  @Override
  public ComputeService findComputeService(ConfigBag conf, boolean allowReuse) {
    String provider = checkNotNull(conf.get(CLOUD_PROVIDER), "provider must not be null");
    String identity =
        checkNotNull(conf.get(CloudLocationConfig.ACCESS_IDENTITY), "identity must not be null");
    String credential =
        checkNotNull(
            conf.get(CloudLocationConfig.ACCESS_CREDENTIAL), "credential must not be null");

    Properties properties = new Properties();
    properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, Boolean.toString(true));
    properties.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, Boolean.toString(true));
    properties.setProperty(
        "jclouds.ssh.max-retries",
        conf.getStringKey("jclouds.ssh.max-retries") != null
            ? conf.getStringKey("jclouds.ssh.max-retries").toString()
            : "50");
    // Enable aws-ec2 lazy image fetching, if given a specific imageId; otherwise customize for
    // specific owners; or all as a last resort
    // See https://issues.apache.org/jira/browse/WHIRR-416
    if ("aws-ec2".equals(provider)) {
      // TODO convert AWS-only flags to config keys
      if (groovyTruth(conf.get(IMAGE_ID))) {
        properties.setProperty(PROPERTY_EC2_AMI_QUERY, "");
        properties.setProperty(PROPERTY_EC2_CC_AMI_QUERY, "");
      } else if (groovyTruth(conf.getStringKey("imageOwner"))) {
        properties.setProperty(
            PROPERTY_EC2_AMI_QUERY,
            "owner-id=" + conf.getStringKey("imageOwner") + ";state=available;image-type=machine");
      } else if (groovyTruth(conf.getStringKey("anyOwner"))) {
        // set `anyOwner: true` to override the default query (which is restricted to certain owners
        // as per below),
        // allowing the AMI query to bind to any machine
        // (note however, we sometimes pick defaults in JcloudsLocationFactory);
        // (and be careful, this can give a LOT of data back, taking several minutes,
        // and requiring extra memory allocated on the command-line)
        properties.setProperty(PROPERTY_EC2_AMI_QUERY, "state=available;image-type=machine");
        /*
         * by default the following filters are applied:
         * Filter.1.Name=owner-id&Filter.1.Value.1=137112412989&
         * Filter.1.Value.2=063491364108&
         * Filter.1.Value.3=099720109477&
         * Filter.1.Value.4=411009282317&
         * Filter.2.Name=state&Filter.2.Value.1=available&
         * Filter.3.Name=image-type&Filter.3.Value.1=machine&
         */
      }

      // occasionally can get com.google.common.util.concurrent.UncheckedExecutionException:
      // java.lang.RuntimeException:
      //     security group eu-central-1/jclouds#brooklyn-bxza-alex-eu-central-shoul-u2jy-nginx-ielm
      // is not available after creating
      // the default timeout was 500ms so let's raise it in case that helps
      properties.setProperty(
          EC2Constants.PROPERTY_EC2_TIMEOUT_SECURITYGROUP_PRESENT,
          "" + Duration.seconds(30).toMilliseconds());
    }

    // FIXME Deprecated mechanism, should have a ConfigKey for overrides
    Map<String, Object> extra =
        Maps.filterKeys(conf.getAllConfig(), Predicates.containsPattern("^jclouds\\."));
    if (extra.size() > 0) {
      LOG.warn("Jclouds using deprecated property overrides: " + Sanitizer.sanitize(extra));
    }
    properties.putAll(extra);

    String endpoint = conf.get(CloudLocationConfig.CLOUD_ENDPOINT);
    if (!groovyTruth(endpoint)) endpoint = getDeprecatedProperty(conf, Constants.PROPERTY_ENDPOINT);
    if (groovyTruth(endpoint)) properties.setProperty(Constants.PROPERTY_ENDPOINT, endpoint);

    Map<?, ?> cacheKey =
        MutableMap.builder()
            .putAll(properties)
            .put("provider", provider)
            .put("identity", identity)
            .put("credential", credential)
            .putIfNotNull("endpoint", endpoint)
            .build()
            .asUnmodifiable();

    if (allowReuse) {
      ComputeService result = cachedComputeServices.get(cacheKey);
      if (result != null) {
        LOG.trace(
            "jclouds ComputeService cache hit for compute service, for "
                + Sanitizer.sanitize(properties));
        return result;
      }
      LOG.debug(
          "jclouds ComputeService cache miss for compute service, creating, for "
              + Sanitizer.sanitize(properties));
    }

    Iterable<Module> modules = getCommonModules();

    // Synchronizing to avoid deadlock from sun.reflect.annotation.AnnotationType.
    // See https://github.com/brooklyncentral/brooklyn/issues/974
    ComputeServiceContext computeServiceContext;
    synchronized (createComputeServicesMutex) {
      computeServiceContext =
          ContextBuilder.newBuilder(provider)
              .modules(modules)
              .credentials(identity, credential)
              .overrides(properties)
              .build(ComputeServiceContext.class);
    }
    final ComputeService computeService = computeServiceContext.getComputeService();
    if (allowReuse) {
      synchronized (cachedComputeServices) {
        ComputeService result = cachedComputeServices.get(cacheKey);
        if (result != null) {
          LOG.debug(
              "jclouds ComputeService cache recovery for compute service, for "
                  + Sanitizer.sanitize(cacheKey));
          // keep the old one, discard the new one
          computeService.getContext().close();
          return result;
        }
        LOG.debug(
            "jclouds ComputeService created "
                + computeService
                + ", adding to cache, for "
                + Sanitizer.sanitize(properties));
        cachedComputeServices.put(cacheKey, computeService);
      }
    }
    return computeService;
  }
Exemplo n.º 6
0
  @Override
  public DockerContainerLocation obtain(Map<?, ?> flags) throws NoMachinesAvailableException {
    lock.readLock().lock();
    try {
      // Lookup entity from context or flags
      Object context = flags.get(LocationConfigKeys.CALLER_CONTEXT.getName());
      if (context == null || !(context instanceof Entity)) {
        throw new IllegalStateException("Invalid location context: " + context);
      }
      Entity entity = (Entity) context;

      // Flag to configure adding SSHable layer
      boolean useSsh =
          entity.config().get(DockerContainer.DOCKER_USE_SSH)
              && dockerHost.config().get(DockerContainer.DOCKER_USE_SSH);

      // Configure the entity
      LOG.info("Configuring entity {} via subnet {}", entity, dockerHost.getSubnetTier());
      entity
          .config()
          .set(
              SubnetTier.PORT_FORWARDING_MANAGER,
              dockerHost.getSubnetTier().getPortForwardManager());
      entity.config().set(SubnetTier.PORT_FORWARDER, portForwarder);
      if (getOwner().config().get(SdnAttributes.SDN_ENABLE)) {
        SdnAgent agent = getOwner().sensors().get(SdnAgent.SDN_AGENT);
        if (agent == null) {
          throw new IllegalStateException("SDN agent entity on " + getOwner() + " is null");
        }
        Map<String, Cidr> networks =
            agent.sensors().get(SdnAgent.SDN_PROVIDER).sensors().get(SdnProvider.SUBNETS);
        entity.config().set(SubnetTier.SUBNET_CIDR, networks.get(entity.getApplicationId()));
      } else {
        entity.config().set(SubnetTier.SUBNET_CIDR, Cidr.UNIVERSAL);
      }
      configureEnrichers(entity);

      // Add the entity Dockerfile if configured
      String dockerfile = entity.config().get(DockerAttributes.DOCKERFILE_URL);
      String entrypoint = entity.config().get(DockerAttributes.DOCKERFILE_ENTRYPOINT_URL);
      String contextArchive = entity.config().get(DockerAttributes.DOCKERFILE_CONTEXT_URL);
      String imageId = entity.config().get(DockerAttributes.DOCKER_IMAGE_ID);

      Optional<String> baseImage =
          Optional.fromNullable(entity.config().get(DockerAttributes.DOCKER_IMAGE_NAME));
      String imageTag =
          Optional.fromNullable(entity.config().get(DockerAttributes.DOCKER_IMAGE_TAG))
              .or("latest");

      // TODO incorporate more info
      final String imageName = DockerUtils.imageName(entity, dockerfile);

      // Lookup image ID or build new image from Dockerfile
      LOG.info("ImageName for entity {}: {}", entity, imageName);

      if (dockerHost.getImageNamed(imageName, imageTag).isPresent()) {
        // Wait until committed before continuing - Brooklyn may be midway through its creation.
        waitForImage(imageName);

        // Look up imageId again
        imageId = dockerHost.getImageNamed(imageName, imageTag).get();
        LOG.info("Found image {} for entity: {}", imageName, imageId);

        // Skip install phase
        entity.config().set(SoftwareProcess.SKIP_INSTALLATION, true);
      } else if (baseImage.isPresent()) {
        if (useSsh) {
          // Create an SSHable image from the one configured
          imageId = dockerHost.layerSshableImageOn(baseImage.get(), imageTag);
          LOG.info("Created SSHable image from {}: {}", baseImage.get(), imageId);
        } else {
          dockerHost.runDockerCommand(String.format("pull %s:%s", baseImage.get(), imageTag));
          imageId = dockerHost.getImageNamed(baseImage.get(), imageTag).get();
        }
        entity.config().set(SoftwareProcess.SKIP_INSTALLATION, true);
      } else {
        // Otherwise Clocker is going to make an image for the entity once it is installed.
        insertCallback(entity, SoftwareProcess.POST_INSTALL_COMMAND, DockerCallbacks.commit());

        if (Strings.isNonBlank(dockerfile)) {
          if (imageId != null) {
            LOG.warn(
                "Ignoring container imageId {} as dockerfile URL is set: {}", imageId, dockerfile);
          }
          Map<String, Object> substitutions = getExtraTemplateSubstitutions(imageName, entity);
          imageId =
              dockerHost.buildImage(
                  dockerfile, entrypoint, contextArchive, imageName, useSsh, substitutions);
        }
        if (Strings.isBlank(imageId)) {
          imageId = getOwner().sensors().get(DockerHost.DOCKER_IMAGE_ID);
        }

        // Tag the image name and create its latch
        images.putIfAbsent(imageName, new CountDownLatch(1));
        dockerHost.runDockerCommand(String.format("tag -f %s %s:latest", imageId, imageName));
      }

      // Look up hardware ID
      String hardwareId = entity.config().get(DockerAttributes.DOCKER_HARDWARE_ID);
      if (Strings.isEmpty(hardwareId)) {
        hardwareId = getOwner().config().get(DockerAttributes.DOCKER_HARDWARE_ID);
      }

      // Create new Docker container in the host cluster
      LOG.info(
          "Starting container with imageId {} and hardwareId {} at {}",
          new Object[] {imageId, hardwareId, machine});
      Map<Object, Object> containerFlags =
          MutableMap.builder()
              .putAll(flags)
              .put("useSsh", useSsh)
              .put("entity", entity)
              .putIfNotNull("imageId", imageId)
              .putIfNotNull("hardwareId", hardwareId)
              .build();
      DynamicCluster cluster = dockerHost.getDockerContainerCluster();
      Entity added = cluster.addNode(machine, containerFlags);
      if (added == null) {
        throw new NoMachinesAvailableException(
            String.format("Failed to create container at %s", dockerHost.getDockerHostName()));
      } else {
        Entities.invokeEffector(
                (EntityLocal) entity,
                added,
                Startable.START,
                MutableMap.of("locations", ImmutableList.of(machine)))
            .getUnchecked();
      }
      DockerContainer dockerContainer = (DockerContainer) added;

      // Save the container attributes
      dockerContainer.sensors().set(DockerContainer.IMAGE_ID, imageId);
      dockerContainer.sensors().set(DockerContainer.IMAGE_NAME, imageName);
      dockerContainer.sensors().set(DockerContainer.HARDWARE_ID, hardwareId);

      // record SDN application network details
      if (getOwner().config().get(SdnAttributes.SDN_ENABLE)) {
        SdnAgent agent = getOwner().sensors().get(SdnAgent.SDN_AGENT);
        Cidr applicationCidr =
            agent.sensors().get(SdnAgent.SDN_PROVIDER).getSubnetCidr(entity.getApplicationId());
        entity.sensors().set(SdnProvider.APPLICATION_CIDR, applicationCidr);
        dockerContainer.sensors().set(SdnProvider.APPLICATION_CIDR, applicationCidr);
      }

      return dockerContainer.getDynamicLocation();
    } finally {
      lock.readLock().unlock();
    }
  }