def create_instance(host, ami_spec, subnet_id)
      amitype = host['vmname'] || host['platform']
      amisize = host['amisize'] || 'm1.small'
      vpc_id = host['vpc_id'] || @options['vpc_id'] || nil
      host['sg_cidr_ips'] = host['sg_cidr_ips'] || '0.0.0.0/0';
      sg_cidr_ips = host['sg_cidr_ips'].split(',')
      assoc_pub_ip_addr = host['associate_public_ip_address']

      if vpc_id && !subnet_id
        raise RuntimeError, "A subnet_id must be provided with a vpc_id"
      end
      
      if assoc_pub_ip_addr && !subnet_id
        raise RuntimeError, "A subnet_id must be provided when configuring assoc_pub_ip_addr"
      end

      # Use snapshot provided for this host
      image_type = host['snapshot']
      raise RuntimeError, "No snapshot/image_type provided for EC2 provisioning" unless image_type

      ami = ami_spec[amitype]
      ami_region = ami[:region]

      # Main region object for ec2 operations
      region = ami_region

      # If we haven't defined a vpc_id then we use the default vpc for the provided region
      unless vpc_id
        @logger.notify("aws-sdk: filtering available vpcs in region by 'isDefault'")

        default_vpcs = client(region).describe_vpcs(:filters => [{:name => 'isDefault', :values => ['true']}])
        vpc_id = if default_vpcs.vpcs.empty?
                   nil
                 else
                   default_vpcs.vpcs.first.vpc_id
                 end
      end

      # Grab the vpc object based upon provided id
      vpc = vpc_id ? client(region).describe_vpcs(:vpc_ids => [vpc_id]).vpcs.first : nil

      # Grab image object
      image_id = ami[:image][image_type.to_sym]
      @logger.notify("aws-sdk: Checking image #{image_id} exists and getting its root device")
      image = client(region).describe_images(:image_ids => [image_id]).images.first
      raise RuntimeError, "Image not found: #{image_id}" if image.nil?

      @logger.notify("Image Storage Type: #{image.root_device_type}")

      # Transform the images block_device_mappings output into a format
      # ready for a create.
      block_device_mappings = []
      if image.root_device_type == :ebs
        orig_bdm = image.block_device_mappings
        @logger.notify("aws-sdk: Image block_device_mappings: #{orig_bdm}")
        orig_bdm.each do |block_device|
          block_device_mappings << {
            :device_name => block_device.device_name,
            :ebs => {
              # Change the default size of the root volume.
              :volume_size => host['volume_size'] || block_device.ebs.volume_size,
              # This is required to override the images default for
              # delete_on_termination, forcing all volumes to be deleted once the
              # instance is terminated.
              :delete_on_termination => true,
            }
          }
        end
      end

      security_group = ensure_group(vpc || region, Beaker::EC2Helper.amiports(host), sg_cidr_ips)
      #check if ping is enabled
      ping_security_group = ensure_ping_group(vpc || region, sg_cidr_ips)

      msg = "aws-sdk: launching %p on %p using %p/%p%s" %
            [host.name, amitype, amisize, image_type,
             subnet_id ? ("in %p" % subnet_id) : '']
      @logger.notify(msg)
      config = {
        :max_count  => 1,
        :min_count  => 1,
        :image_id   => image_id,
        :monitoring => {
          :enabled => true,
        },
        :key_name => ensure_key_pair(region).key_pairs.first.key_name,
        :instance_type => amisize,
        :disable_api_termination => false,
        :instance_initiated_shutdown_behavior => "terminate",
      }
      if assoc_pub_ip_addr
        # this never gets created, so they end up with
        # default security group which only allows for
        # ssh access from outside world which
        # doesn't work well with remote devices etc.
        config[:network_interfaces] = [{
          :subnet_id => subnet_id,
          :groups => [security_group.group_id, ping_security_group.group_id],
          :device_index => 0,
          :associate_public_ip_address => assoc_pub_ip_addr,
        }]
      else
        config[:subnet_id] = subnet_id
      end
      config[:block_device_mappings] = block_device_mappings if image.root_device_type == :ebs
      reservation = client(region).run_instances(config)
      reservation.instances.first
    end
