@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;
  }
  public static void start() {
    AWSCredentials credentials = null;
    try {
      credentials =
          new PropertiesCredentials(
              CreateInitialVMs.class.getResourceAsStream("AwsCredentials.properties"));
    } catch (IOException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }

    /**
     * *******************************************
     *
     * <p>#1 Create Amazon Client object
     *
     * <p>*******************************************
     */
    System.out.println("#1 Create Amazon Client object");
    ec2 = new AmazonEC2Client(credentials);

    try {

      /**
       * *******************************************
       *
       * <p>#6 Create an Instance
       *
       * <p>*******************************************
       */
      System.out.println("#5 Create an Instance");

      String imageId = "ami-76f0061f"; // Basic 32-bit Amazon Linux AMI
      int minInstanceCount = 1;
      int maxInstanceCount = 2; // create 2 instances
      String keyPairName = "testElastic";
      String securityGroupName = "Prachi";
      ArrayList<String> securityGroup = new ArrayList<String>();
      securityGroup.add(securityGroupName);

      RunInstancesRequest rir =
          new RunInstancesRequest(imageId, minInstanceCount, maxInstanceCount);
      rir.setKeyName(keyPairName);
      rir.setSecurityGroups(securityGroup);
      Placement p = new Placement();
      p.setAvailabilityZone("us-east-1a");
      rir.setPlacement(p);

      RunInstancesResult result = ec2.runInstances(rir);

      // get instanceId from the result
      List<Instance> resultInstance = result.getReservation().getInstances();
      String createdInstanceId = null;
      for (Instance ins : resultInstance) {
        createdInstanceId = ins.getInstanceId();

        System.out.println("State of instance " + ins.getInstanceId() + " : ");
        while (true) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          System.out.print(ins.getState().getName() + "\n");

          ins = updatedInstance(ins);
          // if(ins.getPublicIpAddress()!= null){
          // if(ins.getState().getName().equals("running")){
          if (ins.getPublicIpAddress() != null && ins.getState().getName().equals("running")) {
            break;
          }
        }

        System.out.println("State: " + ins.getState().getName());

        System.out.println("New instance has been created: " + ins.getInstanceId());
        System.out.println("Instance Key: " + ins.getKeyName());
        System.out.println("Public DNS Name: " + ins.getPublicDnsName());
        System.out.println("Public DNS IP Address: " + ins.getPublicIpAddress());
        System.out.println("Instance ID: " + ins.getInstanceId());

        VMNode vmn = new VMNode();

        vmn.setInstanceId(ins.getInstanceId());

        /**
         * ******************************************* Allocate elastic IP addresses.
         * *******************************************
         */
        System.out.println("Public IP before association: " + ins.getPublicIpAddress());

        ins = allocateElasticIP(ins);

        vmn.setElasticIp(ins.getPublicIpAddress());

        System.out.println("Public IP after association: " + ins.getPublicIpAddress());

        /**
         * ******************************************* Create a volume
         * *******************************************
         */
        String createdVolumeId = createVolume();

        /**
         * ******************************************* Attach the volume to the instance
         * *******************************************
         */
        attachVolume(createdInstanceId, createdVolumeId);

        vmn.setVolumeId(createdVolumeId);

        /**
         * ******************************************* Detach the volume from the instance
         * *******************************************
         */
        detachVolume(createdInstanceId, createdVolumeId);

        /**
         * ********************************* Create an AMI from an instance
         * *******************************
         */
        String createdImageId = createAmi(createdInstanceId);

        vmn.setAmiId(createdImageId);
        nodes.add(vmn);

        /** ********************************* Stop the instance ******************************* */
        // stopInstance(ins.getInstanceId());
        // Diassociate Elastic IP from instance
        disassociateElasticIp(ins.getPublicIpAddress());
      }

      System.out.println("Listing Nodes: ");
      for (VMNode n : nodes) {
        System.out.println("Instance ID: " + n.getInstanceid());
        System.out.println("Elastic IP: " + n.getElasticIp());
        System.out.println("Volume ID: " + n.getVolumeId());
        System.out.println("AMI ID: " + n.getAmiId());
        System.out.println();
      }

      /**
       * *******************************************
       *
       * <p>#10 shutdown client object
       *
       * <p>*******************************************
       */
      ec2.shutdown();

    } catch (AmazonServiceException ase) {
      System.out.println("Caught Exception: " + ase.getMessage());
      System.out.println("Reponse Status Code: " + ase.getStatusCode());
      System.out.println("Error Code: " + ase.getErrorCode());
      System.out.println("Request ID: " + ase.getRequestId());
    }
  }