Ejemplo n.º 1
0
 private void configureEnrichers(Entity entity) {
   for (AttributeSensor sensor :
       Iterables.filter(entity.getEntityType().getSensors(), AttributeSensor.class)) {
     if ((DockerUtils.URL_SENSOR_NAMES.contains(sensor.getName())
             || sensor.getName().endsWith(".url")
             || URI.class.isAssignableFrom(sensor.getType()))
         && !DockerUtils.BLACKLIST_URL_SENSOR_NAMES.contains(sensor.getName())) {
       AttributeSensor<String> target = DockerUtils.<String>mappedSensor(sensor);
       entity.addEnricher(
           dockerHost
               .getSubnetTier()
               .uriTransformingEnricher(EntityAndAttribute.create(entity, sensor), target));
       Set<Hint<?>> hints = RendererHints.getHintsFor(sensor);
       for (Hint<?> hint : hints) {
         RendererHints.register(target, (NamedActionWithUrl) hint);
       }
       if (LOG.isDebugEnabled()) {
         LOG.debug("Mapped URL sensor: origin={}, mapped={}", sensor.getName(), target.getName());
       }
     } else if (PortAttributeSensorAndConfigKey.class.isAssignableFrom(sensor.getClass())) {
       AttributeSensor<String> target =
           DockerUtils.mappedPortSensor((PortAttributeSensorAndConfigKey) sensor);
       entity.addEnricher(
           dockerHost
               .getSubnetTier()
               .hostAndPortTransformingEnricher(
                   EntityAndAttribute.create(entity, sensor), target));
       if (LOG.isDebugEnabled()) {
         LOG.debug("Mapped port sensor: origin={}, mapped={}", sensor.getName(), target.getName());
       }
     }
   }
 }
Ejemplo n.º 2
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();
    }
  }