a method to add a copy of an image to another AWS region

            https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html

            REQUIRED: iam credentials must have valid access to both regions

        :param image_id: string of AWS id of image to be copied
        :param region_name: string of AWS region to copy image to
        :return: string with AWS id of new image

def export_image(self, image_id, region_name):

        '''
            a method to add a copy of an image to another AWS region

            https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html

            REQUIRED: iam credentials must have valid access to both regions

        :param image_id: string of AWS id of image to be copied
        :param region_name: string of AWS region to copy image to
        :return: string with AWS id of new image
        '''

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

    # validate inputs
        input_fields = {
            'image_id': image_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)
        input_fields = {
            'region_name': region_name
        }
        for key, value in input_fields.items():
            object_title = '%s(%s=%s)' % (title, key, str(value))
            self.iam.fields.validate(value, '.%s' % key, object_title)
        if region_name == self.iam.region_name:
            raise ValueError('%s cannot export an image to the same region.' % title)
        
    # construct ec2 client connection for source region
        client_kwargs = {
            'service_name': 'ec2',
            'region_name': region_name,
            'aws_access_key_id': self.iam.access_id,
            'aws_secret_access_key': self.iam.secret_key
        }
        destination_connection = boto3.client(**client_kwargs)

    # check state of image to be copied
        self.check_image_state(image_id)

    # discover tags and name associated with image to be copied
        image_details = self.read_image(image_id)
        tag_list = image_details['tags']
        image_name = image_details['name']

    # copy image over to current region
        self.iam.printer('Copying image %s to region %s.' % (image_id, region_name))
        try:
            response = destination_connection.copy_image(
                SourceRegion=self.iam.region_name,
                SourceImageId=image_id,
                Name=image_name
            )
        except:
            raise AWSConnectionError(title)
        new_id = response['ImageId']

    # check into state of new image
        try:
            response = destination_connection.describe_images(
                ImageIds=[ new_id ]
            )
        except:
            raise AWSConnectionError(title)
        if not 'State' in response['Images'][0].keys():
            from time import sleep
            from timeit import default_timer as timer
            self.iam.printer('Checking into the status of image %s in AWS region %s' % (new_id, region_name), flush=True)
            state_timeout = 0
            while not 'State' in response['Images'][0].keys():
                self.iam.printer('.', flush=True)
                sleep(3)
                state_timeout += 1
                try:
                    response = destination_connection.describe_images(
                        ImageIds=[ new_id ]
                    )
                except:
                    raise AWSConnectionError(title)
                if state_timeout > 3:
                    raise Exception('Failure to determine status of image %s in AWS region %s.' % (new_id, region_name))
            self.iam.printer(' done.')
        image_state = response['Images'][0]['State']

    # wait while image is pending
        if image_state == 'pending':
            from time import sleep
            from timeit import default_timer as timer
            self.iam.printer('Image %s in AWS region %s is %s' % (new_id, region_name, image_state), flush=True)
            delay = 3
            state_timeout = 0
            while image_state != 'available':
                self.iam.printer('.', flush=True)
                sleep(delay)
                t3 = timer()
                try:
                    response = destination_connection.describe_images(
                        ImageIds=[ new_id ]
                    )
                except:
                    raise AWSConnectionError(title)
                t4 = timer()
                state_timeout += 1
                response_time = t4 - t3
                if 3 - response_time > 0:
                    delay = 3 - response_time
                else:
                    delay = 0
                if state_timeout > 300:
                    raise Exception('Timeout. Failure initializing image %s in region %s in less than 15min' % (new_id, region_name))
                image_state = response['Images'][0]['State']
            self.iam.printer(' done.')

    # add tags from image to image copy
        try:
            destination_connection.create_tags(
                Resources=[ new_id ],
                Tags=tag_list
            )
        except:
            raise AWSConnectionError(title)
        self.iam.printer('Tags from image %s have been added to image %s.' % (image_id, new_id))

        return new_id