Example #1
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();
    }
  }
Example #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();
    }
  }