示例#1
1
 private Integer startTunnelSSH(Instance instance) throws InterruptedException {
   Instance tunnelInstance = runningInstances(tunnelResourceId).get(0);
   Integer localPort = Double.valueOf(Randoms.number(3000, 10000)).intValue();
   CountDownLatch latch = new CountDownLatch(1);
   Thread tunnelThread =
       new Thread(
           () -> {
             Process process = null;
             try {
               Path keyPath = KeyPair.keyFile(tunnelInstance.getKeyName(), env);
               String userAndHost = "ubuntu@" + hostName(tunnelInstance);
               String portBinding =
                   Strings.format("{}:{}:22", localPort, instance.getPrivateIpAddress());
               List<String> command = tunnelCommand(keyPath, userAndHost, portBinding);
               logger.info("tunnel command => {}", String.join(" ", command));
               process = new ProcessBuilder().command(command).start();
               process.getInputStream().read(); // wait until there is output
               latch.countDown();
               process.waitFor();
             } catch (InterruptedException | IOException e) {
               throw new IllegalStateException(e);
             } finally {
               if (process != null) process.destroy();
             }
           });
   tunnelThread.setDaemon(true);
   tunnelThread.start();
   latch.await();
   return localPort;
 }
  @Override
  public void execute(Context context) throws Exception {
    RunInstancesRequest request =
        new RunInstancesRequest()
            .withKeyName(resource.keyPair.remoteKeyPair.getKeyName())
            .withInstanceType(resource.instanceType)
            .withImageId(resource.ami.imageId())
            .withMinCount(addedCount)
            .withMaxCount(addedCount)
            .withUserData(Base64.encodeBase64String(Strings.bytes(userData(context.env))));

    if (resource.instanceProfile != null)
      request.withIamInstanceProfile(
          new IamInstanceProfileSpecification()
              .withName(resource.instanceProfile.remoteInstanceProfile.getInstanceProfileName()));

    String sgId = resource.securityGroup.remoteSecurityGroup.getGroupId();

    request
        .getNetworkInterfaces()
        .add(
            new InstanceNetworkInterfaceSpecification()
                .withDeviceIndex(0)
                .withSubnetId(resource.subnet.firstRemoteSubnet().getSubnetId())
                .withGroups(sgId)
                .withAssociatePublicIpAddress(resource.subnet.type == SubnetType.PUBLIC));

    if (resource.ebs.rootVolumeSize != null) {
      request
          .getBlockDeviceMappings()
          .add(
              new BlockDeviceMapping()
                  .withDeviceName("/dev/sda1")
                  .withEbs(new EbsBlockDevice().withVolumeSize(resource.ebs.rootVolumeSize)));
    }

    List<com.amazonaws.services.ec2.model.Instance> remoteInstances =
        AWS.ec2.runInstances(request, tags(context.env));
    resource.remoteInstances.addAll(remoteInstances);

    for (com.amazonaws.services.ec2.model.Instance remoteInstance : remoteInstances) {
      String key = String.format("instance/%s/%s", resource.id, remoteInstance.getInstanceId());
      StringBuilder builder = new StringBuilder();
      builder.append("privateIP=").append(remoteInstance.getPrivateIpAddress());
      if (resource.subnet == null || resource.subnet.type == SubnetType.PUBLIC) {
        builder.append(", publicDNS=").append(remoteInstance.getPublicDnsName());
      }
      context.output(key, builder.toString());
    }

    if (resource.elb != null) {
      List<String> instanceIds =
          remoteInstances
              .stream()
              .map(com.amazonaws.services.ec2.model.Instance::getInstanceId)
              .collect(Collectors.toList());
      AWS.elb.attachInstances(
          resource.elb.remoteELB.getLoadBalancerName(), instanceIds, waitUntilInService);
    }
  }
  /*
   * Much of the EC2 data is beyond our direct control, therefore we need to refresh it from time to time to ensure we
   * reflect the reality of the instances.
   */
  protected void fetchLiveInstanceData(boolean force) throws AmazonClientException {
    /*
     * If we've grabbed the data recently, don't bother getting it again unless we are forced
     */
    long now = System.currentTimeMillis();
    if ((lastFetchTime > 0) && (now - lastFetchTime < MIN_FETCH_TIME) && !force) {
      return;
    }

    if (getInstanceId() == null || getInstanceId() == "") {
      /*
       * The getInstanceId() implementation on EC2SpotSlave can return null if the spot request doesn't yet know
       * the instance id that it is starting. What happens is that null is passed to getInstanceId() which
       * searches AWS but without an instanceID the search returns some random box. We then fetch its metadata,
       * including tags, and then later, when the spot request eventually gets the instanceID correctly we push
       * the saved tags from that random box up to the new spot resulting in confusion and delay.
       */
      return;
    }

    Instance i = getInstance(getInstanceId(), getCloud());

    lastFetchTime = now;
    lastFetchInstance = i;
    if (i == null) return;

    publicDNS = i.getPublicDnsName();
    privateDNS = i.getPrivateIpAddress();
    createdTime = i.getLaunchTime().getTime();
    tags = new LinkedList<EC2Tag>();

    for (Tag t : i.getTags()) {
      tags.add(new EC2Tag(t.getKey(), t.getValue()));
    }
  }
  private String getHostName(EC2Computer computer)
      throws AmazonClientException, InterruptedException {
    Instance instance;
    instance = computer.updateInstanceDescription();
    String vpc_id = instance.getVpcId();
    String host;

    if (computer.getNode().usePrivateDnsName) {
      host = instance.getPrivateDnsName();
    } else {
      /* VPC hosts don't have public DNS names, so we need to use an IP address instead */
      if (vpc_id == null || vpc_id.equals("")) {
        host = instance.getPublicDnsName();
      } else {
        host = instance.getPrivateIpAddress();
      }
    }
    return host;
  }
  @Override
  public List<DiscoveryNode> buildDynamicNodes() {
    List<DiscoveryNode> discoNodes = new ArrayList<>();

    DescribeInstancesResult descInstances;
    try {
      // Query EC2 API based on AZ, instance state, and tag.

      // NOTE: we don't filter by security group during the describe instances request for two
      // reasons:
      // 1. differences in VPCs require different parameters during query (ID vs Name)
      // 2. We want to use two different strategies: (all security groups vs. any security groups)
      descInstances = client.describeInstances(buildDescribeInstancesRequest());
    } catch (AmazonClientException e) {
      logger.info("Exception while retrieving instance list from AWS API: {}", e.getMessage());
      logger.debug("Full exception:", e);
      return discoNodes;
    }

    logger.trace("building dynamic unicast discovery nodes...");
    for (Reservation reservation : descInstances.getReservations()) {
      for (Instance instance : reservation.getInstances()) {
        // lets see if we can filter based on groups
        if (!groups.isEmpty()) {
          List<GroupIdentifier> instanceSecurityGroups = instance.getSecurityGroups();
          ArrayList<String> securityGroupNames = new ArrayList<String>();
          ArrayList<String> securityGroupIds = new ArrayList<String>();
          for (GroupIdentifier sg : instanceSecurityGroups) {
            securityGroupNames.add(sg.getGroupName());
            securityGroupIds.add(sg.getGroupId());
          }
          if (bindAnyGroup) {
            // We check if we can find at least one group name or one group id in groups.
            if (Collections.disjoint(securityGroupNames, groups)
                && Collections.disjoint(securityGroupIds, groups)) {
              logger.trace(
                  "filtering out instance {} based on groups {}, not part of {}",
                  instance.getInstanceId(),
                  instanceSecurityGroups,
                  groups);
              // continue to the next instance
              continue;
            }
          } else {
            // We need tp match all group names or group ids, otherwise we ignore this instance
            if (!(securityGroupNames.containsAll(groups) || securityGroupIds.containsAll(groups))) {
              logger.trace(
                  "filtering out instance {} based on groups {}, does not include all of {}",
                  instance.getInstanceId(),
                  instanceSecurityGroups,
                  groups);
              // continue to the next instance
              continue;
            }
          }
        }

        String address = null;
        switch (hostType) {
          case PRIVATE_DNS:
            address = instance.getPrivateDnsName();
            break;
          case PRIVATE_IP:
            address = instance.getPrivateIpAddress();
            break;
          case PUBLIC_DNS:
            address = instance.getPublicDnsName();
            break;
          case PUBLIC_IP:
            address = instance.getPublicIpAddress();
            break;
        }
        if (address != null) {
          try {
            TransportAddress[] addresses = transportService.addressesFromString(address);
            // we only limit to 1 addresses, makes no sense to ping 100 ports
            for (int i = 0; (i < addresses.length && i < UnicastZenPing.LIMIT_PORTS_COUNT); i++) {
              logger.trace(
                  "adding {}, address {}, transport_address {}",
                  instance.getInstanceId(),
                  address,
                  addresses[i]);
              discoNodes.add(
                  new DiscoveryNode(
                      "#cloud-" + instance.getInstanceId() + "-" + i,
                      addresses[i],
                      version.minimumCompatibilityVersion()));
            }
          } catch (Exception e) {
            logger.warn("failed ot add {}, address {}", e, instance.getInstanceId(), address);
          }
        } else {
          logger.trace(
              "not adding {}, address is null, host_type {}", instance.getInstanceId(), hostType);
        }
      }
    }

    logger.debug("using dynamic discovery nodes {}", discoNodes);

    return discoNodes;
  }