method for checking the state of an instance on AWS EC2
            
        :param instance_id: string with AWS id of instance
        :param wait: [optional] boolean to wait for instance while pending
        :return: string reporting state of instance

def check_instance_state(self, instance_id, wait=True):
        
        '''
            method for checking the state of an instance on AWS EC2
            
        :param instance_id: string with AWS id of instance
        :param wait: [optional] boolean to wait for instance while pending
        :return: string reporting state of instance
        '''

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

    # validate inputs
        input_fields = {
            'instance_id': instance_id
        }
        for key, value in input_fields.items():
            object_title = '%s(%s=%s)' % (title, key, str(value))
            self.fields.validate(value, '.%s' % key, object_title)

    # notify state check
        self.iam.printer('Querying AWS region %s for state of instance %s.' % (self.iam.region_name, instance_id))

    # check connection to API
        try:
            self.connection.describe_instances()
        except:
            raise AWSConnectionError(title)
                
    # check existence of instance
        try:
            response = self.connection.describe_instances(
                InstanceIds=[ instance_id ]
            )
        except:
            raise ValueError('\nInstance %s does not exist.' % instance_id)
        if not 'Reservations' in response.keys():
            raise ValueError('\nInstance %s does not exist.' % instance_id)
        elif not response['Reservations']:
            raise ValueError('\nInstance %s does not exist.' % instance_id)
        elif not 'Instances' in response['Reservations'][0].keys():
            raise ValueError('\nInstance %s does not exist.' % instance_id)
        elif not response['Reservations'][0]['Instances'][0]:
            raise ValueError('\nInstance %s does not exist.' % instance_id)
                
    # check into state of instance
        elif not 'State' in response['Reservations'][0]['Instances'][0].keys():
            from time import sleep
            from timeit import timeit as timer
            self.iam.printer('Checking into the status of instance %s ... ' % instance_id, flush=True)
            state_timeout = 0
            while not 'State' in response['Reservations'][0]['Instances'][0].keys():
                self.iam.printer('.', flush=True)
                sleep(3)
                state_timeout += 1
                response = self.connection.describe_instances(
                    InstanceIds=[ instance_id ]
                )
                if state_timeout > 3:
                    raise Exception('\nFailure to determine status of instance %s.' % instance_id)
            self.iam.printer('done.')
            
    # return None if instance has already been terminated
        instance_state = response['Reservations'][0]['Instances'][0]['State']['Name']
        if instance_state == 'shutting-down' or instance_state == 'terminated':
            self.iam.printer('Instance %s has already been terminated.' % instance_id)
            return None
            
    # wait while instance is pending
        elif instance_state == 'pending':
            self.iam.printer('Instance %s is %s.' % (instance_id, instance_state), flush=True)
            if not wait:
                return instance_state
            else:
                from time import sleep
                from timeit import timeit as timer
                delay = 3
                while instance_state == 'pending':
                    self.iam.printer('.', flush=True)
                    sleep(delay)
                    t3 = timer()
                    response = self.connection.describe_instances(
                        InstanceIds=[ instance_id ]
                    )
                    t4 = timer()
                    response_time = t4 - t3
                    if 3 - response_time > 0:
                        delay = 3 - response_time
                    else:
                        delay = 0
                    instance_state = response['Reservations'][0]['Instances'][0]['State']['Name']
                self.iam.printer(' done.')

    # report outcome
        self.iam.printer('Instance %s is %s.' % (instance_id, instance_state))

        return instance_state