def _get_retry_strategy():
    retry_strategy_builder = RetryStrategyBuilder(max_attempts_check=True, max_attempts=10,
                                                  retry_max_wait_between_calls_seconds=30,
                                                  retry_base_sleep_time_seconds=3,
                                                  backoff_type=oci.retry.BACKOFF_FULL_JITTER_EQUAL_ON_THROTTLE_VALUE)
    retry_strategy_builder.add_service_error_check(
        service_error_retry_config={429: [], 400: ['QuotaExceeded', 'LimitExceeded']},
        service_error_retry_on_any_5xx=True)
    return retry_strategy_builder.get_retry_strategy()
    def do_work_hook(self):
        if 'content_md5' in self.multipart_kwargs:
            self.multipart_kwargs.pop('content_md5')

        self.multipart_kwargs['part_size'] = self.part_size
        ma = PooledMultipartObjectAssembler(self.object_storage_client,
                                            self.namespace_name,
                                            self.bucket_name, self.object_name,
                                            self.object_storage_request_pool,
                                            **self.multipart_kwargs)

        ma.new_upload()

        # max_attempts retries - with exponential sleep time and a max wait of 60 secs.
        retry_strategy = RetryStrategyBuilder(retry_max_wait_between_calls_seconds=60).add_max_attempts(self.max_retries)\
            .no_total_elapsed_time() \
            .add_service_error_check() \
            .get_retry_strategy()

        ma.add_parts_from_file(self.file_path)
        if self.multipart_part_completion_callback:
            ma.upload(
                progress_callback=self.multipart_part_completion_callback)
        else:
            ma.upload(retry_strategy=retry_strategy)
        response = ma.commit()

        multipart_hash = cli_util.verify_checksum(
            self.file_path, no_multipart=False,
            ma=ma) if self.verify_checksum else None
        return response, multipart_hash
Exemple #3
0
    def run_job(self):
        self.status = SUCCESS
        self.log_callback.info('Creating image.')

        self.request_credentials([self.account])
        credentials = self.credentials[self.account]

        config = {
            'user': self.oci_user_id,
            'key_content': credentials['signing_key'],
            'fingerprint': credentials['fingerprint'],
            'tenancy': self.tenancy,
            'region': self.region
        }
        compute_client = ComputeClient(config)
        compute_composite_client = ComputeClientCompositeOperations(
            compute_client)

        object_name = self.status_msg['object_name']
        namespace = self.status_msg['namespace']
        self.cloud_image_name = self.status_msg['cloud_image_name']

        image_source_details = ImageSourceViaObjectStorageTupleDetails(
            bucket_name=self.bucket,
            namespace_name=namespace,
            object_name=object_name,
            source_image_type=self.image_type,
            operating_system=self.operating_system,
            operating_system_version=self.operating_system_version)

        image_details = CreateImageDetails(
            compartment_id=self.compartment_id,
            display_name=self.cloud_image_name,
            image_source_details=image_source_details,
            launch_mode=self.launch_mode)

        retry_strategy = RetryStrategyBuilder(
            max_attempts=self.max_oci_attempts,
            service_error_retry_config={
                'service_error_retry_config': {
                    400: ['LimitExceeded']
                }
            }).get_retry_strategy()
        response = compute_composite_client.create_image_and_wait_for_state(
            create_image_details=image_details,
            wait_for_states=[Image.LIFECYCLE_STATE_AVAILABLE],
            operation_kwargs={'retry_strategy': retry_strategy},
            waiter_kwargs={'max_wait_seconds': self.max_oci_wait_seconds})

        self.status_msg['image_id'] = response.data.id
        self.log_callback.info(
            'Created image has ID: {0}.'.format(object_name))