def create_instance(host, ami_spec, subnet_id)
      amitype = host['vmname'] || host['platform']
      amisize = host['amisize'] || 'm1.small'
      vpc_id = host['vpc_id'] || @options['vpc_id'] || nil
      host['sg_cidr_ips'] = host['sg_cidr_ips'] || '0.0.0.0/0';
      sg_cidr_ips = host['sg_cidr_ips'].split(',')
      assoc_pub_ip_addr = host['associate_public_ip_address']

      if vpc_id && !subnet_id
        raise RuntimeError, "A subnet_id must be provided with a vpc_id"
      end
      
      if assoc_pub_ip_addr && !subnet_id
        raise RuntimeError, "A subnet_id must be provided when configuring assoc_pub_ip_addr"
      end

      # Use snapshot provided for this host
      image_type = host['snapshot']
      raise RuntimeError, "No snapshot/image_type provided for EC2 provisioning" unless image_type

      ami = ami_spec[amitype]
      ami_region = ami[:region]

      # Main region object for ec2 operations
      region = ami_region

      # If we haven't defined a vpc_id then we use the default vpc for the provided region
      unless vpc_id
        @logger.notify("aws-sdk: filtering available vpcs in region by 'isDefault'")

        default_vpcs = client(region).describe_vpcs(:filters => [{:name => 'isDefault', :values => ['true']}])
        vpc_id = if default_vpcs.vpcs.empty?
                   nil
                 else
                   default_vpcs.vpcs.first.vpc_id
                 end
      end

      # Grab the vpc object based upon provided id
      vpc = vpc_id ? client(region).describe_vpcs(:vpc_ids => [vpc_id]).vpcs.first : nil

      # Grab image object
      image_id = ami[:image][image_type.to_sym]
      @logger.notify("aws-sdk: Checking image #{image_id} exists and getting its root device")
      image = client(region).describe_images(:image_ids => [image_id]).images.first
      raise RuntimeError, "Image not found: #{image_id}" if image.nil?

      @logger.notify("Image Storage Type: #{image.root_device_type}")

      # Transform the images block_device_mappings output into a format
      # ready for a create.
      block_device_mappings = []
      if image.root_device_type == :ebs
        orig_bdm = image.block_device_mappings
        @logger.notify("aws-sdk: Image block_device_mappings: #{orig_bdm}")
        orig_bdm.each do |block_device|
          block_device_mappings << {
            :device_name => block_device.device_name,
            :ebs => {
              # Change the default size of the root volume.
              :volume_size => host['volume_size'] || block_device.ebs.volume_size,
              # This is required to override the images default for
              # delete_on_termination, forcing all volumes to be deleted once the
              # instance is terminated.
              :delete_on_termination => true,
            }
          }
        end
      end

      security_group = ensure_group(vpc || region, Beaker::EC2Helper.amiports(host), sg_cidr_ips)
      #check if ping is enabled
      ping_security_group = ensure_ping_group(vpc || region, sg_cidr_ips)

      msg = "aws-sdk: launching %p on %p using %p/%p%s" %
            [host.name, amitype, amisize, image_type,
             subnet_id ? ("in %p" % subnet_id) : '']
      @logger.notify(msg)
      config = {
        :max_count  => 1,
        :min_count  => 1,
        :image_id   => image_id,
        :monitoring => {
          :enabled => true,
        },
        :key_name => ensure_key_pair(region).key_pairs.first.key_name,
        :instance_type => amisize,
        :disable_api_termination => false,
        :instance_initiated_shutdown_behavior => "terminate",
      }
      if assoc_pub_ip_addr
        # this never gets created, so they end up with
        # default security group which only allows for
        # ssh access from outside world which
        # doesn't work well with remote devices etc.
        config[:network_interfaces] = [{
          :subnet_id => subnet_id,
          :groups => [security_group.group_id, ping_security_group.group_id],
          :device_index => 0,
          :associate_public_ip_address => assoc_pub_ip_addr,
        }]
      else
        config[:subnet_id] = subnet_id
      end
      config[:block_device_mappings] = block_device_mappings if image.root_device_type == :ebs
      reservation = client(region).run_instances(config)
      reservation.instances.first
    end
Create an EC2 instance for host, tag it, and return it.

 @return [void]
 @api private