a method for starting an instance on AWS EC2
            
        :param image_id: string with aws id of image for instance 
        :param pem_file: string with path to pem file to access image
        :param group_ids: list with aws id of security group(s) to attach to instance
        :param instance_type: string with type of instance resource to use
        :param volume_type: string with type of on-disk storage
        :param ebs_optimized: [optional] boolean to activate ebs optimization 
        :param instance_monitoring: [optional] boolean to active instance monitoring
        :param iam_profile: [optional] string with name of iam instance profile role
        :param tag_list: [optional] list of single key-pair tags for instance
        :param auction_bid: [optional] float with dollar amount to bid for instance hour
        :return: string with id of instance

def create_instance(self, image_id, pem_file, group_ids, instance_type, volume_type='gp2', ebs_optimized=False, instance_monitoring=False, iam_profile='', tag_list=None, auction_bid=0.0):

        '''
            a method for starting an instance on AWS EC2
            
        :param image_id: string with aws id of image for instance 
        :param pem_file: string with path to pem file to access image
        :param group_ids: list with aws id of security group(s) to attach to instance
        :param instance_type: string with type of instance resource to use
        :param volume_type: string with type of on-disk storage
        :param ebs_optimized: [optional] boolean to activate ebs optimization 
        :param instance_monitoring: [optional] boolean to active instance monitoring
        :param iam_profile: [optional] string with name of iam instance profile role
        :param tag_list: [optional] list of single key-pair tags for instance
        :param auction_bid: [optional] float with dollar amount to bid for instance hour
        :return: string with id of instance
        '''

        title = '%s.create_instance' % self.__class__.__name__

    # validate inputs
        input_fields = {
            'image_id': image_id,
            'pem_file': pem_file,
            'group_ids': group_ids,
            'instance_type': instance_type,
            'volume_type': volume_type,
            'iam_profile': iam_profile,
            'tag_list': tag_list,
            'auction_bid': auction_bid
        }
        for key, value in input_fields.items():
            if value:
                object_title = '%s(%s=%s)' % (title, key, str(value))
                self.fields.validate(value, '.%s' % key, object_title)

    # print warning about auction
        if auction_bid:
            self.iam.printer('[WARNING]: auction bidding is not yet available.')

    # turn off verbosity
        self.iam.printer_on = False
        
    # verify existence of image
        try:
            self.read_image(image_id)
        except:
            raise ValueError('Image %s does not exist in EC2 account or permission scope.')
        
    # verify existence of security group
        group_list = self.list_security_groups()
        for id in group_ids:
            if id not in group_list:
                raise ValueError('Security group %s does not exist in EC2 account.' % id)
        
    # verify existence of iam profile
        if iam_profile:    
            if not iam_profile in self.iam.list_roles():
                raise ValueError('Iam instance profile %s does not exist in IAM account.' % iam_profile)

    # validate path to pem file
        from os import path
        if not path.exists(pem_file):
            raise ValueError('%s is not a valid path on localhost.' % pem_file)
    
    # verify existence of pem name
        pem_absolute = path.abspath(pem_file)
        pem_root, pem_ext = path.splitext(pem_absolute)
        pem_path, pem_name = path.split(pem_root)
        if not pem_name in self.list_keypairs():
            raise ValueError('Pem file name %s does not exist in EC2 account.' % pem_name)
    
    # turn on verbosity
        self.iam.printer_on = True
    
    # create client token and timestamp for instance
        from labpack.records.id import labID
        record_id = labID()
        client_token = 'CT-%s' % record_id.id36
        from labpack.records.time import labDT
        timestamp = labDT.new().zulu()
    
    # construct tag list
        if not tag_list:
            tag_list = []
        for tag in tag_list:
            if tag['key'] == 'BuildDate':
                tag['value'] = timestamp

    # create keyword argument definitions
        kw_args = {
            'DryRun': False,
            'ImageId': image_id,
            'MinCount': 1,
            'MaxCount': 1,
            'KeyName': pem_name,
            'SecurityGroupIds': group_ids,
            'InstanceType': instance_type,
            'ClientToken': client_token,
            'Monitoring': { 'Enabled': instance_monitoring },
            'EbsOptimized': ebs_optimized,
            'BlockDeviceMappings': []
        }
        kw_args['BlockDeviceMappings'].append(
            { "DeviceName": "/dev/xvda", "Ebs": { "VolumeType": volume_type } }
        )
        if iam_profile:
            kw_args['IamInstanceProfile'] = { 'Name': iam_profile }

    # start instance on aws
        self.iam.printer('Initiating instance of image %s.' % image_id)
        try:
            response = self.connection.run_instances(**kw_args)
        except Exception as err:
            if str(err).find('non-VPC'):
                self.iam.printer('Default VPC Error Detected!\nAttempting to add Subnet declaration.')
                group_details = self.read_security_group(group_ids[0])
                env_type = ''
                for tag in group_details['tags']:
                    if tag['Key'] == 'Env':
                        env_type = tag['Value']
                if env_type:
                    subnet_list = self.list_subnets(tag_values=[env_type])
                else:
                    subnet_list = self.list_subnets()
                error_msg = '%s requires a Subnet match the Security Group %s' % (title, group_ids[0])
                if not subnet_list:
                    raise AWSConnectionError(error_msg)
                subnet_id = ''
                for subnet in subnet_list:
                    subnet_details = self.read_subnet(subnet)
                    if subnet_details['vpc_id'] == group_details['vpc_id']:
                        subnet_id = subnet
                if not subnet_id:
                    raise AWSConnectionError(error_msg)
                kw_args['SubnetId'] = subnet_id
                try:
                    response = self.connection.run_instances(**kw_args)
                except:
                    raise AWSConnectionError('%s(%s)' % (title, kw_args))
            else:
                raise AWSConnectionError('%s(%s)' % (title, kw_args))

    # parse instance id from response
        instance_id = ''
        instance_list = response['Instances']
        for i in range(0, len(instance_list)):
            if instance_list[i]['ClientToken'] == client_token:
                instance_id = instance_list[i]['InstanceId']
        if instance_id:
            self.iam.printer('Instance %s has been initiated.' % instance_id)
        else:
            raise Exception('Failure creating instance from image %s.' % image_id)

    # tag instance with instance tags
        self.tag_instance(instance_id, tag_list)

        return instance_id