Exemple #4
0
    def cleanup_image(self, credentials, image_id):
        self.log_callback.info(
            'Cleaning up image: {0} in region: {1}.'.format(
                self.cloud_image_name,
                self.region
            )
        )

        config = {
            'user': self.oci_user_id,
            'key_content': credentials['signing_key'],
            'fingerprint': credentials['fingerprint'],
            'tenancy': self.tenancy,
            'region': self.region
        }
        compute_client = ComputeClient(config)
        compute_composite_client = ComputeClientCompositeOperations(
            compute_client
        )
        retry_strategy = RetryStrategyBuilder(
            max_attempts=self.max_oci_attempts,
            service_error_retry_config={
                'service_error_retry_config': {400: ['LimitExceeded']}
            }
        ).get_retry_strategy()

        try:
            compute_composite_client.delete_image_and_wait_for_state(
                image_id=image_id,
                wait_for_states=[
                    Image.LIFECYCLE_STATE_DELETED
                ],
                operation_kwargs={'retry_strategy': retry_strategy},
                waiter_kwargs={'max_wait_seconds': self.max_oci_wait_seconds}
            )
        except Exception as error:
            msg = 'Failed to cleanup image: {0}'.format(error)
            self.add_error_msg(msg)
            self.log_callback.warning(msg)
Exemple #5
0
def _make_raw_request(ctx, target_uri, http_method, request_body,
                      request_headers):
    # Endpoint doesn't make sense because we're asking someone for a --target-uri. We could also just use the --endpoint parameter but that
    # feels like an overloading of that concept (which is declared in cli_root)
    if ctx.obj['endpoint']:
        raise click.UsageError(
            'The --endpoint parameter cannot be specified with this command')

    # Table output may not make too much sense here because we're also dumping out headers and status code, in addition
    # to the data
    if ctx.obj['output'] == 'table':
        raise click.UsageError(
            'The table output format is not supported with this command')

    if ctx.obj['debug']:
        six.moves.http_client.HTTPConnection.debuglevel = 1

    jmespath_expression = cli_util.get_jmespath_expression_from_context(ctx)

    # Deliberately a bit open as we can permit an empty string through as an empty request body
    parsed_request_body = ''
    if request_body is not None and request_body.strip() != '':
        request_body_as_dict = cli_util.parse_json_parameter(
            'request_body', request_body, 'camelize_keys', False)
        parsed_request_body = json.dumps(request_body_as_dict)

    additional_headers = {}
    if request_headers:
        additional_headers = cli_util.parse_json_parameter(
            'request_headers', request_headers, 'camelize_keys', False)

    retry_strategy = DEFAULT_RETRY_STRATEGY
    if ctx.obj['max_attempts']:
        retry_strategy = RetryStrategyBuilder().add_max_attempts(max_attempts=ctx.obj['max_attempts']) \
            .add_total_elapsed_time(total_elapsed_time_seconds=600) \
            .add_service_error_check(service_error_retry_config=retry_checkers.RETRYABLE_STATUSES_AND_CODES,
                                     service_error_retry_on_any_5xx=True) \
            .get_retry_strategy()
    if ctx.obj['no_retry']:
        retry_strategy = oci.retry.NoneRetryStrategy()

    # Make a request and output the results. The retry strategy should make sure that we can ride out
    # connection errors or timeouts, but its logic around ServiceError will not kick in because that's our
    # construct and not something which requests raises.
    #
    # However, with the spirit of this operation I think that is OK because really we just want to make a
    # call and then display the result (even if the result of that call is not a 2xx), so even a 4xx or 5xx
    # would be considered successful from this operation's perspective as it was able to hit a URI and get
    # a response
    with cli_util.build_raw_requests_session(ctx) as requests_session:
        response = retry_strategy.make_retrying_call(
            requests_session.request,
            method=http_method,
            url=target_uri,
            data=parsed_request_body,
            headers=additional_headers)

        result_dict = {
            'status': '{} {}'.format(response.status_code, response.reason),
            'headers':
            {key: value
             for (key, value) in response.headers.items()}
        }
        try:
            dict_from_response_body = response.json()
            if jmespath_expression:
                result_dict['data'] = jmespath_expression.search(
                    dict_from_response_body)
            else:
                result_dict['data'] = dict_from_response_body
        except ValueError:
            # We may not have gotten valid JSON. In that case, do our best and just display something
            result_dict['data'] = response.text

        print(cli_util.pretty_print_format(result_dict))